Panda3D

softNodeDesc.cxx

00001 // Filename: softNodeDesc.cxx
00002 // Created by:  masad (03Oct03)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "softNodeDesc.h"
00016 #include "config_softegg.h"
00017 #include "eggGroup.h"
00018 #include "eggXfmSAnim.h"
00019 #include "eggSAnimData.h"
00020 #include "softToEggConverter.h"
00021 #include "dcast.h"
00022 
00023 TypeHandle SoftNodeDesc::_type_handle;
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: SoftNodeDesc::Constructor
00027 //       Access: Public
00028 //  Description: 
00029 ////////////////////////////////////////////////////////////////////
00030 SoftNodeDesc::
00031 SoftNodeDesc(SoftNodeDesc *parent, const string &name) :
00032   Namable(name),
00033   _parent(parent)
00034 {
00035   _model = (SAA_Elem *)NULL;
00036   _egg_group = (EggGroup *)NULL;
00037   _egg_table = (EggTable *)NULL;
00038   _anim = (EggXfmSAnim *)NULL;
00039   _joint_type = JT_none;
00040 
00041   // Add ourselves to our parent.
00042   if (_parent != (SoftNodeDesc *)NULL) {
00043     softegg_cat.spam() << "parent name " << _parent->get_name();
00044     _parent->_children.push_back(this);
00045   }
00046 
00047   // set the _parentJoint to Null
00048   _parentJoint = NULL;
00049 
00050   fullname = NULL;
00051 
00052   numTexLoc = 0;
00053   numTexGlb = 0;
00054 
00055   uScale = NULL; 
00056   vScale = NULL;
00057   uOffset = NULL;
00058   vOffset = NULL;
00059   
00060   valid;
00061   uv_swap;
00062   //  SAA_Boolean visible;
00063   numTexTri = NULL;
00064   textures = NULL;
00065   materials = NULL;
00066   triangles = NULL;
00067   gtype = SAA_GEOM_ORIGINAL;
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: SoftNodeDesc::Destructor
00072 //       Access: Public
00073 //  Description: 
00074 ////////////////////////////////////////////////////////////////////
00075 SoftNodeDesc::
00076 ~SoftNodeDesc() {
00077   // I think it is a mistake to try to delete this.  This was one
00078   // member of an entire array allocated at once; you can't delete
00079   // individual elements of an array.
00080 
00081   // Screw cleanup, anyway--we'll just let the array leak.
00082   /*
00083   if (_model != (SAA_Elem *)NULL) {
00084     delete _model;
00085   }
00086   */
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 //     Function: SoftNodeDesc::set_model
00091 //       Access: Public
00092 //  Description: Indicates an associated between the SoftNodeDesc and
00093 //               some SAA_Elem instance.
00094 ////////////////////////////////////////////////////////////////////
00095 void SoftNodeDesc::
00096 set_model(SAA_Elem *model) {
00097   _model = model;
00098 }
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: SoftNodeDesc::set_parent
00102 //       Access: Public
00103 //  Description: Sometimes, parent is not known at node creation
00104 //               As soon as it is known, set the parent
00105 ////////////////////////////////////////////////////////////////////
00106 void SoftNodeDesc::
00107 set_parent(SoftNodeDesc *parent) {
00108   if (_parent) {
00109     softegg_cat.spam() << endl;
00110     /*
00111     softegg_cat.spam() << " expected _parent to be null!?\n";
00112     if (_parent == parent)
00113       softegg_cat.spam() << " parent already set\n";
00114     else {
00115       softegg_cat.spam() << " current parent " << _parent->get_name() << " new parent " 
00116            << parent << endl;
00117     }
00118     */
00119     return;
00120   }
00121   _parent = parent;
00122   softegg_cat.spam() << " set parent to " << _parent->get_name() << endl;
00123 
00124   // Add ourselves to our parent.
00125   _parent->_children.push_back(this);
00126 }
00127 
00128 ////////////////////////////////////////////////////////////////////
00129 //     Function: SoftNodeDesc::set_parent
00130 //       Access: Public
00131 //  Description: Sometimes, parent is not known at node creation
00132 //               As soon as it is known, set the parent
00133 ////////////////////////////////////////////////////////////////////
00134 void SoftNodeDesc::
00135 force_set_parent(SoftNodeDesc *parent) {
00136   if (_parent)
00137     softegg_cat.spam() << " current parent " << _parent->get_name();
00138 
00139   _parent = parent;
00140   
00141   if (_parent)
00142     softegg_cat.spam() << " new parent " << _parent->get_name() << endl;
00143 
00144   // Add ourselves to our parent.
00145   _parent->_children.push_back(this);
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: SoftNodeDesc::has_model
00150 //       Access: Public
00151 //  Description: Returns true if a Soft dag path has been associated
00152 //               with this node, false otherwise.
00153 ////////////////////////////////////////////////////////////////////
00154 bool SoftNodeDesc::
00155 has_model() const {
00156   return (_model != (SAA_Elem *)NULL);
00157 }
00158 
00159 ////////////////////////////////////////////////////////////////////
00160 //     Function: SoftNodeDesc::get_model
00161 //       Access: Public
00162 //  Description: Returns the SAA_Elem * associated with this node.  It
00163 //               is an error to call this unless has_model()
00164 //               returned true.
00165 ////////////////////////////////////////////////////////////////////
00166 SAA_Elem *SoftNodeDesc::
00167 get_model() const {
00168   nassertr(_model != (SAA_Elem *)NULL, _model);
00169   return _model;
00170 }
00171 
00172 ////////////////////////////////////////////////////////////////////
00173 //     Function: SoftNodeDesc::is_joint
00174 //       Access: Private
00175 //  Description: Returns true if the node should be treated as a joint
00176 //               by the converter.
00177 ////////////////////////////////////////////////////////////////////
00178 bool SoftNodeDesc::
00179 is_joint() const {
00180   //  return _joint_type == JT_joint || _joint_type == JT_pseudo_joint;
00181   return _joint_type == JT_joint;
00182 }
00183 
00184 ////////////////////////////////////////////////////////////////////
00185 //     Function: SoftNodeDesc::is_junk
00186 //       Access: Private
00187 //  Description: Returns true if the node should be treated as a junk
00188 //               by the converter.
00189 ////////////////////////////////////////////////////////////////////
00190 bool SoftNodeDesc::
00191 is_junk() const {
00192   return _joint_type == JT_junk;
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: SoftNodeDesc::set_joint
00197 //       Access: Private
00198 //  Description: sets the _joint_type to JT_joint
00199 ////////////////////////////////////////////////////////////////////
00200 void SoftNodeDesc::
00201 set_joint() {
00202   _joint_type = JT_joint;
00203 }
00204 ////////////////////////////////////////////////////////////////////
00205 //     Function: SoftNodeDesc::is_joint_parent
00206 //       Access: Private
00207 //  Description: Returns true if the node is the parent or ancestor of
00208 //               a joint.
00209 ////////////////////////////////////////////////////////////////////
00210 bool SoftNodeDesc::
00211 is_joint_parent() const {
00212   return _joint_type == JT_joint_parent;
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: SoftNodeDesc::clear_egg
00217 //       Access: Private
00218 //  Description: Recursively clears the egg pointers from this node
00219 //               and all children.
00220 ////////////////////////////////////////////////////////////////////
00221 void SoftNodeDesc::
00222 clear_egg() {
00223   _egg_group = (EggGroup *)NULL;
00224   _egg_table = (EggTable *)NULL;
00225   _anim = (EggXfmSAnim *)NULL;
00226 
00227   Children::const_iterator ci;
00228   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00229     SoftNodeDesc *child = (*ci);
00230     child->clear_egg();
00231   }
00232 }
00233 
00234 ////////////////////////////////////////////////////////////////////
00235 //     Function: SoftNodeDesc::mark_joint_parent
00236 //       Access: Private
00237 //  Description: Indicates that this node has at least one child that
00238 //               is a joint or a pseudo-joint.
00239 ////////////////////////////////////////////////////////////////////
00240 void SoftNodeDesc::
00241 mark_joint_parent() {
00242   if (_joint_type == JT_none) {
00243     _joint_type = JT_joint_parent;
00244     softegg_cat.spam() << " marked parent " << get_name();
00245   }
00246   else
00247     softegg_cat.spam() << " ?parent " << get_name() << " joint type " << _joint_type;
00248   
00249   if (_parent != (SoftNodeDesc *)NULL) {
00250     _parent->mark_joint_parent();
00251   }
00252   softegg_cat.spam() << endl;
00253 }
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: SoftNodeDesc::check_joint_parent
00257 //       Access: Private
00258 //  Description: Walks the hierarchy, if a node is joint, make
00259 //               sure all its parents are marked JT_joint_parent
00260 ////////////////////////////////////////////////////////////////////
00261 void SoftNodeDesc::
00262 check_joint_parent() {
00263   Children::const_iterator ci;
00264   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00265     SoftNodeDesc *child = (*ci);
00266     if (child->is_joint()) {
00267       softegg_cat.spam() << "child " << child->get_name();
00268       mark_joint_parent();
00269     }
00270     child->check_joint_parent();
00271   }
00272 }
00273 
00274 ///////////////////////////////////////////////////////////////////////
00275 //     Function: SoftNodeTree::check_junk
00276 //       Access: Public
00277 //  Description: check to see if this is a branch we don't want to 
00278 //               descend - this will prevent creating geometry for 
00279 //               animation control structures
00280 ///////////////////////////////////////////////////////////////////////
00281 void SoftNodeDesc::
00282 check_junk(bool parent_junk) {
00283   const char *name = get_name().c_str();
00284 
00285   if (parent_junk) {
00286     _joint_type = JT_junk;
00287     softegg_cat.spam() << "junk node " << get_name() << endl;
00288   }
00289   if ( (strstr(name, "con-") != NULL) || 
00290        (strstr(name, "con_") != NULL) || 
00291        (strstr(name, "fly_") != NULL) || 
00292        (strstr(name, "fly-") != NULL) || 
00293        (strstr(name, "camRIG") != NULL) ||
00294        (strstr(name, "cam_rig") != NULL) ||
00295        (strstr(name, "bars") != NULL) )
00296     {
00297       _joint_type = JT_junk;
00298       softegg_cat.spam() << "junk node " << get_name() << endl;
00299       parent_junk = true;
00300       Children::const_iterator ci;
00301       for (ci = _children.begin(); ci != _children.end(); ++ci) {
00302         SoftNodeDesc *child = (*ci);
00303         softegg_cat.spam() << child->get_name() << ",";
00304       }
00305       softegg_cat.spam() << endl;
00306     }
00307   Children::const_iterator ci;
00308   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00309     SoftNodeDesc *child = (*ci);
00310     child->check_junk(parent_junk);
00311   }
00312 }
00313 
00314 ///////////////////////////////////////////////////////////////////////
00315 //     Function: SoftNodeTree::is_partial
00316 //       Access: Public
00317 //  Description: check to see if this is a selected branch we want to 
00318 //               descend - this will prevent creating geometry for 
00319 //               other parts
00320 ///////////////////////////////////////////////////////////////////////
00321 bool SoftNodeDesc::
00322 is_partial(char *search_prefix) {
00323   const char *name = fullname;
00324 
00325   // if no search prefix then return false
00326   if (!search_prefix)
00327     return false;
00328   // if name is search_prefix, return false
00329   if (strstr(name, search_prefix) != NULL) {
00330     softegg_cat.debug() << "matched " << name << " ";
00331     return false;
00332   }
00333   // if name is not search_prefix, look in its parent
00334   if (strstr(name, search_prefix) == NULL) {
00335     softegg_cat.debug() << "node " << name << " ";
00336     if (_parent) 
00337       return _parent->is_partial(search_prefix);
00338   }
00339   // neither name nor its parent is search_prefix
00340   return true;
00341 }
00342 
00343 ///////////////////////////////////////////////////////////////////////
00344 //     Function: SoftNodeTree::set_parentJoint
00345 //       Access: Public
00346 //  Description: Go through the ancestors and figure out who is the 
00347 //               immediate _parentJoint of this node
00348 ///////////////////////////////////////////////////////////////////////
00349 void SoftNodeDesc::
00350 set_parentJoint(SAA_Scene *scene, SoftNodeDesc *lastJoint) {
00351   if (is_junk())
00352     return;
00353   //set its parent joint to the lastJoint
00354   _parentJoint = lastJoint;
00355   softegg_cat.spam() << get_name() << ": parent joint set to :" << lastJoint;
00356   if (lastJoint)
00357     softegg_cat.spam() << "(" << lastJoint->get_name() << ")";
00358   softegg_cat.spam() << endl;
00359 
00360   // is this node a joint?
00361   SAA_Boolean isSkeleton = false;
00362   if (has_model())
00363     SAA_modelIsSkeleton( scene, get_model(), &isSkeleton );
00364   
00365   // if  already a joint or name has "joint" in it
00366   const char *name = get_name().c_str();
00367   if (is_joint() || isSkeleton || strstr(name, "joint") != NULL) {
00368     lastJoint = this;
00369   }
00370   if ( _parentJoint && strstr( _parentJoint->get_name().c_str(), "scale" ) != NULL ) {
00371     // make sure _parentJoint didn't have the name "joint" in it
00372     if (strstr(_parentJoint->get_name().c_str(), "joint") == NULL) {
00373       _parentJoint = NULL;
00374       //    _parentJoint = lastJoint = NULL;
00375       softegg_cat.spam() << "scale joint flag set!\n";
00376     }
00377   }
00378 
00379   // look in the children
00380   Children::const_iterator ci;
00381   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00382     SoftNodeDesc *child = (*ci);
00383     child->set_parentJoint(scene, lastJoint);
00384   }
00385 }
00386 
00387 ////////////////////////////////////////////////////////////////////
00388 //     Function: SoftNodeDesc::check_pseudo_joints
00389 //       Access: Private
00390 //  Description: Walks the hierarchy, looking for non-joint nodes that
00391 //               are both children and parents of a joint.  These
00392 //               nodes are deemed to be pseudo joints, since the
00393 //               converter must treat them as joints.
00394 ////////////////////////////////////////////////////////////////////
00395 void SoftNodeDesc::
00396 check_pseudo_joints(bool joint_above) {
00397   if (_joint_type == JT_joint_parent && joint_above) {
00398     // This is one such node: it is the parent of a joint
00399     // (JT_joint_parent is set), and it is the child of a joint
00400     // (joint_above is set).
00401     _joint_type = JT_pseudo_joint;
00402     softegg_cat.debug() << "pseudo " << get_name() << " case1\n";
00403   }
00404 
00405   if (_joint_type == JT_joint) {
00406     // If this node is itself a joint, then joint_above is true for
00407     // all child nodes.
00408     joint_above = true;
00409   }
00410 
00411   // Don't bother traversing further if _joint_type is none or junk, since
00412   // that means this node has no joint children.
00413   if (_joint_type != JT_none && _joint_type != JT_junk) {
00414 
00415     bool any_joints = false;
00416     Children::const_iterator ci;
00417     for (ci = _children.begin(); ci != _children.end(); ++ci) {
00418       SoftNodeDesc *child = (*ci);
00419       child->check_pseudo_joints(joint_above);
00420       if (child->is_joint()) {
00421         softegg_cat.spam() << get_name() << " any_joint true by " << child->get_name() << endl;
00422         any_joints = true;
00423       }
00424     }
00425 
00426     // If any children qualify as joints, then any sibling nodes that
00427     // are parents of joints are also elevated to joints.
00428     if (any_joints) {
00429       bool all_joints = true;
00430       for (ci = _children.begin(); ci != _children.end(); ++ci) {
00431         SoftNodeDesc *child = (*ci);
00432         if (child->_joint_type == JT_joint_parent) {
00433           child->_joint_type = JT_pseudo_joint;
00434           softegg_cat.debug() << "pseudo " << child->get_name() << " case2 by parent " << get_name() << "\n";
00435         } else if (child->_joint_type == JT_none || child->_joint_type == JT_junk) {
00436           all_joints = false;
00437         }
00438       }
00439 
00440       if (all_joints || any_joints) {
00441         // Finally, if all children or at least one is a joint, then we are too.
00442         if (_joint_type == JT_joint_parent) {
00443           _joint_type = JT_pseudo_joint;
00444           softegg_cat.debug() << "pseudo " << get_name() << " case3\n";
00445         }
00446       }
00447     }
00448   }
00449   else
00450     softegg_cat.spam() << "found null joint " << get_name() << endl;
00451 }
00452 
00453 ////////////////////////////////////////////////////////////////////
00454 //     Function: SoftToEggConverter::get_transform
00455 //       Access: Private
00456 //  Description: Extracts the transform on the indicated Soft node,
00457 //               and applies it to the corresponding Egg node.
00458 ////////////////////////////////////////////////////////////////////
00459 void SoftNodeDesc::
00460 get_transform(SAA_Scene *scene, EggGroup *egg_group, bool global) {
00461   // Get the model's matrix
00462   int scale_joint = 0;
00463 
00464   if (!global && _parentJoint && !stec.flatten && !scale_joint) {
00465 
00466     SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_LOCAL,  matrix );
00467     softegg_cat.debug() << get_name() << " using local matrix :parent ";
00468 
00469   } else {
00470 
00471     SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_GLOBAL,  matrix );
00472     softegg_cat.debug() << get_name() << " using global matrix :parent ";
00473 
00474   }
00475 
00476   if (_parentJoint && !stec.flatten)
00477     softegg_cat.debug() << _parentJoint->get_name() << endl;
00478   else
00479     softegg_cat.debug() << _parentJoint << endl;
00480     
00481 
00482   softegg_cat.spam() << "model matrix = " << matrix[0][0] << " " << matrix[0][1] << " " << matrix[0][2] << " " << matrix[0][3] << "\n";
00483   softegg_cat.spam() << "model matrix = " << matrix[1][0] << " " << matrix[1][1] << " " << matrix[1][2] << " " << matrix[1][3] << "\n";
00484   softegg_cat.spam() << "model matrix = " << matrix[2][0] << " " << matrix[2][1] << " " << matrix[2][2] << " " << matrix[2][3] << "\n";
00485   softegg_cat.spam() << "model matrix = " << matrix[3][0] << " " << matrix[3][1] << " " << matrix[3][2] << " " << matrix[3][3] << "\n";
00486 
00487   if (!global && is_joint()) {
00488     LMatrix4d m4d(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
00489                   matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
00490                   matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
00491                   matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
00492     if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
00493       egg_group->set_transform3d(m4d);
00494       softegg_cat.spam() << "set transform in egg_group\n";
00495     }
00496   }
00497   return;
00498 }
00499 
00500 ////////////////////////////////////////////////////////////////////
00501 //     Function: SoftNodeDesc::get_joint_transform
00502 //       Access: Private
00503 //  Description: Extracts the transform on the indicated Soft node,
00504 //               as appropriate for a joint in an animated character,
00505 //               and applies it to the indicated node.  This is
00506 //               different from get_transform() in that it does not
00507 //               respect the _transform_type flag, and it does not
00508 //               consider the relative transforms within the egg file.
00509 //               more added functionality: now fills in components of
00510 //               anim (EffXfmSAnim) class (masad).
00511 ////////////////////////////////////////////////////////////////////
00512 void SoftNodeDesc::
00513 get_joint_transform(SAA_Scene *scene,  EggGroup *egg_group, EggXfmSAnim *anim, bool global) {
00514   //  SI_Error result;
00515   SAA_Elem *skeletonPart = _model;
00516   const char *name = get_name().c_str();
00517 
00518   if ( skeletonPart != NULL ) {
00519     PN_stdfloat i,j,k;
00520     PN_stdfloat h,p,r;
00521     PN_stdfloat x,y,z;
00522     int scale_joint = 0;
00523 
00524     softegg_cat.spam() << "\n\nanimating child " << name << endl;
00525 
00526     if (_parentJoint && !stec.flatten && !scale_joint ) {
00527       softegg_cat.debug() << "using local matrix\n";
00528 
00529       //get SAA orientation
00530       SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
00531                             &p, &h, &r );
00532 
00533       //get SAA translation
00534       SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
00535                                &x, &y, &z );
00536       
00537       //get SAA scaling
00538       SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
00539                            &i, &j, &k );
00540     } else {
00541       softegg_cat.debug() << " using global matrix\n";
00542 
00543       //get SAA orientation
00544       SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
00545                             &p, &h, &r );
00546 
00547       //get SAA translation
00548       SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
00549                                &x, &y, &z );
00550 
00551       //get SAA scaling
00552       SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
00553                            &i, &j, &k );
00554     }
00555     
00556     softegg_cat.spam() << "\nanim data: " << i << " " << j << " " << k << endl;
00557     softegg_cat.spam() << "\t" << p << " " << h << " " << r << endl;
00558     softegg_cat.spam() << "\t" << x << " " << y << " " << z << endl;
00559 
00560     // Encode the component multiplication ordering in the egg file.
00561     // SoftImage always uses this order, regardless of the setting of
00562     // temp-hpr-fix.
00563     anim->set_order("sphrt");
00564 
00565     // Add each component by their names
00566     anim->add_component_data("i", i);
00567     anim->add_component_data("j", j);
00568     anim->add_component_data("k", k);
00569     anim->add_component_data("p", p);
00570     anim->add_component_data("h", h);
00571     anim->add_component_data("r", r);
00572     anim->add_component_data("x", x);
00573     anim->add_component_data("y", y);
00574     anim->add_component_data("z", z);
00575   }
00576   else {
00577     softegg_cat.debug() << "Cannot build anim table - no skeleton\n";
00578   }
00579 }
00580 
00581 ////////////////////////////////////////////////////////////////////
00582 //     Function: SoftNodeDesc::load_poly_model
00583 //       Access: Private
00584 //  Description: Converts the indicated Soft polyset to a bunch of
00585 //               EggPolygons and parents them to the indicated egg
00586 //               group.
00587 ////////////////////////////////////////////////////////////////////
00588 void SoftNodeDesc::
00589 load_poly_model(SAA_Scene *scene, SAA_ModelType type) {
00590   SI_Error result;
00591   const char *name = get_name().c_str();
00592   
00593   int i;
00594   int id = 0;
00595 
00596   // if making a pose - get deformed geometry
00597   if ( stec.make_pose )
00598     gtype = SAA_GEOM_DEFORMED;
00599         
00600   // If the model is a PATCH in soft, set its step before tesselating
00601   else if ( type == SAA_MPTCH )
00602     SAA_patchSetStep( scene, _model, stec.nurbs_step, stec.nurbs_step );
00603   
00604   // Get the number of triangles    
00605   result = SAA_modelGetNbTriangles( scene, _model, gtype, id, &numTri);
00606   softegg_cat.spam() << "triangles: " << numTri << "\n";
00607   
00608   if ( result != SI_SUCCESS ) {
00609     softegg_cat.spam() << "Error: couldn't get number of triangles!\n";
00610     softegg_cat.debug() << "\tbailing on model: " << name << "\n";
00611     return;    
00612   }
00613   
00614   // check to see if surface is also skeleton...
00615   SAA_Boolean isSkeleton = FALSE;
00616   
00617   SAA_modelIsSkeleton( scene, _model, &isSkeleton );
00618   
00619   // check to see if this surface is used as a skeleton
00620   // or is animated via constraint only ( these nodes are
00621   // tagged by the animator with the keyword "joint"
00622   // somewhere in the nodes name)
00623   softegg_cat.spam() << "is Skeleton? " << isSkeleton << "\n";
00624   
00625   /*************************************************************************************/
00626   
00627   // model is not a null and has no triangles!
00628   if ( !numTri ) {
00629     softegg_cat.spam() << "no triangles!\n";
00630   }
00631   else {
00632     // allocate array of triangles
00633     triangles = (SAA_SubElem *) new SAA_SubElem[numTri];
00634     if (!triangles) {
00635       softegg_cat.info() << "Not enough Memory for triangles...\n";
00636       exit(1);
00637     }
00638     // triangulate model and read the triangles into array
00639     SAA_modelGetTriangles( scene, _model, gtype, id, numTri, triangles );
00640     softegg_cat.spam() << "got triangles\n";
00641     
00642     /***********************************************************************************/
00643     
00644     // allocate array of materials (Asad: it gives a warning if try to get one triangle
00645     //                                    at a time...investigate later
00646     // read each triangle's material into array  
00647     materials = (SAA_Elem*) new SAA_Elem[numTri];
00648     SAA_triangleGetMaterials( scene, _model, numTri, triangles, materials );
00649     if (!materials) {
00650       softegg_cat.info() << "Not enough Memory for materials...\n";
00651       exit(1);
00652     }
00653     softegg_cat.spam() << "got materials\n";
00654     
00655     /***********************************************************************************/
00656     
00657     // allocate array of textures per triangle
00658     numTexTri = new int[numTri];
00659     const void *relinfo;
00660     
00661     // find out how many local textures per triangle
00662     for (i = 0; i < numTri; i++) {    
00663       result = SAA_materialRelationGetT2DLocNbElements( scene, &materials[i], FALSE, 
00664                                                         &relinfo, &numTexTri[i] );
00665       // polytex    
00666       if ( result == SI_SUCCESS )
00667         numTexLoc += numTexTri[i];
00668     }
00669     
00670     // don't need this anymore...
00671     //free( numTexTri ); 
00672     
00673     // get local textures if present
00674     if ( numTexLoc ) {
00675       softegg_cat.spam() << "numTexLoc = " << numTexLoc << endl;
00676       
00677       // allocate arrays of texture info
00678       uScale = new PN_stdfloat[numTri];
00679       vScale = new PN_stdfloat[numTri];
00680       uOffset = new PN_stdfloat[numTri];
00681       vOffset = new PN_stdfloat[numTri];
00682       texNameArray = new char *[numTri];
00683       uRepeat = new int[numTri];
00684       vRepeat = new int[numTri];
00685       
00686       // ASSUME only one texture per material
00687       textures = new SAA_Elem[numTri];
00688       
00689       for ( i = 0; i < numTri; i++ ) {
00690         // and read all referenced local textures into array
00691         SAA_materialRelationGetT2DLocElements( scene, &materials[i],
00692                                                TEX_PER_MAT , &textures[i] );
00693 
00694         // initialize the array value
00695         texNameArray[i] = NULL;
00696         // initialize the repeats
00697         uRepeat[i] = vRepeat[i] = 0;
00698         
00699         // see if this triangle has texture info
00700         if (numTexTri[i] == 0)
00701           continue;
00702 
00703         // check to see if texture is present
00704         result = SAA_elementIsValid( scene, &textures[i], &valid );
00705         
00706         if ( result != SI_SUCCESS )
00707           softegg_cat.spam() << "SAA_elementIsValid failed!!!!\n";
00708         
00709         // texture present - get the name and uv info 
00710         if ( valid ) {
00711           // according to drose, we don't need to convert .pic files to .rgb,
00712           // panda can now read the .pic files.
00713           texNameArray[i] = stec.GetTextureName(scene, &textures[i]);
00714           
00715           softegg_cat.spam() << " tritex[" << i << "] named: " << texNameArray[i] << endl;
00716           
00717           SAA_texture2DGetUVSwap( scene, &textures[i], &uv_swap );
00718           
00719           if ( uv_swap == TRUE )
00720             softegg_cat.spam() << " swapping u and v...\n" ;
00721           
00722           SAA_texture2DGetUScale( scene, &textures[i], &uScale[i] );
00723           SAA_texture2DGetVScale( scene, &textures[i], &vScale[i] );
00724           SAA_texture2DGetUOffset( scene, &textures[i], &uOffset[i] );
00725           SAA_texture2DGetVOffset( scene, &textures[i], &vOffset[i] );
00726           
00727           softegg_cat.spam() << "tritex[" << i << "] uScale: " << uScale[i] << " vScale: " << vScale[i] << endl;
00728           softegg_cat.spam() << " uOffset: " << uOffset[i] << " vOffset: " << vOffset[i] << endl;
00729           
00730           SAA_texture2DGetRepeats( scene, &textures[i], &uRepeat[i], &vRepeat[i] );
00731           softegg_cat.spam() << "uRepeat = " << uRepeat[i] << ", vRepeat = " << vRepeat[i] << endl;
00732         }
00733         else {
00734           softegg_cat.spam() << "Invalid texture...\n";
00735           softegg_cat.spam() << " tritex[" << i << "] named: (null)\n";
00736         }
00737       }
00738     }
00739     else { // if no local textures, try to get global textures
00740       SAA_modelRelationGetT2DGlbNbElements( scene, _model,
00741                                             FALSE, &relinfo, &numTexGlb );
00742       if ( numTexGlb ) {
00743         // ASSUME only one texture per model
00744         textures = new SAA_Elem;
00745         // get the referenced texture
00746         SAA_modelRelationGetT2DGlbElements( scene, _model, 
00747                                             TEX_PER_MAT, textures ); 
00748         softegg_cat.spam() << "numTexGlb = " << numTexGlb << endl;
00749         // check to see if texture is present
00750         SAA_elementIsValid( scene, textures, &valid );
00751         if ( valid ) {  // texture present - get the name and uv info 
00752           SAA_texture2DGetUVSwap( scene, textures, &uv_swap );
00753           
00754           if ( uv_swap == TRUE )
00755             softegg_cat.spam() << " swapping u and v...\n";
00756           
00757           // according to drose, we don't need to convert .pic files to .rgb,
00758           // panda can now read the .pic files.
00759           texNameArray = new char *[1];
00760           *texNameArray = stec.GetTextureName(scene, textures);
00761 
00762           uRepeat = new int;
00763           vRepeat = new int;
00764           
00765           softegg_cat.spam() << " global tex named: " << *texNameArray << endl;
00766           
00767           // allocate arrays of texture info
00768           uScale = new PN_stdfloat;
00769           vScale = new PN_stdfloat;
00770           uOffset = new PN_stdfloat;
00771           vOffset = new PN_stdfloat;
00772           
00773           SAA_texture2DGetUScale( scene, textures, uScale );
00774           SAA_texture2DGetVScale( scene, textures, vScale );
00775           SAA_texture2DGetUOffset( scene, textures, uOffset );
00776           SAA_texture2DGetVOffset( scene, textures, vOffset );
00777           
00778           softegg_cat.spam() << " global tex uScale: " << *uScale << " vScale: " << *vScale << endl;
00779           softegg_cat.spam() << "            uOffset: " << *uOffset << " vOffset: " << *vOffset << endl;
00780           
00781           SAA_texture2DGetRepeats(  scene, textures, uRepeat, vRepeat );
00782           softegg_cat.spam() << "uRepeat = " << *uRepeat << ", vRepeat = " << *vRepeat << endl;
00783         }
00784         else {
00785           softegg_cat.spam() << "Invalid Texture...\n";
00786         }
00787       }
00788     }
00789   }
00790   softegg_cat.spam() << "got textures" << endl;
00791 }
00792 
00793 ////////////////////////////////////////////////////////////////////
00794 //     Function: SoftNodeDesc::load_nurbs_model
00795 //       Access: Private
00796 //  Description: Converts the indicated Soft polyset to a bunch of
00797 //               EggPolygons and parents them to the indicated egg
00798 //               group.
00799 ////////////////////////////////////////////////////////////////////
00800 void SoftNodeDesc::
00801 load_nurbs_model(SAA_Scene *scene, SAA_ModelType type) {
00802   SI_Error result;
00803   const char *name = get_name().c_str();
00804   
00805   // if making a pose - get deformed geometry
00806   if ( stec.make_pose )
00807     gtype = SAA_GEOM_DEFORMED;
00808         
00809   // If the model is a NURBS in soft, set its step before tesselating
00810   if ( type == SAA_MNSRF )
00811     SAA_nurbsSurfaceSetStep( scene, _model, stec.nurbs_step, stec.nurbs_step );
00812   
00813   // get the materials
00814   /***********************************************************************************/
00815   const void *relinfo;
00816 
00817   SAA_modelRelationGetMatNbElements( scene, get_model(), FALSE, &relinfo,
00818                                      &numNurbMats );
00819 
00820   softegg_cat.spam() << "nurbs surf has " << numNurbMats << " materials\n";
00821 
00822   if ( numNurbMats ) {
00823     materials = new SAA_Elem[numNurbMats];
00824     if (!materials) {
00825       softegg_cat.info() << "Out Of Memory on allocating materials\n";
00826       exit(1);
00827     }
00828     
00829     SAA_modelRelationGetMatElements( scene, get_model(), relinfo, 
00830                                      numNurbMats, materials ); 
00831     
00832     softegg_cat.spam() << "got materials\n";
00833 
00834     // get the textures
00835     /***********************************************************************************/
00836     numNurbTexLoc = 0;
00837     numNurbTexGlb = 0;
00838     
00839     // find out how many local textures per NURBS surface
00840     // ASSUME it only has one material
00841     SAA_materialRelationGetT2DLocNbElements( scene, &materials[0], FALSE, &relinfo, &numNurbTexLoc );
00842     
00843     // if present, get local textures
00844     if ( numNurbTexLoc ) {
00845       softegg_cat.spam() << name << " had " << numNurbTexLoc << " local tex\n";
00846       nassertv(numNurbTexLoc == 1);
00847       
00848       textures = new SAA_Elem[numNurbTexLoc];
00849       
00850       // get the referenced texture
00851       SAA_materialRelationGetT2DLocElements( scene, &materials[0], TEX_PER_MAT, &textures[0] );
00852       
00853     }
00854     // if no locals, try to get globals
00855     else {
00856       SAA_modelRelationGetT2DGlbNbElements( scene, get_model(), FALSE, &relinfo, &numNurbTexGlb );
00857       
00858       if ( numNurbTexGlb ) {
00859         softegg_cat.spam() << name << " had " << numNurbTexGlb << " global tex\n";
00860         nassertv(numNurbTexGlb == 1);
00861         
00862         textures = new SAA_Elem[numNurbTexGlb];
00863         
00864         // get the referenced texture
00865         SAA_modelRelationGetT2DGlbElements( scene, get_model(), TEX_PER_MAT, &textures[0] );
00866       }
00867     }
00868     
00869     if ( numNurbTexLoc || numNurbTexGlb) {
00870       
00871       // allocate the texture name array
00872       texNameArray = new char *[1];
00873       // allocate arrays of texture info
00874       uScale = new PN_stdfloat;
00875       vScale = new PN_stdfloat;
00876       uOffset = new PN_stdfloat;
00877       vOffset = new PN_stdfloat;
00878       uRepeat = new int;
00879       vRepeat = new int;
00880       
00881       // check to see if texture is present
00882       result = SAA_elementIsValid( scene, &textures[0], &valid );
00883       
00884       if ( result != SI_SUCCESS )
00885         softegg_cat.spam() << "SAA_elementIsValid failed!!!!\n";
00886       
00887       // texture present - get the name and uv info 
00888       if ( valid ) {
00889         // according to drose, we don't need to convert .pic files to .rgb,
00890         // panda can now read the .pic files.
00891         texNameArray[0] = stec.GetTextureName(scene, &textures[0]);
00892         
00893         softegg_cat.spam() << " tritex[0] named: " << texNameArray[0] << endl;
00894         
00895         SAA_texture2DGetUVSwap( scene, &textures[0], &uv_swap );
00896         
00897         if ( uv_swap == TRUE )
00898           softegg_cat.spam() << " swapping u and v...\n" ;
00899         
00900         SAA_texture2DGetUScale( scene, &textures[0], uScale );
00901         SAA_texture2DGetVScale( scene, &textures[0], vScale );
00902         SAA_texture2DGetUOffset( scene, &textures[0], uOffset );
00903         SAA_texture2DGetVOffset( scene, &textures[0], vOffset );
00904         
00905         softegg_cat.spam() << "tritex[0] uScale: " << *uScale << " vScale: " << *vScale << endl;
00906         softegg_cat.spam() << " uOffset: " << *uOffset << " vOffset: " << *vOffset << endl;
00907         
00908         SAA_texture2DGetRepeats( scene, &textures[0], uRepeat, vRepeat );
00909         softegg_cat.spam() << "uRepeat = " << *uRepeat << ", vRepeat = " << *vRepeat << endl;
00910       }
00911       else {
00912         softegg_cat.spam() << "Invalid texture...\n";
00913         softegg_cat.spam() << " tritex[0] named: (null)\n";
00914       }
00915     }
00916     
00917     softegg_cat.spam() << "got textures\n";
00918   }
00919 }
00920 
00921 ////////////////////////////////////////////////////////////////////
00922 //     Function: find_shape_vert
00923 //       Access: Public
00924 //  Description: given a vertex, find its corresponding shape vertex
00925 //               and return its index.
00926 ////////////////////////////////////////////////////////////////////
00927 int SoftNodeDesc::
00928 find_shape_vert(LPoint3d p3d, SAA_DVector *vertices, int numVert) {
00929   int i, found = 0;
00930 
00931   for (i = 0; i < numVert && !found ; i++) {
00932     if ((p3d[0] == vertices[i].x) && 
00933         (p3d[1] == vertices[i].y) && 
00934         (p3d[2] == vertices[i].z)) {
00935       found = 1;
00936       softegg_cat.spam() << "found shape vert at index " << i << endl;
00937     }
00938   }
00939 
00940   if (!found )
00941     i = -1;
00942   else
00943     i--;
00944 
00945   return i;
00946 }
00947 
00948 ////////////////////////////////////////////////////////////////////
00949 //     Function: make_vertex_offsets
00950 //       Access: Public 
00951 //  Description: Given a scene, a model , the vertices of its original
00952 //               shape and its name find the difference between the 
00953 //               geometry of its key shapes and the models original 
00954 //               geometry and add morph vertices to the egg data to 
00955 //               reflect these changes.
00956 ////////////////////////////////////////////////////////////////////
00957 void SoftNodeDesc::
00958 make_vertex_offsets(int numShapes) {
00959   int i, j;
00960   int offset;
00961   int numCV;
00962   char tableName[_MAX_PATH];
00963   SAA_DVector *shapeVerts = NULL;
00964   SAA_DVector *uniqueVerts = NULL;
00965   SAA_Elem *model = get_model();
00966   SAA_Scene *scene = &stec.scene;
00967 
00968   EggVertexPool *vpool = NULL;
00969   string vpool_name = get_name() + ".verts";
00970   EggNode *t = stec._tree.get_egg_root()->find_child(vpool_name);
00971   if (t)
00972     DCAST_INTO_V(vpool, t);
00973 
00974   int numOrigVert = (int) vpool->size();
00975   EggVertexPool::iterator vi;
00976 
00977   if ((type == SAA_MNSRF) && stec.make_nurbs)
00978     SAA_nurbsSurfaceSetStep( scene, model, stec.nurbs_step, stec.nurbs_step );
00979 
00980   SAA_modelGetNbVertices( scene, model, &numCV );
00981 
00982   // get the shape verts
00983   uniqueVerts = new SAA_DVector[numCV];
00984   SAA_modelGetVertices( scene, model, SAA_GEOM_ORIGINAL, 0,
00985                         numCV, uniqueVerts );
00986 
00987   softegg_cat.spam() << numCV << " CV's\n";
00988 
00989   for ( i = 0; i < numCV; i++ )
00990     // convert vertices to global
00991     _VCT_X_MAT( uniqueVerts[i], uniqueVerts[i], matrix);
00992     softegg_cat.spam() << "uniqueVerts[" << i << "] = " << uniqueVerts[i].x << " " << uniqueVerts[i].y
00993          << " " << uniqueVerts[i].z << " " << uniqueVerts[i].w << endl;
00994 
00995   // iterate through for each key shape (except original)
00996   for ( i = 1; i < numShapes; i++ ) {
00997     
00998     sprintf(tableName, "%s.%d", get_name().c_str(), i);
00999 
01000     softegg_cat.spam() << "\nMaking geometry offsets for " << tableName << "...\n";
01001 
01002     if ((type == SAA_MNSRF) && stec.make_nurbs)
01003       softegg_cat.spam() << "calculating NURBS morphs...\n";
01004     else 
01005       softegg_cat.spam() << "calculating triangle morphs...\n";
01006     
01007     // get the shape verts
01008     shapeVerts = new SAA_DVector[numCV];
01009     SAA_modelGetVertices( scene, model, SAA_GEOM_SHAPE, i+1, numCV, shapeVerts );
01010 
01011     for ( j=0; j < numCV; j++ ) {
01012       // convert vertices to global
01013       _VCT_X_MAT( shapeVerts[j], shapeVerts[j], matrix);
01014     
01015       softegg_cat.spam() << "shapeVerts[" << j << "] = " << shapeVerts[j].x << " " 
01016            << shapeVerts[j].y << " " << shapeVerts[j].z << endl;
01017     }
01018     softegg_cat.spam() << endl;
01019 
01020     // for every original vertex, compare to the corresponding
01021     // key shape vertex and see if a vertex offset is needed 
01022     j = 0;
01023     for (vi = vpool->begin(); vi != vpool->end(); ++vi, ++j) {
01024 
01025       double dx, dy, dz;
01026       EggVertex *vert = (*vi);
01027       LPoint3d p3d = vert->get_pos3();
01028       
01029       softegg_cat.spam() << "oVert[" << j << "] = " <<  p3d[0] << " " <<  p3d[1] << " " <<  p3d[2] << endl;
01030       if ((type == SAA_MNSRF) && stec.make_nurbs) {
01031         dx = shapeVerts[j].x - p3d[0]; 
01032         dy = shapeVerts[j].y - p3d[1]; 
01033         dz = shapeVerts[j].z - p3d[2]; 
01034 
01035         softegg_cat.spam() << "global shapeVerts[" << j << "] = " << shapeVerts[j].x << " "
01036              << shapeVerts[j].y << " " << shapeVerts[j].z << " " << shapeVerts[j].w << endl;
01037       }
01038       else {
01039         // we need to map from original vertices
01040         // to triangle shape vertices here
01041         offset = find_shape_vert(p3d, uniqueVerts, numCV);
01042 
01043         dx = shapeVerts[offset].x - p3d[0]; 
01044         dy = shapeVerts[offset].y - p3d[1]; 
01045         dz = shapeVerts[offset].z - p3d[2]; 
01046 
01047         softegg_cat.spam() << "global shapeVerts[" << offset << "] = " << shapeVerts[offset].x << " "
01048              << shapeVerts[offset].y << " " << shapeVerts[offset].z << endl;
01049       }
01050 
01051       softegg_cat.spam() << j << ": dx = " << dx << ", dy = " << dy << ", dz = " << dz << endl;
01052 
01053       // if change isn't negligible, make a morph vertex entry 
01054       double total = fabs(dx)+fabs(dy)+fabs(dz);
01055       if ( total > 0.00001 ) {
01056         if ( vpool != NULL ) {
01057           // create offset
01058           LVector3d p(dx, dy, dz);
01059           EggMorphVertex *dxyz = new EggMorphVertex(tableName, p);
01060           // add the offset to the vertex
01061           vert->_dxyzs.insert(*dxyz);
01062         }
01063         else
01064           softegg_cat.spam() << "Error: couldn't find vertex pool " << vpool_name << endl; 
01065                 
01066       } // if total
01067     } //for j
01068   } //for i
01069 }
01070 
01071 ////////////////////////////////////////////////////////////////////
01072 //     Function: make_morph_table
01073 //       Access: Public 
01074 //  Description: Given a scene, a model, a name and a frame time,
01075 //               determine what type of shape interpolation is
01076 //               used and call the appropriate function to extract
01077 //               the shape weight info for this frame...
01078 ////////////////////////////////////////////////////////////////////
01079 void SoftNodeDesc::
01080 make_morph_table(  PN_stdfloat time ) {
01081   int numShapes;
01082   SAA_Elem *model = NULL;
01083   SAA_AnimInterpType type;
01084   SAA_Scene *scene = &stec.scene;
01085   
01086   if (has_model())
01087     model = get_model();
01088   else 
01089     return;
01090 
01091   // Get the number of key shapes
01092   SAA_modelGetNbShapes( scene, model, &numShapes );
01093 
01094   if ( numShapes <= 0 ) {
01095     return;
01096   }
01097 
01098   stec.has_morph = true;
01099 
01100   softegg_cat.spam() << "make_morph_table: " << get_name() << " : num shapes: " << numShapes << endl;
01101 
01102   SAA_modelGetShapeInterpolation( scene, model, &type );
01103 
01104   if ( type == SAA_ANIM_LINEAR || type == SAA_ANIM_CARDINAL ) {
01105     softegg_cat.spam() << "linear morph" << endl;
01106     make_linear_morph_table( numShapes, time );
01107   }
01108   else {    // must be weighted...
01109     // check first for expressions
01110     softegg_cat.spam() << "expression morph" << endl;
01111     make_expression_morph_table( numShapes, time );
01112   }
01113 }
01114 
01115 ////////////////////////////////////////////////////////////////////
01116 //     Function: make_linear_morph_table
01117 //       Access: Public 
01118 //  Description: Given a scene, a model, its name, and the time,
01119 //               get the shape fcurve for the model and determine
01120 //               the shape weights for the given time and use them
01121 //               to populate the morph table.
01122 ////////////////////////////////////////////////////////////////////
01123 void SoftNodeDesc::
01124 make_linear_morph_table(int numShapes, PN_stdfloat time) {    
01125   int i;
01126   PN_stdfloat curveVal;
01127   char tableName[_MAX_PATH];
01128   SAA_Elem fcurve;
01129   //SAnimTable *thisTable;
01130   EggSAnimData *anim;
01131   SAA_Elem *model = get_model();
01132   SAA_Scene *scene = &stec.scene;
01133 
01134   softegg_cat.spam() << "linear interp, getting fcurve\n";
01135 
01136   SAA_modelFcurveGetShape( scene, model, &fcurve );
01137 
01138   SAA_fcurveEval( scene, &fcurve, time, &curveVal );    
01139     
01140   softegg_cat.spam() << "at time " << time << ", fcurve for " << get_name() << " = " << curveVal << endl;
01141 
01142   PN_stdfloat nextVal = 0.0f;
01143 
01144   // populate morph table values for this frame
01145   for ( i = 1; i < numShapes; i++ ) {
01146     // derive table name from the model name
01147     sprintf(tableName, "%s.%d", get_name().c_str(), i);
01148 
01149     softegg_cat.spam() << "Linear: looking for table '" << tableName << "'\n";
01150 
01151     //find the morph table associated with this key shape
01152     anim = stec.find_morph_table(tableName);
01153 
01154     if ( anim != NULL ) {
01155       if ( i == (int)curveVal ) {
01156         if ( curveVal - i == 0 ) {
01157           anim->add_data(1.0f ); 
01158           softegg_cat.spam() << "adding element 1.0f\n";
01159         }
01160         else {
01161           anim->add_data(1.0f - (curveVal - i));
01162           nextVal = curveVal - i;
01163           softegg_cat.spam() << "adding element " << 1.0f - (curveVal - i) << endl;
01164         }
01165       }
01166       else {
01167         if ( nextVal ) {
01168           anim->add_data(nextVal );
01169           nextVal = 0.0f;
01170           softegg_cat.spam() << "adding element " << nextVal << endl;
01171         }
01172         else {
01173           anim->add_data(0.0f);
01174           softegg_cat.spam() << "adding element 0.0f\n";
01175         }
01176       }
01177       
01178       softegg_cat.spam() <<" to '" << tableName << "'\n";
01179     }
01180     else
01181       softegg_cat.spam() << i << " : Couldn't find table '" << tableName << "'\n";
01182   }
01183 }
01184 
01185 ////////////////////////////////////////////////////////////////////
01186 //     Function: make_weighted_morph_table
01187 //       Access: Public 
01188 //  Description: Given a scene, a model, a list of all models in the
01189 //               scene, the number of models in the scece, the number 
01190 //               of key shapes for this model, the name of the model
01191 //               and the current time, determine what method of
01192 //               controlling the shape weights is used and call the
01193 //               appropriate routine.
01194 ////////////////////////////////////////////////////////////////////
01195 void SoftNodeDesc::
01196 make_weighted_morph_table(int numShapes, PN_stdfloat time) {
01197   PN_stdfloat curveVal;
01198   SI_Error result;
01199   char tableName[_MAX_PATH];
01200   SAA_Elem *weightCurves;
01201   //SAnimTable *thisTable;
01202   EggSAnimData *anim;
01203   SAA_Elem *model = get_model();
01204   SAA_Scene *scene = &stec.scene;
01205 
01206   // allocate array of weight curves (one for each shape)
01207   weightCurves = new SAA_Elem[numShapes]; 
01208 
01209   result = SAA_modelFcurveGetShapeWeights(scene, model, numShapes, weightCurves);
01210 
01211   if ( result == SI_SUCCESS ) {
01212     for ( int i = 1; i < numShapes; i++ ) {
01213       SAA_fcurveEval( scene, &weightCurves[i], time, &curveVal );    
01214 
01215       // make sure soft gave us a reasonable number
01216       //if (!isNum(curveVal))
01217       //curveVal = 0.0f;
01218       
01219       softegg_cat.spam() << "at time " << time << ", weightCurve[" << i << "] for " << get_name() << " = " << curveVal << endl;
01220       
01221       // derive table name from the model name
01222       sprintf(tableName, "%s.%d", get_name().c_str(), i);
01223       
01224       // find and populate shape table
01225       softegg_cat.spam() << "Weight: looking for table '" << tableName << "'\n";
01226       
01227       //find the morph table associated with this key shape
01228       anim = stec.find_morph_table(tableName);
01229       
01230       if ( anim != NULL ) {    
01231         anim->add_data(curveVal); 
01232         softegg_cat.spam() << "adding element " << curveVal << endl;
01233       }
01234       else
01235         softegg_cat.spam() << i << " : Couldn't find table '" << tableName << "'\n";
01236     }
01237   }
01238 }
01239 
01240 ////////////////////////////////////////////////////////////////////
01241 //     Function: make_expression_morph_table
01242 //       Access: Public 
01243 //  Description: Given a scene, a model and its number of key shapes
01244 //               generate a morph table describing transitions btwn
01245 //               the key shapes by evaluating the positions of the
01246 //               controlling sliders. 
01247 ////////////////////////////////////////////////////////////////////
01248 void SoftNodeDesc::
01249 make_expression_morph_table(int numShapes, PN_stdfloat time)
01250 {    
01251   //int j;
01252   int numExp;
01253   char *track;
01254   //PN_stdfloat expVal;
01255   //PN_stdfloat sliderVal;
01256   //char *tableName;
01257   //char *sliderName;
01258   //SAnimTable *thisTable;
01259   SAA_Elem *expressions;
01260   SI_Error result;
01261 
01262   SAA_Elem *model = get_model();
01263   SAA_Scene *scene = &stec.scene;
01264 
01265   // populate morph table values for this frame
01266 
01267   // compose track name
01268   track = NULL;
01269 
01270   // find how many expressions for this shape
01271   SAA_elementGetNbExpressions( scene, model, track, FALSE, &numExp );
01272 
01273   softegg_cat.spam() << get_name() << " has " << numExp << " RHS expressions\n";
01274 
01275   if ( numExp ) {
01276     // get the expressions for this shape
01277     expressions = new SAA_Elem[numExp];
01278     softegg_cat.spam() << "getting " << numExp << " RHS expressions...\n";
01279 
01280     result = SAA_elementGetExpressions( scene, model, track, FALSE,
01281                                         numExp, expressions );
01282     /*
01283     if ( !result ) {
01284       for ( j = 1; j < numExp; j++ ) {
01285         if ( verbose >= 2 )
01286                 {
01287                 // debug see what we got
01288                 int numvars;
01289         
01290                 SAA_expressionGetNbVars( scene, &expressions[j], &numvars );
01291 
01292                 int *varnamelen;
01293                 int *varstrlen;
01294                 int  expstrlen;
01295 
01296                 varnamelen = (int *)malloc(sizeof(int)*numvars);
01297                 varstrlen = (int *)malloc(sizeof(int)*numvars);
01298 
01299                 SAA_expressionGetStringLengths( scene, &expressions[j],
01300                     numvars, varnamelen, varstrlen, &expstrlen );    
01301 
01302                 int *varnamesizes;    
01303                 int *varstrsizes;
01304 
01305                 varnamesizes = (int *)malloc(sizeof(int)*numvars);
01306                 varstrsizes = (int *)malloc(sizeof(int)*numvars);
01307 
01308                 for ( int k = 0; k < numvars; k++ )
01309                 {
01310                     varnamesizes[k] = varnamelen[k] + 1;
01311                     varstrsizes[k] = varstrlen[k] + 1;
01312                 }
01313     
01314                 int expstrsize = expstrlen + 1;
01315 
01316                 char **varnames;
01317                 char **varstrs;
01318 
01319                 varnames = (char **)malloc(sizeof(char *)*numvars);
01320                 varstrs = (char **)malloc(sizeof(char *)*numvars);
01321 
01322                 for ( k = 0; k < numvars; k++ )
01323                 {
01324                     varnames[k] = (char *)malloc(sizeof(char)*
01325                         varnamesizes[k]);
01326 
01327                     varstrs[k] = (char *)malloc(sizeof(char)*
01328                         varstrsizes[k]);
01329                 }
01330         
01331                 char *expstr = (char *)malloc(sizeof(char)* expstrsize );    
01332 
01333                 SAA_expressionGetStrings( scene, &expressions[j], numvars,
01334                     varnamesizes, varstrsizes, expstrsize, varnames,
01335                     varstrs, expstr );
01336                 
01337                 if ( verbose >= 2 )
01338                 {
01339                     fprintf( outStream, "expression = '%s'\n", expstr );
01340                     fprintf( outStream, "has %d variables\n", numvars );
01341                 }
01342                 } //if verbose
01343                 
01344                 if ( verbose >= 2 )
01345                     fprintf( outStream, "evaling expression...\n" );
01346 
01347                 SAA_expressionEval( scene, &expressions[j], time, &expVal ); 
01348 
01349                 if ( verbose >= 2 )
01350                     fprintf( outStream, "time %f: exp val %f\n", 
01351                         time, expVal );
01352 
01353                 // derive table name from the model name
01354                 tableName = MakeTableName( name, j );
01355 
01356                 if ( verbose >= 2 )
01357                     fprintf( outStream, "Exp: looking for table '%s'\n", 
01358                         tableName );
01359 
01360                 //find the morph table associated with this key shape
01361                 anim = (SAnimTable *)
01362                     (morphRoot->FindDescendent( tableName ));
01363 
01364                 if ( anim != NULL )
01365                 {    
01366                     anim->AddElement( expVal ); 
01367                     if ( verbose >= 1 )    
01368                         fprintf( outStream, "%d: adding element %f to %s\n",
01369                             j, expVal, tableName );
01370                     fflush( outStream );
01371                 }
01372                 else
01373                 {
01374                     fprintf( outStream, "%d: Couldn't find table '%s'", j, 
01375                             tableName ); 
01376 
01377                     fprintf( outStream, " for value %f\n", expVal );
01378                 }
01379             }
01380         }
01381         else
01382             fprintf( outStream, "couldn't get expressions!!!\n" );
01383     */
01384   }
01385   else {
01386     softegg_cat.spam() << "weighted morph" << endl;
01387     // no expression, use weight curves
01388     make_weighted_morph_table(numShapes, time );
01389   }
01390 }
01391 
01392 //
01393 //
01394 //
 All Classes Functions Variables Enumerations