Panda3D
 All Classes Functions Variables Enumerations
softNodeDesc.cxx
1 // Filename: softNodeDesc.cxx
2 // Created by: masad (03Oct03)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "softNodeDesc.h"
16 #include "config_softegg.h"
17 #include "eggGroup.h"
18 #include "eggXfmSAnim.h"
19 #include "eggSAnimData.h"
20 #include "softToEggConverter.h"
21 #include "dcast.h"
22 
23 TypeHandle SoftNodeDesc::_type_handle;
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: SoftNodeDesc::Constructor
27 // Access: Public
28 // Description:
29 ////////////////////////////////////////////////////////////////////
30 SoftNodeDesc::
31 SoftNodeDesc(SoftNodeDesc *parent, const string &name) :
32  Namable(name),
33  _parent(parent)
34 {
35  _model = (SAA_Elem *)NULL;
36  _egg_group = (EggGroup *)NULL;
37  _egg_table = (EggTable *)NULL;
38  _anim = (EggXfmSAnim *)NULL;
39  _joint_type = JT_none;
40 
41  // Add ourselves to our parent.
42  if (_parent != (SoftNodeDesc *)NULL) {
43  softegg_cat.spam() << "parent name " << _parent->get_name();
44  _parent->_children.push_back(this);
45  }
46 
47  // set the _parentJoint to Null
48  _parentJoint = NULL;
49 
50  fullname = NULL;
51 
52  numTexLoc = 0;
53  numTexGlb = 0;
54 
55  uScale = NULL;
56  vScale = NULL;
57  uOffset = NULL;
58  vOffset = NULL;
59 
60  valid;
61  uv_swap;
62  // SAA_Boolean visible;
63  numTexTri = NULL;
64  textures = NULL;
65  materials = NULL;
66  triangles = NULL;
67  gtype = SAA_GEOM_ORIGINAL;
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: SoftNodeDesc::Destructor
72 // Access: Public
73 // Description:
74 ////////////////////////////////////////////////////////////////////
75 SoftNodeDesc::
76 ~SoftNodeDesc() {
77  // I think it is a mistake to try to delete this. This was one
78  // member of an entire array allocated at once; you can't delete
79  // individual elements of an array.
80 
81  // Screw cleanup, anyway--we'll just let the array leak.
82  /*
83  if (_model != (SAA_Elem *)NULL) {
84  delete _model;
85  }
86  */
87 }
88 
89 ////////////////////////////////////////////////////////////////////
90 // Function: SoftNodeDesc::set_model
91 // Access: Public
92 // Description: Indicates an associated between the SoftNodeDesc and
93 // some SAA_Elem instance.
94 ////////////////////////////////////////////////////////////////////
95 void SoftNodeDesc::
96 set_model(SAA_Elem *model) {
97  _model = model;
98 }
99 
100 ////////////////////////////////////////////////////////////////////
101 // Function: SoftNodeDesc::set_parent
102 // Access: Public
103 // Description: Sometimes, parent is not known at node creation
104 // As soon as it is known, set the parent
105 ////////////////////////////////////////////////////////////////////
106 void SoftNodeDesc::
108  if (_parent) {
109  softegg_cat.spam() << endl;
110  /*
111  softegg_cat.spam() << " expected _parent to be null!?\n";
112  if (_parent == parent)
113  softegg_cat.spam() << " parent already set\n";
114  else {
115  softegg_cat.spam() << " current parent " << _parent->get_name() << " new parent "
116  << parent << endl;
117  }
118  */
119  return;
120  }
121  _parent = parent;
122  softegg_cat.spam() << " set parent to " << _parent->get_name() << endl;
123 
124  // Add ourselves to our parent.
125  _parent->_children.push_back(this);
126 }
127 
128 ////////////////////////////////////////////////////////////////////
129 // Function: SoftNodeDesc::set_parent
130 // Access: Public
131 // Description: Sometimes, parent is not known at node creation
132 // As soon as it is known, set the parent
133 ////////////////////////////////////////////////////////////////////
134 void SoftNodeDesc::
136  if (_parent)
137  softegg_cat.spam() << " current parent " << _parent->get_name();
138 
139  _parent = parent;
140 
141  if (_parent)
142  softegg_cat.spam() << " new parent " << _parent->get_name() << endl;
143 
144  // Add ourselves to our parent.
145  _parent->_children.push_back(this);
146 }
147 
148 ////////////////////////////////////////////////////////////////////
149 // Function: SoftNodeDesc::has_model
150 // Access: Public
151 // Description: Returns true if a Soft dag path has been associated
152 // with this node, false otherwise.
153 ////////////////////////////////////////////////////////////////////
154 bool SoftNodeDesc::
155 has_model() const {
156  return (_model != (SAA_Elem *)NULL);
157 }
158 
159 ////////////////////////////////////////////////////////////////////
160 // Function: SoftNodeDesc::get_model
161 // Access: Public
162 // Description: Returns the SAA_Elem * associated with this node. It
163 // is an error to call this unless has_model()
164 // returned true.
165 ////////////////////////////////////////////////////////////////////
166 SAA_Elem *SoftNodeDesc::
167 get_model() const {
168  nassertr(_model != (SAA_Elem *)NULL, _model);
169  return _model;
170 }
171 
172 ////////////////////////////////////////////////////////////////////
173 // Function: SoftNodeDesc::is_joint
174 // Access: Private
175 // Description: Returns true if the node should be treated as a joint
176 // by the converter.
177 ////////////////////////////////////////////////////////////////////
178 bool SoftNodeDesc::
179 is_joint() const {
180  // return _joint_type == JT_joint || _joint_type == JT_pseudo_joint;
181  return _joint_type == JT_joint;
182 }
183 
184 ////////////////////////////////////////////////////////////////////
185 // Function: SoftNodeDesc::is_junk
186 // Access: Private
187 // Description: Returns true if the node should be treated as a junk
188 // by the converter.
189 ////////////////////////////////////////////////////////////////////
190 bool SoftNodeDesc::
191 is_junk() const {
192  return _joint_type == JT_junk;
193 }
194 
195 ////////////////////////////////////////////////////////////////////
196 // Function: SoftNodeDesc::set_joint
197 // Access: Private
198 // Description: sets the _joint_type to JT_joint
199 ////////////////////////////////////////////////////////////////////
200 void SoftNodeDesc::
202  _joint_type = JT_joint;
203 }
204 ////////////////////////////////////////////////////////////////////
205 // Function: SoftNodeDesc::is_joint_parent
206 // Access: Private
207 // Description: Returns true if the node is the parent or ancestor of
208 // a joint.
209 ////////////////////////////////////////////////////////////////////
210 bool SoftNodeDesc::
212  return _joint_type == JT_joint_parent;
213 }
214 
215 ////////////////////////////////////////////////////////////////////
216 // Function: SoftNodeDesc::clear_egg
217 // Access: Private
218 // Description: Recursively clears the egg pointers from this node
219 // and all children.
220 ////////////////////////////////////////////////////////////////////
221 void SoftNodeDesc::
222 clear_egg() {
223  _egg_group = (EggGroup *)NULL;
224  _egg_table = (EggTable *)NULL;
225  _anim = (EggXfmSAnim *)NULL;
226 
227  Children::const_iterator ci;
228  for (ci = _children.begin(); ci != _children.end(); ++ci) {
229  SoftNodeDesc *child = (*ci);
230  child->clear_egg();
231  }
232 }
233 
234 ////////////////////////////////////////////////////////////////////
235 // Function: SoftNodeDesc::mark_joint_parent
236 // Access: Private
237 // Description: Indicates that this node has at least one child that
238 // is a joint or a pseudo-joint.
239 ////////////////////////////////////////////////////////////////////
240 void SoftNodeDesc::
241 mark_joint_parent() {
242  if (_joint_type == JT_none) {
243  _joint_type = JT_joint_parent;
244  softegg_cat.spam() << " marked parent " << get_name();
245  }
246  else
247  softegg_cat.spam() << " ?parent " << get_name() << " joint type " << _joint_type;
248 
249  if (_parent != (SoftNodeDesc *)NULL) {
250  _parent->mark_joint_parent();
251  }
252  softegg_cat.spam() << endl;
253 }
254 
255 ////////////////////////////////////////////////////////////////////
256 // Function: SoftNodeDesc::check_joint_parent
257 // Access: Private
258 // Description: Walks the hierarchy, if a node is joint, make
259 // sure all its parents are marked JT_joint_parent
260 ////////////////////////////////////////////////////////////////////
261 void SoftNodeDesc::
262 check_joint_parent() {
263  Children::const_iterator ci;
264  for (ci = _children.begin(); ci != _children.end(); ++ci) {
265  SoftNodeDesc *child = (*ci);
266  if (child->is_joint()) {
267  softegg_cat.spam() << "child " << child->get_name();
268  mark_joint_parent();
269  }
270  child->check_joint_parent();
271  }
272 }
273 
274 ///////////////////////////////////////////////////////////////////////
275 // Function: SoftNodeTree::check_junk
276 // Access: Public
277 // Description: check to see if this is a branch we don't want to
278 // descend - this will prevent creating geometry for
279 // animation control structures
280 ///////////////////////////////////////////////////////////////////////
281 void SoftNodeDesc::
282 check_junk(bool parent_junk) {
283  const char *name = get_name().c_str();
284 
285  if (parent_junk) {
286  _joint_type = JT_junk;
287  softegg_cat.spam() << "junk node " << get_name() << endl;
288  }
289  if ( (strstr(name, "con-") != NULL) ||
290  (strstr(name, "con_") != NULL) ||
291  (strstr(name, "fly_") != NULL) ||
292  (strstr(name, "fly-") != NULL) ||
293  (strstr(name, "camRIG") != NULL) ||
294  (strstr(name, "cam_rig") != NULL) ||
295  (strstr(name, "bars") != NULL) )
296  {
297  _joint_type = JT_junk;
298  softegg_cat.spam() << "junk node " << get_name() << endl;
299  parent_junk = true;
300  Children::const_iterator ci;
301  for (ci = _children.begin(); ci != _children.end(); ++ci) {
302  SoftNodeDesc *child = (*ci);
303  softegg_cat.spam() << child->get_name() << ",";
304  }
305  softegg_cat.spam() << endl;
306  }
307  Children::const_iterator ci;
308  for (ci = _children.begin(); ci != _children.end(); ++ci) {
309  SoftNodeDesc *child = (*ci);
310  child->check_junk(parent_junk);
311  }
312 }
313 
314 ///////////////////////////////////////////////////////////////////////
315 // Function: SoftNodeTree::is_partial
316 // Access: Public
317 // Description: check to see if this is a selected branch we want to
318 // descend - this will prevent creating geometry for
319 // other parts
320 ///////////////////////////////////////////////////////////////////////
321 bool SoftNodeDesc::
322 is_partial(char *search_prefix) {
323  const char *name = fullname;
324 
325  // if no search prefix then return false
326  if (!search_prefix)
327  return false;
328  // if name is search_prefix, return false
329  if (strstr(name, search_prefix) != NULL) {
330  softegg_cat.debug() << "matched " << name << " ";
331  return false;
332  }
333  // if name is not search_prefix, look in its parent
334  if (strstr(name, search_prefix) == NULL) {
335  softegg_cat.debug() << "node " << name << " ";
336  if (_parent)
337  return _parent->is_partial(search_prefix);
338  }
339  // neither name nor its parent is search_prefix
340  return true;
341 }
342 
343 ///////////////////////////////////////////////////////////////////////
344 // Function: SoftNodeTree::set_parentJoint
345 // Access: Public
346 // Description: Go through the ancestors and figure out who is the
347 // immediate _parentJoint of this node
348 ///////////////////////////////////////////////////////////////////////
349 void SoftNodeDesc::
350 set_parentJoint(SAA_Scene *scene, SoftNodeDesc *lastJoint) {
351  if (is_junk())
352  return;
353  //set its parent joint to the lastJoint
354  _parentJoint = lastJoint;
355  softegg_cat.spam() << get_name() << ": parent joint set to :" << lastJoint;
356  if (lastJoint)
357  softegg_cat.spam() << "(" << lastJoint->get_name() << ")";
358  softegg_cat.spam() << endl;
359 
360  // is this node a joint?
361  SAA_Boolean isSkeleton = false;
362  if (has_model())
363  SAA_modelIsSkeleton( scene, get_model(), &isSkeleton );
364 
365  // if already a joint or name has "joint" in it
366  const char *name = get_name().c_str();
367  if (is_joint() || isSkeleton || strstr(name, "joint") != NULL) {
368  lastJoint = this;
369  }
370  if ( _parentJoint && strstr( _parentJoint->get_name().c_str(), "scale" ) != NULL ) {
371  // make sure _parentJoint didn't have the name "joint" in it
372  if (strstr(_parentJoint->get_name().c_str(), "joint") == NULL) {
373  _parentJoint = NULL;
374  // _parentJoint = lastJoint = NULL;
375  softegg_cat.spam() << "scale joint flag set!\n";
376  }
377  }
378 
379  // look in the children
380  Children::const_iterator ci;
381  for (ci = _children.begin(); ci != _children.end(); ++ci) {
382  SoftNodeDesc *child = (*ci);
383  child->set_parentJoint(scene, lastJoint);
384  }
385 }
386 
387 ////////////////////////////////////////////////////////////////////
388 // Function: SoftNodeDesc::check_pseudo_joints
389 // Access: Private
390 // Description: Walks the hierarchy, looking for non-joint nodes that
391 // are both children and parents of a joint. These
392 // nodes are deemed to be pseudo joints, since the
393 // converter must treat them as joints.
394 ////////////////////////////////////////////////////////////////////
395 void SoftNodeDesc::
396 check_pseudo_joints(bool joint_above) {
397  if (_joint_type == JT_joint_parent && joint_above) {
398  // This is one such node: it is the parent of a joint
399  // (JT_joint_parent is set), and it is the child of a joint
400  // (joint_above is set).
401  _joint_type = JT_pseudo_joint;
402  softegg_cat.debug() << "pseudo " << get_name() << " case1\n";
403  }
404 
405  if (_joint_type == JT_joint) {
406  // If this node is itself a joint, then joint_above is true for
407  // all child nodes.
408  joint_above = true;
409  }
410 
411  // Don't bother traversing further if _joint_type is none or junk, since
412  // that means this node has no joint children.
413  if (_joint_type != JT_none && _joint_type != JT_junk) {
414 
415  bool any_joints = false;
416  Children::const_iterator ci;
417  for (ci = _children.begin(); ci != _children.end(); ++ci) {
418  SoftNodeDesc *child = (*ci);
419  child->check_pseudo_joints(joint_above);
420  if (child->is_joint()) {
421  softegg_cat.spam() << get_name() << " any_joint true by " << child->get_name() << endl;
422  any_joints = true;
423  }
424  }
425 
426  // If any children qualify as joints, then any sibling nodes that
427  // are parents of joints are also elevated to joints.
428  if (any_joints) {
429  bool all_joints = true;
430  for (ci = _children.begin(); ci != _children.end(); ++ci) {
431  SoftNodeDesc *child = (*ci);
432  if (child->_joint_type == JT_joint_parent) {
433  child->_joint_type = JT_pseudo_joint;
434  softegg_cat.debug() << "pseudo " << child->get_name() << " case2 by parent " << get_name() << "\n";
435  } else if (child->_joint_type == JT_none || child->_joint_type == JT_junk) {
436  all_joints = false;
437  }
438  }
439 
440  if (all_joints || any_joints) {
441  // Finally, if all children or at least one is a joint, then we are too.
442  if (_joint_type == JT_joint_parent) {
443  _joint_type = JT_pseudo_joint;
444  softegg_cat.debug() << "pseudo " << get_name() << " case3\n";
445  }
446  }
447  }
448  }
449  else
450  softegg_cat.spam() << "found null joint " << get_name() << endl;
451 }
452 
453 ////////////////////////////////////////////////////////////////////
454 // Function: SoftToEggConverter::get_transform
455 // Access: Private
456 // Description: Extracts the transform on the indicated Soft node,
457 // and applies it to the corresponding Egg node.
458 ////////////////////////////////////////////////////////////////////
459 void SoftNodeDesc::
460 get_transform(SAA_Scene *scene, EggGroup *egg_group, bool global) {
461  // Get the model's matrix
462  int scale_joint = 0;
463 
464  if (!global && _parentJoint && !stec.flatten && !scale_joint) {
465 
466  SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_LOCAL, matrix );
467  softegg_cat.debug() << get_name() << " using local matrix :parent ";
468 
469  } else {
470 
471  SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_GLOBAL, matrix );
472  softegg_cat.debug() << get_name() << " using global matrix :parent ";
473 
474  }
475 
476  if (_parentJoint && !stec.flatten)
477  softegg_cat.debug() << _parentJoint->get_name() << endl;
478  else
479  softegg_cat.debug() << _parentJoint << endl;
480 
481 
482  softegg_cat.spam() << "model matrix = " << matrix[0][0] << " " << matrix[0][1] << " " << matrix[0][2] << " " << matrix[0][3] << "\n";
483  softegg_cat.spam() << "model matrix = " << matrix[1][0] << " " << matrix[1][1] << " " << matrix[1][2] << " " << matrix[1][3] << "\n";
484  softegg_cat.spam() << "model matrix = " << matrix[2][0] << " " << matrix[2][1] << " " << matrix[2][2] << " " << matrix[2][3] << "\n";
485  softegg_cat.spam() << "model matrix = " << matrix[3][0] << " " << matrix[3][1] << " " << matrix[3][2] << " " << matrix[3][3] << "\n";
486 
487  if (!global && is_joint()) {
488  LMatrix4d m4d(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
489  matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
490  matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
491  matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
492  if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
493  egg_group->set_transform3d(m4d);
494  softegg_cat.spam() << "set transform in egg_group\n";
495  }
496  }
497  return;
498 }
499 
500 ////////////////////////////////////////////////////////////////////
501 // Function: SoftNodeDesc::get_joint_transform
502 // Access: Private
503 // Description: Extracts the transform on the indicated Soft node,
504 // as appropriate for a joint in an animated character,
505 // and applies it to the indicated node. This is
506 // different from get_transform() in that it does not
507 // respect the _transform_type flag, and it does not
508 // consider the relative transforms within the egg file.
509 // more added functionality: now fills in components of
510 // anim (EffXfmSAnim) class (masad).
511 ////////////////////////////////////////////////////////////////////
512 void SoftNodeDesc::
513 get_joint_transform(SAA_Scene *scene, EggGroup *egg_group, EggXfmSAnim *anim, bool global) {
514  // SI_Error result;
515  SAA_Elem *skeletonPart = _model;
516  const char *name = get_name().c_str();
517 
518  if ( skeletonPart != NULL ) {
519  PN_stdfloat i,j,k;
520  PN_stdfloat h,p,r;
521  PN_stdfloat x,y,z;
522  int scale_joint = 0;
523 
524  softegg_cat.spam() << "\n\nanimating child " << name << endl;
525 
526  if (_parentJoint && !stec.flatten && !scale_joint ) {
527  softegg_cat.debug() << "using local matrix\n";
528 
529  //get SAA orientation
530  SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_LOCAL,
531  &p, &h, &r );
532 
533  //get SAA translation
534  SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_LOCAL,
535  &x, &y, &z );
536 
537  //get SAA scaling
538  SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_LOCAL,
539  &i, &j, &k );
540  } else {
541  softegg_cat.debug() << " using global matrix\n";
542 
543  //get SAA orientation
544  SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_GLOBAL,
545  &p, &h, &r );
546 
547  //get SAA translation
548  SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_GLOBAL,
549  &x, &y, &z );
550 
551  //get SAA scaling
552  SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_GLOBAL,
553  &i, &j, &k );
554  }
555 
556  softegg_cat.spam() << "\nanim data: " << i << " " << j << " " << k << endl;
557  softegg_cat.spam() << "\t" << p << " " << h << " " << r << endl;
558  softegg_cat.spam() << "\t" << x << " " << y << " " << z << endl;
559 
560  // Encode the component multiplication ordering in the egg file.
561  // SoftImage always uses this order, regardless of the setting of
562  // temp-hpr-fix.
563  anim->set_order("sphrt");
564 
565  // Add each component by their names
566  anim->add_component_data("i", i);
567  anim->add_component_data("j", j);
568  anim->add_component_data("k", k);
569  anim->add_component_data("p", p);
570  anim->add_component_data("h", h);
571  anim->add_component_data("r", r);
572  anim->add_component_data("x", x);
573  anim->add_component_data("y", y);
574  anim->add_component_data("z", z);
575  }
576  else {
577  softegg_cat.debug() << "Cannot build anim table - no skeleton\n";
578  }
579 }
580 
581 ////////////////////////////////////////////////////////////////////
582 // Function: SoftNodeDesc::load_poly_model
583 // Access: Private
584 // Description: Converts the indicated Soft polyset to a bunch of
585 // EggPolygons and parents them to the indicated egg
586 // group.
587 ////////////////////////////////////////////////////////////////////
588 void SoftNodeDesc::
589 load_poly_model(SAA_Scene *scene, SAA_ModelType type) {
590  SI_Error result;
591  const char *name = get_name().c_str();
592 
593  int i;
594  int id = 0;
595 
596  // if making a pose - get deformed geometry
597  if ( stec.make_pose )
598  gtype = SAA_GEOM_DEFORMED;
599 
600  // If the model is a PATCH in soft, set its step before tesselating
601  else if ( type == SAA_MPTCH )
602  SAA_patchSetStep( scene, _model, stec.nurbs_step, stec.nurbs_step );
603 
604  // Get the number of triangles
605  result = SAA_modelGetNbTriangles( scene, _model, gtype, id, &numTri);
606  softegg_cat.spam() << "triangles: " << numTri << "\n";
607 
608  if ( result != SI_SUCCESS ) {
609  softegg_cat.spam() << "Error: couldn't get number of triangles!\n";
610  softegg_cat.debug() << "\tbailing on model: " << name << "\n";
611  return;
612  }
613 
614  // check to see if surface is also skeleton...
615  SAA_Boolean isSkeleton = FALSE;
616 
617  SAA_modelIsSkeleton( scene, _model, &isSkeleton );
618 
619  // check to see if this surface is used as a skeleton
620  // or is animated via constraint only ( these nodes are
621  // tagged by the animator with the keyword "joint"
622  // somewhere in the nodes name)
623  softegg_cat.spam() << "is Skeleton? " << isSkeleton << "\n";
624 
625  /*************************************************************************************/
626 
627  // model is not a null and has no triangles!
628  if ( !numTri ) {
629  softegg_cat.spam() << "no triangles!\n";
630  }
631  else {
632  // allocate array of triangles
633  triangles = (SAA_SubElem *) new SAA_SubElem[numTri];
634  if (!triangles) {
635  softegg_cat.info() << "Not enough Memory for triangles...\n";
636  exit(1);
637  }
638  // triangulate model and read the triangles into array
639  SAA_modelGetTriangles( scene, _model, gtype, id, numTri, triangles );
640  softegg_cat.spam() << "got triangles\n";
641 
642  /***********************************************************************************/
643 
644  // allocate array of materials (Asad: it gives a warning if try to get one triangle
645  // at a time...investigate later
646  // read each triangle's material into array
647  materials = (SAA_Elem*) new SAA_Elem[numTri];
648  SAA_triangleGetMaterials( scene, _model, numTri, triangles, materials );
649  if (!materials) {
650  softegg_cat.info() << "Not enough Memory for materials...\n";
651  exit(1);
652  }
653  softegg_cat.spam() << "got materials\n";
654 
655  /***********************************************************************************/
656 
657  // allocate array of textures per triangle
658  numTexTri = new int[numTri];
659  const void *relinfo;
660 
661  // find out how many local textures per triangle
662  for (i = 0; i < numTri; i++) {
663  result = SAA_materialRelationGetT2DLocNbElements( scene, &materials[i], FALSE,
664  &relinfo, &numTexTri[i] );
665  // polytex
666  if ( result == SI_SUCCESS )
667  numTexLoc += numTexTri[i];
668  }
669 
670  // don't need this anymore...
671  //free( numTexTri );
672 
673  // get local textures if present
674  if ( numTexLoc ) {
675  softegg_cat.spam() << "numTexLoc = " << numTexLoc << endl;
676 
677  // allocate arrays of texture info
678  uScale = new PN_stdfloat[numTri];
679  vScale = new PN_stdfloat[numTri];
680  uOffset = new PN_stdfloat[numTri];
681  vOffset = new PN_stdfloat[numTri];
682  texNameArray = new char *[numTri];
683  uRepeat = new int[numTri];
684  vRepeat = new int[numTri];
685 
686  // ASSUME only one texture per material
687  textures = new SAA_Elem[numTri];
688 
689  for ( i = 0; i < numTri; i++ ) {
690  // and read all referenced local textures into array
691  SAA_materialRelationGetT2DLocElements( scene, &materials[i],
692  TEX_PER_MAT , &textures[i] );
693 
694  // initialize the array value
695  texNameArray[i] = NULL;
696  // initialize the repeats
697  uRepeat[i] = vRepeat[i] = 0;
698 
699  // see if this triangle has texture info
700  if (numTexTri[i] == 0)
701  continue;
702 
703  // check to see if texture is present
704  result = SAA_elementIsValid( scene, &textures[i], &valid );
705 
706  if ( result != SI_SUCCESS )
707  softegg_cat.spam() << "SAA_elementIsValid failed!!!!\n";
708 
709  // texture present - get the name and uv info
710  if ( valid ) {
711  // according to drose, we don't need to convert .pic files to .rgb,
712  // panda can now read the .pic files.
713  texNameArray[i] = stec.GetTextureName(scene, &textures[i]);
714 
715  softegg_cat.spam() << " tritex[" << i << "] named: " << texNameArray[i] << endl;
716 
717  SAA_texture2DGetUVSwap( scene, &textures[i], &uv_swap );
718 
719  if ( uv_swap == TRUE )
720  softegg_cat.spam() << " swapping u and v...\n" ;
721 
722  SAA_texture2DGetUScale( scene, &textures[i], &uScale[i] );
723  SAA_texture2DGetVScale( scene, &textures[i], &vScale[i] );
724  SAA_texture2DGetUOffset( scene, &textures[i], &uOffset[i] );
725  SAA_texture2DGetVOffset( scene, &textures[i], &vOffset[i] );
726 
727  softegg_cat.spam() << "tritex[" << i << "] uScale: " << uScale[i] << " vScale: " << vScale[i] << endl;
728  softegg_cat.spam() << " uOffset: " << uOffset[i] << " vOffset: " << vOffset[i] << endl;
729 
730  SAA_texture2DGetRepeats( scene, &textures[i], &uRepeat[i], &vRepeat[i] );
731  softegg_cat.spam() << "uRepeat = " << uRepeat[i] << ", vRepeat = " << vRepeat[i] << endl;
732  }
733  else {
734  softegg_cat.spam() << "Invalid texture...\n";
735  softegg_cat.spam() << " tritex[" << i << "] named: (null)\n";
736  }
737  }
738  }
739  else { // if no local textures, try to get global textures
740  SAA_modelRelationGetT2DGlbNbElements( scene, _model,
741  FALSE, &relinfo, &numTexGlb );
742  if ( numTexGlb ) {
743  // ASSUME only one texture per model
744  textures = new SAA_Elem;
745  // get the referenced texture
746  SAA_modelRelationGetT2DGlbElements( scene, _model,
747  TEX_PER_MAT, textures );
748  softegg_cat.spam() << "numTexGlb = " << numTexGlb << endl;
749  // check to see if texture is present
750  SAA_elementIsValid( scene, textures, &valid );
751  if ( valid ) { // texture present - get the name and uv info
752  SAA_texture2DGetUVSwap( scene, textures, &uv_swap );
753 
754  if ( uv_swap == TRUE )
755  softegg_cat.spam() << " swapping u and v...\n";
756 
757  // according to drose, we don't need to convert .pic files to .rgb,
758  // panda can now read the .pic files.
759  texNameArray = new char *[1];
760  *texNameArray = stec.GetTextureName(scene, textures);
761 
762  uRepeat = new int;
763  vRepeat = new int;
764 
765  softegg_cat.spam() << " global tex named: " << *texNameArray << endl;
766 
767  // allocate arrays of texture info
768  uScale = new PN_stdfloat;
769  vScale = new PN_stdfloat;
770  uOffset = new PN_stdfloat;
771  vOffset = new PN_stdfloat;
772 
773  SAA_texture2DGetUScale( scene, textures, uScale );
774  SAA_texture2DGetVScale( scene, textures, vScale );
775  SAA_texture2DGetUOffset( scene, textures, uOffset );
776  SAA_texture2DGetVOffset( scene, textures, vOffset );
777 
778  softegg_cat.spam() << " global tex uScale: " << *uScale << " vScale: " << *vScale << endl;
779  softegg_cat.spam() << " uOffset: " << *uOffset << " vOffset: " << *vOffset << endl;
780 
781  SAA_texture2DGetRepeats( scene, textures, uRepeat, vRepeat );
782  softegg_cat.spam() << "uRepeat = " << *uRepeat << ", vRepeat = " << *vRepeat << endl;
783  }
784  else {
785  softegg_cat.spam() << "Invalid Texture...\n";
786  }
787  }
788  }
789  }
790  softegg_cat.spam() << "got textures" << endl;
791 }
792 
793 ////////////////////////////////////////////////////////////////////
794 // Function: SoftNodeDesc::load_nurbs_model
795 // Access: Private
796 // Description: Converts the indicated Soft polyset to a bunch of
797 // EggPolygons and parents them to the indicated egg
798 // group.
799 ////////////////////////////////////////////////////////////////////
800 void SoftNodeDesc::
801 load_nurbs_model(SAA_Scene *scene, SAA_ModelType type) {
802  SI_Error result;
803  const char *name = get_name().c_str();
804 
805  // if making a pose - get deformed geometry
806  if ( stec.make_pose )
807  gtype = SAA_GEOM_DEFORMED;
808 
809  // If the model is a NURBS in soft, set its step before tesselating
810  if ( type == SAA_MNSRF )
811  SAA_nurbsSurfaceSetStep( scene, _model, stec.nurbs_step, stec.nurbs_step );
812 
813  // get the materials
814  /***********************************************************************************/
815  const void *relinfo;
816 
817  SAA_modelRelationGetMatNbElements( scene, get_model(), FALSE, &relinfo,
818  &numNurbMats );
819 
820  softegg_cat.spam() << "nurbs surf has " << numNurbMats << " materials\n";
821 
822  if ( numNurbMats ) {
823  materials = new SAA_Elem[numNurbMats];
824  if (!materials) {
825  softegg_cat.info() << "Out Of Memory on allocating materials\n";
826  exit(1);
827  }
828 
829  SAA_modelRelationGetMatElements( scene, get_model(), relinfo,
830  numNurbMats, materials );
831 
832  softegg_cat.spam() << "got materials\n";
833 
834  // get the textures
835  /***********************************************************************************/
836  numNurbTexLoc = 0;
837  numNurbTexGlb = 0;
838 
839  // find out how many local textures per NURBS surface
840  // ASSUME it only has one material
841  SAA_materialRelationGetT2DLocNbElements( scene, &materials[0], FALSE, &relinfo, &numNurbTexLoc );
842 
843  // if present, get local textures
844  if ( numNurbTexLoc ) {
845  softegg_cat.spam() << name << " had " << numNurbTexLoc << " local tex\n";
846  nassertv(numNurbTexLoc == 1);
847 
848  textures = new SAA_Elem[numNurbTexLoc];
849 
850  // get the referenced texture
851  SAA_materialRelationGetT2DLocElements( scene, &materials[0], TEX_PER_MAT, &textures[0] );
852 
853  }
854  // if no locals, try to get globals
855  else {
856  SAA_modelRelationGetT2DGlbNbElements( scene, get_model(), FALSE, &relinfo, &numNurbTexGlb );
857 
858  if ( numNurbTexGlb ) {
859  softegg_cat.spam() << name << " had " << numNurbTexGlb << " global tex\n";
860  nassertv(numNurbTexGlb == 1);
861 
862  textures = new SAA_Elem[numNurbTexGlb];
863 
864  // get the referenced texture
865  SAA_modelRelationGetT2DGlbElements( scene, get_model(), TEX_PER_MAT, &textures[0] );
866  }
867  }
868 
869  if ( numNurbTexLoc || numNurbTexGlb) {
870 
871  // allocate the texture name array
872  texNameArray = new char *[1];
873  // allocate arrays of texture info
874  uScale = new PN_stdfloat;
875  vScale = new PN_stdfloat;
876  uOffset = new PN_stdfloat;
877  vOffset = new PN_stdfloat;
878  uRepeat = new int;
879  vRepeat = new int;
880 
881  // check to see if texture is present
882  result = SAA_elementIsValid( scene, &textures[0], &valid );
883 
884  if ( result != SI_SUCCESS )
885  softegg_cat.spam() << "SAA_elementIsValid failed!!!!\n";
886 
887  // texture present - get the name and uv info
888  if ( valid ) {
889  // according to drose, we don't need to convert .pic files to .rgb,
890  // panda can now read the .pic files.
891  texNameArray[0] = stec.GetTextureName(scene, &textures[0]);
892 
893  softegg_cat.spam() << " tritex[0] named: " << texNameArray[0] << endl;
894 
895  SAA_texture2DGetUVSwap( scene, &textures[0], &uv_swap );
896 
897  if ( uv_swap == TRUE )
898  softegg_cat.spam() << " swapping u and v...\n" ;
899 
900  SAA_texture2DGetUScale( scene, &textures[0], uScale );
901  SAA_texture2DGetVScale( scene, &textures[0], vScale );
902  SAA_texture2DGetUOffset( scene, &textures[0], uOffset );
903  SAA_texture2DGetVOffset( scene, &textures[0], vOffset );
904 
905  softegg_cat.spam() << "tritex[0] uScale: " << *uScale << " vScale: " << *vScale << endl;
906  softegg_cat.spam() << " uOffset: " << *uOffset << " vOffset: " << *vOffset << endl;
907 
908  SAA_texture2DGetRepeats( scene, &textures[0], uRepeat, vRepeat );
909  softegg_cat.spam() << "uRepeat = " << *uRepeat << ", vRepeat = " << *vRepeat << endl;
910  }
911  else {
912  softegg_cat.spam() << "Invalid texture...\n";
913  softegg_cat.spam() << " tritex[0] named: (null)\n";
914  }
915  }
916 
917  softegg_cat.spam() << "got textures\n";
918  }
919 }
920 
921 ////////////////////////////////////////////////////////////////////
922 // Function: find_shape_vert
923 // Access: Public
924 // Description: given a vertex, find its corresponding shape vertex
925 // and return its index.
926 ////////////////////////////////////////////////////////////////////
927 int SoftNodeDesc::
928 find_shape_vert(LPoint3d p3d, SAA_DVector *vertices, int numVert) {
929  int i, found = 0;
930 
931  for (i = 0; i < numVert && !found ; i++) {
932  if ((p3d[0] == vertices[i].x) &&
933  (p3d[1] == vertices[i].y) &&
934  (p3d[2] == vertices[i].z)) {
935  found = 1;
936  softegg_cat.spam() << "found shape vert at index " << i << endl;
937  }
938  }
939 
940  if (!found )
941  i = -1;
942  else
943  i--;
944 
945  return i;
946 }
947 
948 ////////////////////////////////////////////////////////////////////
949 // Function: make_vertex_offsets
950 // Access: Public
951 // Description: Given a scene, a model , the vertices of its original
952 // shape and its name find the difference between the
953 // geometry of its key shapes and the models original
954 // geometry and add morph vertices to the egg data to
955 // reflect these changes.
956 ////////////////////////////////////////////////////////////////////
957 void SoftNodeDesc::
958 make_vertex_offsets(int numShapes) {
959  int i, j;
960  int offset;
961  int numCV;
962  char tableName[_MAX_PATH];
963  SAA_DVector *shapeVerts = NULL;
964  SAA_DVector *uniqueVerts = NULL;
965  SAA_Elem *model = get_model();
966  SAA_Scene *scene = &stec.scene;
967 
968  EggVertexPool *vpool = NULL;
969  string vpool_name = get_name() + ".verts";
970  EggNode *t = stec._tree.get_egg_root()->find_child(vpool_name);
971  if (t)
972  DCAST_INTO_V(vpool, t);
973 
974  int numOrigVert = (int) vpool->size();
976 
977  if ((type == SAA_MNSRF) && stec.make_nurbs)
978  SAA_nurbsSurfaceSetStep( scene, model, stec.nurbs_step, stec.nurbs_step );
979 
980  SAA_modelGetNbVertices( scene, model, &numCV );
981 
982  // get the shape verts
983  uniqueVerts = new SAA_DVector[numCV];
984  SAA_modelGetVertices( scene, model, SAA_GEOM_ORIGINAL, 0,
985  numCV, uniqueVerts );
986 
987  softegg_cat.spam() << numCV << " CV's\n";
988 
989  for ( i = 0; i < numCV; i++ )
990  // convert vertices to global
991  _VCT_X_MAT( uniqueVerts[i], uniqueVerts[i], matrix);
992  softegg_cat.spam() << "uniqueVerts[" << i << "] = " << uniqueVerts[i].x << " " << uniqueVerts[i].y
993  << " " << uniqueVerts[i].z << " " << uniqueVerts[i].w << endl;
994 
995  // iterate through for each key shape (except original)
996  for ( i = 1; i < numShapes; i++ ) {
997 
998  sprintf(tableName, "%s.%d", get_name().c_str(), i);
999 
1000  softegg_cat.spam() << "\nMaking geometry offsets for " << tableName << "...\n";
1001 
1002  if ((type == SAA_MNSRF) && stec.make_nurbs)
1003  softegg_cat.spam() << "calculating NURBS morphs...\n";
1004  else
1005  softegg_cat.spam() << "calculating triangle morphs...\n";
1006 
1007  // get the shape verts
1008  shapeVerts = new SAA_DVector[numCV];
1009  SAA_modelGetVertices( scene, model, SAA_GEOM_SHAPE, i+1, numCV, shapeVerts );
1010 
1011  for ( j=0; j < numCV; j++ ) {
1012  // convert vertices to global
1013  _VCT_X_MAT( shapeVerts[j], shapeVerts[j], matrix);
1014 
1015  softegg_cat.spam() << "shapeVerts[" << j << "] = " << shapeVerts[j].x << " "
1016  << shapeVerts[j].y << " " << shapeVerts[j].z << endl;
1017  }
1018  softegg_cat.spam() << endl;
1019 
1020  // for every original vertex, compare to the corresponding
1021  // key shape vertex and see if a vertex offset is needed
1022  j = 0;
1023  for (vi = vpool->begin(); vi != vpool->end(); ++vi, ++j) {
1024 
1025  double dx, dy, dz;
1026  EggVertex *vert = (*vi);
1027  LPoint3d p3d = vert->get_pos3();
1028 
1029  softegg_cat.spam() << "oVert[" << j << "] = " << p3d[0] << " " << p3d[1] << " " << p3d[2] << endl;
1030  if ((type == SAA_MNSRF) && stec.make_nurbs) {
1031  dx = shapeVerts[j].x - p3d[0];
1032  dy = shapeVerts[j].y - p3d[1];
1033  dz = shapeVerts[j].z - p3d[2];
1034 
1035  softegg_cat.spam() << "global shapeVerts[" << j << "] = " << shapeVerts[j].x << " "
1036  << shapeVerts[j].y << " " << shapeVerts[j].z << " " << shapeVerts[j].w << endl;
1037  }
1038  else {
1039  // we need to map from original vertices
1040  // to triangle shape vertices here
1041  offset = find_shape_vert(p3d, uniqueVerts, numCV);
1042 
1043  dx = shapeVerts[offset].x - p3d[0];
1044  dy = shapeVerts[offset].y - p3d[1];
1045  dz = shapeVerts[offset].z - p3d[2];
1046 
1047  softegg_cat.spam() << "global shapeVerts[" << offset << "] = " << shapeVerts[offset].x << " "
1048  << shapeVerts[offset].y << " " << shapeVerts[offset].z << endl;
1049  }
1050 
1051  softegg_cat.spam() << j << ": dx = " << dx << ", dy = " << dy << ", dz = " << dz << endl;
1052 
1053  // if change isn't negligible, make a morph vertex entry
1054  double total = fabs(dx)+fabs(dy)+fabs(dz);
1055  if ( total > 0.00001 ) {
1056  if ( vpool != NULL ) {
1057  // create offset
1058  LVector3d p(dx, dy, dz);
1059  EggMorphVertex *dxyz = new EggMorphVertex(tableName, p);
1060  // add the offset to the vertex
1061  vert->_dxyzs.insert(*dxyz);
1062  }
1063  else
1064  softegg_cat.spam() << "Error: couldn't find vertex pool " << vpool_name << endl;
1065 
1066  } // if total
1067  } //for j
1068  } //for i
1069 }
1070 
1071 ////////////////////////////////////////////////////////////////////
1072 // Function: make_morph_table
1073 // Access: Public
1074 // Description: Given a scene, a model, a name and a frame time,
1075 // determine what type of shape interpolation is
1076 // used and call the appropriate function to extract
1077 // the shape weight info for this frame...
1078 ////////////////////////////////////////////////////////////////////
1079 void SoftNodeDesc::
1080 make_morph_table( PN_stdfloat time ) {
1081  int numShapes;
1082  SAA_Elem *model = NULL;
1083  SAA_AnimInterpType type;
1084  SAA_Scene *scene = &stec.scene;
1085 
1086  if (has_model())
1087  model = get_model();
1088  else
1089  return;
1090 
1091  // Get the number of key shapes
1092  SAA_modelGetNbShapes( scene, model, &numShapes );
1093 
1094  if ( numShapes <= 0 ) {
1095  return;
1096  }
1097 
1098  stec.has_morph = true;
1099 
1100  softegg_cat.spam() << "make_morph_table: " << get_name() << " : num shapes: " << numShapes << endl;
1101 
1102  SAA_modelGetShapeInterpolation( scene, model, &type );
1103 
1104  if ( type == SAA_ANIM_LINEAR || type == SAA_ANIM_CARDINAL ) {
1105  softegg_cat.spam() << "linear morph" << endl;
1106  make_linear_morph_table( numShapes, time );
1107  }
1108  else { // must be weighted...
1109  // check first for expressions
1110  softegg_cat.spam() << "expression morph" << endl;
1111  make_expression_morph_table( numShapes, time );
1112  }
1113 }
1114 
1115 ////////////////////////////////////////////////////////////////////
1116 // Function: make_linear_morph_table
1117 // Access: Public
1118 // Description: Given a scene, a model, its name, and the time,
1119 // get the shape fcurve for the model and determine
1120 // the shape weights for the given time and use them
1121 // to populate the morph table.
1122 ////////////////////////////////////////////////////////////////////
1123 void SoftNodeDesc::
1124 make_linear_morph_table(int numShapes, PN_stdfloat time) {
1125  int i;
1126  PN_stdfloat curveVal;
1127  char tableName[_MAX_PATH];
1128  SAA_Elem fcurve;
1129  //SAnimTable *thisTable;
1130  EggSAnimData *anim;
1131  SAA_Elem *model = get_model();
1132  SAA_Scene *scene = &stec.scene;
1133 
1134  softegg_cat.spam() << "linear interp, getting fcurve\n";
1135 
1136  SAA_modelFcurveGetShape( scene, model, &fcurve );
1137 
1138  SAA_fcurveEval( scene, &fcurve, time, &curveVal );
1139 
1140  softegg_cat.spam() << "at time " << time << ", fcurve for " << get_name() << " = " << curveVal << endl;
1141 
1142  PN_stdfloat nextVal = 0.0f;
1143 
1144  // populate morph table values for this frame
1145  for ( i = 1; i < numShapes; i++ ) {
1146  // derive table name from the model name
1147  sprintf(tableName, "%s.%d", get_name().c_str(), i);
1148 
1149  softegg_cat.spam() << "Linear: looking for table '" << tableName << "'\n";
1150 
1151  //find the morph table associated with this key shape
1152  anim = stec.find_morph_table(tableName);
1153 
1154  if ( anim != NULL ) {
1155  if ( i == (int)curveVal ) {
1156  if ( curveVal - i == 0 ) {
1157  anim->add_data(1.0f );
1158  softegg_cat.spam() << "adding element 1.0f\n";
1159  }
1160  else {
1161  anim->add_data(1.0f - (curveVal - i));
1162  nextVal = curveVal - i;
1163  softegg_cat.spam() << "adding element " << 1.0f - (curveVal - i) << endl;
1164  }
1165  }
1166  else {
1167  if ( nextVal ) {
1168  anim->add_data(nextVal );
1169  nextVal = 0.0f;
1170  softegg_cat.spam() << "adding element " << nextVal << endl;
1171  }
1172  else {
1173  anim->add_data(0.0f);
1174  softegg_cat.spam() << "adding element 0.0f\n";
1175  }
1176  }
1177 
1178  softegg_cat.spam() <<" to '" << tableName << "'\n";
1179  }
1180  else
1181  softegg_cat.spam() << i << " : Couldn't find table '" << tableName << "'\n";
1182  }
1183 }
1184 
1185 ////////////////////////////////////////////////////////////////////
1186 // Function: make_weighted_morph_table
1187 // Access: Public
1188 // Description: Given a scene, a model, a list of all models in the
1189 // scene, the number of models in the scece, the number
1190 // of key shapes for this model, the name of the model
1191 // and the current time, determine what method of
1192 // controlling the shape weights is used and call the
1193 // appropriate routine.
1194 ////////////////////////////////////////////////////////////////////
1195 void SoftNodeDesc::
1196 make_weighted_morph_table(int numShapes, PN_stdfloat time) {
1197  PN_stdfloat curveVal;
1198  SI_Error result;
1199  char tableName[_MAX_PATH];
1200  SAA_Elem *weightCurves;
1201  //SAnimTable *thisTable;
1202  EggSAnimData *anim;
1203  SAA_Elem *model = get_model();
1204  SAA_Scene *scene = &stec.scene;
1205 
1206  // allocate array of weight curves (one for each shape)
1207  weightCurves = new SAA_Elem[numShapes];
1208 
1209  result = SAA_modelFcurveGetShapeWeights(scene, model, numShapes, weightCurves);
1210 
1211  if ( result == SI_SUCCESS ) {
1212  for ( int i = 1; i < numShapes; i++ ) {
1213  SAA_fcurveEval( scene, &weightCurves[i], time, &curveVal );
1214 
1215  // make sure soft gave us a reasonable number
1216  //if (!isNum(curveVal))
1217  //curveVal = 0.0f;
1218 
1219  softegg_cat.spam() << "at time " << time << ", weightCurve[" << i << "] for " << get_name() << " = " << curveVal << endl;
1220 
1221  // derive table name from the model name
1222  sprintf(tableName, "%s.%d", get_name().c_str(), i);
1223 
1224  // find and populate shape table
1225  softegg_cat.spam() << "Weight: looking for table '" << tableName << "'\n";
1226 
1227  //find the morph table associated with this key shape
1228  anim = stec.find_morph_table(tableName);
1229 
1230  if ( anim != NULL ) {
1231  anim->add_data(curveVal);
1232  softegg_cat.spam() << "adding element " << curveVal << endl;
1233  }
1234  else
1235  softegg_cat.spam() << i << " : Couldn't find table '" << tableName << "'\n";
1236  }
1237  }
1238 }
1239 
1240 ////////////////////////////////////////////////////////////////////
1241 // Function: make_expression_morph_table
1242 // Access: Public
1243 // Description: Given a scene, a model and its number of key shapes
1244 // generate a morph table describing transitions btwn
1245 // the key shapes by evaluating the positions of the
1246 // controlling sliders.
1247 ////////////////////////////////////////////////////////////////////
1248 void SoftNodeDesc::
1249 make_expression_morph_table(int numShapes, PN_stdfloat time)
1250 {
1251  //int j;
1252  int numExp;
1253  char *track;
1254  //PN_stdfloat expVal;
1255  //PN_stdfloat sliderVal;
1256  //char *tableName;
1257  //char *sliderName;
1258  //SAnimTable *thisTable;
1259  SAA_Elem *expressions;
1260  SI_Error result;
1261 
1262  SAA_Elem *model = get_model();
1263  SAA_Scene *scene = &stec.scene;
1264 
1265  // populate morph table values for this frame
1266 
1267  // compose track name
1268  track = NULL;
1269 
1270  // find how many expressions for this shape
1271  SAA_elementGetNbExpressions( scene, model, track, FALSE, &numExp );
1272 
1273  softegg_cat.spam() << get_name() << " has " << numExp << " RHS expressions\n";
1274 
1275  if ( numExp ) {
1276  // get the expressions for this shape
1277  expressions = new SAA_Elem[numExp];
1278  softegg_cat.spam() << "getting " << numExp << " RHS expressions...\n";
1279 
1280  result = SAA_elementGetExpressions( scene, model, track, FALSE,
1281  numExp, expressions );
1282  /*
1283  if ( !result ) {
1284  for ( j = 1; j < numExp; j++ ) {
1285  if ( verbose >= 2 )
1286  {
1287  // debug see what we got
1288  int numvars;
1289 
1290  SAA_expressionGetNbVars( scene, &expressions[j], &numvars );
1291 
1292  int *varnamelen;
1293  int *varstrlen;
1294  int expstrlen;
1295 
1296  varnamelen = (int *)malloc(sizeof(int)*numvars);
1297  varstrlen = (int *)malloc(sizeof(int)*numvars);
1298 
1299  SAA_expressionGetStringLengths( scene, &expressions[j],
1300  numvars, varnamelen, varstrlen, &expstrlen );
1301 
1302  int *varnamesizes;
1303  int *varstrsizes;
1304 
1305  varnamesizes = (int *)malloc(sizeof(int)*numvars);
1306  varstrsizes = (int *)malloc(sizeof(int)*numvars);
1307 
1308  for ( int k = 0; k < numvars; k++ )
1309  {
1310  varnamesizes[k] = varnamelen[k] + 1;
1311  varstrsizes[k] = varstrlen[k] + 1;
1312  }
1313 
1314  int expstrsize = expstrlen + 1;
1315 
1316  char **varnames;
1317  char **varstrs;
1318 
1319  varnames = (char **)malloc(sizeof(char *)*numvars);
1320  varstrs = (char **)malloc(sizeof(char *)*numvars);
1321 
1322  for ( k = 0; k < numvars; k++ )
1323  {
1324  varnames[k] = (char *)malloc(sizeof(char)*
1325  varnamesizes[k]);
1326 
1327  varstrs[k] = (char *)malloc(sizeof(char)*
1328  varstrsizes[k]);
1329  }
1330 
1331  char *expstr = (char *)malloc(sizeof(char)* expstrsize );
1332 
1333  SAA_expressionGetStrings( scene, &expressions[j], numvars,
1334  varnamesizes, varstrsizes, expstrsize, varnames,
1335  varstrs, expstr );
1336 
1337  if ( verbose >= 2 )
1338  {
1339  fprintf( outStream, "expression = '%s'\n", expstr );
1340  fprintf( outStream, "has %d variables\n", numvars );
1341  }
1342  } //if verbose
1343 
1344  if ( verbose >= 2 )
1345  fprintf( outStream, "evaling expression...\n" );
1346 
1347  SAA_expressionEval( scene, &expressions[j], time, &expVal );
1348 
1349  if ( verbose >= 2 )
1350  fprintf( outStream, "time %f: exp val %f\n",
1351  time, expVal );
1352 
1353  // derive table name from the model name
1354  tableName = MakeTableName( name, j );
1355 
1356  if ( verbose >= 2 )
1357  fprintf( outStream, "Exp: looking for table '%s'\n",
1358  tableName );
1359 
1360  //find the morph table associated with this key shape
1361  anim = (SAnimTable *)
1362  (morphRoot->FindDescendent( tableName ));
1363 
1364  if ( anim != NULL )
1365  {
1366  anim->AddElement( expVal );
1367  if ( verbose >= 1 )
1368  fprintf( outStream, "%d: adding element %f to %s\n",
1369  j, expVal, tableName );
1370  fflush( outStream );
1371  }
1372  else
1373  {
1374  fprintf( outStream, "%d: Couldn't find table '%s'", j,
1375  tableName );
1376 
1377  fprintf( outStream, " for value %f\n", expVal );
1378  }
1379  }
1380  }
1381  else
1382  fprintf( outStream, "couldn't get expressions!!!\n" );
1383  */
1384  }
1385  else {
1386  softegg_cat.spam() << "weighted morph" << endl;
1387  // no expression, use weight curves
1388  make_weighted_morph_table(numShapes, time );
1389  }
1390 }
1391 
1392 //
1393 //
1394 //
bool has_model() const
Returns true if a Soft dag path has been associated with this node, false otherwise.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
void get_joint_transform(SAA_Scene *scene, EggGroup *egg_group, EggXfmSAnim *anim, bool global)
Extracts the transform on the indicated Soft node, as appropriate for a joint in an animated characte...
void add_data(double value)
Adds a single element to the table.
Definition: eggAnimData.I:116
void add_component_data(const string &component_name, double value)
Adds a new row to the named component (one of matrix_component_letters) of the table.
void force_set_parent(SoftNodeDesc *parent)
Sometimes, parent is not known at node creation As soon as it is known, set the parent.
void make_linear_morph_table(int numShapes, PN_stdfloat time)
Given a scene, a model, its name, and the time, get the shape fcurve for the model and determine the ...
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
Definition: eggVertex.I:160
void make_expression_morph_table(int numShapes, PN_stdfloat time)
Given a scene, a model and its number of key shapes generate a morph table describing transitions btw...
pair< iterator, bool > insert(const MorphType &value)
This is similar to the insert() interface for sets, except it does not guarantee that the resulting l...
Definition: eggMorphList.I:193
EggNode * find_child(const string &name) const
Returns the child of this node whose name is the indicated string, or NULL if there is no child of th...
Corresponding to an &lt;S$Anim&gt; entry, this stores a single column of numbers, for instance for a morph ...
Definition: eggSAnimData.h:28
A single &lt;Dxyz&gt; or &lt;Duv&gt; or some such entry.
Definition: eggMorph.h:33
char * GetTextureName(SAA_Scene *scene, SAA_Elem *texture)
Given a texture element, return texture name with given tex_path.
SAA_Elem * get_model() const
Returns the SAA_Elem * associated with this node.
EggSAnimData * find_morph_table(char *name)
Given a tablename, it either creates a new eggSAnimData structure (if doesn&#39;t exist) or locates it...
bool is_joint_parent() const
Returns true if the node is the parent or ancestor of a joint.
The main glue of the egg hierarchy, this corresponds to the &lt;Group&gt;, &lt;Instance&gt;, and &lt;Joint&gt; type nod...
Definition: eggGroup.h:36
bool almost_equal(const LMatrix4d &other, double threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
Definition: lmatrix.cxx:2058
void set_transform3d(const LMatrix4d &mat)
Sets the overall transform as a 4x4 matrix.
Definition: eggTransform.I:222
A base class for all things which can have a name.
Definition: namable.h:29
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
bool is_joint() const
Returns true if the node should be treated as a joint by the converter.
bool is_partial(char *search_prefix)
check to see if this is a selected branch we want to descend - this will prevent creating geometry fo...
static const LMatrix4d & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:5168
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
Definition: eggVertex.h:41
This corresponds to an &lt;Xfm$Anim_S$&gt; entry, which is a collection of up to nine &lt;S$Anim&gt; entries that...
Definition: eggXfmSAnim.h:33
void make_vertex_offsets(int numShapes)
Given a scene, a model , the vertices of its original shape and its name find the difference between ...
Describes a single instance of a node aka element in the Soft scene graph, relating it to the corresp...
Definition: softNodeDesc.h:46
void set_joint()
sets the _joint_type to JT_joint
void make_weighted_morph_table(int numShapes, PN_stdfloat time)
Given a scene, a model, a list of all models in the scene, the number of models in the scece...
bool is_junk() const
Returns true if the node should be treated as a junk by the converter.
size_type size() const
Returns the number of vertices in the pool.
This corresponds to a.
Definition: eggTable.h:31
void load_nurbs_model(SAA_Scene *scene, SAA_ModelType type)
Converts the indicated Soft polyset to a bunch of EggPolygons and parents them to the indicated egg g...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:746
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:531
void set_parent(SoftNodeDesc *parent)
Sometimes, parent is not known at node creation As soon as it is known, set the parent.
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:38
int find_shape_vert(LPoint3d p3d, SAA_DVector *vertices, int numVert)
given a vertex, find its corresponding shape vertex and return its index.
void get_transform(SAA_Scene *scene, EggGroup *egg_group, bool global)
Extracts the transform on the indicated Soft node, and applies it to the corresponding Egg node...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
void set_model(SAA_Elem *model)
Indicates an associated between the SoftNodeDesc and some SAA_Elem instance.
A collection of vertices.
Definition: eggVertexPool.h:46
void load_poly_model(SAA_Scene *scene, SAA_ModelType type)
Converts the indicated Soft polyset to a bunch of EggPolygons and parents them to the indicated egg g...
void make_morph_table(PN_stdfloat time)
Given a scene, a model, a name and a frame time, determine what type of shape interpolation is used a...
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.