From 8ce02ceab88c5834f1b919d99850953096cb8c5c Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 10 Nov 2000 08:12:21 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/egg/Sources.pp | 9 +- panda/src/egg/config_egg.cxx | 6 + panda/src/egg/eggBinMaker.h | 6 +- panda/src/egg/eggData.cxx | 34 +++--- panda/src/egg/eggMaterial.cxx | 2 + panda/src/egg/eggMaterial.h | 18 +++ panda/src/egg/eggNameUniquifier.cxx | 153 +++++++++++++++++++++++++ panda/src/egg/eggNameUniquifier.h | 118 +++++++++++++++++++ panda/src/egg/eggPoolUniquifier.cxx | 44 +++++++ panda/src/egg/eggPoolUniquifier.h | 51 +++++++++ panda/src/egg/eggTextureCollection.cxx | 10 +- panda/src/loader/bamFile.cxx | 2 +- pandatool/src/bam/eggToBam.cxx | 6 +- pandatool/src/eggbase/eggWriter.cxx | 1 + 14 files changed, 430 insertions(+), 30 deletions(-) create mode 100644 panda/src/egg/eggNameUniquifier.cxx create mode 100644 panda/src/egg/eggNameUniquifier.h create mode 100644 panda/src/egg/eggPoolUniquifier.cxx create mode 100644 panda/src/egg/eggPoolUniquifier.h diff --git a/panda/src/egg/Sources.pp b/panda/src/egg/Sources.pp index c0ee30c998..ab4e249a2c 100644 --- a/panda/src/egg/Sources.pp +++ b/panda/src/egg/Sources.pp @@ -20,11 +20,13 @@ eggGroup.h eggGroupNode.I eggGroupNode.cxx eggGroupNode.h \ eggMaterial.I eggMaterial.cxx eggMaterial.h eggMiscFuncs.I \ eggMiscFuncs.cxx eggMiscFuncs.h eggNamedObject.I eggNamedObject.cxx \ - eggNamedObject.h eggNode.I eggNode.cxx eggNode.h eggNurbsCurve.I \ + eggNamedObject.h eggNameUniquifier.cxx eggNameUniquifier.h \ + eggNode.I eggNode.cxx eggNode.h eggNurbsCurve.I \ eggNurbsCurve.cxx eggNurbsCurve.h eggNurbsSurface.I \ eggNurbsSurface.cxx eggNurbsSurface.h eggObject.I eggObject.cxx \ eggObject.h eggParameters.cxx eggParameters.h eggPoint.I \ eggPoint.cxx eggPoint.h eggPolygon.I eggPolygon.cxx eggPolygon.h \ + eggPoolUniquifier.cxx eggPoolUniquifier.h \ eggPrimitive.I eggPrimitive.cxx eggPrimitive.h eggSAnimData.I \ eggSAnimData.cxx eggSAnimData.h eggSurface.I eggSurface.cxx \ eggSurface.h eggSwitchCondition.cxx eggSwitchCondition.h eggTable.I \ @@ -44,10 +46,11 @@ eggExternalReference.h eggFilenameNode.I eggFilenameNode.h \ eggGroup.I eggGroup.h eggGroupNode.I eggGroupNode.h eggMaterial.I \ eggMaterial.h eggMorph.I eggMorph.h eggMorphList.I eggMorphList.h \ - eggNamedObject.I eggNamedObject.h eggNode.I eggNode.h \ + eggNamedObject.I eggNamedObject.h eggNameUniquifier.h eggNode.I eggNode.h \ eggNurbsCurve.I eggNurbsCurve.h eggNurbsSurface.I eggNurbsSurface.h \ eggObject.I eggObject.h eggParameters.h eggPoint.I eggPoint.h \ - eggPolygon.I eggPolygon.h eggPrimitive.I eggPrimitive.h \ + eggPolygon.I eggPolygon.h eggPoolUniquifier.h \ + eggPrimitive.I eggPrimitive.h \ eggSAnimData.I eggSAnimData.h eggSurface.I eggSurface.h \ eggSwitchCondition.h eggTable.I eggTable.h eggTexture.I \ eggTexture.h eggTextureCollection.I eggTextureCollection.h \ diff --git a/panda/src/egg/config_egg.cxx b/panda/src/egg/config_egg.cxx index 5a3ba2af19..f66e02f6c9 100644 --- a/panda/src/egg/config_egg.cxx +++ b/panda/src/egg/config_egg.cxx @@ -16,6 +16,8 @@ #include "eggFilenameNode.h" #include "eggGroup.h" #include "eggGroupNode.h" +#include "eggMaterial.h" +#include "eggNameUniquifier.h" #include "eggNamedObject.h" #include "eggNode.h" #include "eggNurbsCurve.h" @@ -23,6 +25,7 @@ #include "eggObject.h" #include "eggPoint.h" #include "eggPolygon.h" +#include "eggPoolUniquifier.h" #include "eggPrimitive.h" #include "eggSAnimData.h" #include "eggSurface.h" @@ -54,6 +57,8 @@ ConfigureFn(config_egg) { EggFilenameNode::init_type(); EggGroup::init_type(); EggGroupNode::init_type(); + EggMaterial::init_type(); + EggNameUniquifier::init_type(); EggNamedObject::init_type(); EggNode::init_type(); EggNurbsCurve::init_type(); @@ -61,6 +66,7 @@ ConfigureFn(config_egg) { EggObject::init_type(); EggPoint::init_type(); EggPolygon::init_type(); + EggPoolUniquifier::init_type(); EggPrimitive::init_type(); EggSAnimData::init_type(); EggSurface::init_type(); diff --git a/panda/src/egg/eggBinMaker.h b/panda/src/egg/eggBinMaker.h index b2272f2fb6..61ed1a3bf8 100644 --- a/panda/src/egg/eggBinMaker.h +++ b/panda/src/egg/eggBinMaker.h @@ -48,7 +48,7 @@ // } // } // - +// // This function may also return the bin number that a given node // should be dropped into. The bin number is completely arbitrary, // and it just serves to differentiate different bins. @@ -207,7 +207,7 @@ class EggGroupNode; class EggBin; class EggBinMaker; -/////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// // Class : EggBinMakerCompareNodes // Description : This is just an STL function object, used to sort // nodes within EggBinMaker. It's part of the private @@ -227,7 +227,7 @@ public: }; -/////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// // Class : EggBinMaker // Description : This is a handy class for collecting related nodes // together. It is an abstract class; to use it you diff --git a/panda/src/egg/eggData.cxx b/panda/src/egg/eggData.cxx index 3dcc69c2fb..0078f1cb0a 100644 --- a/panda/src/egg/eggData.cxx +++ b/panda/src/egg/eggData.cxx @@ -7,6 +7,7 @@ #include "eggCoordinateSystem.h" #include "eggTextureCollection.h" #include "eggComment.h" +#include "eggPoolUniquifier.h" #include "config_egg.h" #include @@ -181,6 +182,20 @@ set_coordinate_system(CoordinateSystem new_coordsys) { _coordsys = new_coordsys; } +//////////////////////////////////////////////////////////////////// +// Function: EggData::write +// Access: Protected, Virtual +// Description: Writes the egg data out to the indicated output +// stream. +//////////////////////////////////////////////////////////////////// +void EggData:: +write(ostream &out, int indent_level) const { + EggCoordinateSystem ecs(_coordsys); + ecs.write(out, indent_level); + EggGroupNode::write(out, indent_level); + out << flush; +} + //////////////////////////////////////////////////////////////////// // Function: EggData::post_read @@ -251,19 +266,10 @@ pre_write() { } textures.insert_textures(this, ci); -} -//////////////////////////////////////////////////////////////////// -// Function: EggData::write -// Access: Public, Virtual -// Description: Writes the egg data out to the indicated output -// stream. -//////////////////////////////////////////////////////////////////// -void EggData:: -write(ostream &out, int indent_level) const { - EggCoordinateSystem ecs(_coordsys); - ecs.write(out, indent_level); - EggGroupNode::write(out, indent_level); - out << flush; + // Also make sure that the vertex pools and materials are uniquely + // named. This also checks textures, which is kind of redundant + // since we just did that, but we don't mind. + EggPoolUniquifier pu; + pu.uniquify(this); } - diff --git a/panda/src/egg/eggMaterial.cxx b/panda/src/egg/eggMaterial.cxx index 6ec35a2788..234f6cf7f5 100644 --- a/panda/src/egg/eggMaterial.cxx +++ b/panda/src/egg/eggMaterial.cxx @@ -7,6 +7,8 @@ #include +TypeHandle EggMaterial::_type_handle; + //////////////////////////////////////////////////////////////////// // Function: EggMaterial::Constructor diff --git a/panda/src/egg/eggMaterial.h b/panda/src/egg/eggMaterial.h index b16ef24b30..f74229409c 100644 --- a/panda/src/egg/eggMaterial.h +++ b/panda/src/egg/eggMaterial.h @@ -31,6 +31,24 @@ public: private: bool _has_diff; Colorf _diff; + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + EggNode::init_type(); + register_type(_type_handle, "EggMaterial", + EggNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; }; #include "eggMaterial.I" diff --git a/panda/src/egg/eggNameUniquifier.cxx b/panda/src/egg/eggNameUniquifier.cxx new file mode 100644 index 0000000000..ce66e74ff3 --- /dev/null +++ b/panda/src/egg/eggNameUniquifier.cxx @@ -0,0 +1,153 @@ +// Filename: eggNameUniquifier.cxx +// Created by: drose (09Nov00) +// +//////////////////////////////////////////////////////////////////// + +#include "eggNameUniquifier.h" +#include "eggNode.h" +#include "eggGroupNode.h" + +#include + +TypeHandle EggNameUniquifier::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: EggNameUniquifier::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggNameUniquifier:: +EggNameUniquifier() { + _index = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggNameUniquifier::clear +// Access: Public +// Description: Empties the table of used named and prepares the +// Uniquifier for a new tree. +//////////////////////////////////////////////////////////////////// +void EggNameUniquifier:: +clear() { + _categories.clear(); + _index = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggNameUniquifier::uniquify +// Access: Public +// Description: Begins the traversal from the indicated node. +//////////////////////////////////////////////////////////////////// +void EggNameUniquifier:: +uniquify(EggNode *node) { + string category = get_category(node); + + if (!category.empty()) { + string name = node->get_name(); + + UsedNames &names = _categories[category]; + bool inserted; + inserted = names.insert(UsedNames::value_type(name, node)).second; + if (!inserted) { + while (!inserted) { + _index++; + name = generate_name(node, category, _index); + inserted = names.insert(UsedNames::value_type(name, node)).second; + } + node->set_name(name); + } + } + + if (node->is_of_type(EggGroupNode::get_class_type())) { + EggGroupNode *group; + DCAST_INTO_V(group, node); + + EggGroupNode::iterator ci; + for (ci = group->begin(); ci != group->end(); ++ci) { + uniquify(*ci); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggNameUniquifier::get_node +// Access: Public +// Description: Returns the node associated with the given category +// and name, or NULL if the name has not been used. +//////////////////////////////////////////////////////////////////// +EggNode *EggNameUniquifier:: +get_node(const string &category, const string &name) const { + Categories::const_iterator ci; + ci = _categories.find(category); + if (ci == _categories.end()) { + return (EggNode *)NULL; + } + + const UsedNames &names = (*ci).second; + UsedNames::const_iterator ni; + ni = names.find(name); + if (ni == names.end()) { + return (EggNode *)NULL; + } + + return (*ni).second; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggNameUniquifier::has_name +// Access: Public +// Description: Returns true if the name has been used for the +// indicated category already, false otherwise. +//////////////////////////////////////////////////////////////////// +bool EggNameUniquifier:: +has_name(const string &category, const string &name) const { + Categories::const_iterator ci; + ci = _categories.find(category); + if (ci == _categories.end()) { + return false; + } + + const UsedNames &names = (*ci).second; + UsedNames::const_iterator ni; + ni = names.find(name); + if (ni == names.end()) { + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggNameUniquifier::add_name +// Access: Public +// Description: Adds the name to the indicated category. This name +// will not be used for any other egg node within this +// category. Returns true if the name was added, or +// false if it was already in use for the category. +//////////////////////////////////////////////////////////////////// +bool EggNameUniquifier:: +add_name(const string &category, const string &name, EggNode *node) { + UsedNames &names = _categories[category]; + bool inserted = names.insert(UsedNames::value_type(name, node)).second; + return inserted; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggNameUniquifier::generate_name +// Access: Public, Virtual +// Description: Generates a new name for the given node when its +// existing name clashes with some other node. This +// function will be called repeatedly, if necessary, +// until it returns a name that actually is unique. +// +// The category is the string returned by +// get_category(), and index is a uniquely-generated +// number that may be useful for synthesizing the name. +//////////////////////////////////////////////////////////////////// +string EggNameUniquifier:: +generate_name(EggNode *node, const string &category, int index) { + ostringstream str; + str << node->get_name() << "." << category << index; + return str.str(); +} diff --git a/panda/src/egg/eggNameUniquifier.h b/panda/src/egg/eggNameUniquifier.h new file mode 100644 index 0000000000..b33a3fe52b --- /dev/null +++ b/panda/src/egg/eggNameUniquifier.h @@ -0,0 +1,118 @@ +// Filename: eggNameUniquifier.h +// Created by: drose (09Nov00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGNAMEUNIQUIFIER_H +#define EGGNAMEUNIQUIFIER_H + +/////////////////////////////////////////////////////////////////// +// +// EggNameUniquifier +// +// This is a utility class for renaming nodes in an egg hierarchy so +// that no two nodes share the same name. It's useful, for instance, +// as a preprocess before translating the egg hierarchy to a scene +// graph format that doesn't tolerate two identically-named nodes; +// it's also particularly useful for guaranteeing that VertexPools and +// Textures do not have conflicting names. +// +// This is actually an abstract class; in order to use it, you must +// derive your own class and redefine some key functions (but see +// EggPoolUniquifier). +// +// You must define at least the following function: +// +// virtual string get_category(EggNode *node); +// +// This function defines the particular category that the +// particular node should be grouped into. All nodes that share +// the same category name will be considered in the same name pool +// and may not have the same name; two nodes that have different +// categories will be allowed to keep the same name. +// +// If the category is the empty string, the node will not be +// considered for uniquification. +// +// +// You may also define the following function: +// +// virtual string generate_name(EggNode *node, +// const string &category, int index); +// +// This returns a new name for the given node, once a node has been +// identified as having the same name as another node. It may use +// any algorithm you please to generate a new name, using any +// combination of the node's original name, the category (as +// returned by get_category()), and/or the supplied unique index +// number. +// +// If this function returns a name that happens to collide with +// some other already-existing node, it will simply be called again +// (with a new index number) until it finally returns a unique +// name. +// +/////////////////////////////////////////////////////////////////// + +#include + +#include "eggObject.h" + +#include + +class EggNode; + +//////////////////////////////////////////////////////////////////// +// Class : EggNameUniquifier +// Description : This is a handy class for guaranteeing unique node +// names in an egg hierarchy. It is an abstract class; +// to use it you must subclass off of it. See the +// comment above. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAEGG EggNameUniquifier : public EggObject { +public: + EggNameUniquifier(); + + void clear(); + + void uniquify(EggNode *node); + + EggNode *get_node(const string &category, const string &name) const; + bool has_name(const string &category, const string &name) const; + bool add_name(const string &category, const string &name, + EggNode *node = NULL); + + virtual string get_category(EggNode *node)=0; + virtual string generate_name(EggNode *node, + const string &category, int index); + +private: + typedef map UsedNames; + typedef map Categories; + + Categories _categories; + int _index; + +public: + + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + EggObject::init_type(); + register_type(_type_handle, "EggNameUniquifier", + EggObject::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + +}; + +#endif + + diff --git a/panda/src/egg/eggPoolUniquifier.cxx b/panda/src/egg/eggPoolUniquifier.cxx new file mode 100644 index 0000000000..c583cbe9ca --- /dev/null +++ b/panda/src/egg/eggPoolUniquifier.cxx @@ -0,0 +1,44 @@ +// Filename: eggPoolUniquifier.cxx +// Created by: drose (09Nov00) +// +//////////////////////////////////////////////////////////////////// + +#include "eggPoolUniquifier.h" +#include "eggNode.h" +#include "eggTexture.h" +#include "eggMaterial.h" +#include "eggVertexPool.h" + +#include + +TypeHandle EggPoolUniquifier::_type_handle; + + +//////////////////////////////////////////////////////////////////// +// Function: EggPoolUniquifier::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggPoolUniquifier:: +EggPoolUniquifier() { +} + +//////////////////////////////////////////////////////////////////// +// Function: EggPoolUniquifier::get_category +// Access: Public +// Description: Returns the category name into which the given node +// should be collected, or the empty string if the +// node's name should be left alone. +//////////////////////////////////////////////////////////////////// +string EggPoolUniquifier:: +get_category(EggNode *node) { + if (node->is_of_type(EggTexture::get_class_type())) { + return "tex"; + } else if (node->is_of_type(EggMaterial::get_class_type())) { + return "mat"; + } else if (node->is_of_type(EggVertexPool::get_class_type())) { + return "vpool"; + } + + return string(); +} diff --git a/panda/src/egg/eggPoolUniquifier.h b/panda/src/egg/eggPoolUniquifier.h new file mode 100644 index 0000000000..b38423101d --- /dev/null +++ b/panda/src/egg/eggPoolUniquifier.h @@ -0,0 +1,51 @@ +// Filename: eggPoolUniquifier.h +// Created by: drose (09Nov00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGPOOLUNIQUIFIER_H +#define EGGPOOLUNIQUIFIER_H + +#include + +#include "eggNameUniquifier.h" + +#include + +class EggNode; + +//////////////////////////////////////////////////////////////////// +// Class : EggPoolUniquifier +// Description : This is a specialization of EggNameUniquifier to +// generate unique names for textures, materials, and +// vertex pools prior to writing out an egg file. It's +// called by EggData prior to writing out an egg file. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAEGG EggPoolUniquifier : public EggNameUniquifier { +public: + EggPoolUniquifier(); + + virtual string get_category(EggNode *node); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + EggNameUniquifier::init_type(); + register_type(_type_handle, "EggPoolUniquifier", + EggNameUniquifier::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + +}; + +#endif + + diff --git a/panda/src/egg/eggTextureCollection.cxx b/panda/src/egg/eggTextureCollection.cxx index 382b8d7f85..ce877580c6 100644 --- a/panda/src/egg/eggTextureCollection.cxx +++ b/panda/src/egg/eggTextureCollection.cxx @@ -94,13 +94,9 @@ insert_textures(EggGroupNode *node) { //////////////////////////////////////////////////////////////////// int EggTextureCollection:: insert_textures(EggGroupNode *node, EggGroupNode::iterator position) { - // We add the textures in reverse order because we stick each one at - // the head of the group's children. When we're done, they'll all - // be in the correct order. - - OrderedTextures::reverse_iterator oti; - for (oti = _ordered_textures.rbegin(); - oti != _ordered_textures.rend(); + OrderedTextures::iterator oti; + for (oti = _ordered_textures.begin(); + oti != _ordered_textures.end(); ++oti) { node->insert(position, (*oti).p()); } diff --git a/panda/src/loader/bamFile.cxx b/panda/src/loader/bamFile.cxx index e4d948f22a..6f8b2e548d 100644 --- a/panda/src/loader/bamFile.cxx +++ b/panda/src/loader/bamFile.cxx @@ -140,7 +140,7 @@ open_write(const Filename &filename, bool) { loader_cat.info() << "Writing " << filename << "\n"; - filename.make_dir(); + filename.unlink(); if (!_dout.open(filename)) { loader_cat.error() << "Unable to open " << filename << "\n"; return false; diff --git a/pandatool/src/bam/eggToBam.cxx b/pandatool/src/bam/eggToBam.cxx index 58e51a7633..050df4417a 100644 --- a/pandatool/src/bam/eggToBam.cxx +++ b/pandatool/src/bam/eggToBam.cxx @@ -52,9 +52,11 @@ run() { // constructor, above. nassertv(has_output_filename()); - nout << "Writing " << get_output_filename() << "\n"; + Filename filename = get_output_filename(); + filename.make_dir(); + nout << "Writing " << filename << "\n"; BamFile bam_file; - if (!bam_file.open_write(get_output_filename())) { + if (!bam_file.open_write(filename)) { nout << "Error in writing.\n"; exit(1); } diff --git a/pandatool/src/eggbase/eggWriter.cxx b/pandatool/src/eggbase/eggWriter.cxx index a369f87bb7..a44741b53a 100644 --- a/pandatool/src/eggbase/eggWriter.cxx +++ b/pandatool/src/eggbase/eggWriter.cxx @@ -97,6 +97,7 @@ get_output() { // Attempt to open the named file. unlink(_output_filename.c_str()); _output_filename.make_dir(); + _output_filename.set_text(); if (!_output_filename.open_write(_output_stream)) { nout << "Unable to write to " << _output_filename << "\n"; exit(1);