38 EggCharacterCollection::
    39 EggCharacterCollection() {
    40   _next_model_index = 0;
    46 EggCharacterCollection::
    47 ~EggCharacterCollection() {
    48   Characters::iterator ci;
    50   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
    68   _top_egg_nodes.clear();
    70   if (!scan_hierarchy(egg)) {
    74   int egg_index = _eggs.size();
    76   EggInfo &egg_info = _eggs.back();
    78   egg_info._first_model_index = 0;
    82   TopEggNodesByName::iterator tni;
    83   for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) {
    84     string character_name = (*tni).first;
    89     TopEggNodes::iterator ti;
    90     for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) {
    91       EggNode *model_root = (*ti).first;
    92       ModelDescription &desc = (*ti).second;
    94       int model_index = _next_model_index++;
    95       if (egg_info._models.empty()) {
    96         egg_info._first_model_index = model_index;
    98       egg_info._models.push_back(model_root);
   100       char_data->
add_model(model_index, model_root, egg);
   101       nassertr(model_index == (
int)_characters_by_model_index.size(), -1);
   102       _characters_by_model_index.push_back(char_data);
   105       match_egg_nodes(char_data, root_joint, desc._top_nodes,
   106                       egg_index, model_index);
   108       scan_for_morphs(model_root, model_index, char_data);
   109       scan_for_sliders(model_root, model_index, char_data);
   122   Characters::const_iterator ci;
   123   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
   125     if (char_data->get_name() == character_name) {
   173   Characters::iterator ci;
   174   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
   176     if (char_data->get_name() == character_name) {
   183   char_data->set_name(character_name);
   184   _characters.push_back(char_data);
   196 bool EggCharacterCollection::
   197 scan_hierarchy(
EggNode *egg_node) {
   198   if (egg_node->
is_of_type(EggGroup::get_class_type())) {
   200     if (group->get_dart_type() != EggGroup::DT_none) {
   202       scan_for_top_joints(group, group, group->get_name());
   206   } 
else if (egg_node->
is_of_type(EggTable::get_class_type())) {
   208     if (table->get_table_type() == EggTable::TT_bundle) {
   210       scan_for_top_tables(table, table, table->get_name());
   215   bool character_found = 
false;
   216   if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
   218     EggGroupNode::iterator gi;
   219     for (gi = group->begin(); gi != group->end(); ++gi) {
   220       if (scan_hierarchy(*gi)) {
   221         character_found = 
true;
   226   return character_found;
   233 void EggCharacterCollection::
   235                     const string &character_name) {
   236   if (egg_node->
is_of_type(EggGroup::get_class_type())) {
   239     if (group->has_lod()) {
   245     if (group->get_group_type() == EggGroup::GT_joint) {
   247       ModelDescription &desc = _top_egg_nodes[character_name][model_root];
   248       desc._root_node = model_root;
   249       desc._top_nodes.push_back(group);
   254   if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
   256     EggGroupNode::iterator gi;
   257     for (gi = group->begin(); gi != group->end(); ++gi) {
   258       scan_for_top_joints(*gi, model_root, character_name);
   267 void EggCharacterCollection::
   269                     const string &character_name) {
   272   EggGroupNode::iterator gi;
   273   for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
   275     if (child->
is_of_type(EggTable::get_class_type())) {
   277       if (table->get_name() == 
"<skeleton>") {
   280         ModelDescription &desc = _top_egg_nodes[character_name][model_root];
   281         desc._root_node = table;
   283         EggGroupNode::iterator cgi;
   284         for (cgi = table->begin(); cgi != table->end(); ++cgi) {
   286           if (grandchild->
is_of_type(EggTable::get_class_type())) {
   287             desc._top_nodes.push_back(grandchild);
   299 void EggCharacterCollection::
   300 scan_for_morphs(
EggNode *egg_node, 
int model_index,
   302   if (egg_node->
is_of_type(EggPrimitive::get_class_type())) {
   305     add_morph_back_pointers(prim, prim, model_index, char_data);
   308     EggPrimitive::const_iterator vi;
   309     for (vi = prim->begin(); vi != prim->end(); ++vi) {
   312       add_morph_back_pointers(vertex, vertex, model_index, char_data);
   313       add_morph_back_pointers_vertex(vertex, vertex, model_index, char_data);
   315       EggMorphVertexList::const_iterator mvi;
   316       for (mvi = vertex->_dxyzs.begin();
   317            mvi != vertex->_dxyzs.end();
   320         char_data->
make_slider(morph.get_name())->add_back_pointer(model_index, vertex);
   325   if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
   327     EggGroupNode::iterator gi;
   328     for (gi = group->begin(); gi != group->end(); ++gi) {
   329       scan_for_morphs(*gi, model_index, char_data);
   338 void EggCharacterCollection::
   339 scan_for_sliders(
EggNode *egg_node, 
int model_index,
   341   if (egg_node->
is_of_type(EggTable::get_class_type())) {
   349     EggGroupNode::iterator gi;
   350     for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
   352       if (child->
is_of_type(EggTable::get_class_type())) {
   354         if (table->get_name() == 
"morph") {
   358           EggGroupNode::iterator cgi;
   359           for (cgi = table->begin(); cgi != table->end(); ++cgi) {
   361             if (grandchild->
is_of_type(EggSAnimData::get_class_type())) {
   362               char_data->
make_slider(grandchild->get_name())->add_back_pointer(model_index, grandchild);
   375 void EggCharacterCollection::
   378   EggMorphNormalList::const_iterator mni;
   379   for (mni = attrib->_dnormals.begin();
   380        mni != attrib->_dnormals.end();
   383     char_data->
make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
   386   EggMorphColorList::const_iterator mci;
   387   for (mci = attrib->_drgbas.begin();
   388        mci != attrib->_drgbas.end();
   391     char_data->
make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
   399 void EggCharacterCollection::
   405     EggMorphTexCoordList::const_iterator mti;
   406     for (mti = vert_uv->_duvs.begin();
   407          mti != vert_uv->_duvs.end();
   410       char_data->
make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
   421 void EggCharacterCollection::
   423                 EggNodeList &egg_nodes, 
int egg_index, 
int model_index) {
   428   if (joint_data->_children.empty()) {
   431     EggNodeList::iterator ei;
   432     for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) {
   435       joint_data->_children.push_back(data);
   436       char_data->_joints.push_back(data);
   437       char_data->_components.push_back(data);
   438       data->_parent = joint_data;
   439       data->_new_parent = joint_data;
   440       found_egg_match(char_data, data, egg_node, egg_index, model_index);
   447     EggNodeList extra_egg_nodes;
   450     EggNodeList::iterator ei;
   451     EggJointData::Children::iterator di;
   453     ei = egg_nodes.begin();
   454     di = joint_data->_children.begin();
   456     while (ei != egg_nodes.end() && di != joint_data->_children.end()) {
   460       if (egg_node->get_name() < data->get_name()) {
   462         extra_egg_nodes.push_back(egg_node);
   465       } 
else if (data->get_name() < egg_node->get_name()) {
   467         extra_data.push_back(data);
   472         found_egg_match(char_data, data, egg_node, egg_index, model_index);
   478     while (ei != egg_nodes.end()) {
   482       extra_egg_nodes.push_back(egg_node);
   486     while (di != joint_data->_children.end()) {
   490       extra_data.push_back(data);
   494     if (!extra_egg_nodes.empty()) {
   499       EggNodeList more_egg_nodes;
   501       for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
   503         bool matched = 
false;
   504         for (di = extra_data.begin(); di != extra_data.end(); ++di) {
   506           if (data->matches_name(egg_node->get_name())) {
   507             found_egg_match(char_data, data, egg_node, egg_index, model_index);
   508             extra_data.erase(di);
   516           more_egg_nodes.push_back(egg_node);
   519       extra_egg_nodes.swap(more_egg_nodes);
   522     if (!extra_egg_nodes.empty()) {
   524       if (extra_egg_nodes.size() == extra_data.size()) {
   527         for (i = 0; i < extra_egg_nodes.size(); i++) {
   528           EggNode *egg_node = extra_egg_nodes[i];
   530           found_egg_match(char_data, data, egg_node, egg_index, model_index);
   535         EggNodeList::iterator ei;
   536         for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
   539           joint_data->_children.push_back(data);
   540           char_data->_joints.push_back(data);
   541           char_data->_components.push_back(data);
   542           data->_parent = joint_data;
   543           data->_new_parent = joint_data;
   544           found_egg_match(char_data, data, egg_node, egg_index, model_index);
   551   sort(joint_data->_children.begin(), joint_data->_children.end(),
   559 void EggCharacterCollection::
   561                 EggNode *egg_node, 
int egg_index, 
int model_index) {
   563     joint_data->
add_name(egg_node->get_name(), char_data->_component_names);
   565   egg_node->set_name(joint_data->get_name());
   568   if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
   573     EggNodeList egg_nodes;
   578     if (egg_node->
is_of_type(EggGroup::get_class_type())) {
   580       EggGroupNode::iterator gi;
   581       for (gi = group_node->begin(); gi != group_node->end(); ++gi) {
   583         if (child->
is_of_type(EggGroup::get_class_type())) {
   585           if (group->get_group_type() == EggGroup::GT_joint) {
   586             egg_nodes.push_back(group);
   593       EggGroupNode::iterator gi;
   594       for (gi = group_node->begin(); gi != group_node->end(); ++gi) {
   596         if (child->
is_of_type(EggTable::get_class_type())) {
   598           if (!(table->get_name() == 
"xform")) {
   599             egg_nodes.push_back(table);
   605     if (!egg_nodes.empty()) {
   606       match_egg_nodes(char_data, joint_data, egg_nodes,
   607                       egg_index, model_index);
   618   nassertv(i >= 0 && i < (
int)_characters.size());
   621   if (char_data->get_name() != name) {
   623     char_data->rename_char(name);
   630 void EggCharacterCollection::
   631 write(std::ostream &out, 
int indent_level)
 const {
   632   Characters::const_iterator ci;
   634   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
   636     char_data->write(out, indent_level);
   652   Characters::const_iterator ci;
   653   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
   656     for (
int j = 0; j < num_joints; j++) {
   659         if (force_initial_rest_frame) {
   661           out << 
"Forced rest frames the same for " << joint_data->get_name()
   664           out << 
"Warning: rest frames for " << joint_data->get_name()
   671     for (
int mi = 0; mi < num_models; mi++) {
   674         out << 
"Warning: animation from "   676             << 
" had an inconsistent number of frames.\n";
 A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
The set of UV's that may or may not be assigned to a vertex.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual EggCharacterData * make_character_data()
Allocates and returns a new EggCharacterData structure.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_num_joints() const
Returns the total number of joints in the character joint hierarchy.
void rename_char(int i, const std::string &name)
Renames the ith character to the indicated name.
This is our own Panda specialization on the default STL map.
void add_name(const std::string &name, NameUniquifier &uniquifier)
Adds the indicated name to the set of names that this component can be identified with.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggJointData * get_root_joint() const
Returns the root joint of the character hierarchy.
bool check_num_frames(int model_index)
Walks through each component and ensures that all have the same number of frames of animation (except...
EggCharacterData * make_character(const std::string &character_name)
Allocates and returns a new EggCharacterData object representing the named character,...
A base class for nodes in the hierarchy that are not leaf nodes.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_egg_filename
Returns the directory in which the egg file is considered to reside.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This corresponds to a single morph slider control.
int add_egg(EggData *egg)
Adds a new egg file to the list of models and animation files for this particular character.
int get_num_models() const
Returns the total number of models associated with this character.
A single <Dxyz> or <Duv> or some such entry.
This is the primary interface into all the egg data, and the root of the egg file structure.
bool rest_frames_differ() const
Returns true if the rest frames for different models differ in their initial value.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggData * get_egg_data(int n) const
Returns the EggData representing the egg file that defined this particular model.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggCharacterData * get_character_by_name(const std::string &character_name) const
Returns the Character with the indicated name, if it exists in the collection, or NULL if it does not...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
The set of attributes that may be applied to vertices as well as polygons, such as surface normal and...
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a single character, as read and collected from several models and animation files.
EggSliderData * make_slider(const std::string &name)
Returns the slider matching the indicated name.
This is one node of a hierarchy of EggJointData nodes, each of which represents a single joint of the...
virtual void add_back_pointer(int model_index, EggObject *egg_object)
Adds the indicated model joint or anim table to the data.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual EggSliderData * make_slider_data(EggCharacterData *char_data)
Allocates and returns a new EggSliderData structure for the given character.
EggJointData * get_joint(int n) const
Returns the nth joint in the character joint hierarchy.
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
A base class for things that may be directly added into the egg hierarchy.
void force_initial_rest_frame()
Forces all of the joints to have the same rest frame value as the first joint read in.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
void add_model(int model_index, EggNode *model_root, EggData *egg_data)
Indicates that the given model_index (with the indicated model_root) is associated with this characte...
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The highest-level base class in the egg directory.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual EggJointData * make_joint_data(EggCharacterData *char_data)
Allocates and returns a new EggJointData structure for the given character.
const_uv_iterator uv_end() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
void check_errors(std::ostream &out, bool force_initial_rest_frame)
Can be called after the collection has been completely filled up with egg files to output any message...
int get_model_index(int n) const
Returns the model_index of the nth model associated with this character.