diff --git a/pandatool/src/egg-palettize/eggFile.cxx b/pandatool/src/egg-palettize/eggFile.cxx index 30ec9c5c0f..aec5a201cf 100644 --- a/pandatool/src/egg-palettize/eggFile.cxx +++ b/pandatool/src/egg-palettize/eggFile.cxx @@ -35,6 +35,9 @@ #include "bamWriter.h" #include "executionEnvironment.h" #include "dSearchPath.h" +#include "indirectLess.h" + +#include TypeHandle EggFile::_type_handle; @@ -99,15 +102,16 @@ void EggFile:: scan_textures() { nassertv(_data != (EggData *)NULL); + // Extract the set of textures referenced by this egg file. EggTextureCollection tc; tc.find_used_textures(_data); + + // Make sure each tref name is unique within a given file. + tc.uniquify_trefs(); - // Remove the old TextureReference objects. - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - delete (*ti); - } - _textures.clear(); + // Now build up a list of new TextureReference objects that + // represent the textures actually used and their uv range, etc. + Textures new_textures; EggTextureCollection::iterator eti; for (eti = tc.begin(); eti != tc.end(); ++eti) { @@ -123,9 +127,77 @@ scan_textures() { delete ref; } else { - _textures.push_back(ref); + new_textures.push_back(ref); } } + + // Sort the new references into order so we can compare them with + // the original references. + sort(new_textures.begin(), new_textures.end(), + IndirectLess()); + + // Sort the original references too. This should already be sorted + // from the previous run, but we might as well be neurotic about it. + sort(_textures.begin(), _textures.end(), + IndirectLess()); + + // Now go through and merge the lists. + Textures combined_textures; + Textures::const_iterator ai = _textures.begin(); + Textures::const_iterator bi = new_textures.begin(); + + while (ai != _textures.end() && bi != new_textures.end()) { + TextureReference *aref = (*ai); + TextureReference *bref = (*bi); + + if ((*aref) < (*bref)) { + // Here's a texture reference in the original list, but not in + // the new list. Remove it. + delete aref; + ++ai; + + } else if ((*bref) < (*aref)) { + // Here's a texture reference in the new list, but not in the + // original list. Add it. + combined_textures.push_back(bref); + ++bi; + + } else { // (*bref) == (*aref) + // Here's a texture reference that was in both lists. Compare it. + if (aref->is_equivalent(*bref)) { + // It hasn't changed substantially, so keep the original + // (which still has the placement references from a previous + // pass). + combined_textures.push_back(aref); + delete bref; + + } else { + // It has changed, so drop the original and keep the new one. + combined_textures.push_back(bref); + delete aref; + } + ++ai; + ++bi; + } + } + + while (bi != new_textures.end()) { + TextureReference *bref = (*bi); + // Here's a texture reference in the new list, but not in the + // original list. Add it. + combined_textures.push_back(bref); + ++bi; + } + + while (ai != _textures.end()) { + TextureReference *aref = (*ai); + // Here's a texture reference in the original list, but not in + // the new list. Remove it. + delete aref; + ++ai; + } + + _textures.swap(combined_textures); } //////////////////////////////////////////////////////////////////// @@ -306,7 +378,7 @@ build_cross_links() { // Actually, this may count the same egg file multiple times for a // particular SourceTextureImage, since a given texture may be - // reference multiples times within an egg file. No harm done, + // referenced multiples times within an egg file. No harm done, // however. reference->get_source()->increment_egg_count(); } @@ -706,4 +778,12 @@ fillin(DatagramIterator &scan, BamReader *manager) { _is_surprise = scan.get_bool(); _is_stale = scan.get_bool(); + + if (Palettizer::_read_pi_version < 11) { + // If this file was written by a version of egg-palettize prior to + // 11, we didn't store the tref names on the texture references. + // Since we need that information now, it follows that every egg + // file is stale. + _is_stale = true; + } } diff --git a/pandatool/src/egg-palettize/palettizer.cxx b/pandatool/src/egg-palettize/palettizer.cxx index 63211ed5fd..8ac8b18330 100644 --- a/pandatool/src/egg-palettize/palettizer.cxx +++ b/pandatool/src/egg-palettize/palettizer.cxx @@ -41,10 +41,11 @@ Palettizer *pal = (Palettizer *)NULL; // allows us to easily update egg-palettize to write out additional // information to its pi file, without having it increment the bam // version number for all bam and boo files anywhere in the world. -int Palettizer::_pi_version = 10; +int Palettizer::_pi_version = 11; // Updated to version 8 on 3/20/03 to remove extensions from texture key names. // Updated to version 9 on 4/13/03 to add a few properties in various places. // Updated to version 10 on 4/15/03 to add _alpha_file_channel. +// Updated to version 11 on 4/30/03 to add TextureReference::_tref_name int Palettizer::_min_pi_version = 8; // Dropped support for versions 7 and below on 7/14/03. diff --git a/pandatool/src/egg-palettize/textureReference.cxx b/pandatool/src/egg-palettize/textureReference.cxx index 1b0f7b7bde..ece744dead 100644 --- a/pandatool/src/egg-palettize/textureReference.cxx +++ b/pandatool/src/egg-palettize/textureReference.cxx @@ -84,6 +84,7 @@ from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex) { _egg_file = egg_file; _egg_tex = egg_tex; _egg_data = data; + _tref_name = egg_tex->get_name(); if (_egg_tex->has_transform()) { _tex_mat = _egg_tex->get_transform(); @@ -166,6 +167,28 @@ get_texture() const { return _source_texture->get_texture(); } +//////////////////////////////////////////////////////////////////// +// Function: TextureReference::get_tref_name +// Access: Public +// Description: Returns the name of the EggTexture entry that +// references this texture. +//////////////////////////////////////////////////////////////////// +const string &TextureReference:: +get_tref_name() const { + return _tref_name; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureReference::operator < +// Access: Public +// Description: Defines an ordering of TextureReference pointers in +// alphabetical order by their tref name. +//////////////////////////////////////////////////////////////////// +bool TextureReference:: +operator < (const TextureReference &other) const { + return _tref_name < other._tref_name; +} + //////////////////////////////////////////////////////////////////// // Function: TextureReference::has_uvs // Access: Public @@ -225,6 +248,48 @@ get_wrap_v() const { return _wrap_v; } +//////////////////////////////////////////////////////////////////// +// Function: TextureReference::is_equivalent +// Access: Public +// Description: Returns true if all essential properties of this +// TextureReference are the same as that of the other, +// or false if any of them differ. This is useful when +// reading a new egg file and comparing its references +// to its previously-defined references. +//////////////////////////////////////////////////////////////////// +bool TextureReference:: +is_equivalent(const TextureReference &other) const { + if (_source_texture != other._source_texture) { + return false; + } + if (!_properties.egg_properties_match(other._properties)) { + return false; + } + if (_uses_alpha != other._uses_alpha) { + return false; + } + if (_any_uvs != other._any_uvs) { + return false; + } + if (_wrap_u != other._wrap_u || + _wrap_v != other._wrap_v) { + return false; + } + if (_any_uvs) { + if (!_min_uv.almost_equal(other._min_uv, 0.00001)) { + return false; + } + if (!_max_uv.almost_equal(other._max_uv, 0.00001)) { + return false; + } + } + if (!_tex_mat.almost_equal(other._tex_mat, 0.00001)) { + return false; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: TextureReference::set_placement // Access: Public @@ -734,6 +799,8 @@ write_datagram(BamWriter *writer, Datagram &datagram) { // We don't write _egg_tex or _egg_data; that's specific to the // session. + datagram.add_string(_tref_name); + _tex_mat.write_datagram(datagram); _inv_tex_mat.write_datagram(datagram); @@ -815,6 +882,10 @@ fillin(DatagramIterator &scan, BamReader *manager) { TypedWritable::fillin(scan, manager); manager->read_pointer(scan); // _egg_file + if (Palettizer::_read_pi_version >= 11) { + _tref_name = scan.get_string(); + } + _tex_mat.read_datagram(scan); _inv_tex_mat.read_datagram(scan); diff --git a/pandatool/src/egg-palettize/textureReference.h b/pandatool/src/egg-palettize/textureReference.h index d542072287..6a22f3e828 100644 --- a/pandatool/src/egg-palettize/textureReference.h +++ b/pandatool/src/egg-palettize/textureReference.h @@ -54,6 +54,9 @@ public: EggFile *get_egg_file() const; SourceTextureImage *get_source() const; TextureImage *get_texture() const; + const string &get_tref_name() const; + + bool operator < (const TextureReference &other) const; bool has_uvs() const; const TexCoordd &get_min_uv() const; @@ -62,6 +65,8 @@ public: EggTexture::WrapMode get_wrap_u() const; EggTexture::WrapMode get_wrap_v() const; + bool is_equivalent(const TextureReference &other) const; + void set_placement(TexturePlacement *placement); void clear_placement(); TexturePlacement *get_placement() const; @@ -90,6 +95,7 @@ private: EggTexture *_egg_tex; EggData *_egg_data; + string _tref_name; LMatrix3d _tex_mat, _inv_tex_mat; SourceTextureImage *_source_texture; TexturePlacement *_placement;