diff --git a/pandatool/src/eggbase/Sources.pp b/pandatool/src/eggbase/Sources.pp index 1393ab626b..a22470a016 100644 --- a/pandatool/src/eggbase/Sources.pp +++ b/pandatool/src/eggbase/Sources.pp @@ -7,24 +7,19 @@ #define SOURCES \ eggBase.cxx eggBase.h \ - eggCharacterData.cxx eggCharacterData.h eggCharacterData.I \ - eggCharacterFilter.cxx eggCharacterFilter.h \ - eggConverter.cxx eggConverter.h eggFilter.cxx \ - eggFilter.h eggJointData.cxx eggJointData.h eggJointData.I \ + eggConverter.cxx eggConverter.h \ + eggFilter.cxx eggFilter.h \ eggMultiBase.cxx eggMultiBase.h \ eggMultiFilter.cxx eggMultiFilter.h \ eggReader.cxx eggReader.h \ - eggToSomething.cxx \ - eggToSomething.h eggWriter.cxx eggWriter.h somethingToEgg.cxx \ - somethingToEgg.h + eggToSomething.cxx eggToSomething.h \ + eggWriter.cxx eggWriter.h \ + somethingToEgg.cxx somethingToEgg.h #define INSTALL_HEADERS \ - eggBase.h eggCharacterData.h \ - eggCharacterData.I eggCharacterFilter.h \ - eggConverter.h eggFilter.h eggJointData.h eggJointData.I \ + eggBase.h eggConverter.h eggFilter.h \ eggMultiBase.h eggMultiFilter.h \ - eggReader.h \ - eggToSomething.h eggWriter.h somethingToEgg.h + eggReader.h eggToSomething.h eggWriter.h somethingToEgg.h #end ss_lib_target diff --git a/pandatool/src/eggbase/eggCharacterData.I b/pandatool/src/eggbase/eggCharacterData.I deleted file mode 100644 index b58510ef70..0000000000 --- a/pandatool/src/eggbase/eggCharacterData.I +++ /dev/null @@ -1,27 +0,0 @@ -// Filename: eggCharacterData.I -// Created by: drose (23Feb01) -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::get_num_eggs -// Access: Public -// Description: Returns the number of egg files that have -// successfully been added to the Character table. -//////////////////////////////////////////////////////////////////// -INLINE int EggCharacterData:: -get_num_eggs() const { - return _eggs.size(); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::get_egg -// Access: Public -// Description: Returns the ith egg file. -//////////////////////////////////////////////////////////////////// -INLINE EggData *EggCharacterData:: -get_egg(int i) const { - nassertr(i >= 0 && i < (int)_eggs.size(), (EggData *)NULL); - return _eggs[i]._egg; -} diff --git a/pandatool/src/eggbase/eggCharacterData.h b/pandatool/src/eggbase/eggCharacterData.h deleted file mode 100644 index 5fdb00c238..0000000000 --- a/pandatool/src/eggbase/eggCharacterData.h +++ /dev/null @@ -1,82 +0,0 @@ -// Filename: eggCharacterData.h -// Created by: drose (23Feb01) -// -//////////////////////////////////////////////////////////////////// - -#ifndef EGGCHARACTERDATA_H -#define EGGCHARACTERDATA_H - -#include - -#include -#include -#include - -class EggJointData; -class EggTable; - -//////////////////////////////////////////////////////////////////// -// Class : EggCharacterData -// Description : Represents a set of characters, as read and collected -// from several models and animation files. Each -// character is the root of a hierarchy of EggJointData -// nodes. -//////////////////////////////////////////////////////////////////// -class EggCharacterData { -public: - EggCharacterData(); - virtual ~EggCharacterData(); - - bool add_egg(EggData *egg); - - INLINE int get_num_eggs() const; - INLINE EggData *get_egg(int i) const; - - virtual void write(ostream &out, int indent_level = 0) const; - -protected: - virtual EggJointData *make_joint_data(); - EggJointData *get_root_joint(const string &character_name); - - class EggInfo { - public: - PT(EggData) _egg; - typedef vector Models; - Models _models; - }; - - typedef vector Eggs; - Eggs _eggs; - - class CharacterInfo { - public: - string _name; - EggJointData *_root_joint; - }; - - typedef vector Characters; - Characters _characters; - -private: - bool scan_hierarchy(EggNode *egg_node); - void scan_for_top_joints(EggNode *egg_node, EggNode *model_root, - const string &character_name); - void scan_for_top_tables(EggTable *bundle, EggNode *model_root, - const string &character_name); - - typedef vector EggNodeList; - typedef map TopEggNodes; - typedef map TopEggNodesByName; - TopEggNodesByName _top_egg_nodes; - - void match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, - int egg_index, int model_index); - void found_egg_node_match(EggJointData *data, EggNode *egg_node, - int egg_index, int model_index); -}; - -#include "eggCharacterData.I" - -#endif - - diff --git a/pandatool/src/eggbase/eggJointData.cxx b/pandatool/src/eggbase/eggJointData.cxx deleted file mode 100644 index c6715e1fca..0000000000 --- a/pandatool/src/eggbase/eggJointData.cxx +++ /dev/null @@ -1,93 +0,0 @@ -// Filename: eggJointData.cxx -// Created by: drose (23Feb01) -// -//////////////////////////////////////////////////////////////////// - -#include "eggJointData.h" - -#include - - -//////////////////////////////////////////////////////////////////// -// Function: EggJointData::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -EggJointData:: -EggJointData() { -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointData::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -EggJointData:: -~EggJointData() { -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointData::matches_name -// Access: Public -// Description: Returns true if the indicated name matches any name -// that was ever matched with this particular joint, -// false otherwise. -//////////////////////////////////////////////////////////////////// -bool EggJointData:: -matches_name(const string &name) const { - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointData::add_egg_node -// Access: Public -// Description: Adds the indicated model joint or anim table to the -// data. -//////////////////////////////////////////////////////////////////// -void EggJointData:: -add_egg_node(int egg_index, int model_index, EggNode *egg_node) { - if (!has_name() && egg_node->has_name()) { - set_name(egg_node->get_name()); - } - - while ((int)_joints.size() <= egg_index) { - _joints.push_back(JointNodes()); - } - JointNodes &nodes = _joints[egg_index]; - while ((int)nodes.size() <= model_index) { - nodes.push_back((EggNode *)NULL); - } - nodes[model_index] = egg_node; -} - -//////////////////////////////////////////////////////////////////// -// Function: EggJointData::write -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void EggJointData:: -write(ostream &out, int indent_level) const { - indent(out, indent_level) - << "Joint " << get_name() - << " (models:"; - for (size_t egg_index = 0; egg_index < _joints.size(); egg_index++) { - const JointNodes &nodes = _joints[egg_index]; - if (nodes.size() == 1) { - out << " " << egg_index; - } else if (nodes.size() > 1) { - for (size_t model_index = 0; model_index < nodes.size(); model_index++) { - if (nodes[model_index] != (EggNode *)NULL) { - out << " " << egg_index << "/" << model_index; - } - } - } - } - out << ") {\n"; - - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - (*ci)->write(out, indent_level + 2); - } - - indent(out, indent_level) << "}\n"; -} diff --git a/pandatool/src/eggcharbase/Sources.pp b/pandatool/src/eggcharbase/Sources.pp new file mode 100644 index 0000000000..11aa77ffe8 --- /dev/null +++ b/pandatool/src/eggcharbase/Sources.pp @@ -0,0 +1,33 @@ +#begin ss_lib_target + #define TARGET eggcharbase + #define LOCAL_LIBS \ + eggbase progbase + #define OTHER_LIBS \ + egg:c panda:m + + #define SOURCES \ + eggBackPointer.cxx eggBackPointer.h \ + eggCharacterCollection.cxx eggCharacterCollection.h \ + eggCharacterCollection.I \ + eggCharacterData.cxx eggCharacterData.h eggCharacterData.I \ + eggCharacterFilter.cxx eggCharacterFilter.h \ + eggComponentData.cxx eggComponentData.h eggComponentData.I \ + eggJointData.cxx eggJointData.h eggJointData.I \ + eggJointPointer.cxx eggJointPointer.h \ + eggMatrixTablePointer.cxx eggMatrixTablePointer.h \ + eggSliderData.cxx eggSliderData.h eggSliderData.I \ + eggVertexPointer.cxx eggVertexPointer.h + + #define INSTALL_HEADERS \ + eggBackPointer.h \ + eggCharacterCollection.I eggCharacterCollection.h \ + eggCharacterData.I eggCharacterData.h eggCharacterFilter.h \ + eggComponentData.I eggComponentData.h \ + eggJointData.h eggJointData.I \ + eggJointPointer.h \ + eggMatrixTablePointer.h \ + eggSliderData.I eggSliderData.h \ + eggVertexPointer.h + +#end ss_lib_target + diff --git a/pandatool/src/eggcharbase/eggBackPointer.cxx b/pandatool/src/eggcharbase/eggBackPointer.cxx new file mode 100644 index 0000000000..bc1689dbee --- /dev/null +++ b/pandatool/src/eggcharbase/eggBackPointer.cxx @@ -0,0 +1,18 @@ +// Filename: eggBackPointer.cxx +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggBackPointer.h" + + +TypeHandle EggBackPointer::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: EggBackPointer::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggBackPointer:: +EggBackPointer() { +} diff --git a/pandatool/src/eggcharbase/eggBackPointer.h b/pandatool/src/eggcharbase/eggBackPointer.h new file mode 100644 index 0000000000..1e9d244181 --- /dev/null +++ b/pandatool/src/eggcharbase/eggBackPointer.h @@ -0,0 +1,51 @@ +// Filename: eggBackPointer.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGBACKPOINTER_H +#define EGGBACKPOINTER_H + +#include + +#include + +//////////////////////////////////////////////////////////////////// +// Class : EggBackPointer +// Description : This stores a pointer from an EggJointData or +// EggSlider object back to the referencing data in an +// egg file. One of these objects corresponds to each +// model appearing in an egg file, and may reference +// either a single node, or a table, or a slew of +// vertices and primitives, depending on the type of +// data stored. +// +// This is just an abstract base class. The actual +// details are stored in the various subclasses. +//////////////////////////////////////////////////////////////////// +class EggBackPointer : public TypedObject { +public: + EggBackPointer(); + + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedObject::init_type(); + register_type(_type_handle, "EggBackPointer", + TypedObject::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/pandatool/src/eggcharbase/eggCharacterCollection.I b/pandatool/src/eggcharbase/eggCharacterCollection.I new file mode 100644 index 0000000000..7305e4c689 --- /dev/null +++ b/pandatool/src/eggcharbase/eggCharacterCollection.I @@ -0,0 +1,50 @@ +// Filename: eggCharacterCollection.I +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::get_num_eggs +// Access: Public +// Description: Returns the number of egg files that have +// successfully been added to the Character table. +//////////////////////////////////////////////////////////////////// +INLINE int EggCharacterCollection:: +get_num_eggs() const { + return _eggs.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::get_egg +// Access: Public +// Description: Returns the ith egg file. +//////////////////////////////////////////////////////////////////// +INLINE EggData *EggCharacterCollection:: +get_egg(int i) const { + nassertr(i >= 0 && i < (int)_eggs.size(), (EggData *)NULL); + return _eggs[i]._egg; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::get_num_characters +// Access: Public +// Description: Returns the number of separate Characters that have +// been discovered in the various egg files added to the +// collection. +//////////////////////////////////////////////////////////////////// +INLINE int EggCharacterCollection:: +get_num_characters() const { + return _characters.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::get_character +// Access: Public +// Description: Returns the ith character in the collection. +//////////////////////////////////////////////////////////////////// +INLINE EggCharacterData *EggCharacterCollection:: +get_character(int i) const { + nassertr(i >= 0 && i < (int)_characters.size(), (EggCharacterData *)NULL); + return _characters[i]; +} diff --git a/pandatool/src/eggbase/eggCharacterData.cxx b/pandatool/src/eggcharbase/eggCharacterCollection.cxx similarity index 54% rename from pandatool/src/eggbase/eggCharacterData.cxx rename to pandatool/src/eggcharbase/eggCharacterCollection.cxx index 73b9076d60..9febd19d98 100644 --- a/pandatool/src/eggbase/eggCharacterData.cxx +++ b/pandatool/src/eggcharbase/eggCharacterCollection.cxx @@ -1,44 +1,51 @@ -// Filename: eggCharacterData.cxx -// Created by: drose (23Feb01) +// Filename: eggCharacterCollection.cxx +// Created by: drose (26Feb01) // //////////////////////////////////////////////////////////////////// +#include "eggCharacterCollection.h" #include "eggCharacterData.h" #include "eggJointData.h" -#include "eggGroup.h" -#include "eggTable.h" +#include "eggSliderData.h" +#include +#include +#include +#include +#include +#include #include #include #include + //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::Constructor +// Function: EggCharacterCollection::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// -EggCharacterData:: -EggCharacterData() { +EggCharacterCollection:: +EggCharacterCollection() { + _next_model_index = 0; } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::Destructor +// Function: EggCharacterCollection::Destructor // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -EggCharacterData:: -~EggCharacterData() { +EggCharacterCollection:: +~EggCharacterCollection() { Characters::iterator ci; for (ci = _characters.begin(); ci != _characters.end(); ++ci) { - CharacterInfo &character_info = (*ci); - delete character_info._root_joint; + delete (*ci); } } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::add_egg +// Function: EggCharacterCollection::add_egg // Access: Public // Description: Adds a new egg file to the list of models and // animation files for this particular character. @@ -49,7 +56,7 @@ EggCharacterData:: // If the joint hierarchy does not match the existing // joint hierarchy, a best match is attempted. //////////////////////////////////////////////////////////////////// -bool EggCharacterData:: +bool EggCharacterCollection:: add_egg(EggData *egg) { _top_egg_nodes.clear(); @@ -68,16 +75,21 @@ add_egg(EggData *egg) { for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) { string character_name = (*tni).first; TopEggNodes &top_nodes = (*tni).second; + EggCharacterData *char_data = make_character(character_name); + EggJointData *root_joint = char_data->get_root_joint(); TopEggNodes::iterator ti; for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) { - EggNode *model = (*ti).first; + EggNode *model_root = (*ti).first; EggNodeList &egg_nodes = (*ti).second; - int model_index = egg_info._models.size(); - egg_info._models.push_back(model); - match_egg_nodes(get_root_joint(character_name), - egg_nodes, egg_index, model_index); + int model_index = _next_model_index++; + egg_info._models.push_back(model_root); + match_egg_nodes(char_data, root_joint, egg_nodes, + egg_index, model_index); + + scan_for_morphs(model_root, model_index, char_data); + scan_for_sliders(model_root, model_index, char_data); } } @@ -85,50 +97,95 @@ add_egg(EggData *egg) { } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::get_root_joint -// Access: Protected -// Description: Returns the root of the joint hierarchy for the named -// character. This is actually a fictitious node that -// does not correspond to any particular nodes in the -// character hierarchy; it exists to hold all of the top -// joints (if any) read from the character hierarchy. +// Function: EggCharacterCollection::get_character_by_name +// Access: Public +// Description: Returns the Character with the indicated name, if it +// exists in the collection, or NULL if it does not. //////////////////////////////////////////////////////////////////// -EggJointData *EggCharacterData:: -get_root_joint(const string &character_name) { +EggCharacterData *EggCharacterCollection:: +get_character_by_name(const string &character_name) const { + Characters::const_iterator ci; + for (ci = _characters.begin(); ci != _characters.end(); ++ci) { + EggCharacterData *char_data = (*ci); + if (char_data->get_name() == character_name) { + return char_data; + } + } + + return (EggCharacterData *)NULL; +} + + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::make_character_data +// Access: Public, Virtual +// Description: Allocates and returns a new EggCharacterData +// structure. This is primarily intended as a hook so +// derived classes can customize the type of +// EggCharacterData nodes used to represent the +// characters in this collection. +//////////////////////////////////////////////////////////////////// +EggCharacterData *EggCharacterCollection:: +make_character_data() { + return new EggCharacterData(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::make_joint_data +// Access: Public, Virtual +// Description: Allocates and returns a new EggJointData structure +// for the given character. This is primarily intended +// as a hook so derived classes can customize the type +// of EggJointData nodes used to represent the joint +// hierarchy. +//////////////////////////////////////////////////////////////////// +EggJointData *EggCharacterCollection:: +make_joint_data(EggCharacterData *char_data) { + return new EggJointData(this, char_data); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::make_slider_data +// Access: Public, Virtual +// Description: Allocates and returns a new EggSliderData structure +// for the given character. This is primarily intended +// as a hook so derived classes can customize the type +// of EggSliderData nodes used to represent the slider +// list. +//////////////////////////////////////////////////////////////////// +EggSliderData *EggCharacterCollection:: +make_slider_data(EggCharacterData *char_data) { + return new EggSliderData(this, char_data); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::make_character +// Access: Protected +// Description: Allocates and returns a new EggCharacterData object +// representing the named character, if there is not +// already a character by that name. +//////////////////////////////////////////////////////////////////// +EggCharacterData *EggCharacterCollection:: +make_character(const string &character_name) { // Does the named character exist yet? Characters::iterator ci; for (ci = _characters.begin(); ci != _characters.end(); ++ci) { - CharacterInfo &character_info = (*ci); - if (character_info._name == character_name) { - return character_info._root_joint; + EggCharacterData *char_data = (*ci); + if (char_data->get_name() == character_name) { + return char_data; } } // Define a new character. - _characters.push_back(CharacterInfo()); - CharacterInfo &character_info = _characters.back(); - character_info._name = character_name; - character_info._root_joint = make_joint_data(); - return character_info._root_joint; -} - - -//////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::make_joint_data -// Access: Protected, Virtual -// Description: Allocates and returns a new EggJointData structure. -// This is primarily intended as a hook so derived -// classes can customize the type of EggJointData nodes -// used to represent the joint hierarchy. -//////////////////////////////////////////////////////////////////// -EggJointData *EggCharacterData:: -make_joint_data() { - return new EggJointData; + EggCharacterData *char_data = make_character_data(); + char_data->set_name(character_name); + _characters.push_back(char_data); + return char_data; } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::scan_hierarchy +// Function: EggCharacterCollection::scan_hierarchy // Access: Private // Description: Walks the given egg data's hierarchy, looking for // either the start of an animation channel or the start @@ -139,7 +196,7 @@ make_joint_data() { // Fills up the _top_egg_nodes according to the nodes // found. //////////////////////////////////////////////////////////////////// -bool EggCharacterData:: +bool EggCharacterCollection:: scan_hierarchy(EggNode *egg_node) { if (egg_node->is_of_type(EggGroup::get_class_type())) { EggGroup *group = DCAST(EggGroup, egg_node); @@ -173,13 +230,13 @@ scan_hierarchy(EggNode *egg_node) { } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::scan_for_top_joints +// Function: EggCharacterCollection::scan_for_top_joints // Access: Private // Description: Once a character model has been found, continue // scanning the egg hierarchy to look for the topmost // nodes encountered. //////////////////////////////////////////////////////////////////// -void EggCharacterData:: +void EggCharacterCollection:: scan_for_top_joints(EggNode *egg_node, EggNode *model_root, const string &character_name) { if (egg_node->is_of_type(EggGroup::get_class_type())) { @@ -206,13 +263,13 @@ scan_for_top_joints(EggNode *egg_node, EggNode *model_root, } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::scan_for_top_tables +// Function: EggCharacterCollection::scan_for_top_tables // Access: Private // Description: Once an animation has been found, continue scanning // the egg hierarchy to look for the topmost // nodes encountered. //////////////////////////////////////////////////////////////////// -void EggCharacterData:: +void EggCharacterCollection:: scan_for_top_tables(EggTable *bundle, EggNode *model_root, const string &character_name) { // We really only need to check the immediate children of the bundle @@ -239,7 +296,121 @@ scan_for_top_tables(EggTable *bundle, EggNode *model_root, } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::match_egg_nodes +// Function: EggCharacterCollection::scan_for_morphs +// Access: Private +// Description: Go back through a model's hierarchy and look for +// morph targets on the vertices and primitives. +//////////////////////////////////////////////////////////////////// +void EggCharacterCollection:: +scan_for_morphs(EggNode *egg_node, int model_index, + EggCharacterData *char_data) { + if (egg_node->is_of_type(EggPrimitive::get_class_type())) { + EggPrimitive *prim = DCAST(EggPrimitive, egg_node); + // Check for morphs on the primitive. + add_morph_back_pointers(prim, prim, model_index, char_data); + + // Also check for morphs on each of the prim's vertices. + EggPrimitive::const_iterator vi; + for (vi = prim->begin(); vi != prim->end(); ++vi) { + EggVertex *vertex = (*vi); + + add_morph_back_pointers(vertex, vertex, model_index, char_data); + + EggMorphVertexList::const_iterator mvi; + for (mvi = vertex->_dxyzs.begin(); + mvi != vertex->_dxyzs.end(); + ++mvi) { + const EggMorphVertex &morph = (*mvi); + char_data->make_slider(morph.get_name())->add_back_pointer(model_index, vertex); + } + } + } + + if (egg_node->is_of_type(EggGroupNode::get_class_type())) { + EggGroupNode *group = DCAST(EggGroupNode, egg_node); + EggGroupNode::iterator gi; + for (gi = group->begin(); gi != group->end(); ++gi) { + scan_for_morphs(*gi, model_index, char_data); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::scan_for_sliders +// Access: Private +// Description: Go back to the animation tables and look for morph +// slider animation channels. +//////////////////////////////////////////////////////////////////// +void EggCharacterCollection:: +scan_for_sliders(EggNode *egg_node, int model_index, + EggCharacterData *char_data) { + if (egg_node->is_of_type(EggTable::get_class_type())) { + EggTable *bundle = DCAST(EggTable, egg_node); + + // We really only need to check the immediate children of the + // bundle for a table node called "morph". This is a sibling of + // "", which we found a minute ago, but we weren't ready + // to scan for the morph sliders at the time, so we have to look + // again now. + + EggGroupNode::iterator gi; + for (gi = bundle->begin(); gi != bundle->end(); ++gi) { + EggNode *child = (*gi); + if (child->is_of_type(EggTable::get_class_type())) { + EggTable *table = DCAST(EggTable, child); + if (table->get_name() == "morph") { + // Here it is! Now the immediate children of this node are + // all the slider channels. + + EggGroupNode::iterator cgi; + for (cgi = table->begin(); cgi != table->end(); ++cgi) { + EggNode *grandchild = (*cgi); + if (grandchild->is_of_type(EggSAnimData::get_class_type())) { + char_data->make_slider(grandchild->get_name())->add_back_pointer(model_index, grandchild); + } + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::add_morph_back_pointers +// Access: Private +// Description: Adds the back pointers for the kinds of morphs we +// might find in an EggAttributes object. +//////////////////////////////////////////////////////////////////// +void EggCharacterCollection:: +add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object, + int model_index, EggCharacterData *char_data) { + EggMorphNormalList::const_iterator mni; + for (mni = attrib->_dnormals.begin(); + mni != attrib->_dnormals.end(); + ++mni) { + const EggMorphNormal &morph = (*mni); + char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); + } + + EggMorphTexCoordList::const_iterator mti; + for (mti = attrib->_duvs.begin(); + mti != attrib->_duvs.end(); + ++mti) { + const EggMorphTexCoord &morph = (*mti); + char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); + } + + EggMorphColorList::const_iterator mci; + for (mci = attrib->_drgbas.begin(); + mci != attrib->_drgbas.end(); + ++mci) { + const EggMorphColor &morph = (*mci); + char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::match_egg_nodes // Access: Private // Description: Attempts to match up the indicated list of egg_nodes // with the children of the given joint_data, by name if @@ -248,9 +419,9 @@ scan_for_top_tables(EggTable *bundle, EggNode *model_root, // Also recurses on each matched joint to build up the // entire joint hierarchy. //////////////////////////////////////////////////////////////////// -void EggCharacterData:: -match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, - int egg_index, int model_index) { +void EggCharacterCollection:: +match_egg_nodes(EggCharacterData *char_data, EggJointData *joint_data, + EggNodeList &egg_nodes, int egg_index, int model_index) { // Sort the list of egg_nodes in order by name. This will make the // matching up by names easier and more reliable. sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames()); @@ -261,9 +432,9 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, EggNodeList::iterator ei; for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) { EggNode *egg_node = (*ei); - EggJointData *data = make_joint_data(); + EggJointData *data = make_joint_data(char_data); joint_data->_children.push_back(data); - found_egg_node_match(data, egg_node, egg_index, model_index); + found_egg_match(char_data, data, egg_node, egg_index, model_index); } } else { @@ -295,7 +466,7 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, } else { // Hey, these two match! Hooray! - found_egg_node_match(data, egg_node, egg_index, model_index); + found_egg_match(char_data, data, egg_node, egg_index, model_index); ++ei; ++di; } @@ -335,7 +506,7 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, EggJointData *data = (*di); if (data->matches_name(egg_node->get_name())) { matched = true; - found_egg_node_match(data, egg_node, egg_index, model_index); + found_egg_match(char_data, data, egg_node, egg_index, model_index); extra_data.erase(di); } } @@ -357,7 +528,7 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, for (i = 0; i < extra_egg_nodes.size(); i++) { EggNode *egg_node = extra_egg_nodes[i]; EggJointData *data = extra_data[i]; - found_egg_node_match(data, egg_node, egg_index, model_index); + found_egg_match(char_data, data, egg_node, egg_index, model_index); } } else { @@ -365,9 +536,9 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, EggNodeList::iterator ei; for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) { EggNode *egg_node = (*ei); - EggJointData *data = make_joint_data(); + EggJointData *data = make_joint_data(char_data); joint_data->_children.push_back(data); - found_egg_node_match(data, egg_node, egg_index, model_index); + found_egg_match(char_data, data, egg_node, egg_index, model_index); } } } @@ -380,16 +551,19 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::found_egg_node_match +// Function: EggCharacterCollection::found_egg_match // Access: Private // Description: Marks a one-to-one association between the indicated // EggJointData and the indicated EggNode, and then // recurses below. //////////////////////////////////////////////////////////////////// -void EggCharacterData:: -found_egg_node_match(EggJointData *data, EggNode *egg_node, - int egg_index, int model_index) { - data->add_egg_node(egg_index, model_index, egg_node); +void EggCharacterCollection:: +found_egg_match(EggCharacterData *char_data, EggJointData *joint_data, + EggNode *egg_node, int egg_index, int model_index) { + if (egg_node->has_name()) { + joint_data->add_name(egg_node->get_name()); + } + joint_data->add_back_pointer(model_index, egg_node); if (egg_node->is_of_type(EggGroupNode::get_class_type())) { EggGroupNode *group_node = DCAST(EggGroupNode, egg_node); @@ -429,24 +603,23 @@ found_egg_node_match(EggJointData *data, EggNode *egg_node, } if (!egg_nodes.empty()) { - match_egg_nodes(data, egg_nodes, egg_index, model_index); + match_egg_nodes(char_data, joint_data, egg_nodes, + egg_index, model_index); } } } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterData::write +// Function: EggCharacterCollection::write // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void EggCharacterData:: +void EggCharacterCollection:: write(ostream &out, int indent_level) const { Characters::const_iterator ci; for (ci = _characters.begin(); ci != _characters.end(); ++ci) { - const CharacterInfo &character_info = (*ci); - indent(out, indent_level) - << "Character " << character_info._name << ":\n"; - character_info._root_joint->write(out, indent_level + 2); + EggCharacterData *char_data = (*ci); + char_data->write(out, indent_level); } } diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.h b/pandatool/src/eggcharbase/eggCharacterCollection.h new file mode 100644 index 0000000000..11b2946972 --- /dev/null +++ b/pandatool/src/eggcharbase/eggCharacterCollection.h @@ -0,0 +1,93 @@ +// Filename: eggCharacterCollection.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGCHARACTERCOLLECTION_H +#define EGGCHARACTERCOLLECTION_H + +#include + +#include "eggCharacterData.h" + +#include +#include +#include + +class EggTable; +class EggAttributes; + +//////////////////////////////////////////////////////////////////// +// Class : EggCharacterCollection +// Description : Represents a set of characters, as read and collected +// from possibly several model and/or animation egg +// files. +//////////////////////////////////////////////////////////////////// +class EggCharacterCollection { +public: + EggCharacterCollection(); + virtual ~EggCharacterCollection(); + + bool add_egg(EggData *egg); + + INLINE int get_num_eggs() const; + INLINE EggData *get_egg(int i) const; + + INLINE int get_num_characters() const; + INLINE EggCharacterData *get_character(int i) const; + EggCharacterData *get_character_by_name(const string &character_name) const; + + virtual void write(ostream &out, int indent_level = 0) const; + + virtual EggCharacterData *make_character_data(); + virtual EggJointData *make_joint_data(EggCharacterData *char_data); + virtual EggSliderData *make_slider_data(EggCharacterData *char_data); + +public: + EggCharacterData *make_character(const string &character_name); + + class EggInfo { + public: + PT(EggData) _egg; + typedef vector Models; + Models _models; + }; + + typedef vector Eggs; + Eggs _eggs; + + typedef vector Characters; + Characters _characters; + +private: + bool scan_hierarchy(EggNode *egg_node); + void scan_for_top_joints(EggNode *egg_node, EggNode *model_root, + const string &character_name); + void scan_for_top_tables(EggTable *bundle, EggNode *model_root, + const string &character_name); + void scan_for_morphs(EggNode *egg_node, int model_index, + EggCharacterData *char_data); + void scan_for_sliders(EggNode *egg_node, int model_index, + EggCharacterData *char_data); + + void add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object, + int model_index, EggCharacterData *char_data); + + typedef vector EggNodeList; + typedef map TopEggNodes; + typedef map TopEggNodesByName; + TopEggNodesByName _top_egg_nodes; + + int _next_model_index; + + void match_egg_nodes(EggCharacterData *char_Data, EggJointData *joint_data, + EggNodeList &egg_nodes, int egg_index, int model_index); + void found_egg_match(EggCharacterData *char_data, EggJointData *joint_data, + EggNode *egg_node, int egg_index, int model_index); +}; + +#include "eggCharacterCollection.I" + +#endif + + diff --git a/pandatool/src/eggcharbase/eggCharacterData.I b/pandatool/src/eggcharbase/eggCharacterData.I new file mode 100644 index 0000000000..3cfc23b2ad --- /dev/null +++ b/pandatool/src/eggcharbase/eggCharacterData.I @@ -0,0 +1,20 @@ +// Filename: eggCharacterData.I +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::get_root_joint +// Access: Public +// Description: Returns the root joint of the character hierarchy. +// This root joint does not represent an actual joint in +// the hierarchy, but instead is a fictitious joint that +// is the parent of all the top joints in the hierarchy +// (since the hierarchy may actually contain zero or +// more top joints). +//////////////////////////////////////////////////////////////////// +INLINE EggJointData *EggCharacterData:: +get_root_joint() const { + return _root_joint; +} diff --git a/pandatool/src/eggcharbase/eggCharacterData.cxx b/pandatool/src/eggcharbase/eggCharacterData.cxx new file mode 100644 index 0000000000..edb5cc33c0 --- /dev/null +++ b/pandatool/src/eggcharbase/eggCharacterData.cxx @@ -0,0 +1,76 @@ +// Filename: eggCharacterData.cxx +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggCharacterData.h" +#include "eggCharacterCollection.h" +#include "eggJointData.h" +#include "eggSliderData.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggCharacterData:: +EggCharacterData(EggCharacterCollection *collection) { + _collection = collection; + _root_joint = _collection->make_joint_data(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +EggCharacterData:: +~EggCharacterData() { + delete _root_joint; + + Sliders::iterator si; + for (si = _sliders.begin(); si != _sliders.end(); ++si) { + EggSliderData *slider = (*si).second; + delete slider; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::make_slider +// Access: Public +// Description: Returns the slider matching the indicated name. If +// no such slider exists already, creates a new one. +//////////////////////////////////////////////////////////////////// +EggSliderData *EggCharacterData:: +make_slider(const string &name) { + Sliders::iterator si; + si = _sliders.find(name); + if (si != _sliders.end()) { + return (*si).second; + } + + EggSliderData *slider = _collection->make_slider_data(this); + slider->set_name(name); + _sliders.insert(Sliders::value_type(name, slider)); + return slider; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void EggCharacterData:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << "Character " << get_name() << ":\n"; + get_root_joint()->write(out, indent_level + 2); + + Sliders::const_iterator si; + for (si = _sliders.begin(); si != _sliders.end(); ++si) { + EggSliderData *slider = (*si).second; + slider->write(out, indent_level + 2); + } +} diff --git a/pandatool/src/eggcharbase/eggCharacterData.h b/pandatool/src/eggcharbase/eggCharacterData.h new file mode 100644 index 0000000000..d9194d29cf --- /dev/null +++ b/pandatool/src/eggcharbase/eggCharacterData.h @@ -0,0 +1,66 @@ +// Filename: eggCharacterData.h +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGCHARACTERDATA_H +#define EGGCHARACTERDATA_H + +#include + +#include + +#include + +class EggCharacterCollection; +class EggJointData; +class EggSliderData; + +//////////////////////////////////////////////////////////////////// +// Class : EggCharacterData +// Description : Represents a single character, as read and collected +// from several models and animation files. This +// contains a hierarchy of EggJointData nodes +// representing the skeleton, as well as a list of +// EggSliderData nodes representing the morph channels +// for the character. +// +// This is very similar to the Character class from +// Panda, in that it's capable of associating +// skeleton-morph animation channels with models and +// calculating the vertex position for each frame. To +// some degree, it duplicates the functionality of +// Character. However, it differs in one fundamental +// principle: it is designed to be a non-real-time +// operation, working directly on the Egg structures as +// they are, instead of first boiling the Egg data into +// native Panda Geom tables for real-time animation. +// Because of this, it is (a) double-precision instead +// of single precision, (b) capable of generating +// modified Egg files, and (c) about a hundred times +// slower than the Panda Character class. +//////////////////////////////////////////////////////////////////// +class EggCharacterData : public Namable { +public: + EggCharacterData(EggCharacterCollection *collection); + virtual ~EggCharacterData(); + + INLINE EggJointData *get_root_joint() const; + + EggSliderData *make_slider(const string &name); + + virtual void write(ostream &out, int indent_level = 0) const; + +protected: + EggCharacterCollection *_collection; + EggJointData *_root_joint; + + typedef map Sliders; + Sliders _sliders; +}; + +#include "eggCharacterData.I" + +#endif + + diff --git a/pandatool/src/eggbase/eggCharacterFilter.cxx b/pandatool/src/eggcharbase/eggCharacterFilter.cxx similarity index 67% rename from pandatool/src/eggbase/eggCharacterFilter.cxx rename to pandatool/src/eggcharbase/eggCharacterFilter.cxx index 44557953d4..5006665242 100644 --- a/pandatool/src/eggbase/eggCharacterFilter.cxx +++ b/pandatool/src/eggcharbase/eggCharacterFilter.cxx @@ -4,7 +4,7 @@ //////////////////////////////////////////////////////////////////// #include "eggCharacterFilter.h" -#include "eggCharacterData.h" +#include "eggCharacterCollection.h" //////////////////////////////////////////////////////////////////// @@ -14,7 +14,7 @@ //////////////////////////////////////////////////////////////////// EggCharacterFilter:: EggCharacterFilter() : EggMultiFilter(false) { - _character_data = (EggCharacterData *)NULL; + _collection = (EggCharacterCollection *)NULL; } //////////////////////////////////////////////////////////////////// @@ -24,8 +24,8 @@ EggCharacterFilter() : EggMultiFilter(false) { //////////////////////////////////////////////////////////////////// EggCharacterFilter:: ~EggCharacterFilter() { - if (_character_data != (EggCharacterData *)NULL) { - delete _character_data; + if (_collection != (EggCharacterCollection *)NULL) { + delete _collection; } } @@ -37,8 +37,8 @@ EggCharacterFilter:: //////////////////////////////////////////////////////////////////// bool EggCharacterFilter:: post_command_line() { - if (_character_data == (EggCharacterData *)NULL) { - _character_data = make_character_data(); + if (_collection == (EggCharacterCollection *)NULL) { + _collection = make_collection(); } if (!EggMultiFilter::post_command_line()) { @@ -49,27 +49,28 @@ post_command_line() { for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { EggData *data = (*ei); - if (!_character_data->add_egg(data)) { + if (!_collection->add_egg(data)) { nout << data->get_egg_filename().get_basename() << " does not contain a character model or animation channel.\n"; return false; } } - _character_data->write(cerr); + _collection->write(cerr); return true; } //////////////////////////////////////////////////////////////////// -// Function: EggCharacterFilter::make_character_data +// Function: EggCharacterFilter::make_collection // Access: Protected, Virtual -// Description: Allocates and returns a new EggCharacterData structure. -// This is primarily intended as a hook so derived -// classes can customize the type of EggCharacterData nodes -// used to represent the character information. +// Description: Allocates and returns a new EggCharacterCollection +// structure. This is primarily intended as a hook so +// derived classes can customize the type of +// EggCharacterCollection object used to represent the +// character information. //////////////////////////////////////////////////////////////////// -EggCharacterData *EggCharacterFilter:: -make_character_data() { - return new EggCharacterData; +EggCharacterCollection *EggCharacterFilter:: +make_collection() { + return new EggCharacterCollection; } diff --git a/pandatool/src/eggbase/eggCharacterFilter.h b/pandatool/src/eggcharbase/eggCharacterFilter.h similarity index 90% rename from pandatool/src/eggbase/eggCharacterFilter.h rename to pandatool/src/eggcharbase/eggCharacterFilter.h index f3c2b155cb..fa1e665c67 100644 --- a/pandatool/src/eggbase/eggCharacterFilter.h +++ b/pandatool/src/eggcharbase/eggCharacterFilter.h @@ -11,6 +11,7 @@ #include "eggMultiFilter.h" class EggCharacterData; +class EggCharacterCollection; //////////////////////////////////////////////////////////////////// // Class : EggCharacterFilter @@ -31,9 +32,9 @@ public: protected: virtual bool post_command_line(); - virtual EggCharacterData *make_character_data(); + virtual EggCharacterCollection *make_collection(); - EggCharacterData *_character_data; + EggCharacterCollection *_collection; }; #endif diff --git a/pandatool/src/eggcharbase/eggComponentData.I b/pandatool/src/eggcharbase/eggComponentData.I new file mode 100644 index 0000000000..02d1cfb81a --- /dev/null +++ b/pandatool/src/eggcharbase/eggComponentData.I @@ -0,0 +1,49 @@ +// Filename: eggComponentData.I +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: EggComponentData::get_num_back_pointers +// Access: Public +// Description: Returns the maximum number of back pointers this +// component may have. The component may store a back +// pointer for models indexed 0 .. num_back_pointers - +// 1. You must call has_back_pointer() on each model +// index to confirm whether a particular model in that +// range has a back pointer. +//////////////////////////////////////////////////////////////////// +INLINE int EggComponentData:: +get_num_back_pointers() const { + return _back_pointers.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggComponentData::has_back_pointer +// Access: Public +// Description: Returns true if the component has a back pointer to +// an egg file somewhere for the indicated model, false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool EggComponentData:: +has_back_pointer(int model_index) const { + if (model_index >= 0 && model_index < (int)_back_pointers.size()) { + return _back_pointers[model_index] != (EggBackPointer *)NULL; + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggComponentData::get_back_pointer +// Access: Public +// Description: Returns the back pointer to an egg file for the +// indicated model if it exists, or NULL if it does not. +//////////////////////////////////////////////////////////////////// +INLINE EggBackPointer *EggComponentData:: +get_back_pointer(int model_index) const { + if (model_index >= 0 && model_index < (int)_back_pointers.size()) { + return _back_pointers[model_index]; + } + return (EggBackPointer *)NULL; +} diff --git a/pandatool/src/eggcharbase/eggComponentData.cxx b/pandatool/src/eggcharbase/eggComponentData.cxx new file mode 100644 index 0000000000..4aad1618ee --- /dev/null +++ b/pandatool/src/eggcharbase/eggComponentData.cxx @@ -0,0 +1,87 @@ +// Filename: eggComponentData.cxx +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggComponentData.h" +#include "eggBackPointer.h" + +#include + + +//////////////////////////////////////////////////////////////////// +// Function: EggComponentData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggComponentData:: +EggComponentData(EggCharacterCollection *collection, + EggCharacterData *char_data) : + _collection(collection), + _char_data(char_data) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: EggComponentData::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +EggComponentData:: +~EggComponentData() { + BackPointers::iterator bpi; + for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { + EggBackPointer *back = (*bpi); + if (back != (EggBackPointer *)NULL) { + delete back; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggComponentData::add_name +// Access: Public +// Description: Adds the indicated name to the set of names that this +// component can be identified with. If this is the +// first name added, it becomes the primary name of the +// component; later names added do not replace the +// primary name, but do get added to the list of names +// that will be accepted by matched_name(). +//////////////////////////////////////////////////////////////////// +void EggComponentData:: +add_name(const string &name) { + if (!has_name()) { + set_name(name); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggComponentData::matches_name +// Access: Public +// Description: Returns true if the indicated name matches any name +// that was ever matched with this particular joint, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool EggComponentData:: +matches_name(const string &name) const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggComponentData::set_back_pointer +// Access: Public +// Description: Sets the back_pointer associated with the given +// model_index. +//////////////////////////////////////////////////////////////////// +void EggComponentData:: +set_back_pointer(int model_index, EggBackPointer *back) { + while ((int)_back_pointers.size() <= model_index) { + _back_pointers.push_back((EggBackPointer *)NULL); + } + + if (_back_pointers[model_index] != (EggBackPointer *)NULL) { + nout << "Warning: deleting old back pointer.\n"; + delete _back_pointers[model_index]; + } + _back_pointers[model_index] = back; +} diff --git a/pandatool/src/eggcharbase/eggComponentData.h b/pandatool/src/eggcharbase/eggComponentData.h new file mode 100644 index 0000000000..791d120a02 --- /dev/null +++ b/pandatool/src/eggcharbase/eggComponentData.h @@ -0,0 +1,59 @@ +// Filename: eggComponentData.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGCOMPONENTDATA_H +#define EGGCOMPONENTDATA_H + +#include + +#include + +class EggCharacterCollection; +class EggCharacterData; +class EggBackPointer; +class EggObject; + +//////////////////////////////////////////////////////////////////// +// Class : EggComponentData +// Description : This is the base class of both EggJointData and +// EggSliderData. It represents a single component of a +// character, either a joint or a slider, along with +// back pointers to the references to this component in +// all model and animation egg files read. +//////////////////////////////////////////////////////////////////// +class EggComponentData : public Namable { +public: + EggComponentData(EggCharacterCollection *collection, + EggCharacterData *char_data); + virtual ~EggComponentData(); + + void add_name(const string &name); + bool matches_name(const string &name) const; + + virtual void add_back_pointer(int model_index, EggObject *egg_object)=0; + virtual void write(ostream &out, int indent_level = 0) const=0; + + INLINE int get_num_back_pointers() const; + INLINE bool has_back_pointer(int model_index) const; + INLINE EggBackPointer *get_back_pointer(int model_index) const; + void set_back_pointer(int model_index, EggBackPointer *back); + +protected: + + // This points back to all the egg structures that reference this + // particular table or slider. + typedef vector BackPointers; + BackPointers _back_pointers; + + + EggCharacterCollection *_collection; + EggCharacterData *_char_data; +}; + +#include "eggComponentData.I" + +#endif + + diff --git a/pandatool/src/eggbase/eggJointData.I b/pandatool/src/eggcharbase/eggJointData.I similarity index 100% rename from pandatool/src/eggbase/eggJointData.I rename to pandatool/src/eggcharbase/eggJointData.I diff --git a/pandatool/src/eggcharbase/eggJointData.cxx b/pandatool/src/eggcharbase/eggJointData.cxx new file mode 100644 index 0000000000..b422df1900 --- /dev/null +++ b/pandatool/src/eggcharbase/eggJointData.cxx @@ -0,0 +1,74 @@ +// Filename: eggJointData.cxx +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggJointData.h" +#include "eggJointPointer.h" +#include "eggMatrixTablePointer.h" + +#include +#include +#include + + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggJointData:: +EggJointData(EggCharacterCollection *collection, + EggCharacterData *char_data) : + EggComponentData(collection, char_data) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::add_back_pointer +// Access: Public, Virtual +// Description: Adds the indicated model joint or anim table to the +// data. +//////////////////////////////////////////////////////////////////// +void EggJointData:: +add_back_pointer(int model_index, EggObject *egg_object) { + if (egg_object->is_of_type(EggGroup::get_class_type())) { + // It must be a . + EggJointPointer *joint = new EggJointPointer(egg_object); + set_back_pointer(model_index, joint); + + } else if (egg_object->is_of_type(EggTable::get_class_type())) { + // It's a
with an "xform" child beneath it. + EggMatrixTablePointer *xform = new EggMatrixTablePointer(egg_object); + set_back_pointer(model_index, xform); + + } else { + nout << "Invalid object added to joint for back pointer.\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void EggJointData:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << "Joint " << get_name() + << " (models:"; + int num_back_pointers = get_num_back_pointers(); + for (int model_index = 0; model_index < num_back_pointers; model_index++) { + if (has_back_pointer(model_index)) { + out << " " << model_index; + } + } + out << ") {\n"; + + Children::const_iterator ci; + for (ci = _children.begin(); ci != _children.end(); ++ci) { + (*ci)->write(out, indent_level + 2); + } + + indent(out, indent_level) << "}\n"; +} diff --git a/pandatool/src/eggbase/eggJointData.h b/pandatool/src/eggcharbase/eggJointData.h similarity index 59% rename from pandatool/src/eggbase/eggJointData.h rename to pandatool/src/eggcharbase/eggJointData.h index 8969a121f8..278846eb29 100644 --- a/pandatool/src/eggbase/eggJointData.h +++ b/pandatool/src/eggcharbase/eggJointData.h @@ -8,11 +8,7 @@ #include -#include -#include -#include - -class EggGroup; +#include "eggComponentData.h" //////////////////////////////////////////////////////////////////// // Class : EggJointData @@ -22,42 +18,24 @@ class EggGroup; // various models, the LOD's of each model, and the // various animation channel files. //////////////////////////////////////////////////////////////////// -class EggJointData : public Namable { +class EggJointData : public EggComponentData { public: - EggJointData(); - virtual ~EggJointData(); + EggJointData(EggCharacterCollection *collection, + EggCharacterData *char_data); INLINE int get_num_children() const; INLINE EggJointData *get_child(int n) const; - bool matches_name(const string &name) const; - void add_egg_node(int egg_index, int model_index, EggNode *egg_node); - + virtual void add_back_pointer(int model_index, EggObject *egg_object); virtual void write(ostream &out, int indent_level = 0) const; protected: - typedef vector JointNodes; - typedef vector Joints; - - Joints _tables; - // _tables[i][anim] is the table for the animth bundle of the ith - // file. - - Joints _joints; - // _joints[i][model] is the joint for the modelth lod of the ith - // file. - - LMatrix4d _rest_transform; - LMatrix4d _net_rest_transform; - typedef vector Children; Children _children; - friend class EggCharacterData; + friend class EggCharacterCollection; }; #include "eggJointData.I" #endif - - diff --git a/pandatool/src/eggcharbase/eggJointPointer.cxx b/pandatool/src/eggcharbase/eggJointPointer.cxx new file mode 100644 index 0000000000..88151cec77 --- /dev/null +++ b/pandatool/src/eggcharbase/eggJointPointer.cxx @@ -0,0 +1,19 @@ +// Filename: eggJointPointer.cxx +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggJointPointer.h" + + +TypeHandle EggJointPointer::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: EggJointPointer::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggJointPointer:: +EggJointPointer(EggObject *object) { + _joint = DCAST(EggGroup, object); +} diff --git a/pandatool/src/eggcharbase/eggJointPointer.h b/pandatool/src/eggcharbase/eggJointPointer.h new file mode 100644 index 0000000000..1f13dc8804 --- /dev/null +++ b/pandatool/src/eggcharbase/eggJointPointer.h @@ -0,0 +1,47 @@ +// Filename: eggJointPointer.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGJOINTPOINTER_H +#define EGGJOINTPOINTER_H + +#include + +#include "eggBackPointer.h" + +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : EggJointPointer +// Description : This stores a pointer back to a node. +//////////////////////////////////////////////////////////////////// +class EggJointPointer : public EggBackPointer { +public: + EggJointPointer(EggObject *object); + +private: + PT(EggGroup) _joint; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + EggBackPointer::init_type(); + register_type(_type_handle, "EggJointPointer", + EggBackPointer::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/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx new file mode 100644 index 0000000000..40f8444941 --- /dev/null +++ b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx @@ -0,0 +1,45 @@ +// Filename: eggMatrixTablePointer.cxx +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggMatrixTablePointer.h" + +#include +#include + +TypeHandle EggMatrixTablePointer::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: EggMatrixTablePointer::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggMatrixTablePointer:: +EggMatrixTablePointer(EggObject *object) { + _table = DCAST(EggTable, object); + + if (_table != (EggTable *)NULL) { + // Now search for the child named "xform". This contains the + // actual table data. + EggGroupNode::iterator ci; + bool found = false; + for (ci = _table->begin(); ci != _table->end() && !found; ++ci) { + EggNode *child = (*ci); + if (child->get_name() == "xform") { + if (child->is_of_type(EggXfmSAnim::get_class_type())) { + _xform = DCAST(EggXfmSAnim, child); + found = true; + + } else if (child->is_of_type(EggXfmAnimData::get_class_type())) { + // Quietly replace old-style XfmAnim tables with new-style + // XfmSAnim tables. + PT(EggXfmAnimData) anim = DCAST(EggXfmAnimData, child); + _xform = new EggXfmSAnim(*anim); + _table->replace(ci, _xform.p()); + found = true; + } + } + } + } +} diff --git a/pandatool/src/eggcharbase/eggMatrixTablePointer.h b/pandatool/src/eggcharbase/eggMatrixTablePointer.h new file mode 100644 index 0000000000..c9865270db --- /dev/null +++ b/pandatool/src/eggcharbase/eggMatrixTablePointer.h @@ -0,0 +1,52 @@ +// Filename: eggMatrixTablePointer.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGMATRIXTABLEPOINTER_H +#define EGGMATRIXTABLEPOINTER_H + +#include + +#include "eggBackPointer.h" + +#include +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : EggMatrixTablePointer +// Description : This stores a pointer back to an EggXfmSAnim table +// (i.e. an entry in an egg file), +// corresponding to the animation data from a single +// bundle for this joint. +//////////////////////////////////////////////////////////////////// +class EggMatrixTablePointer : public EggBackPointer { +public: + EggMatrixTablePointer(EggObject *object); + +private: + PT(EggTable) _table; + PT(EggXfmSAnim) _xform; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + EggBackPointer::init_type(); + register_type(_type_handle, "EggMatrixTablePointer", + EggBackPointer::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/pandatool/src/eggcharbase/eggSliderData.I b/pandatool/src/eggcharbase/eggSliderData.I new file mode 100644 index 0000000000..b90620716c --- /dev/null +++ b/pandatool/src/eggcharbase/eggSliderData.I @@ -0,0 +1,4 @@ +// Filename: eggSliderData.I +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/eggcharbase/eggSliderData.cxx b/pandatool/src/eggcharbase/eggSliderData.cxx new file mode 100644 index 0000000000..d81e846c56 --- /dev/null +++ b/pandatool/src/eggcharbase/eggSliderData.cxx @@ -0,0 +1,80 @@ +// Filename: eggSliderData.cxx +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggSliderData.h" +#include "eggVertexPointer.h" + +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////// +// Function: EggSliderData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggSliderData:: +EggSliderData(EggCharacterCollection *collection, + EggCharacterData *char_data) : + EggComponentData(collection, char_data) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: EggSliderData::add_back_pointer +// Access: Public, Virtual +// Description: Adds the indicated vertex, primitive, or morph table +// to the data. +//////////////////////////////////////////////////////////////////// +void EggSliderData:: +add_back_pointer(int model_index, EggObject *egg_object) { + if (egg_object->is_of_type(EggPrimitive::get_class_type())) { + // A primitive! + EggBackPointer *back = get_back_pointer(model_index); + if (back == (EggBackPointer *)NULL) { + back = new EggVertexPointer; + set_back_pointer(model_index, back); + } + + } else if (egg_object->is_of_type(EggVertex::get_class_type())) { + // A vertex! + EggBackPointer *back = get_back_pointer(model_index); + if (back == (EggBackPointer *)NULL) { + back = new EggVertexPointer; + set_back_pointer(model_index, back); + } + + } else if (egg_object->is_of_type(EggSAnimData::get_class_type())) { + // A slider animation table! Woo hoo! + EggBackPointer *back = get_back_pointer(model_index); + if (back == (EggBackPointer *)NULL) { + back = new EggVertexPointer; + set_back_pointer(model_index, back); + } + + } else { + nout << "Invalid object added to slider for back pointer.\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggSliderData::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void EggSliderData:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << "Slider " << get_name() + << " (models:"; + int num_back_pointers = get_num_back_pointers(); + for (int model_index = 0; model_index < num_back_pointers; model_index++) { + if (has_back_pointer(model_index)) { + out << " " << model_index; + } + } + out << ")\n"; +} diff --git a/pandatool/src/eggcharbase/eggSliderData.h b/pandatool/src/eggcharbase/eggSliderData.h new file mode 100644 index 0000000000..acab2726f6 --- /dev/null +++ b/pandatool/src/eggcharbase/eggSliderData.h @@ -0,0 +1,35 @@ +// Filename: eggSliderData.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGSLIDERDATA_H +#define EGGSLIDERDATA_H + +#include + +#include "eggComponentData.h" + + +//////////////////////////////////////////////////////////////////// +// Class : EggSliderData +// Description : This corresponds to a single morph slider control. +// It contains back pointers to all the vertices and +// primitives that reference this slider across all +// models, as well as all the tables in which it appears +// in all animation files. +//////////////////////////////////////////////////////////////////// +class EggSliderData : public EggComponentData { +public: + EggSliderData(EggCharacterCollection *collection, + EggCharacterData *char_data); + + virtual void add_back_pointer(int model_index, EggObject *egg_object); + virtual void write(ostream &out, int indent_level = 0) const; +}; + +#include "eggSliderData.I" + +#endif + + diff --git a/pandatool/src/eggcharbase/eggVertexPointer.cxx b/pandatool/src/eggcharbase/eggVertexPointer.cxx new file mode 100644 index 0000000000..99808f56e3 --- /dev/null +++ b/pandatool/src/eggcharbase/eggVertexPointer.cxx @@ -0,0 +1,18 @@ +// Filename: eggVertexPointer.cxx +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggVertexPointer.h" + + +TypeHandle EggVertexPointer::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: EggVertexPointer::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggVertexPointer:: +EggVertexPointer() { +} diff --git a/pandatool/src/eggcharbase/eggVertexPointer.h b/pandatool/src/eggcharbase/eggVertexPointer.h new file mode 100644 index 0000000000..ceded40e3c --- /dev/null +++ b/pandatool/src/eggcharbase/eggVertexPointer.h @@ -0,0 +1,46 @@ +// Filename: eggVertexPointer.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGVERTEXPOINTER_H +#define EGGVERTEXPOINTER_H + +#include + +#include "eggBackPointer.h" + +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : EggVertexPointer +// Description : This stores a pointer back to a , or to a +// particular pritimive like a , representing a +// morph offset. +//////////////////////////////////////////////////////////////////// +class EggVertexPointer : public EggBackPointer { +public: + EggVertexPointer(); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + EggBackPointer::init_type(); + register_type(_type_handle, "EggVertexPointer", + EggBackPointer::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/pandatool/src/eggprogs/Sources.pp b/pandatool/src/eggprogs/Sources.pp index 75706996f4..8d0db5ccf0 100644 --- a/pandatool/src/eggprogs/Sources.pp +++ b/pandatool/src/eggprogs/Sources.pp @@ -22,6 +22,7 @@ #end bin_target #begin noinst_bin_target + #define LOCAL_LIBS eggcharbase $[LOCAL_LIBS] #define TARGET egg-topstrip #define SOURCES \