15 #include "texturePlacement.h" 16 #include "textureReference.h" 17 #include "textureImage.h" 18 #include "paletteGroup.h" 19 #include "paletteImage.h" 20 #include "palettizer.h" 22 #include "destTextureImage.h" 26 #include "datagramIterator.h" 27 #include "bamReader.h" 28 #include "bamWriter.h" 48 _omit_reason = OR_none;
61 _omit_reason = OR_working;
66 _omit_reason = OR_unknown;
85 References::iterator ri;
86 References copy_references = _references;
87 for (ri = copy_references.begin(); ri != copy_references.end(); ++ri) {
94 _group->unplace(
this);
105 return _texture->get_name();
125 return _texture->get_properties();
154 _references.insert(reference);
170 _references.erase(reference);
182 References::iterator ri;
183 for (ri = _references.begin(); ri != _references.end(); ++ri) {
227 if (!_texture->is_size_known()) {
230 _omit_reason = OR_unknown;
249 _position._wrap_u = EggTexture::WM_clamp;
250 _position._wrap_v = EggTexture::WM_clamp;
254 References::iterator ri;
255 for (ri = _references.begin(); ri != _references.end(); ++ri) {
262 min_uv.set(min(min_uv[0], n[0]), min(min_uv[1], n[1]));
263 max_uv.set(max(max_uv[0], x[0]), max(max_uv[1], x[1]));
273 if (reference->
get_wrap_u() == EggTexture::WM_repeat) {
274 _position._wrap_u = EggTexture::WM_repeat;
276 if (reference->
get_wrap_v() == EggTexture::WM_repeat) {
277 _position._wrap_v = EggTexture::WM_repeat;
283 if (_texture->get_txa_wrap_u() != EggTexture::WM_unspecified) {
284 _position._wrap_u = _texture->get_txa_wrap_u();
286 if (_texture->get_txa_wrap_v() != EggTexture::WM_unspecified) {
287 _position._wrap_v = _texture->get_txa_wrap_v();
292 _omit_reason = OR_unused;
307 if (pal->_round_uvs) {
309 ceil((rounded_max_uv[0] - pal->_round_fuzz) / pal->_round_unit) *
312 ceil((rounded_max_uv[1] - pal->_round_fuzz) / pal->_round_unit) *
316 floor((rounded_min_uv[0] + pal->_round_fuzz) / pal->_round_unit) *
319 floor((rounded_min_uv[1] + pal->_round_fuzz) / pal->_round_unit) *
328 compute_size_from_uvs(rounded_min_uv, rounded_max_uv);
331 if (_texture->get_omit()) {
334 _omit_reason = OR_omitted;
336 }
else if (get_uv_area() > _texture->get_coverage_threshold()) {
339 _omit_reason = OR_coverage;
341 }
else if ((_position._x_size > pal->_pal_x_size ||
342 _position._y_size > pal->_pal_y_size) ||
343 (_position._x_size == pal->_pal_x_size &&
344 _position._y_size == pal->_pal_y_size)) {
350 _omit_reason = OR_size;
352 }
else if (pal->_omit_everything && (_group->is_none_texture_swap())) {
355 _omit_reason = OR_default_omit;
357 }
else if (_omit_reason == OR_omitted ||
358 _omit_reason == OR_default_omit ||
359 _omit_reason == OR_size ||
360 _omit_reason == OR_coverage ||
361 _omit_reason == OR_unknown) {
367 _omit_reason = OR_working;
369 }
else if (is_placed()) {
373 if (_position._x_size != _placed._x_size ||
374 _position._y_size != _placed._y_size ||
375 _position._min_uv[0] < _placed._min_uv[0] ||
376 _position._min_uv[1] < _placed._min_uv[1] ||
377 _position._max_uv[0] > _placed._max_uv[0] ||
378 _position._max_uv[1] > _placed._max_uv[1]) {
386 if ((_position._x_size > _placed._x_size ||
387 _position._y_size > _placed._y_size) &&
389 compute_size_from_uvs(min_uv, max_uv);
390 if (_position._x_size <= _placed._x_size &&
391 _position._y_size <= _placed._y_size &&
392 _position._min_uv[0] >= _placed._min_uv[0] &&
393 _position._min_uv[1] >= _placed._min_uv[1] &&
394 _position._max_uv[0] <= _placed._max_uv[0] &&
395 _position._max_uv[1] <= _placed._max_uv[1]) {
399 compute_size_from_uvs(rounded_min_uv, rounded_max_uv);
407 if (_position._wrap_u != _placed._wrap_u ||
408 _position._wrap_v != _placed._wrap_v) {
412 _placed._wrap_u = _position._wrap_u;
413 _placed._wrap_v = _position._wrap_v;
456 nassertr(_size_known, 0);
457 return _position._x_size;
470 nassertr(_size_known, 0);
471 return _position._y_size;
488 LTexCoordd range = _position._max_uv - _position._min_uv;
489 return range[0] * range[1];
526 return _image->get_page();
538 nassertr(is_placed(), 0);
551 nassertr(is_placed(), 0);
564 nassertr(is_placed(), 0);
565 return _placed._x_size;
577 nassertr(is_placed(), 0);
578 return _placed._y_size;
590 nassertr(is_placed(), 0);
591 LTexCoordd range = _placed._max_uv - _placed._min_uv;
592 return range[0] * range[1];
605 nassertv(!is_placed());
606 nassertv(_size_known);
613 _omit_reason = OR_none;
627 _image->unplace(
this);
630 if (_omit_reason == OR_none) {
633 _omit_reason = OR_working;
648 nassertv(is_placed());
649 if (_omit_reason != OR_solitary) {
651 _omit_reason = OR_solitary;
663 nassertv(is_placed());
664 if (_omit_reason != OR_none) {
666 _omit_reason = OR_none;
680 nassertr(is_placed(),
false);
682 int hright = x + x_size;
683 int hbot = y + y_size;
685 int mright = _placed._x + _placed._x_size;
686 int mbot = _placed._y + _placed._y_size;
688 return !(x >= mright || hright <= _placed._x ||
689 y >= mbot || hbot <= _placed._y);
701 nassertv(is_placed());
705 LTexCoordd range = _placed._max_uv - _placed._min_uv;
706 if (range[0] != 0.0 && range[1] != 0.0) {
712 int top = _placed._y + _placed._margin;
713 int left = _placed._x + _placed._margin;
714 int x_size = _placed._x_size - _placed._margin * 2;
715 int y_size = _placed._y_size - _placed._margin * 2;
717 int bottom = top + y_size;
718 int pal_x_size = _image->get_x_size();
719 int pal_y_size = _image->get_y_size();
721 LVecBase2d t((
double)left / (
double)pal_x_size,
722 (
double)(pal_y_size - bottom) / (
double)pal_y_size);
723 LVecBase2d s((
double)x_size / (
double)pal_x_size,
724 (
double)y_size / (
double)pal_y_size);
731 transform = source_uvs * dest_uvs;
742 indent(out, indent_level)
743 << get_texture()->get_name();
747 << get_placed_x() <<
" " << get_placed_y() <<
" to " 748 << get_placed_x() + get_placed_x_size() <<
" " 749 << get_placed_y() + get_placed_y_size() <<
" (coverage " 750 << get_placed_uv_area() <<
")";
752 if (_placed._wrap_u != EggTexture::WM_unspecified ||
753 _placed._wrap_v != EggTexture::WM_unspecified) {
754 if (_placed._wrap_u != _placed._wrap_v) {
755 out <<
" (" << _placed._wrap_u <<
", " << _placed._wrap_v <<
")";
757 out <<
" " << _placed._wrap_u;
762 out <<
" not yet placed.\n";
798 nassertv(is_placed());
809 compute_tex_matrix(transform);
814 int pal_x_size = _image->get_x_size();
815 int pal_y_size = _image->get_y_size();
817 int top = (int)floor((1.0 - ul[1]) * pal_y_size + 0.5);
818 int left = (int)floor(ul[0] * pal_x_size + 0.5);
819 int bottom = (int)floor((1.0 - lr[1]) * pal_y_size + 0.5);
820 int right = (int)floor(lr[0] * pal_x_size + 0.5);
825 int x_size = right - left;
826 int y_size = bottom - top;
827 nassertv(x_size >= 0 && y_size >= 0);
831 const PNMImage &source_full = _texture->read_source_image();
833 flag_error_image(image);
842 bool source_alpha = source.has_alpha();
850 for (
int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
853 if (_placed._wrap_v == EggTexture::WM_clamp) {
855 sy = max(min(sy, y_size - 1), 0);
859 sy = (sy < 0) ? y_size - 1 - ((-sy - 1) % y_size) : sy % y_size;
862 for (
int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
865 if (_placed._wrap_u == EggTexture::WM_clamp) {
867 sx = max(min(sx, x_size - 1), 0);
871 sx = (sx < 0) ? x_size - 1 - ((-sx - 1) % x_size) : sx % x_size;
874 image.
set_xel(x, y, source.get_xel(sx, sy));
877 image.
set_alpha(x, y, source.get_alpha(sx, sy));
885 _texture->release_source_image();
898 nassertv(is_placed());
909 compute_tex_matrix(transform);
914 int pal_x_size = _image->get_x_size();
915 int pal_y_size = _image->get_y_size();
917 int top = (int)floor((1.0 - ul[1]) * pal_y_size + 0.5);
918 int left = (int)floor(ul[0] * pal_x_size + 0.5);
919 int bottom = (int)floor((1.0 - lr[1]) * pal_y_size + 0.5);
920 int right = (int)floor(lr[0] * pal_x_size + 0.5);
925 int x_size = right - left;
926 int y_size = bottom - top;
927 nassertv(x_size >= 0 && y_size >= 0);
931 TextureSwaps::iterator tsi;
932 tsi = _textureSwaps.begin() + index;
936 flag_error_image(image);
945 bool source_alpha = source.has_alpha();
953 for (
int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
956 if (_placed._wrap_v == EggTexture::WM_clamp) {
958 sy = max(min(sy, y_size - 1), 0);
962 sy = (sy < 0) ? y_size - 1 - ((-sy - 1) % y_size) : sy % y_size;
965 for (
int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
968 if (_placed._wrap_u == EggTexture::WM_clamp) {
970 sx = max(min(sx, x_size - 1), 0);
974 sx = (sx < 0) ? x_size - 1 - ((-sx - 1) % x_size) : sx % x_size;
977 image.
set_xel(x, y, source.get_xel(sx, sy));
980 image.
set_alpha(x, y, source.get_alpha(sx, sy));
1000 nassertv(is_placed());
1001 for (
int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
1002 for (
int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
1007 for (
int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
1008 for (
int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
1023 void TexturePlacement::
1025 _position._min_uv = min_uv;
1026 _position._max_uv = max_uv;
1028 LTexCoordd range = _position._max_uv - _position._min_uv;
1034 _position._x_size = (int)floor(_texture->get_x_size() * range[0] + 0.5);
1035 _position._y_size = (int)floor(_texture->get_y_size() * range[1] + 0.5);
1042 _position._x_size = max(_position._x_size, 4);
1043 _position._y_size = max(_position._y_size, 4);
1045 if(get_group()->has_margin_override()) {
1046 _position._margin = get_group()->get_margin_override();
1048 _position._margin = _texture->get_margin();
1056 if ((
double)_position._margin / (
double)_position._x_size > 0.10) {
1057 _position._x_size += _position._margin * 2;
1059 if ((
double)_position._margin / (
double)_position._y_size > 0.10) {
1060 _position._y_size += _position._margin * 2;
1077 register_factory(get_class_type(), make_TexturePlacement);
1097 _position.write_datagram(writer, datagram);
1100 _placed.write_datagram(writer, datagram);
1104 References::const_iterator ri;
1105 for (ri = _references.begin(); ri != _references.end(); ++ri) {
1109 datagram.
add_int32(_textureSwaps.size());
1110 TextureSwaps::const_iterator tsi;
1111 for (tsi = _textureSwaps.begin(); tsi != _textureSwaps.end(); ++tsi) {
1131 DCAST_INTO_R(_texture, p_list[index], index);
1136 DCAST_INTO_R(_group, p_list[index], index);
1141 DCAST_INTO_R(_image, p_list[index], index);
1146 DCAST_INTO_R(_dest, p_list[index], index);
1151 for (i = 0; i < _num_references; i++) {
1153 DCAST_INTO_R(reference, p_list[index], index);
1154 _references.insert(reference);
1158 for (i = 0; i < _num_textureSwaps; i++) {
1160 DCAST_INTO_R(swapTexture, p_list[index], index);
1161 _textureSwaps.push_back(swapTexture);
1182 parse_params(params, scan, manager);
1183 me->fillin(scan, manager);
1194 void TexturePlacement::
1205 _position.fillin(scan, manager);
1208 _placed.fillin(scan, manager);
1209 _omit_reason = (OmitReason)scan.
get_int32();
1214 if (Palettizer::_read_pi_version >= 20) {
1217 _num_textureSwaps = 0;
bool is_filled() const
Returns true if the texture has been filled (i.e.
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...
This represents a texture filename as it has been resized and copied to the map directory (e...
void not_solitary()
Indicates that the texture, formerly indicated as solitary, is now no longer.
void flag_error_image(PNMImage &image)
Sets the rectangle of the palette image represented by the texture placement to red, to represent a missing texture.
bool determine_size()
Attempts to determine the appropriate size of the texture for the given placement.
bool get_bool()
Extracts a boolean value.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
EggTexture::WrapMode get_wrap_u() const
Returns the specification for the wrapping in the U direction.
void clear_placement()
Removes any reference to a TexturePlacement.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
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...
const string & get_name() const
Returns the name of the texture that this placement represents.
This is the particular reference of a texture filename by an egg file.
This is the base class for all two-component vectors and points.
PaletteGroup * get_group() const
Returns the group that this placement represents.
virtual void write_datagram(BamWriter *writer, Datagram &datagram)
Fills the indicated datagram up with a binary representation of the current object, in preparation for writing to a Bam file.
void set_xel_val(int x, int y, const xel &value)
Changes the RGB color at the indicated pixel.
PaletteImage * get_image() const
Returns the particular PaletteImage on which the texture has been placed.
Base class for objects that can be written to and read from Bam files.
This is the highest level of grouping for TextureImages.
int get_placed_x() const
Returns the X pixel at which the texture has been placed within its PaletteImage. ...
const LTexCoordd & get_min_uv() const
Returns the minimum UV coordinate in use for the texture by this reference.
double get_placed_uv_area() const
Returns the total area of the rectangle occupied by the UV minmax box, as it has been placed...
This is a two-component point in space.
bool operator()(TexturePlacement *a, TexturePlacement *b) const
Compares two TexturePlacement objects and returns true if the first one is bigger than the second one...
const LTexCoordd & get_max_uv() const
Returns the maximum UV coordinate in use for the texture by this reference.
double get_uv_area() const
Returns the total area of the rectangle occupied by the UV minmax box, in UV coordinates.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
PN_int32 get_int32()
Extracts a signed 32-bit integer.
This is a particular collection of textures, within a PaletteGroup, that all share the same TexturePr...
static LMatrix3d translate_mat(const LVecBase2d &trans)
Returns a matrix that applies the indicated translation.
EggTexture::WrapMode get_wrap_v() const
Returns the specification for the wrapping in the V direction.
void place_at(PaletteImage *image, int x, int y)
Assigns the texture to a particular position within the indicated PaletteImage.
void omit_solitary()
Sets the omit reason (returned by get_omit()) to OR_solitary, indicating that the palettized version ...
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...
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
void quick_filter_from(const PNMImage ©, int xborder=0, int yborder=0)
Resizes from the given image, with a fixed radius of 0.5.
int get_placed_y() const
Returns the Y pixel at which the texture has been placed within its PaletteImage. ...
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width...
This is a 3-by-3 transform matrix.
void force_replace()
Removes the texture from its particular PaletteImage, but does not remove it from the PaletteGroup...
void mark_unfilled()
Marks the texture as unfilled, so that it will need to be copied into the palette image again...
void add_bool(bool value)
Adds a boolean value to the datagram.
void compute_tex_matrix(LMatrix3d &transform)
Stores in the indicated matrix the appropriate texture matrix transform for the new placement of the ...
bool is_size_known() const
Returns true if the texture's size is known, false otherwise.
bool is_size_known() const
Returns true if the size of the image file is known, false otherwise.
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()...
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
const TextureProperties & get_properties() const
Returns the grouping properties of the image.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
PalettePage * get_page() const
Returns the particular PalettePage on which the texture has been placed.
This corresponds to a particular assignment of a TextureImage with a PaletteGroup, and specifically describes which PaletteImage (if any), and where on the PaletteImage, the TextureImage has been assigned to.
void add_egg(TextureReference *reference)
Records the fact that a particular egg file is using this particular TexturePlacement.
OmitReason get_omit_reason() const
Returns the reason the texture has been omitted from a palette image, or OR_none if it has not...
void mark_egg_stale()
Marks the egg file that shares this reference as stale.
TextureImage * get_texture() const
Returns the texture that this placement represents.
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
void remove_egg(TextureReference *reference)
Notes that a particular egg file is no longer using this particular TexturePlacement.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
const PNMImage & read_source_image()
Reads in the original image, if it has not already been read, and returns it.
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...
DestTextureImage * get_dest() const
Returns the DestTextureImage that corresponds to this texture as it was copied to the install directo...
static LMatrix3d scale_mat(const LVecBase2d &scale)
Returns a matrix that applies the indicated scale in each of the two axes.
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...
This is a single palette image, one of several within a PalettePage, which is in turn one of several ...
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...
bool has_uvs() const
Returns true if this TextureReference actually uses the texture on geometry, with UV's and everything...
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
void set_alpha_val(int x, int y, xelval a)
Sets the alpha component color only at the indicated pixel.
static const LMatrix3d & ident_mat()
Returns an identity matrix.
A class to retrieve the individual data elements previously stored in a Datagram. ...
This represents a single source texture that is referenced by one or more egg files.
void set_dest(DestTextureImage *dest)
Sets the DestTextureImage that corresponds to this texture as it was copied to the install directory...
TypeHandle is the identifier used to differentiate C++ class types.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
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...
void set_xel(int x, int y, const LRGBColorf &value)
Changes the RGB color at the indicated pixel.
TexturePlacement * get_placement() const
Returns the particular TexturePlacement that is appropriate for this egg file.
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...
void mark_eggs_stale()
Marks all the egg files that reference this placement stale.
void write_placed(ostream &out, int indent_level=0)
Writes the placement position information on a line by itself.
void fill_image(PNMImage &image)
Fills in the rectangle of the palette image represented by the texture placement with the image pixel...
bool is_placed() const
Returns true if the texture has been placed on a palette image, false otherwise.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
void release_source_image()
Frees the memory that was allocated by a previous call to read_source_image().
This is the set of characteristics of a texture that, if different from another texture, prevent the two textures from sharing a PaletteImage.