Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/egg2pg/characterMaker.cxx

Go to the documentation of this file.
00001 // Filename: characterMaker.cxx
00002 // Created by:  drose (06Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "characterMaker.h"
00020 #include "eggLoader.h"
00021 #include "config_egg2pg.h"
00022 
00023 #include "computedVertices.h"
00024 #include "eggGroup.h"
00025 #include "eggPrimitive.h"
00026 #include "partGroup.h"
00027 #include "characterJoint.h"
00028 #include "characterJointBundle.h"
00029 #include "characterSlider.h"
00030 #include "character.h"
00031 #include "transformState.h"
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: CharacterMaker::Construtor
00035 //       Access: Public
00036 //  Description:
00037 ////////////////////////////////////////////////////////////////////
00038 CharacterMaker::
00039 CharacterMaker(EggGroup *root, EggLoader &loader)
00040   : _loader(loader), _egg_root(root) {
00041 
00042   _character_node = new Character(_egg_root->get_name());
00043   _bundle = _character_node->get_bundle();
00044 
00045   _morph_root = (PartGroup *)NULL;
00046   _skeleton_root = new PartGroup(_bundle, "<skeleton>");
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: CharacterMaker::make_node
00051 //       Access: Public
00052 //  Description:
00053 ////////////////////////////////////////////////////////////////////
00054 Character *CharacterMaker::
00055 make_node() {
00056   make_bundle();
00057   _character_node->_parts = _parts;
00058   return _character_node;
00059 }
00060 
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: CharacterMaker::egg_to_part
00064 //       Access: Public
00065 //  Description: Returns the PartGroup node associated with the given
00066 //               egg node.  If the egg node is not a node in the
00067 //               character's hierarchy, returns the top of the
00068 //               character's hierarchy.
00069 ////////////////////////////////////////////////////////////////////
00070 PartGroup *CharacterMaker::
00071 egg_to_part(EggNode *egg_node) const {
00072   int index = egg_to_index(egg_node);
00073   if (index < 0) {
00074     // If there's a reference to the geometry outside of the
00075     // character, just return the root of the character.
00076     return _bundle;
00077   }
00078   nassertr(index < (int)_parts.size(), NULL);
00079   return _parts[index];
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: CharacterMaker::egg_to_index
00084 //       Access: Public
00085 //  Description: Returns the index number associated with the
00086 //               PartGroup node for the given egg node, or -1.
00087 ////////////////////////////////////////////////////////////////////
00088 int CharacterMaker::
00089 egg_to_index(EggNode *egg_node) const {
00090   NodeMap::const_iterator nmi = _node_map.find(egg_node);
00091   if (nmi == _node_map.end()) {
00092     return -1;
00093   }
00094   return (*nmi).second;
00095 }
00096 
00097 ////////////////////////////////////////////////////////////////////
00098 //     Function: CharacterMaker::part_to_node
00099 //       Access: Public
00100 //  Description: Returns the scene graph node associated with the
00101 //               given PartGroup node, if there is one.  If the
00102 //               PartGroup does not have an associated node, returns
00103 //               the character's top node.
00104 ////////////////////////////////////////////////////////////////////
00105 PandaNode *CharacterMaker::
00106 part_to_node(PartGroup *part) const {
00107   if (part->is_of_type(CharacterJoint::get_class_type())) {
00108     CharacterJoint *joint = DCAST(CharacterJoint, part);
00109     if (joint->_geom_node != (PandaNode *)NULL) {
00110       return joint->_geom_node;
00111     }
00112   }
00113 
00114   return _character_node;
00115 }
00116 
00117 
00118 ////////////////////////////////////////////////////////////////////
00119 //     Function: CharacterMaker::create_slider
00120 //       Access: Public
00121 //  Description: Creates a new morph slider of the given name, and
00122 //               returns its index.  This is actually called by
00123 //               ComputedVerticesMaker, which is responsible for
00124 //               identifying all the unique morph target names.
00125 ////////////////////////////////////////////////////////////////////
00126 int CharacterMaker::
00127 create_slider(const string &name) {
00128   if (_morph_root == (PartGroup *)NULL) {
00129     _morph_root = new PartGroup(_bundle, "morph");
00130   }
00131   CharacterSlider *slider = new CharacterSlider(_morph_root, name);
00132   int index = _parts.size();
00133   _parts.push_back(slider);
00134   return index;
00135 }
00136 
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: CharacterMaker::make_bundle
00140 //       Access: Private
00141 //  Description:
00142 ////////////////////////////////////////////////////////////////////
00143 CharacterJointBundle *CharacterMaker::
00144 make_bundle() {
00145   build_joint_hierarchy(_egg_root, _skeleton_root);
00146   _bundle->sort_descendants();
00147 
00148   parent_joint_nodes(_skeleton_root);
00149   make_geometry(_egg_root);
00150 
00151   _character_node->_computed_vertices =
00152     _comp_verts_maker.make_computed_vertices(_character_node, *this);
00153 
00154   return _bundle;
00155 }
00156 
00157 ////////////////////////////////////////////////////////////////////
00158 //     Function: CharacterMaker::build_hierarchy
00159 //       Access: Private
00160 //  Description:
00161 ////////////////////////////////////////////////////////////////////
00162 void CharacterMaker::
00163 build_joint_hierarchy(EggNode *egg_node, PartGroup *part) {
00164   int index = -1;
00165 
00166   if (egg_node->is_of_type(EggGroup::get_class_type())) {
00167     EggGroup *egg_group = DCAST(EggGroup, egg_node);
00168 
00169     // Each joint we come across is significant, and gets added to the
00170     // hierarchy.  Non-joints we encounter are ignored.
00171     if (egg_group->get_group_type() == EggGroup::GT_joint) {
00172       // We need to get the transform of the joint, and then convert
00173       // it to single-precision.
00174       LMatrix4d matd;
00175       if (egg_group->has_transform()) {
00176         matd = egg_group->get_transform();
00177       } else {
00178         matd = LMatrix4d::ident_mat();
00179       }
00180 
00181       LMatrix4f matf = LCAST(float, matd);
00182 
00183       CharacterJoint *joint =
00184         new CharacterJoint(part, egg_group->get_name(), matf);
00185       index = _parts.size();
00186       _parts.push_back(joint);
00187 
00188       if (egg_group->get_dcs_type() != EggGroup::DC_none) {
00189         // If the joint requested an explicit DCS, create a node for
00190         // it.
00191         joint->_geom_node = new PandaNode(egg_group->get_name());
00192       }
00193 
00194       part = joint;
00195     }
00196 
00197     EggGroup::const_iterator ci;
00198     for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
00199       build_joint_hierarchy((*ci), part);
00200     }
00201   }
00202 
00203   _node_map[egg_node] = index;
00204 }
00205 
00206 ////////////////////////////////////////////////////////////////////
00207 //     Function: CharacterMaker::parent_joint_nodes
00208 //       Access: Private
00209 //  Description: Walks the joint hierarchy, and parents any explicit
00210 //               nodes created for the joints under the character
00211 //               node.
00212 ////////////////////////////////////////////////////////////////////
00213 void CharacterMaker::
00214 parent_joint_nodes(PartGroup *part) {
00215   if (part->is_of_type(CharacterJoint::get_class_type())) {
00216     CharacterJoint *joint = DCAST(CharacterJoint, part);
00217     PandaNode *joint_node = joint->_geom_node;
00218     if (joint_node != NULL) {
00219       _character_node->add_child(joint_node);
00220       joint->add_net_transform(joint_node);
00221       joint_node->set_transform(TransformState::make_mat(joint->_net_transform));
00222     }
00223   }
00224 
00225   for (int i = 0; i < part->get_num_children(); i++) {
00226     parent_joint_nodes(part->get_child(i));
00227   }
00228 }
00229 
00230 ////////////////////////////////////////////////////////////////////
00231 //     Function: CharacterMaker::make_geometry
00232 //       Access: Private
00233 //  Description:
00234 ////////////////////////////////////////////////////////////////////
00235 void CharacterMaker::
00236 make_geometry(EggNode *egg_node) {
00237   if (egg_node->is_of_type(EggPrimitive::get_class_type())) {
00238     EggPrimitive *egg_primitive = DCAST(EggPrimitive, egg_node);
00239     if (!egg_primitive->empty()) {
00240       EggGroupNode *prim_home = determine_primitive_home(egg_primitive);
00241 
00242       if (prim_home == NULL) {
00243         // This is a totally dynamic primitive that lives under the
00244         // character's node.
00245         make_dynamic_primitive(egg_primitive, _egg_root);
00246 
00247       } else {
00248         // This is a static primitive that lives under a particular
00249         // node.
00250         make_static_primitive(egg_primitive, prim_home);
00251       }
00252     }
00253   }
00254 
00255   if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00256     EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
00257 
00258     EggGroupNode::const_iterator ci;
00259     for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
00260       make_geometry(*ci);
00261     }
00262   }
00263 }
00264 
00265 ////////////////////////////////////////////////////////////////////
00266 //     Function: CharacterMaker::make_static_primitive
00267 //       Access: Private
00268 //  Description:
00269 ////////////////////////////////////////////////////////////////////
00270 void CharacterMaker::
00271 make_static_primitive(EggPrimitive *egg_primitive, EggGroupNode *prim_home) {
00272   PandaNode *node = part_to_node(egg_to_part(prim_home));
00273 
00274   // We need this funny transform to convert from the coordinate
00275   // space of the original vertices to that of the new joint node.
00276   LMatrix4d transform =
00277     egg_primitive->get_vertex_frame() *
00278     prim_home->get_node_frame_inv();
00279 
00280   _loader.make_nonindexed_primitive(egg_primitive, node, &transform);
00281 }
00282 
00283 ////////////////////////////////////////////////////////////////////
00284 //     Function: CharacterMaker::make_dynamic_primitive
00285 //       Access: Private
00286 //  Description:
00287 ////////////////////////////////////////////////////////////////////
00288 void CharacterMaker::
00289 make_dynamic_primitive(EggPrimitive *egg_primitive, EggGroupNode *prim_home) {
00290   PandaNode *node = part_to_node(egg_to_part(prim_home));
00291 
00292   LMatrix4d transform =
00293     egg_primitive->get_vertex_frame() *
00294     prim_home->get_node_frame_inv();
00295 
00296   _loader.make_indexed_primitive(egg_primitive, node, &transform,
00297                                  _comp_verts_maker);
00298 }
00299 
00300 ////////////////////////////////////////////////////////////////////
00301 //     Function: CharacterMaker::determine_primitive_home
00302 //       Access: Private
00303 //  Description:
00304 ////////////////////////////////////////////////////////////////////
00305 EggGroupNode *CharacterMaker::
00306 determine_primitive_home(EggPrimitive *egg_primitive) {
00307   // A primitive's vertices may be referenced by any joint in the
00308   // character.  Or, the primitive itself may be explicitly placed
00309   // under a joint.
00310 
00311   // If any of the vertices are referenced by multiple joints, or if
00312   // any two vertices are referenced by different joints, then the
00313   // entire primitive must be considered dynamic.  (We'll indicate a
00314   // dynamic primitive by returning NULL.)
00315 
00316   // We need to keep track of the one joint we've encountered so far,
00317   // to see if all the vertices are referenced by the same joint.
00318   EggGroupNode *home = NULL;
00319 
00320   EggPrimitive::const_iterator vi;
00321   for (vi = egg_primitive->begin();
00322        vi != egg_primitive->end();
00323        ++vi) {
00324     EggVertex *vertex = (*vi);
00325     if (vertex->gref_size() > 1) {
00326       // This vertex is referenced by multiple joints; the primitive
00327       // is dynamic.
00328       return NULL;
00329     }
00330 
00331     EggGroupNode *vertex_home;
00332 
00333     if (vertex->gref_size() == 0) {
00334       // This vertex is not referenced at all, which means it belongs
00335       // right where it is.
00336       vertex_home = egg_primitive->get_parent();
00337     } else {
00338       nassertr(vertex->gref_size() == 1, NULL);
00339       // This vertex is referenced exactly once.
00340       vertex_home = *vertex->gref_begin();
00341     }
00342 
00343     if (home != NULL && home != vertex_home) {
00344       // Oops, two vertices are referenced by different joints!  The
00345       // primitive is dynamic.
00346       return NULL;
00347     }
00348 
00349     home = vertex_home;
00350   }
00351 
00352   // This shouldn't be possible, unless there are no vertices--but we
00353   // check for that before calling this function.
00354   nassertr(home != NULL, NULL);
00355 
00356   // So, all the vertices are assigned to the same group.  This means
00357   // the polygon belongs entirely to one joint.
00358 
00359   // If the group is not, in fact, a joint then we return the first
00360   // joint above the group.
00361   EggGroup *egg_group = (EggGroup *)NULL;
00362   if (home->is_of_type(EggGroup::get_class_type())) {
00363     egg_group = DCAST(EggGroup, home);
00364   }
00365   while (egg_group != (EggGroup *)NULL &&
00366          egg_group->get_group_type() != EggGroup::GT_joint &&
00367          egg_group->get_dart_type() == EggGroup::DT_none) {
00368     nassertr(egg_group->get_parent() != (EggGroupNode *)NULL, NULL);
00369     home = egg_group->get_parent();
00370     egg_group = (EggGroup *)NULL;
00371     if (home->is_of_type(EggGroup::get_class_type())) {
00372       egg_group = DCAST(EggGroup, home);
00373     }
00374   }
00375 
00376   if (egg_group != (EggGroup *)NULL &&
00377       egg_group->get_group_type() == EggGroup::GT_joint &&
00378       egg_group->get_dcs_type() == EggGroup::DC_none) {
00379     // If the home is a joint without a <DCS> flag--this is the normal
00380     // case--we'll move the polygon under the character node and
00381     // animate it from there explicitly.
00382     return NULL;
00383   }
00384 
00385   // Otherwise, if the joint *does* have a <DCS> flag, we'll create
00386   // static geometry that we parent directly to the joint node.
00387   // We'll also create static geometry for polygons that have no
00388   // explicit joint assignment.
00389   return home;
00390 }

Generated on Fri May 2 00:38:08 2003 for Panda by doxygen1.3