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

panda/src/egg2pg/computedVerticesMaker.cxx

Go to the documentation of this file.
00001 // Filename: computedVerticesMaker.cxx
00002 // Created by:  drose (01Mar99)
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 "computedVerticesMaker.h"
00020 #include "characterMaker.h"
00021 
00022 #include "characterJoint.h"
00023 #include "character.h"
00024 #include "computedVertices.h"
00025 #include "eggNode.h"
00026 #include "eggGroup.h"
00027 #include "eggVertex.h"
00028 
00029 #include <algorithm>
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: ComputedVerticesMaker::Constructor
00033 //       Access: Public
00034 //  Description:
00035 ////////////////////////////////////////////////////////////////////
00036 ComputedVerticesMaker::
00037 ComputedVerticesMaker() {
00038   _coords= PTA_Vertexf::empty_array(0);
00039   _norms= PTA_Normalf::empty_array(0);
00040   _colors= PTA_Colorf::empty_array(0);
00041   _texcoords= PTA_TexCoordf::empty_array(0);
00042   _current_vc = NULL;
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: ComputedVerticesMaker::begin_new_space
00047 //       Access: Public
00048 //  Description: Should be called before beginning the definition for
00049 //               a new transform space.
00050 ////////////////////////////////////////////////////////////////////
00051 void ComputedVerticesMaker::
00052 begin_new_space() {
00053   _current_jw.clear();
00054   _current_vc = NULL;
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: ComputedVerticesMaker::add_joint
00059 //       Access: Public
00060 //  Description: Adds the joint with its associated membership amount
00061 //               to the current transform space definition.
00062 ////////////////////////////////////////////////////////////////////
00063 void ComputedVerticesMaker::
00064 add_joint(EggNode *joint, double membership) {
00065   // This must be called between a call to begin_new_space() and
00066   // mark_space().
00067   assert(_current_vc == NULL);
00068 
00069   if (membership == 0.0) {
00070     return;
00071   }
00072 
00073   assert(membership > 0.0);
00074 
00075   JointWeights::iterator jwi = _current_jw.find(joint);
00076 
00077   if (jwi != _current_jw.end()) {
00078     // We'd already added this joint previously.  Increment its total
00079     // membership.
00080     (*jwi).second += membership;
00081   } else {
00082     // This is the first time we've added this joint.
00083     _current_jw[joint] = membership;
00084   }
00085 }
00086 
00087 ////////////////////////////////////////////////////////////////////
00088 //     Function: ComputedVerticesMaker::add_vertex_joints
00089 //       Access: Public
00090 //  Description: Adds the joints the vertex belongs to, along with
00091 //               their respective memberships, to the current
00092 //               transform space definition.
00093 ////////////////////////////////////////////////////////////////////
00094 void ComputedVerticesMaker::
00095 add_vertex_joints(EggVertex *vertex, EggNode *object) {
00096   if (vertex->gref_size() == 0) {
00097     // This vertex belongs in the same group as the primitive that
00098     // contains it.
00099     EggGroupNode *egg_joint = object->get_parent();
00100 
00101     // We actually walk up to find the first group above that that's a
00102     // joint, or the character root itself, so we won't (a) be fooled
00103     // by meaningless transforms on non-joints within a character
00104     // hierarchy, or (b) consider meaninglessly different groups to be
00105     // significant.
00106     EggGroup *egg_group = (EggGroup *)NULL;
00107     if (egg_joint->is_of_type(EggGroup::get_class_type())) {
00108       egg_group = DCAST(EggGroup, egg_joint);
00109     }
00110     while (egg_group != (EggGroup *)NULL &&
00111            egg_group->get_group_type() != EggGroup::GT_joint &&
00112            egg_group->get_dart_type() == EggGroup::DT_none) {
00113       nassertv(egg_group->get_parent() != (EggGroupNode *)NULL);
00114       egg_joint = egg_group->get_parent();
00115       egg_group = (EggGroup *)NULL;
00116       if (egg_joint->is_of_type(EggGroup::get_class_type())) {
00117         egg_group = DCAST(EggGroup, egg_joint);
00118       }
00119     }
00120 
00121     add_joint(egg_joint, 1.0);
00122 
00123   } else {
00124     // This vertex belongs in the joint or joints that reference it.
00125     EggVertex::GroupRef::const_iterator gri;
00126     for (gri = vertex->gref_begin(); gri != vertex->gref_end(); ++gri) {
00127       EggGroup *egg_joint = (*gri);
00128       double membership = egg_joint->get_vertex_membership(vertex);
00129       add_joint(egg_joint, membership);
00130     }
00131   }
00132 }
00133 
00134 
00135 ////////////////////////////////////////////////////////////////////
00136 //     Function: ComputedVerticesMaker::mark_space
00137 //       Access: Public
00138 //  Description: Completes the definition of a transform space as a
00139 //               set of joints and memberships.  From this point until
00140 //               the next call to begin_new_space(), vertices may be
00141 //               added to the transform space via calls to
00142 //               add_vertex(), add_normal(), etc.
00143 ////////////////////////////////////////////////////////////////////
00144 void ComputedVerticesMaker::
00145 mark_space() {
00146   // This must be called after a call to begin_new_space().
00147   assert(_current_vc == NULL);
00148 
00149   _current_jw.normalize_weights();
00150 
00151   // This will look up a previously-defined VertexCollection, if we've
00152   // used this transform space before, or it will implicitly create a
00153   // new one if we haven't.
00154   _current_vc = &_transforms[_current_jw];
00155 }
00156 
00157 
00158 ////////////////////////////////////////////////////////////////////
00159 //     Function: ComputedVerticesMaker::add_vertex
00160 //       Access: Public
00161 //  Description: Adds a vertex value to the currently-defined
00162 //               transform space, and returns its index number within
00163 //               the array.
00164 ////////////////////////////////////////////////////////////////////
00165 int ComputedVerticesMaker::
00166 add_vertex(const Vertexd &vertex, const EggMorphVertexList &morphs,
00167            const LMatrix4d &transform) {
00168   // This must be called after a call to mark_space(), and before a
00169   // call to begin_new_space().
00170   assert(_current_vc != NULL);
00171 
00172   Vertexf tv = LCAST(float, vertex * transform);
00173   int index = _current_vc->_vmap.add_value(tv, morphs, _coords);
00174   _current_vc->_vindex.insert(index);
00175 
00176   // Now create any morph sliders.
00177   EggMorphVertexList::const_iterator mli;
00178   for (mli = morphs.begin(); mli != morphs.end(); ++mli) {
00179     const EggMorphVertex &morph = (*mli);
00180     LVector3d offset = morph.get_offset() * transform;
00181     if (!offset.almost_equal(LVector3d(0.0, 0.0, 0.0), 0.0001)) {
00182       MorphList &mlist = _morphs[morph.get_name()];
00183 
00184       // Have we already morphed this vertex?
00185       VertexMorphList::iterator vmi = mlist._vmorphs.find(index);
00186       if (vmi != mlist._vmorphs.end()) {
00187         // Yes, we have.
00188         assert(offset.almost_equal(LCAST(double, (*vmi).second), 0.0001));
00189       } else {
00190         // No, we haven't yet; morph it now.
00191         mlist._vmorphs[index] = LCAST(float, offset);
00192       }
00193     }
00194   }
00195 
00196   return index;
00197 }
00198 
00199 ////////////////////////////////////////////////////////////////////
00200 //     Function: ComputedVerticesMaker::add_normal
00201 //       Access: Public
00202 //  Description: Adds a normal value to the currently-defined
00203 //               transform space, and returns its index number within
00204 //               the array.
00205 ////////////////////////////////////////////////////////////////////
00206 int ComputedVerticesMaker::
00207 add_normal(const Normald &normal, const EggMorphNormalList &morphs,
00208            const LMatrix4d &transform) {
00209   // This must be called after a call to mark_space(), and before a
00210   // call to begin_new_space().
00211   assert(_current_vc != NULL);
00212 
00213   Normald norm = normal * transform;
00214   norm.normalize();
00215   int index = _current_vc->_nmap.add_value(LCAST(float, norm), morphs, _norms);
00216   _current_vc->_nindex.insert(index);
00217 
00218   // Now create any morph sliders.
00219   EggMorphNormalList::const_iterator mli;
00220   for (mli = morphs.begin(); mli != morphs.end(); ++mli) {
00221     const EggMorphNormal &morph = (*mli);
00222     LVector3d offset = morph.get_offset() * transform;
00223     if (!offset.almost_equal(LVector3d(0.0, 0.0, 0.0), 0.0001)) {
00224       MorphList &mlist = _morphs[morph.get_name()];
00225 
00226       // Have we already morphed this normal?
00227       NormalMorphList::iterator vmi = mlist._nmorphs.find(index);
00228       if (vmi != mlist._nmorphs.end()) {
00229         // Yes, we have.
00230         assert(offset.almost_equal(LCAST(double, (*vmi).second), 0.0001));
00231       } else {
00232         // No, we haven't yet; morph it now.
00233         mlist._nmorphs[index] = LCAST(float, offset);
00234       }
00235     }
00236   }
00237 
00238   return index;
00239 }
00240 
00241 ////////////////////////////////////////////////////////////////////
00242 //     Function: ComputedVerticesMaker::add_texcoord
00243 //       Access: Public
00244 //  Description: Adds a texcoord value to the array (texture
00245 //               coordinates are unrelated to the current transform
00246 //               space), and returns its index number within the
00247 //               array.
00248 ////////////////////////////////////////////////////////////////////
00249 int ComputedVerticesMaker::
00250 add_texcoord(const TexCoordd &texcoord, const EggMorphTexCoordList &morphs,
00251              const LMatrix3d &transform) {
00252   TexCoordf ttc = LCAST(float, texcoord * transform);
00253   int index = _tmap.add_value(ttc, morphs, _texcoords);
00254   _tindex.insert(index);
00255 
00256   // Now create any morph sliders.
00257   EggMorphTexCoordList::const_iterator mli;
00258   for (mli = morphs.begin(); mli != morphs.end(); ++mli) {
00259     const EggMorphTexCoord &morph = (*mli);
00260     LVector2d offset = morph.get_offset() * transform;
00261     if (!offset.almost_equal(LVector2d(0.0, 0.0), 0.0001)) {
00262       MorphList &mlist = _morphs[morph.get_name()];
00263 
00264       // Have we already morphed this texcoord?
00265       TexCoordMorphList::iterator vmi = mlist._tmorphs.find(index);
00266       if (vmi != mlist._tmorphs.end()) {
00267         // Yes, we have.
00268         assert(offset.almost_equal(LCAST(double, (*vmi).second), 0.0001));
00269       } else {
00270         // No, we haven't yet; morph it now.
00271         mlist._tmorphs[index] = LCAST(float, offset);
00272       }
00273     }
00274   }
00275 
00276   return index;
00277 }
00278 
00279 ////////////////////////////////////////////////////////////////////
00280 //     Function: ComputedVerticesMaker::add_color
00281 //       Access: Public
00282 //  Description: Adds a color value to the array (color values
00283 //               are unrelated to the current transform space), and
00284 //               returns its index number within the array.
00285 ////////////////////////////////////////////////////////////////////
00286 int ComputedVerticesMaker::
00287 add_color(const Colorf &color, const EggMorphColorList &morphs) {
00288   int index = _cmap.add_value(color, morphs, _colors);
00289   _cindex.insert(index);
00290 
00291   // Now create any morph sliders.
00292   EggMorphColorList::const_iterator mli;
00293   for (mli = morphs.begin(); mli != morphs.end(); ++mli) {
00294     const EggMorphColor &morph = (*mli);
00295     LVector4f offset = morph.get_offset();
00296     if (!offset.almost_equal(LVector4f(0.0, 0.0, 0.0, 0.0), 0.0001)) {
00297       MorphList &mlist = _morphs[morph.get_name()];
00298 
00299       // Have we already morphed this color?
00300       ColorMorphList::iterator vmi = mlist._cmorphs.find(index);
00301       if (vmi != mlist._cmorphs.end()) {
00302         // Yes, we have.
00303         assert(offset.almost_equal((*vmi).second, 0.0001));
00304       } else {
00305         // No, we haven't yet; morph it now.
00306         mlist._cmorphs[index] = offset;
00307       }
00308     }
00309   }
00310 
00311   return index;
00312 }
00313 
00314 ////////////////////////////////////////////////////////////////////
00315 //     Function: ComputedVerticesMaker::make_computed_vertices
00316 //       Access: Public
00317 //  Description: After all spaces have been defined and all vertices
00318 //               added, creates a new ComputedVertices object and
00319 //               returns it.
00320 ////////////////////////////////////////////////////////////////////
00321 ComputedVertices *ComputedVerticesMaker::
00322 make_computed_vertices(Character *character, CharacterMaker &char_maker) {
00323   // We must first build up a set of all the unique kinds of vertex
00324   // transforms.
00325   typedef pset<ComputedVertices::VertexTransform> VertexTransforms;
00326   VertexTransforms transforms;
00327 
00328   TransformSpaces::const_iterator tsi;
00329   for (tsi = _transforms.begin();
00330        tsi != _transforms.end();
00331        ++tsi) {
00332     const JointWeights &jw = (*tsi).first;
00333     const VertexCollection &vc = (*tsi).second;
00334 
00335     JointWeights::const_iterator jwi;
00336     for (jwi = jw.begin(); jwi != jw.end(); ++jwi) {
00337       double weight = (*jwi).second;
00338       EggNode *egg_joint = (*jwi).first;
00339       int joint_index = char_maker.egg_to_index(egg_joint);
00340 
00341       // Look for a VertexTransform that matches this template.
00342       ComputedVertices::VertexTransform new_vt;
00343       new_vt._joint_index = joint_index;
00344       new_vt._effect = (float)weight;
00345 
00346       // This will either insert the VertexTransform into the set and
00347       // return its newly-created iterator, or it will return the
00348       // iterator referring to the previously-inserted VertexTransform
00349       // like this.
00350       VertexTransforms::iterator vti = transforms.insert(new_vt).first;
00351 
00352       // We can discard the const-ness of the set's iterator, because
00353       // we will only be changing a part of the VertexTransform that
00354       // doesn't affect its sort order within the set.
00355       ComputedVertices::VertexTransform &insert_vt =
00356         (ComputedVertices::VertexTransform &)*vti;
00357 
00358       // Now add in all the vertices and normals.
00359       copy(vc._vindex.begin(), vc._vindex.end(),
00360            back_inserter(insert_vt._vindex));
00361       copy(vc._nindex.begin(), vc._nindex.end(),
00362            back_inserter(insert_vt._nindex));
00363     }
00364   }
00365 
00366   // Ok, now we have the set of all VertexTransforms.  Create a
00367   // ComputedVertices object that reflects this.
00368   ComputedVertices *comp_verts = new ComputedVertices;
00369   copy(transforms.begin(), transforms.end(),
00370        back_inserter(comp_verts->_transforms));
00371 
00372   character->_cv._coords = _coords;
00373   character->_cv._norms = _norms;
00374   character->_cv._colors = _colors;
00375   character->_cv._texcoords = _texcoords;
00376 
00377   // Finally, add in all the morph definitions.
00378   Morphs::const_iterator mi;
00379   for (mi = _morphs.begin(); mi != _morphs.end(); ++mi) {
00380     const string &name = (*mi).first;
00381     const MorphList &mlist = (*mi).second;
00382 
00383     int slider_index = char_maker.create_slider(name);
00384 
00385     if (!mlist._vmorphs.empty()) {
00386       // We push an empty MorphVertex object and then modify it,
00387       // rather than filling it first and then pushing it, just to
00388       // avoid unnecessary copying of data.
00389       comp_verts->_vertex_morphs.push_back(ComputedVerticesMorphVertex());
00390       ComputedVerticesMorphVertex &mv = comp_verts->_vertex_morphs.back();
00391       mv._slider_index = slider_index;
00392 
00393       VertexMorphList::const_iterator vmi;
00394       for (vmi = mlist._vmorphs.begin();
00395            vmi != mlist._vmorphs.end();
00396            ++vmi) {
00397         mv._morphs.push_back(ComputedVerticesMorphValue3((*vmi).first,
00398                                                          (*vmi).second));
00399       }
00400     }
00401 
00402     if (!mlist._nmorphs.empty()) {
00403       comp_verts->_normal_morphs.push_back(ComputedVerticesMorphNormal());
00404       ComputedVerticesMorphNormal &mv = comp_verts->_normal_morphs.back();
00405       mv._slider_index = slider_index;
00406 
00407       NormalMorphList::const_iterator vmi;
00408       for (vmi = mlist._nmorphs.begin();
00409            vmi != mlist._nmorphs.end();
00410            ++vmi) {
00411         mv._morphs.push_back(ComputedVerticesMorphValue3((*vmi).first,
00412                                                          (*vmi).second));
00413       }
00414     }
00415 
00416     if (!mlist._tmorphs.empty()) {
00417       comp_verts->_texcoord_morphs.push_back(ComputedVerticesMorphTexCoord());
00418       ComputedVerticesMorphTexCoord &mv = comp_verts->_texcoord_morphs.back();
00419       mv._slider_index = slider_index;
00420 
00421       TexCoordMorphList::const_iterator vmi;
00422       for (vmi = mlist._tmorphs.begin();
00423            vmi != mlist._tmorphs.end();
00424            ++vmi) {
00425         mv._morphs.push_back(ComputedVerticesMorphValue2((*vmi).first,
00426                                                          (*vmi).second));
00427       }
00428     }
00429 
00430     if (!mlist._cmorphs.empty()) {
00431       comp_verts->_color_morphs.push_back(ComputedVerticesMorphColor());
00432       ComputedVerticesMorphColor &mv = comp_verts->_color_morphs.back();
00433       mv._slider_index = slider_index;
00434 
00435       ColorMorphList::const_iterator vmi;
00436       for (vmi = mlist._cmorphs.begin();
00437            vmi != mlist._cmorphs.end();
00438            ++vmi) {
00439         mv._morphs.push_back(ComputedVerticesMorphValue4((*vmi).first,
00440                                                          (*vmi).second));
00441       }
00442     }
00443   }
00444 
00445   comp_verts->make_orig(character);
00446   return comp_verts;
00447 }
00448 
00449 
00450 ////////////////////////////////////////////////////////////////////
00451 //     Function: ComputedVerticesMaker::write
00452 //       Access: Public
00453 //  Description:
00454 ////////////////////////////////////////////////////////////////////
00455 void ComputedVerticesMaker::
00456 write(ostream &out) const {
00457   out << "ComputedVerticesMaker, "
00458       << _transforms.size() << " transform spaces, "
00459       << _coords.size() << " vertices, "
00460       << _norms.size() << " normals, "
00461       << _texcoords.size() << " uvs, "
00462       << _colors.size() << " colors.\n";
00463   TransformSpaces::const_iterator tsi;
00464   for (tsi = _transforms.begin(); tsi != _transforms.end(); ++tsi) {
00465     const JointWeights &jw = (*tsi).first;
00466     const VertexCollection &vc = (*tsi).second;
00467     out << "  " << jw << " has "
00468         << vc._vindex.size() << " vertices and "
00469         << vc._nindex.size() << " normals\n";
00470   }
00471 
00472   Morphs::const_iterator mi;
00473   for (mi = _morphs.begin(); mi != _morphs.end(); ++mi) {
00474     const string &name = (*mi).first;
00475     const MorphList &mlist = (*mi).second;
00476     out << name << " morphs "
00477         << mlist._vmorphs.size() << " vertices, "
00478         << mlist._nmorphs.size() << " normals, "
00479         << mlist._tmorphs.size() << " uvs, and "
00480         << mlist._cmorphs.size() << " colors.\n";
00481   }
00482 }
00483 
00484 
00485 ////////////////////////////////////////////////////////////////////
00486 //     Function: ComputedVerticesMaker::JointWeights::Ordering operator
00487 //       Access: Public
00488 //  Description:
00489 ////////////////////////////////////////////////////////////////////
00490 bool ComputedVerticesMaker::JointWeights::
00491 operator < (const JointWeights &other) const {
00492   const_iterator i = begin();
00493   const_iterator j = other.begin();
00494 
00495   while (i != end() && j != other.end()) {
00496     if ((*i).first != (*j).first) {
00497       return (*i).first < (*j).first;
00498     }
00499     if ((*i).second != (*j).second) {
00500       return (*i).second < (*j).second;
00501     }
00502     ++i;
00503     ++j;
00504   }
00505 
00506   if (i == end() && j != other.end()) {
00507     // The first i.size() items are equivalent, but list j is longer.
00508     return true;
00509   }
00510 
00511   if (i != end() && j == other.end()) {
00512     // The first j.size() items are equivalent, but list i is longer.
00513     return false;
00514   }
00515 
00516   // The lists are equivalent.
00517   return false;
00518 }
00519 
00520 
00521 ////////////////////////////////////////////////////////////////////
00522 //     Function: ComputedVerticesMaker::JointWeights::normalize_weights
00523 //       Access: Public
00524 //  Description:
00525 ////////////////////////////////////////////////////////////////////
00526 void ComputedVerticesMaker::JointWeights::
00527 normalize_weights() {
00528   if (!empty()) {
00529     double net_weight = 0.0;
00530 
00531     iterator i;
00532     for (i = begin(); i != end(); ++i) {
00533       double weight = (*i).second;
00534       assert(weight > 0.0);
00535       net_weight += weight;
00536     }
00537     assert(net_weight != 0.0);
00538 
00539     for (i = begin(); i != end(); ++i) {
00540       (*i).second /= net_weight;
00541     }
00542   }
00543 }
00544 
00545 
00546 ////////////////////////////////////////////////////////////////////
00547 //     Function: ComputedVerticesMaker::JointWeights::output
00548 //       Access: Public
00549 //  Description:
00550 ////////////////////////////////////////////////////////////////////
00551 void ComputedVerticesMaker::JointWeights::
00552 output(ostream &out) const {
00553   out << "jw(";
00554   if (!empty()) {
00555     const_iterator i = begin();
00556     out << (*i).first->get_name() << ":" << (*i).second;
00557     for (++i; i != end(); ++i) {
00558       out << " " << (*i).first->get_name() << ":" << (*i).second;
00559     }
00560   }
00561   out << ")";
00562 }

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