Panda3D
|
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 //