Panda3D
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  */
38 TexturePlacement::
39 TexturePlacement() {
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  */
53 TexturePlacement::
54 TexturePlacement(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  */
76 TexturePlacement::
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  */
103 get_texture() const {
104  return _texture;
105 }
106 
107 /**
108  * Returns the grouping properties of the image.
109  */
111 get_properties() const {
112  return _texture->get_properties();
113 }
114 
115 /**
116  * Returns the group that this placement represents.
117  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
448 is_placed() const {
449  return _image != nullptr;
450 }
451 
452 /**
453  * Returns the particular PaletteImage on which the texture has been placed.
454  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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::
940 compute_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  */
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  */
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  */
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::
1081 make_TexturePlacement(const FactoryParams &params) {
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::
1096 fillin(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  */
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 }
TexturePlacement::is_size_known
bool is_size_known() const
Returns true if the texture's size is known, false otherwise.
Definition: texturePlacement.cxx:392
destTextureImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PaletteImage::unplace
void unplace(TexturePlacement *placement)
Removes the texture from the image.
Definition: paletteImage.cxx:301
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
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
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
PNMImage::get_xel
LRGBColorf get_xel(int x, int y) const
Returns the RGB color at the indicated pixel.
Definition: pnmImage.I:569
PaletteImage
This is a single palette image, one of several within a PalettePage, which is in turn one of several ...
Definition: paletteImage.h:32
DatagramIterator::get_int32
int32_t get_int32()
Extracts a signed 32-bit integer.
Definition: datagramIterator.I:107
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
PaletteGroup
This is the highest level of grouping for TextureImages.
Definition: paletteGroup.h:43
TextureReference::clear_placement
void clear_placement()
Removes any reference to a TexturePlacement.
Definition: textureReference.cxx:326
TexturePosition::write_datagram
virtual void write_datagram(BamWriter *writer, Datagram &datagram)
Fills the indicated datagram up with a binary representation of the current object,...
Definition: texturePosition.cxx:86
TextureReference::get_wrap_v
EggTexture::WrapMode get_wrap_v() const
Returns the specification for the wrapping in the V direction.
Definition: textureReference.cxx:260
TextureImage::get_coverage_threshold
double get_coverage_threshold() const
Returns the appropriate coverage threshold for this texture.
Definition: textureImage.cxx:446
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
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.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureReference::get_max_uv
const LTexCoordd & get_max_uv() const
Returns the maximum UV coordinate in use for the texture by this reference.
Definition: textureReference.cxx:243
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
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
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
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
TexturePlacement::get_name
const std::string & get_name() const
Returns the name of the texture that this placement represents.
Definition: texturePlacement.cxx:95
TextureReference::get_placement
TexturePlacement * get_placement() const
Returns the particular TexturePlacement that is appropriate for this egg file.
Definition: textureReference.cxx:336
PNMImageHeader::get_maxval
get_maxval
Returns the maximum channel value allowable for any pixel in this image; for instance,...
Definition: pnmImageHeader.h:70
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
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
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
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
texturePlacement.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PaletteImage::get_page
PalettePage * get_page() const
Returns the particular PalettePage this image is associated with.
Definition: paletteImage.cxx:184
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
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::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::get_properties
const TextureProperties & get_properties() const
Returns the grouping properties of the image.
Definition: texturePlacement.cxx:111
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
textureImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
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
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
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
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
PNMImageHeader::get_num_channels
get_num_channels
Returns the number of channels in the image.
Definition: pnmImageHeader.h:60
OmitReason
OmitReason
This enumerates the reasons why a texture may not have been placed in a palette image.
Definition: omitReason.h:23
TextureImage::get_omit
bool get_omit() const
Returns true if the user specifically requested to omit this texture via the "omit" keyword in the ....
Definition: textureImage.cxx:435
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
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::get_page
PalettePage * get_page() const
Returns the particular PalettePage on which the texture has been placed.
Definition: texturePlacement.cxx:465
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
paletteImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader::read_pointers
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition: bamReader.cxx:653
DatagramIterator::get_bool
bool get_bool()
Extracts a boolean value.
Definition: datagramIterator.I:48
PaletteGroup::get_margin_override
int get_margin_override() const
Returns the set of groups this group depends on.
Definition: paletteGroup.cxx:110
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
TextureReference::get_wrap_u
EggTexture::WrapMode get_wrap_u() const
Returns the specification for the wrapping in the U direction.
Definition: textureReference.cxx:252
TextureReference::has_uvs
bool has_uvs() const
Returns true if this TextureReference actually uses the texture on geometry, with UV's and everything...
Definition: textureReference.cxx:226
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_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
TexturePlacement::get_image
PaletteImage * get_image() const
Returns the particular PaletteImage on which the texture has been placed.
Definition: texturePlacement.cxx:456
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::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
palettizer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ImageFile::get_properties
const TextureProperties & get_properties() const
Returns the grouping properties of the image.
Definition: imageFile.cxx:119
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
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
textureReference.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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::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::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
PalettePage
This is a particular collection of textures, within a PaletteGroup, that all share the same TexturePr...
Definition: palettePage.h:33
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
Datagram::add_int32
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:67
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::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::get_texture
TextureImage * get_texture() const
Returns the texture that this placement represents.
Definition: texturePlacement.cxx:103
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
TextureProperties
This is the set of characteristics of a texture that, if different from another texture,...
Definition: textureProperties.h:30
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
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
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
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
TexturePlacement::is_filled
bool is_filled() const
Returns true if the texture has been filled (i.e.
Definition: texturePlacement.cxx:676
TexturePlacement
This corresponds to a particular assignment of a TextureImage with a PaletteGroup,...
Definition: texturePlacement.h:41
TextureImage::get_txa_wrap_u
EggTexture::WrapMode get_txa_wrap_u() const
Returns the wrap mode specified in the u direction in the txa file, or WM_unspecified.
Definition: textureImage.cxx:499
Datagram::add_bool
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:34
PNMImage::get_alpha
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
Definition: pnmImage.I:809
TextureImage::get_txa_wrap_v
EggTexture::WrapMode get_txa_wrap_v() const
Returns the wrap mode specified in the v direction in the txa file, or WM_unspecified.
Definition: textureImage.cxx:508
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
TextureReference
This is the particular reference of a texture filename by an egg file.
Definition: textureReference.h:40
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
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PaletteGroup::unplace
void unplace(TexturePlacement *placement)
Removes the texture from its position on a PaletteImage, if it has been so placed.
Definition: paletteGroup.cxx:389
TexturePlacement::get_group
PaletteGroup * get_group() const
Returns the group that this placement represents.
Definition: texturePlacement.cxx:119
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::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
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
TextureReference::mark_egg_stale
void mark_egg_stale()
Marks the egg file that shares this reference as stale.
Definition: textureReference.cxx:344
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::is_placed
bool is_placed() const
Returns true if the texture has been placed on a palette image, false otherwise.
Definition: texturePlacement.cxx:448
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
TexturePlacement::mark_eggs_stale
void mark_eggs_stale()
Marks all the egg files that reference this placement stale.
Definition: texturePlacement.cxx:159
TextureImage::get_margin
int get_margin() const
Returns the appropriate margin for this texture.
Definition: textureImage.cxx:456
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggFile.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DestTextureImage
This represents a texture filename as it has been resized and copied to the map directory (e....
Definition: destTextureImage.h:28
PaletteGroup::is_none_texture_swap
bool is_none_texture_swap() const
Returns textureswap information is set or not, True if it's not set.
Definition: paletteGroup.cxx:711
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
TextureReference::get_min_uv
const LTexCoordd & get_min_uv() const
Returns the minimum UV coordinate in use for the texture by this reference.
Definition: textureReference.cxx:234
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::not_solitary
void not_solitary()
Indicates that the texture, formerly indicated as solitary, is now no longer.
Definition: texturePlacement.cxx:576
TexturePosition::fillin
void fillin(DatagramIterator &scan, BamReader *manager)
Reads the binary data from the given datagram iterator, which was written by a previous call to write...
Definition: texturePosition.cxx:122
paletteGroup.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
TexturePlacement::determine_size
bool determine_size()
Attempts to determine the appropriate size of the texture for the given placement.
Definition: texturePlacement.cxx:196
TextureImage
This represents a single source texture that is referenced by one or more egg files.
Definition: textureImage.h:46