Panda3D

Loading...
Searching...
No Matches
texturePlacement.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file texturePlacement.cxx
10 * @author drose
11 * @date 2000-11-30
12 */
13
14#include "texturePlacement.h"
15#include "textureReference.h"
16#include "textureImage.h"
17#include "paletteGroup.h"
18#include "paletteImage.h"
19#include "palettizer.h"
20#include "eggFile.h"
21#include "destTextureImage.h"
22
23#include "indent.h"
24#include "datagram.h"
25#include "datagramIterator.h"
26#include "bamReader.h"
27#include "bamWriter.h"
28#include "pnmImage.h"
29
30 using std::max;
31 using std::min;
32
33 TypeHandle TexturePlacement::_type_handle;
34
35/**
36 * The default constructor is only for the convenience of the Bam reader.
37 */
38TexturePlacement::
39TexturePlacement() {
40 _texture = nullptr;
41 _group = nullptr;
42 _image = nullptr;
43 _dest = nullptr;
44 _has_uvs = false;
45 _size_known = false;
46 _is_filled = true;
47 _omit_reason = OR_none;
48}
49
50/**
51 *
52 */
53TexturePlacement::
54TexturePlacement(TextureImage *texture, PaletteGroup *group) :
55 _texture(texture),
56 _group(group)
57{
58 _omit_reason = OR_working;
59
60 if (!texture->is_size_known()) {
61 // If we were never able to figure out what size the texture actually is,
62 // then we can't place the texture on a palette.
63 _omit_reason = OR_unknown;
64 }
65
66 _image = nullptr;
67 _dest = nullptr;
68 _has_uvs = false;
69 _size_known = false;
70 _is_filled = false;
71}
72
73/**
74 *
75 */
76TexturePlacement::
77~TexturePlacement() {
78 // Make sure we tell all our egg references they're not using us any more.
79 References::iterator ri;
80 References copy_references = _references;
81 for (ri = copy_references.begin(); ri != copy_references.end(); ++ri) {
82 TextureReference *reference = (*ri);
83 nassertv(reference->get_placement() == this);
84 reference->clear_placement();
85 }
86
87 // And also our group, etc.
88 _group->unplace(this);
89}
90
91/**
92 * Returns the name of the texture that this placement represents.
93 */
94 const std::string &TexturePlacement::
95 get_name() const {
96 return _texture->get_name();
97}
98
99/**
100 * Returns the texture that this placement represents.
101 */
102 TextureImage *TexturePlacement::
103 get_texture() const {
104 return _texture;
105}
106
107/**
108 * Returns the grouping properties of the image.
109 */
110 const TextureProperties &TexturePlacement::
111 get_properties() const {
112 return _texture->get_properties();
113}
114
115/**
116 * Returns the group that this placement represents.
117 */
118 PaletteGroup *TexturePlacement::
119 get_group() const {
120 return _group;
121}
122
123/**
124 * Records the fact that a particular egg file is using this particular
125 * TexturePlacement.
126 */
127 void TexturePlacement::
128 add_egg(TextureReference *reference) {
129 reference->mark_egg_stale();
130
131 // Turns out that turning these off is a bad idea, because it may make us
132 // forget the size information halfway through processing.
133 /*
134 _has_uvs = false;
135 _size_known = false;
136 */
137 _references.insert(reference);
138}
139
140/**
141 * Notes that a particular egg file is no longer using this particular
142 * TexturePlacement.
143 */
144 void TexturePlacement::
145 remove_egg(TextureReference *reference) {
146 reference->mark_egg_stale();
147 /*
148 _has_uvs = false;
149 _size_known = false;
150 */
151 _references.erase(reference);
152}
153
154/**
155 * Marks all the egg files that reference this placement stale. Presumably
156 * this is called after moving the texture around in the palette or something.
157 */
158 void TexturePlacement::
159 mark_eggs_stale() {
160 References::iterator ri;
161 for (ri = _references.begin(); ri != _references.end(); ++ri) {
162 TextureReference *reference = (*ri);
163
164 reference->mark_egg_stale();
165 }
166}
167
168/**
169 * Sets the DestTextureImage that corresponds to this texture as it was copied
170 * to the install directory.
171 */
172 void TexturePlacement::
173 set_dest(DestTextureImage *dest) {
174 _dest = dest;
175}
176
177/**
178 * Returns the DestTextureImage that corresponds to this texture as it was
179 * copied to the install directory.
180 */
181 DestTextureImage *TexturePlacement::
182 get_dest() const {
183 return _dest;
184}
185
186/**
187 * Attempts to determine the appropriate size of the texture for the given
188 * placement. This is based on the UV range of the egg files that reference
189 * the texture. Returns true on success, or false if the texture size cannot
190 * be determined (e.g. the texture file is unknown).
191 *
192 * After this returns true, get_x_size() and get_y_size() may safely be
193 * called.
194 */
195 bool TexturePlacement::
196 determine_size() {
197 if (!_texture->is_size_known()) {
198 // Too bad.
199 force_replace();
200 _omit_reason = OR_unknown;
201 return false;
202 }
203
204 // This seems to be unnecessary (because of omit_solitary() and
205 // not_solitary()), and in fact bitches the logic in omit_solitary() and
206 // not_solitary() so that we call mark_egg_stale() unnecessarily.
207 /*
208 if (_omit_reason == OR_solitary) {
209 // If the texture was previously 'omitted' for being solitary, we give it
210 // a second chance now.
211 _omit_reason = OR_none;
212 }
213 */
214
215 // Determine the actual minmax of the UV's in use, as well as whether we
216 // should wrap or clamp.
217 _has_uvs = false;
218 _position._wrap_u = EggTexture::WM_clamp;
219 _position._wrap_v = EggTexture::WM_clamp;
220
221 LTexCoordd max_uv, min_uv;
222
223 References::iterator ri;
224 for (ri = _references.begin(); ri != _references.end(); ++ri) {
225 TextureReference *reference = (*ri);
226 if (reference->has_uvs()) {
227 const LTexCoordd &n = reference->get_min_uv();
228 const LTexCoordd &x = reference->get_max_uv();
229
230 if (_has_uvs) {
231 min_uv.set(min(min_uv[0], n[0]), min(min_uv[1], n[1]));
232 max_uv.set(max(max_uv[0], x[0]), max(max_uv[1], x[1]));
233 } else {
234 min_uv = n;
235 max_uv = x;
236 _has_uvs = true;
237 }
238 }
239
240 // If any reference repeats the texture, the texture repeats in the
241 // palette.
242 if (reference->get_wrap_u() == EggTexture::WM_repeat) {
243 _position._wrap_u = EggTexture::WM_repeat;
244 }
245 if (reference->get_wrap_v() == EggTexture::WM_repeat) {
246 _position._wrap_v = EggTexture::WM_repeat;
247 }
248 }
249
250 // However, if the user specified an explicit wrap mode, allow it to apply.
251 if (_texture->get_txa_wrap_u() != EggTexture::WM_unspecified) {
252 _position._wrap_u = _texture->get_txa_wrap_u();
253 }
254 if (_texture->get_txa_wrap_v() != EggTexture::WM_unspecified) {
255 _position._wrap_v = _texture->get_txa_wrap_v();
256 }
257
258 if (!_has_uvs) {
259 force_replace();
260 _omit_reason = OR_unused;
261 return false;
262 }
263
264 LTexCoordd rounded_min_uv = min_uv;
265 LTexCoordd rounded_max_uv = max_uv;
266
267 // cout << get_name() << endl;
268
269 // If so requested, round the minmax out to the next _round_unit. This cuts
270 // down on unnecessary resizing of textures within the palettes as the egg
271 // references change in trivial amounts. cout << "rounded_min_uv: " <<
272 // rounded_min_uv << endl; cout << "rounded_max_uv: " << rounded_max_uv <<
273 // endl;
274
275 if (pal->_round_uvs) {
276 rounded_max_uv[0] =
277 ceil((rounded_max_uv[0] - pal->_round_fuzz) / pal->_round_unit) *
278 pal->_round_unit;
279 rounded_max_uv[1] =
280 ceil((rounded_max_uv[1] - pal->_round_fuzz) / pal->_round_unit) *
281 pal->_round_unit;
282
283 rounded_min_uv[0] =
284 floor((rounded_min_uv[0] + pal->_round_fuzz) / pal->_round_unit) *
285 pal->_round_unit;
286 rounded_min_uv[1] =
287 floor((rounded_min_uv[1] + pal->_round_fuzz) / pal->_round_unit) *
288 pal->_round_unit;
289
290 // cout << "after rounded_min_uv: " << rounded_min_uv << endl; cout <<
291 // "after rounded_max_uv: " << rounded_max_uv << endl;
292 }
293
294 // Now determine the size in pixels we require based on the UV's that
295 // actually reference this texture.
296 compute_size_from_uvs(rounded_min_uv, rounded_max_uv);
297
298 // Now, can it be placed?
299 if (_texture->get_omit()) {
300 // Not if the user says it can't.
301 force_replace();
302 _omit_reason = OR_omitted;
303
304 } else if (get_uv_area() > _texture->get_coverage_threshold()) {
305 // If the texture repeats too many times, we can't place it.
306 force_replace();
307 _omit_reason = OR_coverage;
308
309 } else if ((_position._x_size > pal->_pal_x_size ||
310 _position._y_size > pal->_pal_y_size) ||
311 (_position._x_size == pal->_pal_x_size &&
312 _position._y_size == pal->_pal_y_size)) {
313 // If the texture exceeds the size of an empty palette image in either
314 // dimension, or if it exactly equals the size of an empty palette image
315 // in both dimensions, we can't place it because it's too big.
316 force_replace();
317 _omit_reason = OR_size;
318
319 } else if (pal->_omit_everything && (_group->is_none_texture_swap())) {
320 // If we're omitting everything, omit everything.
321 force_replace();
322 _omit_reason = OR_default_omit;
323
324 } else if (_omit_reason == OR_omitted ||
325 _omit_reason == OR_default_omit ||
326 _omit_reason == OR_size ||
327 _omit_reason == OR_coverage ||
328 _omit_reason == OR_unknown) {
329 // On the other hand, if the texture was previously omitted explicitly, or
330 // because of its size or coverage, now it seems to fit.
331 force_replace();
332 mark_eggs_stale();
333 _omit_reason = OR_working;
334
335 } else if (is_placed()) {
336 // It *can* be placed. If it was already placed previously, can we leave
337 // it where it is?
338
339 if (_position._x_size != _placed._x_size ||
340 _position._y_size != _placed._y_size ||
341 _position._min_uv[0] < _placed._min_uv[0] ||
342 _position._min_uv[1] < _placed._min_uv[1] ||
343 _position._max_uv[0] > _placed._max_uv[0] ||
344 _position._max_uv[1] > _placed._max_uv[1]) {
345 // If the texture was previously placed but is now the wrong size, or if
346 // the area we need to cover is different, we need to re-place it.
347
348 // However, we make a special exception: if it would have fit without
349 // rounding up the UV's, then screw rounding it up and just leave it
350 // alone.
351 if ((_position._x_size > _placed._x_size ||
352 _position._y_size > _placed._y_size) &&
353 pal->_round_uvs) {
354 compute_size_from_uvs(min_uv, max_uv);
355 if (_position._x_size <= _placed._x_size &&
356 _position._y_size <= _placed._y_size &&
357 _position._min_uv[0] >= _placed._min_uv[0] &&
358 _position._min_uv[1] >= _placed._min_uv[1] &&
359 _position._max_uv[0] <= _placed._max_uv[0] &&
360 _position._max_uv[1] <= _placed._max_uv[1]) {
361 // No problem! It fits here, so leave well enough alone.
362 } else {
363 // That's not good enough either, so go back to rounding.
364 compute_size_from_uvs(rounded_min_uv, rounded_max_uv);
365 force_replace();
366 }
367 } else {
368 force_replace();
369 }
370 }
371
372 if (_position._wrap_u != _placed._wrap_u ||
373 _position._wrap_v != _placed._wrap_v) {
374 // The wrap mode properties have changed slightly. We may or may not
375 // need to re-place it, but we will need to update it.
376 _is_filled = false;
377 _placed._wrap_u = _position._wrap_u;
378 _placed._wrap_v = _position._wrap_v;
379 }
380 }
381
382 return true;
383}
384
385/**
386 * Returns true if the texture's size is known, false otherwise. Usually this
387 * can only be false after determine_size() has been called there is something
388 * wrong with the texture (in which case the placement will automatically omit
389 * itself from the palette anyway).
390 */
391 bool TexturePlacement::
392 is_size_known() const {
393 return _size_known;
394}
395
396/**
397 * Returns the reason the texture has been omitted from a palette image, or
398 * OR_none if it has not.
399 */
400 OmitReason TexturePlacement::
401 get_omit_reason() const {
402 return _omit_reason;
403}
404
405/**
406 * Returns the size in the X dimension, in pixels, of the texture image as it
407 * must appear in the palette. This accounts for any growing or shrinking of
408 * the texture due to the UV coordinate range.
409 */
410 int TexturePlacement::
411 get_x_size() const {
412 nassertr(_size_known, 0);
413 return _position._x_size;
414}
415
416/**
417 * Returns the size in the Y dimension, in pixels, of the texture image as it
418 * must appear in the palette. This accounts for any growing or shrinking of
419 * the texture due to the UV coordinate range.
420 */
421 int TexturePlacement::
422 get_y_size() const {
423 nassertr(_size_known, 0);
424 return _position._y_size;
425}
426
427/**
428 * Returns the total area of the rectangle occupied by the UV minmax box, in
429 * UV coordinates. 1.0 is the entire texture; values greater than 1 imply the
430 * texture repeats.
431 */
432 double TexturePlacement::
433 get_uv_area() const {
434 if (!_has_uvs) {
435 return 0.0;
436 }
437
438 LTexCoordd range = _position._max_uv - _position._min_uv;
439 return range[0] * range[1];
440}
441
442/**
443 * Returns true if the texture has been placed on a palette image, false
444 * otherwise. This will generally be true if get_omit_reason() returns
445 * OR_none or OR_solitary and false otherwise.
446 */
447 bool TexturePlacement::
448 is_placed() const {
449 return _image != nullptr;
450}
451
452/**
453 * Returns the particular PaletteImage on which the texture has been placed.
454 */
455 PaletteImage *TexturePlacement::
456 get_image() const {
457 nassertr(is_placed(), nullptr);
458 return _image;
459}
460
461/**
462 * Returns the particular PalettePage on which the texture has been placed.
463 */
464 PalettePage *TexturePlacement::
465 get_page() const {
466 nassertr(is_placed(), nullptr);
467 return _image->get_page();
468}
469
470/**
471 * Returns the X pixel at which the texture has been placed within its
472 * PaletteImage. It is an error to call this unless is_placed() returns true.
473 */
474 int TexturePlacement::
475 get_placed_x() const {
476 nassertr(is_placed(), 0);
477 return _placed._x;
478}
479
480/**
481 * Returns the Y pixel at which the texture has been placed within its
482 * PaletteImage. It is an error to call this unless is_placed() returns true.
483 */
484 int TexturePlacement::
485 get_placed_y() const {
486 nassertr(is_placed(), 0);
487 return _placed._y;
488}
489
490/**
491 * Returns the size in the X dimension, in pixels, of the texture image as it
492 * has been placed within the palette.
493 */
494 int TexturePlacement::
495 get_placed_x_size() const {
496 nassertr(is_placed(), 0);
497 return _placed._x_size;
498}
499
500/**
501 * Returns the size in the Y dimension, in pixels, of the texture image as it
502 * has been placed within the palette.
503 */
504 int TexturePlacement::
505 get_placed_y_size() const {
506 nassertr(is_placed(), 0);
507 return _placed._y_size;
508}
509
510/**
511 * Returns the total area of the rectangle occupied by the UV minmax box, as
512 * it has been placed. See also get_uv_area().
513 */
514 double TexturePlacement::
515 get_placed_uv_area() const {
516 nassertr(is_placed(), 0);
517 LTexCoordd range = _placed._max_uv - _placed._min_uv;
518 return range[0] * range[1];
519}
520
521/**
522 * Assigns the texture to a particular position within the indicated
523 * PaletteImage. It is an error to call this if the texture has already been
524 * placed elsewhere.
525 */
526 void TexturePlacement::
527 place_at(PaletteImage *image, int x, int y) {
528 nassertv(!is_placed());
529 nassertv(_size_known);
530
531 _image = image;
532 _is_filled = false;
533 _position._x = x;
534 _position._y = y;
535 _placed = _position;
536 _omit_reason = OR_none;
537}
538
539/**
540 * Removes the texture from its particular PaletteImage, but does not remove
541 * it from the PaletteGroup. It will be re-placed when the
542 * PaletteGroup::place_all() is called.
543 */
544 void TexturePlacement::
545 force_replace() {
546 if (_image != nullptr) {
547 _image->unplace(this);
548 _image = nullptr;
549 }
550 if (_omit_reason == OR_none) {
551 mark_eggs_stale();
552 }
553 _omit_reason = OR_working;
554}
555
556/**
557 * Sets the omit reason (returned by get_omit()) to OR_solitary, indicating
558 * that the palettized version of the texture should not be used because it is
559 * the only texture on a PaletteImage. However, the texture is still
560 * considered placed, and is_placed() will return true.
561 */
562 void TexturePlacement::
563 omit_solitary() {
564 nassertv(is_placed());
565 if (_omit_reason != OR_solitary) {
566 mark_eggs_stale();
567 _omit_reason = OR_solitary;
568 }
569}
570
571/**
572 * Indicates that the texture, formerly indicated as solitary, is now no
573 * longer.
574 */
575 void TexturePlacement::
576 not_solitary() {
577 nassertv(is_placed());
578 if (_omit_reason != OR_none) {
579 mark_eggs_stale();
580 _omit_reason = OR_none;
581 }
582}
583
584/**
585 * Returns true if the particular position this texture has been assigned to
586 * overlaps the rectangle whose top left corner is at x, y and whose size is
587 * given by x_size, y_size, or false otherwise.
588 */
589 bool TexturePlacement::
590 intersects(int x, int y, int x_size, int y_size) {
591 nassertr(is_placed(), false);
592
593 int hright = x + x_size;
594 int hbot = y + y_size;
595
596 int mright = _placed._x + _placed._x_size;
597 int mbot = _placed._y + _placed._y_size;
598
599 return !(x >= mright || hright <= _placed._x ||
600 y >= mbot || hbot <= _placed._y);
601}
602
603/**
604 * Stores in the indicated matrix the appropriate texture matrix transform for
605 * the new placement of the texture.
606 */
607 void TexturePlacement::
608 compute_tex_matrix(LMatrix3d &transform) {
609 nassertv(is_placed());
610
611 LMatrix3d source_uvs = LMatrix3d::ident_mat();
612
613 LTexCoordd range = _placed._max_uv - _placed._min_uv;
614 if (range[0] != 0.0 && range[1] != 0.0) {
615 source_uvs =
616 LMatrix3d::translate_mat(-_placed._min_uv) *
617 LMatrix3d::scale_mat(1.0 / range[0], 1.0 / range[1]);
618 }
619
620 int top = _placed._y + _placed._margin;
621 int left = _placed._x + _placed._margin;
622 int x_size = _placed._x_size - _placed._margin * 2;
623 int y_size = _placed._y_size - _placed._margin * 2;
624
625 int bottom = top + y_size;
626 int pal_x_size = _image->get_x_size();
627 int pal_y_size = _image->get_y_size();
628
629 LVecBase2d t((double)left / (double)pal_x_size,
630 (double)(pal_y_size - bottom) / (double)pal_y_size);
631 LVecBase2d s((double)x_size / (double)pal_x_size,
632 (double)y_size / (double)pal_y_size);
633
634 LMatrix3d dest_uvs
635 (s[0], 0.0, 0.0,
636 0.0, s[1], 0.0,
637 t[0], t[1], 1.0);
638
639 transform = source_uvs * dest_uvs;
640}
641
642/**
643 * Writes the placement position information on a line by itself.
644 */
645 void TexturePlacement::
646 write_placed(std::ostream &out, int indent_level) {
647 indent(out, indent_level)
648 << get_texture()->get_name();
649
650 if (is_placed()) {
651 out << " at "
652 << get_placed_x() << " " << get_placed_y() << " to "
653 << get_placed_x() + get_placed_x_size() << " "
654 << get_placed_y() + get_placed_y_size() << " (coverage "
655 << get_placed_uv_area() << ")";
656
657 if (_placed._wrap_u != EggTexture::WM_unspecified ||
658 _placed._wrap_v != EggTexture::WM_unspecified) {
659 if (_placed._wrap_u != _placed._wrap_v) {
660 out << " (" << _placed._wrap_u << ", " << _placed._wrap_v << ")";
661 } else {
662 out << " " << _placed._wrap_u;
663 }
664 }
665 out << "\n";
666 } else {
667 out << " not yet placed.\n";
668 }
669};
670
671/**
672 * Returns true if the texture has been filled (i.e. fill_image() has been
673 * called) since it was placed.
674 */
675 bool TexturePlacement::
676 is_filled() const {
677 return _is_filled;
678}
679
680/**
681 * Marks the texture as unfilled, so that it will need to be copied into the
682 * palette image again.
683 */
684 void TexturePlacement::
685 mark_unfilled() {
686 _is_filled = false;
687}
688
689/**
690 * Fills in the rectangle of the palette image represented by the texture
691 * placement with the image pixels.
692 */
693 void TexturePlacement::
694 fill_image(PNMImage &image) {
695 nassertv(is_placed());
696
697 _is_filled = true;
698
699 // We determine the pixels to place the source image at by transforming the
700 // unit texture box: the upper-left and lower-right corners. These corners,
701 // in the final texture coordinate space, represent where on the palette
702 // image the original texture should be located.
703
704 LMatrix3d transform;
705 compute_tex_matrix(transform);
706 LTexCoordd ul = LTexCoordd(0.0, 1.0) * transform;
707 LTexCoordd lr = LTexCoordd(1.0, 0.0) * transform;
708
709 // Now we convert those texture coordinates back to pixel units.
710 int pal_x_size = _image->get_x_size();
711 int pal_y_size = _image->get_y_size();
712
713 int top = (int)floor((1.0 - ul[1]) * pal_y_size + 0.5);
714 int left = (int)floor(ul[0] * pal_x_size + 0.5);
715 int bottom = (int)floor((1.0 - lr[1]) * pal_y_size + 0.5);
716 int right = (int)floor(lr[0] * pal_x_size + 0.5);
717
718 // And now we can determine the size to scale the image to based on that.
719 // This may not be the same as texture->size() because of margins.
720 int x_size = right - left;
721 int y_size = bottom - top;
722 nassertv(x_size >= 0 && y_size >= 0);
723
724 // Now we get a PNMImage that represents the source texture at that size.
725 const PNMImage &source_full = _texture->read_source_image();
726 if (!source_full.is_valid()) {
727 flag_error_image(image);
728 return;
729 }
730
731 PNMImage source(x_size, y_size, source_full.get_num_channels(),
732 source_full.get_maxval());
733 source.quick_filter_from(source_full);
734
735 bool alpha = image.has_alpha();
736 bool source_alpha = source.has_alpha();
737
738 // Now copy the pixels. We do this by walking through the rectangular
739 // region on the palette image that we have reserved for this texture; for
740 // each pixel in this region, we determine its appropriate color based on
741 // its relation to the actual texture image location (determined above), and
742 // on whether the texture wraps or clamps.
743 for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
744 int sy = y - top;
745
746 switch (_placed._wrap_v) {
747 case EggTexture::WM_clamp:
748 // Clamp at [0, y_size).
749 sy = max(min(sy, y_size - 1), 0);
750 break;
751
752 case EggTexture::WM_mirror:
753 sy = (sy < 0) ? (y_size * 2) - 1 - ((-sy - 1) % (y_size * 2)) : sy % (y_size * 2);
754 sy = (sy < y_size) ? sy : 2 * y_size - sy - 1;
755 break;
756
757 case EggTexture::WM_mirror_once:
758 sy = (sy < y_size) ? sy : 2 * y_size - sy - 1;
759 // Fall through
760
761 case EggTexture::WM_border_color:
762 if (sy < 0 || sy >= y_size) {
763 continue;
764 }
765 break;
766
767 default:
768 // Wrap: sign-independent modulo.
769 sy = (sy < 0) ? y_size - 1 - ((-sy - 1) % y_size) : sy % y_size;
770 break;
771 }
772
773 for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
774 int sx = x - left;
775
776 switch (_placed._wrap_u) {
777 case EggTexture::WM_clamp:
778 // Clamp at [0, x_size).
779 sx = max(min(sx, x_size - 1), 0);
780 break;
781
782 case EggTexture::WM_mirror:
783 sx = (sx < 0) ? (x_size * 2) - 1 - ((-sx - 1) % (x_size * 2)) : sx % (x_size * 2);
784 sx = (sx < x_size) ? sx : 2 * x_size - sx - 1;
785 break;
786
787 case EggTexture::WM_mirror_once:
788 sx = (sx >= 0) ? sx : ~sx;
789 // Fall through
790
791 case EggTexture::WM_border_color:
792 if (sx < 0 || sx >= x_size) {
793 continue;
794 }
795 break;
796
797 default:
798 // Wrap: sign-independent modulo.
799 sx = (sx < 0) ? x_size - 1 - ((-sx - 1) % x_size) : sx % x_size;
800 break;
801 }
802
803 image.set_xel(x, y, source.get_xel(sx, sy));
804 if (alpha) {
805 if (source_alpha) {
806 image.set_alpha(x, y, source.get_alpha(sx, sy));
807 } else {
808 image.set_alpha(x, y, 1.0);
809 }
810 }
811 }
812 }
813
814 _texture->release_source_image();
815}
816
817
818/**
819 * Fills in the rectangle of the swapped palette image represented by the
820 * texture placement with the image pixels.
821 */
822 void TexturePlacement::
823 fill_swapped_image(PNMImage &image, int index) {
824 nassertv(is_placed());
825
826 _is_filled = true;
827
828 // We determine the pixels to place the source image at by transforming the
829 // unit texture box: the upper-left and lower-right corners. These corners,
830 // in the final texture coordinate space, represent where on the palette
831 // image the original texture should be located.
832
833 LMatrix3d transform;
834 compute_tex_matrix(transform);
835 LTexCoordd ul = LTexCoordd(0.0, 1.0) * transform;
836 LTexCoordd lr = LTexCoordd(1.0, 0.0) * transform;
837
838 // Now we convert those texture coordinates back to pixel units.
839 int pal_x_size = _image->get_x_size();
840 int pal_y_size = _image->get_y_size();
841
842 int top = (int)floor((1.0 - ul[1]) * pal_y_size + 0.5);
843 int left = (int)floor(ul[0] * pal_x_size + 0.5);
844 int bottom = (int)floor((1.0 - lr[1]) * pal_y_size + 0.5);
845 int right = (int)floor(lr[0] * pal_x_size + 0.5);
846
847 // And now we can determine the size to scale the image to based on that.
848 // This may not be the same as texture->size() because of margins.
849 int x_size = right - left;
850 int y_size = bottom - top;
851 nassertv(x_size >= 0 && y_size >= 0);
852
853 // Now we get a PNMImage that represents the swapped texture at that size.
854 TextureSwaps::iterator tsi;
855 tsi = _textureSwaps.begin() + index;
856 TextureImage *swapTexture = (*tsi);
857 const PNMImage &source_full = swapTexture->read_source_image();
858 if (!source_full.is_valid()) {
859 flag_error_image(image);
860 return;
861 }
862
863 PNMImage source(x_size, y_size, source_full.get_num_channels(),
864 source_full.get_maxval());
865 source.quick_filter_from(source_full);
866
867 bool alpha = image.has_alpha();
868 bool source_alpha = source.has_alpha();
869
870 // Now copy the pixels. We do this by walking through the rectangular
871 // region on the palette image that we have reserved for this texture; for
872 // each pixel in this region, we determine its appropriate color based on
873 // its relation to the actual texture image location (determined above), and
874 // on whether the texture wraps or clamps.
875 for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
876 int sy = y - top;
877
878 if (_placed._wrap_v == EggTexture::WM_clamp) {
879 // Clamp at [0, y_size).
880 sy = max(min(sy, y_size - 1), 0);
881
882 } else {
883 // Wrap: sign-independent modulo.
884 sy = (sy < 0) ? y_size - 1 - ((-sy - 1) % y_size) : sy % y_size;
885 }
886
887 for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
888 int sx = x - left;
889
890 if (_placed._wrap_u == EggTexture::WM_clamp) {
891 // Clamp at [0, x_size).
892 sx = max(min(sx, x_size - 1), 0);
893
894 } else {
895 // Wrap: sign-independent modulo.
896 sx = (sx < 0) ? x_size - 1 - ((-sx - 1) % x_size) : sx % x_size;
897 }
898
899 image.set_xel(x, y, source.get_xel(sx, sy));
900 if (alpha) {
901 if (source_alpha) {
902 image.set_alpha(x, y, source.get_alpha(sx, sy));
903 } else {
904 image.set_alpha(x, y, 1.0);
905 }
906 }
907 }
908 }
909
910 swapTexture->release_source_image();
911}
912
913/**
914 * Sets the rectangle of the palette image represented by the texture
915 * placement to red, to represent a missing texture.
916 */
917 void TexturePlacement::
918 flag_error_image(PNMImage &image) {
919 nassertv(is_placed());
920 for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
921 for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
922 image.set_xel_val(x, y, 1, 0, 0);
923 }
924 }
925 if (image.has_alpha()) {
926 for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
927 for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
928 image.set_alpha_val(x, y, 1);
929 }
930 }
931 }
932}
933
934/**
935 * A support function for determine_size(), this computes the appropriate size
936 * of the texture in pixels based on the UV coverage (as well as on the size
937 * of the source texture).
938 */
939 void TexturePlacement::
940compute_size_from_uvs(const LTexCoordd &min_uv, const LTexCoordd &max_uv) {
941 _position._min_uv = min_uv;
942 _position._max_uv = max_uv;
943
944 LTexCoordd range = _position._max_uv - _position._min_uv;
945 // cout << "range: " << range << endl;
946
947 // cout << "_x_size texture: " << _texture->get_x_size() << endl; cout <<
948 // "_y_size texture: " << _texture->get_y_size() << endl;
949
950 _position._x_size = (int)floor(_texture->get_x_size() * range[0] + 0.5);
951 _position._y_size = (int)floor(_texture->get_y_size() * range[1] + 0.5);
952
953 // cout << "_x_size: " << _position._x_size << endl; cout << "_y_size: " <<
954 // _position._y_size << endl;
955
956 // We arbitrarily require at least four pixels in each dimension. Fewer
957 // than this may be asking for trouble.
958 _position._x_size = max(_position._x_size, 4);
959 _position._y_size = max(_position._y_size, 4);
960
961 if(get_group()->has_margin_override()) {
962 _position._margin = get_group()->get_margin_override();
963 } else {
964 _position._margin = _texture->get_margin();
965 }
966 // cout << "margin: " << _position._margin << endl;
967
968 // Normally, we have interior margins, but if the image size is too small--
969 // i.e. the margin size is too great a percentage of the image size--we'll
970 // make them exterior margins so as not to overly degrade the quality of the
971 // image.
972 if ((double)_position._margin / (double)_position._x_size > 0.10) {
973 _position._x_size += _position._margin * 2;
974 }
975 if ((double)_position._margin / (double)_position._y_size > 0.10) {
976 _position._y_size += _position._margin * 2;
977 }
978
979 _size_known = true;
980}
981
982
983
984/**
985 * Registers the current object as something that can be read from a Bam file.
986 */
987 void TexturePlacement::
988 register_with_read_factory() {
989 BamReader::get_factory()->
990 register_factory(get_class_type(), make_TexturePlacement);
991}
992
993/**
994 * Fills the indicated datagram up with a binary representation of the current
995 * object, in preparation for writing to a Bam file.
996 */
997 void TexturePlacement::
998 write_datagram(BamWriter *writer, Datagram &datagram) {
999 TypedWritable::write_datagram(writer, datagram);
1000 writer->write_pointer(datagram, _texture);
1001 writer->write_pointer(datagram, _group);
1002 writer->write_pointer(datagram, _image);
1003 writer->write_pointer(datagram, _dest);
1004
1005 datagram.add_bool(_has_uvs);
1006 datagram.add_bool(_size_known);
1007 _position.write_datagram(writer, datagram);
1008
1009 datagram.add_bool(_is_filled);
1010 _placed.write_datagram(writer, datagram);
1011 datagram.add_int32((int)_omit_reason);
1012
1013 datagram.add_int32(_references.size());
1014 References::const_iterator ri;
1015 for (ri = _references.begin(); ri != _references.end(); ++ri) {
1016 writer->write_pointer(datagram, (*ri));
1017 }
1018
1019 datagram.add_int32(_textureSwaps.size());
1020 TextureSwaps::const_iterator tsi;
1021 for (tsi = _textureSwaps.begin(); tsi != _textureSwaps.end(); ++tsi) {
1022 writer->write_pointer(datagram, (*tsi));
1023 }
1024
1025}
1026
1027/**
1028 * Called after the object is otherwise completely read from a Bam file, this
1029 * function's job is to store the pointers that were retrieved from the Bam
1030 * file for each pointer object written. The return value is the number of
1031 * pointers processed from the list.
1032 */
1033 int TexturePlacement::
1034 complete_pointers(TypedWritable **p_list, BamReader *manager) {
1035 int index = TypedWritable::complete_pointers(p_list, manager);
1036
1037 if (p_list[index] != nullptr) {
1038 DCAST_INTO_R(_texture, p_list[index], index);
1039 }
1040 index++;
1041
1042 if (p_list[index] != nullptr) {
1043 DCAST_INTO_R(_group, p_list[index], index);
1044 }
1045 index++;
1046
1047 if (p_list[index] != nullptr) {
1048 DCAST_INTO_R(_image, p_list[index], index);
1049 }
1050 index++;
1051
1052 if (p_list[index] != nullptr) {
1053 DCAST_INTO_R(_dest, p_list[index], index);
1054 }
1055 index++;
1056
1057 int i;
1058 for (i = 0; i < _num_references; i++) {
1059 TextureReference *reference;
1060 DCAST_INTO_R(reference, p_list[index], index);
1061 _references.insert(reference);
1062 index++;
1063 }
1064
1065 for (i = 0; i < _num_textureSwaps; i++) {
1066 TextureImage *swapTexture;
1067 DCAST_INTO_R(swapTexture, p_list[index], index);
1068 _textureSwaps.push_back(swapTexture);
1069 index++;
1070 }
1071
1072 return index;
1073}
1074
1075/**
1076 * This method is called by the BamReader when an object of this type is
1077 * encountered in a Bam file; it should allocate and return a new object with
1078 * all the data read.
1079 */
1080 TypedWritable* TexturePlacement::
1081make_TexturePlacement(const FactoryParams &params) {
1082 TexturePlacement *me = new TexturePlacement;
1083 DatagramIterator scan;
1084 BamReader *manager;
1085
1086 parse_params(params, scan, manager);
1087 me->fillin(scan, manager);
1088 return me;
1089}
1090
1091/**
1092 * Reads the binary data from the given datagram iterator, which was written
1093 * by a previous call to write_datagram().
1094 */
1095 void TexturePlacement::
1096fillin(DatagramIterator &scan, BamReader *manager) {
1097 TypedWritable::fillin(scan, manager);
1098
1099 manager->read_pointer(scan); // _texture
1100 manager->read_pointer(scan); // _group
1101 manager->read_pointer(scan); // _image
1102 manager->read_pointer(scan); // _dest
1103
1104 _has_uvs = scan.get_bool();
1105 _size_known = scan.get_bool();
1106 _position.fillin(scan, manager);
1107
1108 _is_filled = scan.get_bool();
1109 _placed.fillin(scan, manager);
1110 _omit_reason = (OmitReason)scan.get_int32();
1111
1112 _num_references = scan.get_int32();
1113 manager->read_pointers(scan, _num_references);
1114
1115 if (Palettizer::_read_pi_version >= 20) {
1116 _num_textureSwaps = scan.get_int32();
1117 } else {
1118 _num_textureSwaps = 0;
1119 }
1120 manager->read_pointers(scan, _num_textureSwaps);
1121}
1122
1123
1124/**
1125 * Compares two TexturePlacement objects and returns true if the first one is
1126 * bigger than the second one, false otherwise.
1127 */
1128 bool SortPlacementBySize::
1129 operator ()(TexturePlacement *a, TexturePlacement *b) const {
1130 if (a->get_y_size() < b->get_y_size()) {
1131 return false;
1132
1133 } else if (b->get_y_size() < a->get_y_size()) {
1134 return true;
1135
1136 } else if (a->get_x_size() < b->get_x_size()) {
1137 return false;
1138
1139 } else if (b->get_x_size() < a->get_x_size()) {
1140 return true;
1141 } else if (a->get_name() < b->get_name()) {
1142 // use this fall through case to let alphabetically smaller textures show
1143 // up first
1144 return true;
1145 }
1146
1147 return false;
1148}
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
parse_params
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition bamReader.I:275
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition bamReader.h:110
BamReader::read_pointers
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition bamReader.cxx:653
BamReader::read_pointer
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition bamReader.cxx:610
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition bamReader.I:177
BamWriter::write_pointer
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition bamWriter.cxx:317
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition datagramIterator.h:30
DatagramIterator::get_bool
bool get_bool()
Extracts a boolean value.
Definition datagramIterator.I:48
DatagramIterator::get_int32
int32_t get_int32()
Extracts a signed 32-bit integer.
Definition datagramIterator.I:107
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
Datagram::add_int32
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
Definition datagram.I:67
Datagram::add_bool
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition datagram.I:34
DestTextureImage
This represents a texture filename as it has been resized and copied to the map directory (e....
Definition destTextureImage.h:28
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition factoryParams.h:36
ImageFile::get_x_size
int get_x_size() const
Returns the size of the image file in pixels in the X direction.
Definition imageFile.cxx:82
ImageFile::is_size_known
bool is_size_known() const
Returns true if the size of the image file is known, false otherwise.
Definition imageFile.cxx:73
ImageFile::get_y_size
int get_y_size() const
Returns the size of the image file in pixels in the Y direction.
Definition imageFile.cxx:92
PNMImageHeader::get_maxval
get_maxval
Returns the maximum channel value allowable for any pixel in this image; for instance,...
Definition pnmImageHeader.h:70
PNMImageHeader::get_num_channels
get_num_channels
Returns the number of channels in the image.
Definition pnmImageHeader.h:60
PNMImageHeader::has_alpha
static bool has_alpha(ColorType color_type)
This static variant of has_alpha() returns true if the indicated image type includes an alpha channel...
Definition pnmImageHeader.I:106
PNMImage
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
Definition pnmImage.h:58
PNMImage::set_xel_val
void set_xel_val(int x, int y, const xel &value)
Changes the RGB color at the indicated pixel.
Definition pnmImage.I:419
PNMImage::set_alpha_val
void set_alpha_val(int x, int y, xelval a)
Sets the alpha component color only at the indicated pixel.
Definition pnmImage.I:559
PNMImage::get_alpha
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
Definition pnmImage.I:809
PNMImage::get_xel
LRGBColorf get_xel(int x, int y) const
Returns the RGB color at the indicated pixel.
Definition pnmImage.I:569
PNMImage::quick_filter_from
void quick_filter_from(const PNMImage &copy, int xborder=0, int yborder=0)
Resizes from the given image, with a fixed radius of 0.5.
Definition pnm-image-filter.cxx:754
PNMImage::is_valid
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width.
Definition pnmImage.I:342
PNMImage::set_xel
void set_xel(int x, int y, const LRGBColorf &value)
Changes the RGB color at the indicated pixel.
Definition pnmImage.I:579
PNMImage::set_alpha
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
Definition pnmImage.I:859
PaletteGroup
This is the highest level of grouping for TextureImages.
Definition paletteGroup.h:43
PaletteGroup::get_margin_override
int get_margin_override() const
Returns the set of groups this group depends on.
Definition paletteGroup.cxx:110
PaletteImage
This is a single palette image, one of several within a PalettePage, which is in turn one of several ...
Definition paletteImage.h:32
PalettePage
This is a particular collection of textures, within a PaletteGroup, that all share the same TexturePr...
Definition palettePage.h:33
SortPlacementBySize::operator()
bool operator()(TexturePlacement *a, TexturePlacement *b) const
Compares two TexturePlacement objects and returns true if the first one is bigger than the second one...
Definition texturePlacement.cxx:1129
TextureImage
This represents a single source texture that is referenced by one or more egg files.
Definition textureImage.h:46
TextureImage::release_source_image
void release_source_image()
Frees the memory that was allocated by a previous call to read_source_image().
Definition textureImage.cxx:729
TextureImage::read_source_image
const PNMImage & read_source_image()
Reads in the original image, if it has not already been read, and returns it.
Definition textureImage.cxx:709
TexturePlacement
This corresponds to a particular assignment of a TextureImage with a PaletteGroup,...
Definition texturePlacement.h:41
TexturePlacement::write_placed
void write_placed(std::ostream &out, int indent_level=0)
Writes the placement position information on a line by itself.
Definition texturePlacement.cxx:646
TexturePlacement::place_at
void place_at(PaletteImage *image, int x, int y)
Assigns the texture to a particular position within the indicated PaletteImage.
Definition texturePlacement.cxx:527
TexturePlacement::get_placed_uv_area
double get_placed_uv_area() const
Returns the total area of the rectangle occupied by the UV minmax box, as it has been placed.
Definition texturePlacement.cxx:515
TexturePlacement::is_filled
bool is_filled() const
Returns true if the texture has been filled (i.e.
Definition texturePlacement.cxx:676
TexturePlacement::get_omit_reason
OmitReason get_omit_reason() const
Returns the reason the texture has been omitted from a palette image, or OR_none if it has not.
Definition texturePlacement.cxx:401
TexturePlacement::get_dest
DestTextureImage * get_dest() const
Returns the DestTextureImage that corresponds to this texture as it was copied to the install directo...
Definition texturePlacement.cxx:182
TexturePlacement::get_group
PaletteGroup * get_group() const
Returns the group that this placement represents.
Definition texturePlacement.cxx:119
TexturePlacement::remove_egg
void remove_egg(TextureReference *reference)
Notes that a particular egg file is no longer using this particular TexturePlacement.
Definition texturePlacement.cxx:145
TexturePlacement::get_placed_x_size
int get_placed_x_size() const
Returns the size in the X dimension, in pixels, of the texture image as it has been placed within the...
Definition texturePlacement.cxx:495
TexturePlacement::add_egg
void add_egg(TextureReference *reference)
Records the fact that a particular egg file is using this particular TexturePlacement.
Definition texturePlacement.cxx:128
TexturePlacement::mark_eggs_stale
void mark_eggs_stale()
Marks all the egg files that reference this placement stale.
Definition texturePlacement.cxx:159
TexturePlacement::intersects
bool intersects(int x, int y, int x_size, int y_size)
Returns true if the particular position this texture has been assigned to overlaps the rectangle whos...
Definition texturePlacement.cxx:590
TexturePlacement::is_size_known
bool is_size_known() const
Returns true if the texture's size is known, false otherwise.
Definition texturePlacement.cxx:392
TexturePlacement::get_x_size
int get_x_size() const
Returns the size in the X dimension, in pixels, of the texture image as it must appear in the palette...
Definition texturePlacement.cxx:411
TexturePlacement::get_name
const std::string & get_name() const
Returns the name of the texture that this placement represents.
Definition texturePlacement.cxx:95
TexturePlacement::get_uv_area
double get_uv_area() const
Returns the total area of the rectangle occupied by the UV minmax box, in UV coordinates.
Definition texturePlacement.cxx:433
TexturePlacement::register_with_read_factory
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
Definition texturePlacement.cxx:988
TexturePlacement::get_image
PaletteImage * get_image() const
Returns the particular PaletteImage on which the texture has been placed.
Definition texturePlacement.cxx:456
TexturePlacement::write_datagram
virtual void write_datagram(BamWriter *writer, Datagram &datagram)
Fills the indicated datagram up with a binary representation of the current object,...
Definition texturePlacement.cxx:998
TexturePlacement::set_dest
void set_dest(DestTextureImage *dest)
Sets the DestTextureImage that corresponds to this texture as it was copied to the install directory.
Definition texturePlacement.cxx:173
TexturePlacement::complete_pointers
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Called after the object is otherwise completely read from a Bam file, this function's job is to store...
Definition texturePlacement.cxx:1034
TexturePlacement::fill_swapped_image
void fill_swapped_image(PNMImage &image, int index)
Fills in the rectangle of the swapped palette image represented by the texture placement with the ima...
Definition texturePlacement.cxx:823
TexturePlacement::flag_error_image
void flag_error_image(PNMImage &image)
Sets the rectangle of the palette image represented by the texture placement to red,...
Definition texturePlacement.cxx:918
TexturePlacement::get_properties
const TextureProperties & get_properties() const
Returns the grouping properties of the image.
Definition texturePlacement.cxx:111
TexturePlacement::mark_unfilled
void mark_unfilled()
Marks the texture as unfilled, so that it will need to be copied into the palette image again.
Definition texturePlacement.cxx:685
TexturePlacement::get_placed_x
int get_placed_x() const
Returns the X pixel at which the texture has been placed within its PaletteImage.
Definition texturePlacement.cxx:475
TexturePlacement::compute_tex_matrix
void compute_tex_matrix(LMatrix3d &transform)
Stores in the indicated matrix the appropriate texture matrix transform for the new placement of the ...
Definition texturePlacement.cxx:608
TexturePlacement::get_placed_y
int get_placed_y() const
Returns the Y pixel at which the texture has been placed within its PaletteImage.
Definition texturePlacement.cxx:485
TexturePlacement::is_placed
bool is_placed() const
Returns true if the texture has been placed on a palette image, false otherwise.
Definition texturePlacement.cxx:448
TexturePlacement::get_texture
TextureImage * get_texture() const
Returns the texture that this placement represents.
Definition texturePlacement.cxx:103
TexturePlacement::determine_size
bool determine_size()
Attempts to determine the appropriate size of the texture for the given placement.
Definition texturePlacement.cxx:196
TexturePlacement::fill_image
void fill_image(PNMImage &image)
Fills in the rectangle of the palette image represented by the texture placement with the image pixel...
Definition texturePlacement.cxx:694
TexturePlacement::omit_solitary
void omit_solitary()
Sets the omit reason (returned by get_omit()) to OR_solitary, indicating that the palettized version ...
Definition texturePlacement.cxx:563
TexturePlacement::not_solitary
void not_solitary()
Indicates that the texture, formerly indicated as solitary, is now no longer.
Definition texturePlacement.cxx:576
TexturePlacement::force_replace
void force_replace()
Removes the texture from its particular PaletteImage, but does not remove it from the PaletteGroup.
Definition texturePlacement.cxx:545
TexturePlacement::get_page
PalettePage * get_page() const
Returns the particular PalettePage on which the texture has been placed.
Definition texturePlacement.cxx:465
TexturePlacement::get_placed_y_size
int get_placed_y_size() const
Returns the size in the Y dimension, in pixels, of the texture image as it has been placed within the...
Definition texturePlacement.cxx:505
TexturePlacement::get_y_size
int get_y_size() const
Returns the size in the Y dimension, in pixels, of the texture image as it must appear in the palette...
Definition texturePlacement.cxx:422
TextureProperties
This is the set of characteristics of a texture that, if different from another texture,...
Definition textureProperties.h:30
TextureReference
This is the particular reference of a texture filename by an egg file.
Definition textureReference.h:40
TextureReference::clear_placement
void clear_placement()
Removes any reference to a TexturePlacement.
Definition textureReference.cxx:326
TextureReference::get_placement
TexturePlacement * get_placement() const
Returns the particular TexturePlacement that is appropriate for this egg file.
Definition textureReference.cxx:336
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition typedWritable.h:35
TypedWritable::fillin
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
Definition typedWritable.cxx:103
TypedWritable::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition typedWritable.cxx:54
TypedWritable::complete_pointers
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition typedWritable.cxx:81
reference
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
destTextureImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggFile.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
OmitReason
OmitReason
This enumerates the reasons why a texture may not have been placed in a palette image.
Definition omitReason.h:23
paletteGroup.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
paletteImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
palettizer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pnmImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
textureImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
texturePlacement.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
textureReference.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.