Просмотр исходного кода

one side of animation is good while the other side is bad. A good point to save

Asad M. Zaman 22 лет назад
Родитель
Сommit
58e5f08e5d

+ 177 - 33
pandatool/src/softegg/softNodeDesc.cxx

@@ -38,9 +38,12 @@ SoftNodeDesc(SoftNodeDesc *parent, const string &name) :
 
   // Add ourselves to our parent.
   if (_parent != (SoftNodeDesc *)NULL) {
+    cout << "parent name " << _parent->get_name();
     _parent->_children.push_back(this);
   }
 
+  vpool = NULL;
+
   fullname = NULL;
 
   numTexLoc = 0;
@@ -92,16 +95,23 @@ set_model(SAA_Elem *model) {
 void SoftNodeDesc::
 set_parent(SoftNodeDesc *parent) {
   if (_parent) {
-    cout << "expected _parent to be null!?\n";
+    cout << endl;
+    /*
+    cout << " expected _parent to be null!?\n";
     if (_parent == parent)
-      cout << "parent already set\n";
+      cout << " parent already set\n";
     else {
-      cout << "current parent " << _parent->get_name() << " new parent " 
+      cout << " current parent " << _parent->get_name() << " new parent " 
            << parent << endl;
     }
+    */
     return;
   }
   _parent = parent;
+  cout << " set parent to " << _parent->get_name() << endl;
+
+  // Add ourselves to our parent.
+  _parent->_children.push_back(this);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -139,6 +149,17 @@ is_joint() const {
   return _joint_type == JT_joint || _joint_type == JT_pseudo_joint;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SoftNodeDesc::is_junk
+//       Access: Private
+//  Description: Returns true if the node should be treated as a junk
+//               by the converter.
+////////////////////////////////////////////////////////////////////
+bool SoftNodeDesc::
+is_junk() const {
+  return _joint_type == JT_junk;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SoftNodeDesc::set_joint
 //       Access: Private
@@ -146,9 +167,8 @@ is_joint() const {
 ////////////////////////////////////////////////////////////////////
 void SoftNodeDesc::
 set_joint() {
-  _joint_type = JT_joint; // || _joint_type == JT_pseudo_joint;
+  _joint_type = JT_joint;
 }
-#if 0
 ////////////////////////////////////////////////////////////////////
 //     Function: SoftNodeDesc::is_joint_parent
 //       Access: Private
@@ -189,9 +209,77 @@ void SoftNodeDesc::
 mark_joint_parent() {
   if (_joint_type == JT_none) {
     _joint_type = JT_joint_parent;
-    if (_parent != (SoftNodeDesc *)NULL) {
-      _parent->mark_joint_parent();
+    cout << " marked parent " << get_name();
+  }
+  else
+    cout << " ?parent " << get_name() << " joint type " << _joint_type;
+  
+  if (_parent != (SoftNodeDesc *)NULL) {
+    _parent->mark_joint_parent();
+  }
+  cout << endl;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SoftNodeDesc::check_joint_parent
+//       Access: Private
+//  Description: Walks the hierarchy, if a node is joint, make
+//               sure all its parents are marked JT_joint_parent
+////////////////////////////////////////////////////////////////////
+void SoftNodeDesc::
+check_joint_parent() {
+  Children::const_iterator ci;
+  for (ci = _children.begin(); ci != _children.end(); ++ci) {
+    SoftNodeDesc *child = (*ci);
+    if (child->is_joint()) {
+      cout << "child " << child->get_name();
+      mark_joint_parent();
     }
+    child->check_joint_parent();
+  }
+}
+
+///////////////////////////////////////////////////////////////////////
+//     Function: SoftNodeTree::check_junk
+//       Access: Public
+//  Description: check to see if this is a branch we don't want to 
+//               descend - this will prevent creating geometry for 
+//               animation control structures
+///////////////////////////////////////////////////////////////////////
+void SoftNodeDesc::
+check_junk(bool parent_junk) {
+  const char *name = get_name().c_str();
+
+  if (parent_junk) {
+    _joint_type = JT_junk;
+    cout << "junk node " << get_name() << endl;
+  }
+  if ( (strstr(name, "con-") != NULL) || 
+       (strstr(name, "con_") != NULL) || 
+       (strstr(name, "fly_") != NULL) || 
+       (strstr(name, "fly-") != NULL) || 
+       (strstr(name, "camRIG") != NULL) ||
+       (strstr(name, "cam_rig") != NULL) ||
+       (strstr(name, "bars") != NULL) )
+       // split
+       /*
+       (!_search_prefix || (strstr(name, _search_prefix) != NULL)) )
+       */
+    {
+      _joint_type = JT_junk;
+      cout << "junk node " << get_name() << endl;
+      parent_junk = true;
+      Children::const_iterator ci;
+      for (ci = _children.begin(); ci != _children.end(); ++ci) {
+        SoftNodeDesc *child = (*ci);
+        cout << child->get_name() << ",";
+      }
+      cout << endl;
+    }
+  Children::const_iterator ci;
+  for (ci = _children.begin(); ci != _children.end(); ++ci) {
+    SoftNodeDesc *child = (*ci);
+    child->check_junk(parent_junk);
   }
 }
 
@@ -210,6 +298,7 @@ check_pseudo_joints(bool joint_above) {
     // (JT_joint_parent is set), and it is the child of a joint
     // (joint_above is set).
     _joint_type = JT_pseudo_joint;
+    cout << "pseudo " << get_name() << " case1\n";
   }
 
   if (_joint_type == JT_joint) {
@@ -218,9 +307,9 @@ check_pseudo_joints(bool joint_above) {
     joint_above = true;
   }
 
-  // Don't bother traversing further if _joint_type is none, since
+  // Don't bother traversing further if _joint_type is none or junk, since
   // that means this node has no joint children.
-  if (_joint_type != JT_none) {
+  if (_joint_type != JT_none && _joint_type != JT_junk) {
 
     bool any_joints = false;
     Children::const_iterator ci;
@@ -228,6 +317,7 @@ check_pseudo_joints(bool joint_above) {
       SoftNodeDesc *child = (*ci);
       child->check_pseudo_joints(joint_above);
       if (child->is_joint()) {
+        cout << get_name() << " any_joint true by " << child->get_name() << endl;
         any_joints = true;
       }
     }
@@ -240,21 +330,45 @@ check_pseudo_joints(bool joint_above) {
         SoftNodeDesc *child = (*ci);
         if (child->_joint_type == JT_joint_parent) {
           child->_joint_type = JT_pseudo_joint;
-        } else if (child->_joint_type == JT_none) {
+          cout << "pseudo " << child->get_name() << " case2 by parent " << get_name() << "\n";
+        } else if (child->_joint_type == JT_none || child->_joint_type == JT_junk) {
           all_joints = false;
         }
       }
 
-      if (all_joints) {
-        // Finally, if all children are joints, then we are too.
+      if (all_joints || any_joints) {
+        // Finally, if all children or at least one is a joint, then we are too.
         if (_joint_type == JT_joint_parent) {
           _joint_type = JT_pseudo_joint;
+          cout << "pseudo " << get_name() << " case3\n";
         }
       }
     }
   }
+  else
+    cout << "found null joint " << get_name() << endl;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SoftToEggConverter::create_vpool
+//       Access: Public
+//  Description: Creates a new vpool for future soft skining,
+//               this is a one to one reference to external index.
+////////////////////////////////////////////////////////////////////
+void SoftNodeDesc::
+create_vpool(string vpool_name) {
+  vpool = new EggVertexPool(vpool_name);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SoftToEggConverter::get_vpool
+//       Access: Public
+//  Description: Get vpool 
+////////////////////////////////////////////////////////////////////
+EggVertexPool *SoftNodeDesc::
+get_vpool() {
+  return vpool;
 }
-#endif
 
 ////////////////////////////////////////////////////////////////////
 //     Function: SoftToEggConverter::get_transform
@@ -263,24 +377,43 @@ check_pseudo_joints(bool joint_above) {
 //               and applies it to the corresponding Egg node.
 ////////////////////////////////////////////////////////////////////
 void SoftNodeDesc::
-get_transform(SAA_Scene *scene, EggGroup *egg_group, bool set_transform) {
+get_transform(SAA_Scene *scene, EggGroup *egg_group, bool global) {
   // Get the model's matrix
-  SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_GLOBAL,  matrix );
+  int scale_joint = 0;
+  
+  if ( strstr( _parent->get_name().c_str(), "scale" ) != NULL ) {
+    scale_joint = 1;    
+    cout << "scale joint flag set!\n";
+  }
+
+  if (!global && _parent->is_joint() && !stec.flatten && !scale_joint) {
+
+    SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_LOCAL,  matrix );
+    cout << get_name() << " using local matrix :parent ";
+
+  } else {
+
+    SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_GLOBAL,  matrix );
+    cout << get_name() << " using global matrix :parent ";
+
+  }
+
+  cout << _parent->get_name() << endl;
 
   cout << "model matrix = " << matrix[0][0] << " " << matrix[0][1] << " " << matrix[0][2] << " " << matrix[0][3] << "\n";
   cout << "model matrix = " << matrix[1][0] << " " << matrix[1][1] << " " << matrix[1][2] << " " << matrix[1][3] << "\n";
   cout << "model matrix = " << matrix[2][0] << " " << matrix[2][1] << " " << matrix[2][2] << " " << matrix[2][3] << "\n";
   cout << "model matrix = " << matrix[3][0] << " " << matrix[3][1] << " " << matrix[3][2] << " " << matrix[3][3] << "\n";
 
-  if (set_transform) {
+  if (!global && is_joint()) {
     LMatrix4d m4d(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
                   matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
                   matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
                   matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
-    if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
+    //    if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
       egg_group->set_transform(m4d);
       cout << "set transform in egg_group\n";
-    }
+      //    }
   }
   return;
 }
@@ -298,7 +431,7 @@ get_transform(SAA_Scene *scene, EggGroup *egg_group, bool set_transform) {
 //               anim (EffXfmSAnim) class (masad).
 ////////////////////////////////////////////////////////////////////
 void SoftNodeDesc::
-get_joint_transform(SAA_Scene *scene,  EggGroup *egg_group, EggXfmSAnim *anim) {
+get_joint_transform(SAA_Scene *scene,  EggGroup *egg_group, EggXfmSAnim *anim, bool global) {
   //  SI_Error result;
   SAA_Elem *skeletonPart = _model;
   const char *name = get_name().c_str();
@@ -310,6 +443,12 @@ get_joint_transform(SAA_Scene *scene,  EggGroup *egg_group, EggXfmSAnim *anim) {
     int size;
     SAA_Boolean globalFlag = FALSE;
     SAA_Boolean bigEndian;
+    int scale_joint = 0;
+    
+    if ( strstr( _parent->get_name().c_str(), "scale" ) != NULL ) {
+      scale_joint = 1;    
+      cout << "scale joint flag set!\n";
+    }
 
     cout << "\n\nanimating child " << name << endl;
 
@@ -318,35 +457,35 @@ get_joint_transform(SAA_Scene *scene,  EggGroup *egg_group, EggXfmSAnim *anim) {
     if ( size != 0 )
       SAA_elementGetUserData( scene, skeletonPart, "GLOBAL", 
                               sizeof( SAA_Boolean), &bigEndian, (void *)&globalFlag );
- 
-    if ( globalFlag ) {
-      cout << " using global matrix\n";
+
+    //    if ( global ) {
+    if (_parent->is_joint() && !stec.flatten && !scale_joint ) {
+      cout << "using local matrix\n";
 
       //get SAA orientation
-      SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
+      SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
                             &p, &h, &r );
 
       //get SAA translation
-      SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
+      SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
                                &x, &y, &z );
-
+      
       //get SAA scaling
-      SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
+      SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
                            &i, &j, &k );
-    }
-    else {
-      cout << "using local matrix\n";
+    } else {
+      cout << " using global matrix\n";
 
       //get SAA orientation
-      SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
+      SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
                             &p, &h, &r );
 
       //get SAA translation
-      SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
+      SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
                                &x, &y, &z );
-      
+
       //get SAA scaling
-      SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_LOCAL, 
+      SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 
                            &i, &j, &k );
     }
     
@@ -399,6 +538,10 @@ load_model(SAA_Scene *scene, SAA_ModelType type) {
 
   fullname = name;
   
+  // if making a pose - get deformed geometry
+  if ( stec.make_pose )
+    gtype = SAA_GEOM_DEFORMED;
+        
   // If the model is a NURBS in soft, set its step before tesselating
   if ( type == SAA_MNSRF )
     SAA_nurbsSurfaceSetStep( scene, _model, stec.nurbs_step, stec.nurbs_step );
@@ -583,6 +726,7 @@ load_model(SAA_Scene *scene, SAA_ModelType type) {
   }
   cout << "got textures" << endl;
 }
+
 //
 //
 //

+ 19 - 6
pandatool/src/softegg/softNodeDesc.h

@@ -28,6 +28,8 @@
 
 #include "pandatoolbase.h"
 
+#include "eggVertex.h"
+#include "eggVertexPool.h"
 #include "referenceCount.h"
 #include "pointerTo.h"
 #include "namable.h"
@@ -56,17 +58,20 @@ public:
   SAA_Elem *get_model() const;
 
   bool is_joint() const;
+  bool is_junk() const;
   void set_joint();
-  //  bool is_joint_parent() const;
+  bool is_joint_parent() const;
 
   SoftNodeDesc *_parent;
   typedef pvector< PT(SoftNodeDesc) > Children;
   Children _children;
-  
+
 private:
   void clear_egg();
-  //  void mark_joint_parent();
-  //  void check_pseudo_joints(bool joint_above);
+  void mark_joint_parent();
+  void check_joint_parent();
+  void check_junk(bool parent_junk);
+  void check_pseudo_joints(bool joint_above);
 
   SAA_ModelType type;
   const char *fullname;
@@ -83,6 +88,7 @@ private:
     JT_pseudo_joint, // Not a joint in Soft, but treated just like a
                      // joint for the purposes of the converter.
     JT_joint_parent, // A parent or ancestor of a joint or pseudo joint.
+    JT_junk,         // originated from con-/fly-/car_rig/bars etc.
   };
   JointType _joint_type;
 
@@ -110,10 +116,17 @@ public:
   SAA_SubElem *triangles;
   SAA_GeomType gtype;
 
-  void get_transform(SAA_Scene *scene, EggGroup *egg_group, bool set_transform=FALSE);
-  void get_joint_transform(SAA_Scene *scene, EggGroup *egg_group, EggXfmSAnim *anim);
+  EggGroup *get_egg_group()const {return _egg_group;}
+
+  void get_transform(SAA_Scene *scene, EggGroup *egg_group, bool global);
+  void get_joint_transform(SAA_Scene *scene, EggGroup *egg_group, EggXfmSAnim *anim, bool global);
   void load_model(SAA_Scene *scene, SAA_ModelType type);
 
+  EggVertexPool *vpool;
+
+  EggVertexPool *get_vpool();
+  void create_vpool(string vpool_name);
+
   static TypeHandle get_class_type() {
     return _type_handle;
   }

+ 149 - 170
pandatool/src/softegg/softNodeTree.cxx

@@ -38,7 +38,7 @@
 ////////////////////////////////////////////////////////////////////
 SoftNodeTree::
 SoftNodeTree() {
-  _root = new SoftNodeDesc;
+  _root = new SoftNodeDesc(NULL, "----root");
   _fps = 0.0;
   _use_prefix = 0;
   _search_prefix = NULL;
@@ -168,6 +168,7 @@ GetRootName( const char *name ) {
 bool SoftNodeTree::
 build_complete_hierarchy(SAA_Scene &scene, SAA_Database &database) {
   SI_Error status;
+  SoftNodeDesc *node;
 
   // Get the entire Soft scene.
   int numModels;
@@ -192,18 +193,23 @@ build_complete_hierarchy(SAA_Scene &scene, SAA_Database &database) {
         cout << "model[" << i << "]" << endl;
         cout << " level " << level << endl;
         cout << " status is " << status << "\n";
-        
-        //        if (!level) {
-          build_node(&scene, &models[i]);
-          //        }
+
+        node = build_node(&scene, &models[i]);
+        if (!level && node)
+          node->set_parent(_root);
       }
     }
   }
-# if 0  
-  if (all_ok) {
-    _root->check_pseudo_joints(false);
-  }
-#endif  
+
+  // check the nodes that are junk for animation/artist control purposes
+  _root->check_junk(false);
+
+  // check the nodes that are parent of ancestors of a joint
+  _root->check_joint_parent();
+
+  // check the nodes that are pseudo joints
+  _root->check_pseudo_joints(false);
+
   return all_ok;
 }
 #if 0
@@ -295,6 +301,20 @@ get_node(int n) const {
   return _nodes[n];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SoftNodeTree::get_node
+//       Access: Public
+//  Description: Returns the node named 'name' in the hierarchy, in
+//               an arbitrary ordering.
+////////////////////////////////////////////////////////////////////
+SoftNodeDesc *SoftNodeTree::
+get_node(string name) const {
+  NodesByName::const_iterator ni = _nodes_by_name.find(name);
+  if (ni != _nodes_by_name.end())
+    return (*ni).second;
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SoftNodeTree::clear_egg
 //       Access: Public
@@ -305,7 +325,7 @@ get_node(int n) const {
 void SoftNodeTree::
 clear_egg(EggData *egg_data, EggGroupNode *egg_root, 
           EggGroupNode *skeleton_node) {
-  //  _root->clear_egg();
+  _root->clear_egg();
   _egg_data = egg_data;
   _egg_root = egg_root;
   _skeleton_node = skeleton_node;
@@ -322,8 +342,14 @@ EggGroup *SoftNodeTree::
 get_egg_group(SoftNodeDesc *node_desc) {
   nassertr(_egg_root != (EggGroupNode *)NULL, NULL);
 
-  cout << node_desc->_egg_group << endl;
-  cout << node_desc->_parent << endl;
+  // lets print some relationship
+  cout << " group " << node_desc->get_name() << "(" << node_desc->_egg_group << ")";
+  if (node_desc->_parent)
+    cout << " parent " << node_desc->_parent->get_name() << "(" << node_desc->_parent << ")";
+  else
+    cout << " parent " << node_desc->_parent;
+  cout << endl;
+
   if (node_desc->_egg_group == (EggGroup *)NULL) {
     // We need to make a new group node.
     EggGroup *egg_group;
@@ -335,6 +361,7 @@ get_egg_group(SoftNodeDesc *node_desc) {
 
     if (!node_desc->_parent || node_desc->_parent == _root) {
       // The parent is the root.
+      cout << "came hereeeee\n";
       _egg_root->add_child(egg_group);
     } else {
       // The parent is another node.
@@ -342,96 +369,6 @@ get_egg_group(SoftNodeDesc *node_desc) {
       parent_egg_group->add_child(egg_group);
     }
 
-#if 0
-    SoftEggGroupUserData *parent_user_data = NULL;
-
-    if (node_desc->_parent == _root) {
-      // The parent is the root.
-      _egg_root->add_child(egg_group);
-
-    } else {
-      // The parent is another node.
-      EggGroup *parent_egg_group = get_egg_group(node_desc->_parent);
-      parent_egg_group->add_child(egg_group);
-
-      if (parent_egg_group->has_user_data()) {
-        DCAST_INTO_R(parent_user_data, parent_egg_group->get_user_data(), NULL);
-      }
-    }
-
-    if (node_desc->has_models()) {
-      // Check for an object type setting, from Oliver's plug-in.
-      MObject dag_object = node_desc->get_dag_path().node();
-      string object_type;
-      if (get_enum_attribute(dag_object, "eggObjectTypes1", object_type)) {
-        egg_group->add_object_type(object_type);
-      }
-      if (get_enum_attribute(dag_object, "eggObjectTypes2", object_type)) {
-        egg_group->add_object_type(object_type);
-      }
-      if (get_enum_attribute(dag_object, "eggObjectTypes3", object_type)) {
-        egg_group->add_object_type(object_type);
-      }
-
-      // Is the node flagged to be invisible?  If it is, and is has no
-      // other egg flags, it is implicitly tagged "backstage", so it
-      // won't get converted.  (But it might be an invisible collision
-      // solid, which is why we do this only if it has no other egg
-      // flags.)
-      bool visible = true;
-      get_bool_attribute(dag_object, "visibility", visible);
-      if (!visible && egg_group->get_num_object_types() == 0) {
-        egg_group->add_object_type("backstage");
-      }
-
-      // We treat the object type "billboard" as a special case: we
-      // apply this one right away and also flag the group as an
-      // instance.
-      if (egg_group->has_object_type("billboard")) {    
-        egg_group->remove_object_type("billboard");
-        egg_group->set_group_type(EggGroup::GT_instance);
-        egg_group->set_billboard_type(EggGroup::BT_axis);
-        
-      } else if (egg_group->has_object_type("billboard-point")) {    
-        egg_group->remove_object_type("billboard-point");
-        egg_group->set_group_type(EggGroup::GT_instance);
-        egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
-      }
-      
-      // We also treat the object type "dcs" and "model" as a special
-      // case, so we can test for these flags later.
-      if (egg_group->has_object_type("dcs")) {
-        egg_group->remove_object_type("dcs");
-        egg_group->set_dcs_type(EggGroup::DC_default);
-      }
-      if (egg_group->has_object_type("model")) {
-        egg_group->remove_object_type("model");
-        egg_group->set_model_flag(true);
-      }
-      
-      // And "vertex-color" and "double-sided" have meaning only to
-      // this converter.
-      SoftEggGroupUserData *user_data;
-      if (parent_user_data == (SoftEggGroupUserData *)NULL) {
-        user_data = new SoftEggGroupUserData;
-      } else {
-        // Inherit the flags from above.
-        user_data = new SoftEggGroupUserData(*parent_user_data);
-      }
-
-      if (egg_group->has_object_type("vertex-color")) {
-        egg_group->remove_object_type("vertex-color");
-        user_data->_vertex_color = true;
-      }
-      if (egg_group->has_object_type("double-sided")) {
-        egg_group->remove_object_type("double-sided");
-        user_data->_double_sided = true;
-      }
-      egg_group->set_user_data(user_data);
-    }
-#endif
-    //    EggUserData *user_data = new EggUserData;
-    //    egg_group->set_user_data(user_data);
     node_desc->_egg_group = egg_group;
   }
   
@@ -450,6 +387,14 @@ get_egg_table(SoftNodeDesc *node_desc) {
   nassertr(_skeleton_node != (EggGroupNode *)NULL, NULL);
   nassertr(node_desc->is_joint(), NULL);
   
+  // lets print some relationship
+  cout << " group " << node_desc->get_name() << "(" << node_desc->_egg_group << ")";
+  if (node_desc->_parent)
+    cout << " parent " << node_desc->_parent->get_name() << "(" << node_desc->_parent << ")";
+  else
+    cout << " parent " << node_desc->_parent;
+  cout << endl;
+
   if (node_desc->_egg_table == (EggTable *)NULL) {
     cout << "creating a new table\n";
     // We need to make a new table node.
@@ -460,16 +405,16 @@ get_egg_table(SoftNodeDesc *node_desc) {
     node_desc->_anim->set_fps(_fps);
     egg_table->add_child(node_desc->_anim);
     
-    //    if (!node_desc->_parent->is_joint()) {
-    // The parent is not a joint; put it at the top.
-    _skeleton_node->add_child(egg_table);
-    /*
+    if (!node_desc->_parent || node_desc->_parent == _root) {
+      //    if (!node_desc->_parent->is_joint()) {
+      // The parent is not a joint; put it at the top.
+      _skeleton_node->add_child(egg_table);
     } else {
       // The parent is another joint.
       EggTable *parent_egg_table = get_egg_table(node_desc->_parent);
       parent_egg_table->add_child(egg_table);
     }
-    */
+
     node_desc->_egg_table = egg_table;
   }
   
@@ -489,6 +434,50 @@ get_egg_anim(SoftNodeDesc *node_desc) {
   return node_desc->_anim;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SoftNodeTree::handle_null
+//       Access: Public
+//  Description: Sets joint information for MNILL node
+////////////////////////////////////////////////////////////////////
+void SoftNodeTree::
+handle_null(SAA_Scene *scene, SoftNodeDesc *node_desc, char *node_name) {
+  const char *name = node_name;
+  SAA_AlgorithmType    algo;
+  SAA_Elem *model = node_desc->get_model();
+  
+  SAA_modelGetAlgorithm( scene, model, &algo );
+  cout << " null algorithm: " << algo << endl;
+  
+  if ( algo == SAA_ALG_INV_KIN ) {
+    //    MakeJoint( &scene, lastJoint, lastAnim,  model, name );
+    node_desc->set_joint();
+    cout << " encountered IK root: " << name << endl;
+  }
+  else if ( algo == SAA_ALG_INV_KIN_LEAF ) {
+    //    MakeJoint( &scene, lastJoint, lastAnim, model, name );
+    node_desc->set_joint();
+    cout << " encountered IK leaf: " << name << endl;
+  }
+  else if ( algo == SAA_ALG_STANDARD ) {
+    SAA_Boolean isSkeleton = FALSE;
+    cout << " encountered Standard null: " << name << endl;
+
+    SAA_modelIsSkeleton( scene, model, &isSkeleton );
+
+    // check to see if this NULL is used as a skeleton
+    // or is animated via constraint only ( these nodes are
+    // tagged by the animator with the keyword "joint"
+    // somewhere in the nodes name)
+    if ( isSkeleton || (strstr( name, "joint" ) != NULL) ) {
+      //      MakeJoint( &scene, lastJoint, lastAnim, model, name );
+      node_desc->set_joint();
+      cout << " animating Standard null!!!\n";
+    }
+  }
+  else
+    cout << " encountered some other NULL: " << algo << endl;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SoftNodeTree::build_node
 //       Access: Public
@@ -496,13 +485,14 @@ get_egg_anim(SoftNodeDesc *node_desc) {
 //               indicated dag_path object, creating it first if
 //               necessary.
 ////////////////////////////////////////////////////////////////////
-void SoftNodeTree::
+SoftNodeDesc *SoftNodeTree::
 build_node(SAA_Scene *scene, SAA_Elem *model) {
   char *name;
   string node_name;
   int numChildren;
   int thisChild;
   SAA_Elem *children;
+  SAA_ModelType type;
   SAA_Boolean isSkeleton = FALSE;
 
   if (_use_prefix)
@@ -512,56 +502,46 @@ build_node(SAA_Scene *scene, SAA_Elem *model) {
 
   node_name = name;
 
-  ///////////////////////////////////////////////////////////////////////
-  // check to see if this is a branch we don't want to descend - this
-  // will prevent creating geometry for animation control structures
-  ///////////////////////////////////////////////////////////////////////
-
-  /*
-  if ( (strstr(name, "con-") == NULL) && 
-       (strstr(name, "con_") == NULL) && 
-       (strstr(name, "fly_") == NULL) && 
-       (strstr(name, "fly-") == NULL) && 
-       (strstr(name, "camRIG") == NULL) &&
-       (strstr(name, "bars") == NULL) && 
-       // split
-       (!_search_prefix || (strstr(name, _search_prefix) != NULL)) )
-    {
-  */
-      SoftNodeDesc *node_desc = r_build_node(NULL, node_name);
-      node_desc->set_model(model);
-      SAA_modelIsSkeleton( scene, model, &isSkeleton );
-      if (isSkeleton || (strstr(node_desc->get_name().c_str(), "joint") != NULL))
-        node_desc->set_joint();
+  SoftNodeDesc *node_desc = r_build_node(NULL, node_name);
+  node_desc->set_model(model);
+  SAA_modelIsSkeleton( scene, model, &isSkeleton );
+  if (isSkeleton || (strstr(node_desc->get_name().c_str(), "joint") != NULL))
+    node_desc->set_joint();
+  
+  // find out what type of node we're dealing with
+  SAA_modelGetType( scene, node_desc->get_model(), &type );
+  
+  // treat the MNILL differently, because it needs to detect and set some joints
+  if (type == SAA_MNILL)
+    handle_null(scene, node_desc, name);
+  
+  SAA_modelGetNbChildren( scene, model, &numChildren );
+  cout << " Model " << node_name << " children: " << numChildren << endl;
+  
+  if ( numChildren ) {
+    children = new SAA_Elem[numChildren];
+    SAA_modelGetChildren( scene, model, numChildren, children );
+    if (!children)
+      cout << "Not enough Memory for children...\n";
+    
+    for ( thisChild = 0; thisChild < numChildren; thisChild++ ) {
+      if (_use_prefix)
+        node_name = GetFullName(scene, &children[thisChild]);
+      else
+        node_name = GetName(scene, &children[thisChild]);
       
-      SAA_modelGetNbChildren( scene, model, &numChildren );
-      cout << " Model " << node_name << " children: " << numChildren << endl;
+      cout << " building child " << thisChild << "...";
       
-      if ( numChildren ) {
-        children = new SAA_Elem[numChildren];
-        SAA_modelGetChildren( scene, model, numChildren, children );
-        if (!children)
-          cout << "Not enough Memory for children...\n";
-        
-        for ( thisChild = 0; thisChild < numChildren; thisChild++ ) {
-          if (_use_prefix)
-            node_name = GetFullName(scene, &children[thisChild]);
-          else
-            node_name = GetName(scene, &children[thisChild]);
-          
-          cout << " building child " << thisChild << "...";
-
-          SoftNodeDesc *node_child = r_build_node(node_desc, node_name);
-          node_child->set_model(&children[thisChild]);
-          
-          //  if (strstr(name, "joint") != NULL)
-          SAA_modelIsSkeleton( scene, &children[thisChild], &isSkeleton );
-          if (isSkeleton || (strstr(node_child->get_name().c_str(), "joint") != NULL))
-            node_child->set_joint();
-        }
-      }
-      //    }
-  return;
+      SoftNodeDesc *node_child = r_build_node(node_desc, node_name);
+      node_child->set_model(&children[thisChild]);
+      
+      //  if (strstr(name, "joint") != NULL)
+      SAA_modelIsSkeleton( scene, &children[thisChild], &isSkeleton );
+      if (isSkeleton || (strstr(node_child->get_name().c_str(), "joint") != NULL))
+        node_child->set_joint();
+    }
+  }
+  return node_desc;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -574,27 +554,27 @@ r_build_node(SoftNodeDesc *parent_node, const string &name) {
   SoftNodeDesc *node_desc;
 
   // If we have already encountered this pathname, return the
-  // corresponding MayaNodeDesc immediately.
+  // corresponding SoftNodeDesc immediately.
   NodesByName::const_iterator ni = _nodes_by_name.find(name);
   if (ni != _nodes_by_name.end()) {
-    cout << (*ni).first << endl;
+    cout << "  already built node " << (*ni).first;
     node_desc = (*ni).second;
-    node_desc->set_parent(parent_node);
+    
+    if (stec.flatten)
+      node_desc->set_parent(_root);
+    else
+      node_desc->set_parent(parent_node);
+
     return node_desc;
   }
 
   // Otherwise, we have to create it.  Do this recursively, so we
   // create each node along the path.
-  /*
-  if (!parent_node) {
-    node_desc = _root;
-  }
-  else {
-  */
+  if (stec.flatten)
+    node_desc = new SoftNodeDesc(_root, name);
+  else
     node_desc = new SoftNodeDesc(parent_node, name);
-    /*
-  }
-    */
+
   cout << " node name : " << name << endl;
   _nodes.push_back(node_desc);
 
@@ -602,7 +582,6 @@ r_build_node(SoftNodeDesc *parent_node, const string &name) {
 
   return node_desc;
 }
-
 //
 //
 //

+ 3 - 1
pandatool/src/softegg/softNodeTree.h

@@ -39,12 +39,14 @@ class EggGroupNode;
 class SoftNodeTree {
 public:
   SoftNodeTree();
-  void build_node(SAA_Scene *scene, SAA_Elem *model);
+  SoftNodeDesc *build_node(SAA_Scene *scene, SAA_Elem *model);
   bool build_complete_hierarchy(SAA_Scene &scene, SAA_Database &database);
+  void handle_null(SAA_Scene *scene, SoftNodeDesc *node_desc, char *node_name);
   //  bool build_selected_hierarchy(SAA_Scene *s, SAA_Database *d, char *scene_name);
 
   int get_num_nodes() const;
   SoftNodeDesc *get_node(int n) const;
+  SoftNodeDesc *get_node(string name) const;
 
   char *GetRootName(const char *);
   char *GetModelNoteInfo(SAA_Scene *, SAA_Elem *);

+ 416 - 233
pandatool/src/softegg/softToEggConverter.cxx

@@ -279,7 +279,7 @@ HandleGetopts(int &idx, int argc, char **argv)
       if ( strcmp( argv[idx+1], "" ) ) {
         // Get model name.
         model_name = argv[idx+1];
-        softegg_cat.info() << "loading model %s\n" <<  model_name;
+        softegg_cat.info() << "loading model " <<  model_name << endl;
       }
       ++idx;
       break;
@@ -288,7 +288,7 @@ HandleGetopts(int &idx, int argc, char **argv)
       if ( strcmp( argv[idx+1], "" ) ) {
         // Get tex path name.
         tex_path = argv[idx+1];
-        softegg_cat.info() << "texture path:  %s\n" << tex_path;
+        softegg_cat.info() << "texture path:  " << tex_path << endl;
       }
       ++idx;
       break;
@@ -297,7 +297,7 @@ HandleGetopts(int &idx, int argc, char **argv)
       if ( strcmp( argv[idx+1], "") ) {
         // Get the name.
         tex_filename = argv[idx+1];
-        softegg_cat.info() << "creating texture list file: %s\n" << tex_filename;
+        softegg_cat.info() << "creating texture list file: " << tex_filename << endl;
       }
       ++idx;
       break;
@@ -305,7 +305,7 @@ HandleGetopts(int &idx, int argc, char **argv)
     case 'S':     // Set NURBS step.
       if ( strcmp( argv[idx+1], "" ) ) {
         nurbs_step = atoi(argv[idx+1]);
-        softegg_cat.info() << "NURBS step:  %d\n" << nurbs_step;
+        softegg_cat.info() << "NURBS step:  " << nurbs_step << endl;
       }
       ++idx;
       break;
@@ -313,7 +313,7 @@ HandleGetopts(int &idx, int argc, char **argv)
     case 'M':     // Set model output file name.
       if ( strcmp( argv[idx+1], "" ) ) {
         eggFileName = argv[idx+1];
-        softegg_cat.info() << "Model output filename:  %s\n" << eggFileName;
+        softegg_cat.info() << "Model output filename:  " << eggFileName << endl;
       }
       ++idx;
       break;
@@ -321,7 +321,7 @@ HandleGetopts(int &idx, int argc, char **argv)
     case 'A':     // Set anim output file name.
       if ( strcmp( argv[idx+1], "" ) ) {
         animFileName = argv[idx+1];
-        softegg_cat.info() << "Anim output filename:  %s\n" << animFileName;
+        softegg_cat.info() << "Anim output filename:  " << animFileName << endl;
       }
       ++idx;
       break;
@@ -329,7 +329,7 @@ HandleGetopts(int &idx, int argc, char **argv)
     case 'N':     // Set egg model name.
       if ( strcmp( argv[idx+1], "" ) ) {
         eggGroupName = argv[idx+1];
-        softegg_cat.info() << "Egg group name:  %s\n" << eggGroupName;
+        softegg_cat.info() << "Egg group name:  " << eggGroupName << endl;
       }
       ++idx;
       break;
@@ -337,7 +337,7 @@ HandleGetopts(int &idx, int argc, char **argv)
     case 'o':     // Set search_prefix.
       if ( strcmp( argv[idx+1], "" ) ) {
         search_prefix = argv[idx+1]; 
-        softegg_cat.info() << "Only converting models with prefix:  %s\n" << search_prefix;
+        softegg_cat.info() << "Only converting models with prefix:  " << search_prefix << endl;
       }
       ++idx;
       break;
@@ -382,7 +382,7 @@ HandleGetopts(int &idx, int argc, char **argv)
       if ( strcmp( argv[idx+1], "" ) ) {
         make_pose = TRUE;
         pose_frame = atoi(argv[idx+1]);
-        softegg_cat.info() << "generating static pose from frame %d\n" << pose_frame;
+        softegg_cat.info() << "generating static pose from frame " << pose_frame << endl;
       }
       ++idx;
       break;
@@ -416,7 +416,7 @@ HandleGetopts(int &idx, int argc, char **argv)
     case 'v':     // print debug messages.
       if ( strcmp( argv[idx+1], "" ) ) {
         verbose = atoi(argv[idx+1]);
-        softegg_cat.info() << "using debug level %d\n" << verbose;
+        softegg_cat.info() << "using debug level " << verbose << endl;
       }
       ++idx;
       break;
@@ -424,14 +424,15 @@ HandleGetopts(int &idx, int argc, char **argv)
     case 'b':     // Set animation start frame.
       if ( strcmp( argv[idx+1], "" ) ) {
         anim_start = atoi(argv[idx+1]);
-        softegg_cat.info() << "animation starting at frame:  %d\n" << anim_start;
+        softegg_cat.info() << "animation starting at frame:  " << anim_start << endl;
       }
+      ++idx;
       break;
       
     case 'e':     /// Set animation end frame.
       if ( strcmp( argv[idx+1], "" ) ) {
         anim_end = atoi(argv[idx+1]);
-        softegg_cat.info() << "animation ending at frame:  %d\n" << anim_end;
+        softegg_cat.info() << "animation ending at frame:  " << anim_end << endl;
       }
       ++idx;
       break;
@@ -439,7 +440,7 @@ HandleGetopts(int &idx, int argc, char **argv)
     case 'f':     /// Set animation frame rate.
       if ( strcmp( argv[idx+1], "" ) ) {
         anim_rate = atoi(argv[idx+1]);
-        softegg_cat.info() << "animation frame rate:  %d\n" << anim_rate;
+        softegg_cat.info() << "animation frame rate:  " << anim_rate << endl;
       }
       ++idx;
       break;
@@ -484,6 +485,17 @@ get_extension() const {
   return "mb";
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SoftToEggConverter::get_name
+//       Access: Public, Virtual
+//  Description: Returns the English name of the file type this
+//               converter supports.
+////////////////////////////////////////////////////////////////////
+SoftNodeDesc *SoftToEggConverter::
+find_node(string name) {
+  return _tree.get_node(name);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GetTextureName
 //       Access: Public
@@ -574,9 +586,13 @@ convert_soft(bool from_selection) {
   _tree._use_prefix = use_prefix;
   _tree._search_prefix = search_prefix;
   all_ok = _tree.build_complete_hierarchy(scene, database);
-  //  exit(1);
+
+  // Lets see if we have gotten the hierarchy right
+  //_tree.print_hierarchy();
+  //exit(1);
 
   char *root_name = _tree.GetRootName( eggFileName );
+
   cout << "main group name: " << root_name << endl;
   if (root_name)
     _character_name = root_name;
@@ -586,6 +602,11 @@ convert_soft(bool from_selection) {
       all_ok = false;
     }
 
+    // generate soft skinning assignments if desired
+    if (!make_soft_skin()) {
+      all_ok = false;
+    }
+
     //  reparent_decals(&get_egg_data());
     cout << softegg_cat.info() << "Converted Softimage file\n";
 
@@ -703,7 +724,7 @@ convert_char_model() {
   }
 #endif
   cout << "character name " << _character_name << "\n";
-  EggGroup *char_node = new EggGroup(_character_name);
+  EggGroup *char_node = new EggGroup(eggGroupName);
   get_egg_data().add_child(char_node);
   char_node->set_dart_type(EggGroup::DT_default);
 
@@ -728,11 +749,15 @@ convert_char_chan() {
 
   EggTable *root_table_node = new EggTable();
   get_egg_data().add_child(root_table_node);
-  EggTable *bundle_node = new EggTable(_character_name);
+  EggTable *bundle_node = new EggTable(eggGroupName);
   bundle_node->set_table_type(EggTable::TT_bundle);
   root_table_node->add_child(bundle_node);
   EggTable *skeleton_node = new EggTable("<skeleton>");
   bundle_node->add_child(skeleton_node);
+#if 0
+  EggTable *root_node = new EggTable("root");
+  skeleton_node->add_child(root_node);
+#endif
 
   // Set the frame rate before we start asking for anim tables to be
   // created.
@@ -744,6 +769,7 @@ convert_char_chan() {
   cout << "animation frame inc: " << frame_inc << endl;
   
   _tree._fps = output_frame_rate / frame_inc;
+  //  _tree.clear_egg(&get_egg_data(), NULL, root_node);
   _tree.clear_egg(&get_egg_data(), NULL, skeleton_node);
 
   // Now we can get the animation data by walking through all of the
@@ -760,9 +786,20 @@ convert_char_chan() {
   //  MTime frame(start_frame, MTime::uiUnit());
   //  MTime frame_stop(end_frame, MTime::uiUnit());
   // start at first frame and go to last
+  if (make_pose) {
+    start_frame = pose_frame;
+    end_frame = pose_frame;
+  }
+  if (anim_start > 0)
+    start_frame = anim_start;
+  if (anim_end > 0)
+    end_frame = anim_end;
   for ( frame = start_frame; frame <= end_frame; frame += frame_inc) {
     SAA_frame2Seconds( &scene, frame, &time );
-    SAA_updatelistEvalScene( &scene, time );
+    //    cout << "got time " << time << endl;
+    if (!make_pose) {
+      SAA_updatelistEvalScene( &scene, time );
+    }
     cout << "\n> animating frame " << frame << endl;
 
     //    if (softegg_cat.is_debug()) {
@@ -778,13 +815,10 @@ convert_char_chan() {
     for (i = 0; i < num_nodes; i++) {
       SoftNodeDesc *node_desc = _tree.get_node(i);
       if (node_desc->is_joint()) {
-        if (softegg_cat.is_spam()) {
-          softegg_cat.spam()
-            << "joint " << node_desc->get_name() << "\n";
-        }
+        cout << "-----joint " << node_desc->get_name() << "\n";
         EggXfmSAnim *anim = _tree.get_egg_anim(node_desc);
         // following function fills in the anim structure
-        node_desc->get_joint_transform(&scene, tgroup, anim);
+        node_desc->get_joint_transform(&scene, tgroup, anim, TRUE);
       }
     }
 
@@ -843,29 +877,23 @@ process_model_node(SoftNodeDesc *node_desc) {
   char *fullname = NULL;
   SAA_ModelType type;
 
-#if 0
-  // Get the name of the model
-  if ( use_prefix ) {
-    // Get the FULL name of the model
-    name = fullname = _tree.GetFullName( &scene, node_desc->get_model() );
-  }
-  else {
-    // Get the name of the trim curve
-    name = _tree.GetName( &scene, node_desc->get_model() );
-  }
-#endif
   name = node_desc->get_name().c_str();
   cout << "element name <" << name << ">\n";
 
-  // find out what type of node we're dealing with
-  result = SAA_modelGetType( &scene, node_desc->get_model(), &type );
+  if (node_desc->is_junk()) {
+    cout << "no processing, it is junk\n";
+    return true;
+  }
+
   egg_group = _tree.get_egg_group(node_desc);
+
+  // find out what type of node we're dealing with
+  SAA_modelGetType( &scene, node_desc->get_model(), &type );
+
   cout << "encountered ";
   switch(type){
   case SAA_MNILL:
     cout << "null\n";
-    node_desc->get_transform(&scene, egg_group);
-    handle_null(node_desc->get_model(), egg_group, type, name);
     break;
   case SAA_MPTCH:
     cout << "patch\n";
@@ -875,11 +903,12 @@ process_model_node(SoftNodeDesc *node_desc) {
     break;
   case SAA_MSMSH:
     cout << "mesh\n";
-    node_desc->get_transform(&scene, egg_group);
+    node_desc->get_transform(&scene, egg_group, TRUE);
     make_polyset(node_desc, egg_group, type);
     break;
   case SAA_MJNT:
-    cout << "joint\n";
+    cout << "joint";
+    cout << " joint type " << node_desc->is_joint() << endl;
     break;
   case SAA_MSPLN:
     cout << "spline\n";
@@ -901,7 +930,7 @@ process_model_node(SoftNodeDesc *node_desc) {
   }
 
   if (node_desc->is_joint())
-    node_desc->get_transform(&scene, egg_group, TRUE);
+    node_desc->get_transform(&scene, egg_group, FALSE);
 
   return true;
 }
@@ -950,7 +979,13 @@ make_polyset(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type) {
       string vpool_name = name + ".verts";
       EggVertexPool *vpool = new EggVertexPool(vpool_name);
       egg_group->add_child(vpool);
-      
+
+      /*
+      // create a copy of vpool in node_desc which will be used later
+      // for soft_skinning
+      node_desc->create_vpool(vpool_name);
+      */
+
       // little detour...bear with me for now...TODO: move these to a new function
       
       // We will need to transform all vertices from world coordinate
@@ -1098,6 +1133,17 @@ make_polyset(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type) {
           }
           vert.set_external_index(indices[i]);
           egg_poly->add_vertex(vpool->create_unique_vertex(vert));
+
+          /*
+          // keep a one to one copy in this node's vpool
+          EggVertex *t_vert = new EggVertex(vert);
+          if (!t_vert) {
+            cout << "out of memeory " << endl;
+            nassertv(t_vert != NULL);
+          }
+          node_desc->get_vpool()->add_vertex(t_vert, indices[i]);
+          */
+
           cout << "\n";
         }
         
@@ -1117,116 +1163,346 @@ make_polyset(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type) {
         }
       }
       }
-#if 0
-  come back to it later
-  // Now that we've added all the polygons (and created all the
-  // vertices), go back through the vertex pool and set up the
-  // appropriate joint membership for each of the vertices.
-  bool got_weights = false;
-
-  pvector<EggGroup *> joints;
-  MFloatArray weights;
-  if (_animation_convert == AC_model) {
-    got_weights = 
-      get_vertex_weights(dag_path, mesh, joints, weights);
-  }
+    }
+}
 
-  if (got_weights && !joints.empty()) {
-    int num_joints = joints.size();
-    int num_weights = (int)weights.length();
-    int num_verts = num_weights / num_joints;
-    // The number of weights should be an even multiple of verts *
-    // joints.
-    nassertv(num_weights == num_verts * num_joints);
-
-    EggVertexPool::iterator vi;
-    for (vi = vpool->begin(); vi != vpool->end(); ++vi) {
-      EggVertex *vert = (*vi);
-      int maya_vi = vert->get_external_index();
-      nassertv(maya_vi >= 0 && maya_vi < num_verts);
-
-      for (int ji = 0; ji < num_joints; ++ji) {
-        float weight = weights[maya_vi * num_joints + ji];
-        if (weight != 0.0f) {
-          EggGroup *joint = joints[ji];
-          if (joint != (EggGroup *)NULL) {
-            joint->ref_vertex(vert, weight);
-          }
-        }
+////////////////////////////////////////////////////////////////////
+//     Function: FindClosestTriVert
+//       Access: Public
+//  Description: Given an egg vertex pool, map each vertex therein to 
+//               a vertex within an array of SAA model vertices of
+//               size numVert. Mapping is done by closest proximity.
+////////////////////////////////////////////////////////////////////
+int *SoftToEggConverter::
+FindClosestTriVert( EggVertexPool *vpool, SAA_DVector *vertices, int numVert ) {
+  int i,j;
+  int *vertMap = NULL; 
+  int vpoolSize = (int)vpool->size();
+  float closestDist;
+  float thisDist;
+  int closest;
+    
+  vertMap = new int[vpoolSize];
+  i = 0;
+  EggVertexPool::iterator vi;
+  for (vi = vpool->begin(); vi != vpool->end(); ++vi, ++i) {
+    EggVertex *vert = (*vi);
+    cout << "vert external index = " << vert->get_external_index() << endl;
+    //    cout << "found vert " << vert << endl;
+    //    cout << "vert [" << i << "] " << vpool->get_vertex(i+1);
+    LPoint3d p3d = vert->get_pos3();
+
+    // find closest model vertex 
+    for ( j = 0; j < numVert-1; j++ ) {
+      // calculate distance
+      thisDist = sqrtf( 
+                       powf( p3d[0] - vertices[j].x , 2 ) + 
+                       powf( p3d[1] - vertices[j].y , 2 ) + 
+                       powf( p3d[2] - vertices[j].z , 2 ) ); 
+
+      // remember this if its the closest so far
+      if ( !j || ( thisDist < closestDist ) ) {
+        closest = j;
+        closestDist = thisDist;
       }
     }
+    vertMap[i] = closest;
+    
+    cout << "mapping v " << i << " of " << vpoolSize-1 << ":( "
+         << p3d[0] << " "
+         << p3d[1] << " "
+         << p3d[2] << ")\n";
+
+    cout << "    to cv " << closest << " of " << numVert-1 << ":( "
+         << vertices[closest].x << " "
+         << vertices[closest].y << " "
+         << vertices[closest].z << " )\tdelta = " << closestDist << endl;
+
   }
-#endif
-    }
+  return vertMap;
 }
+
 ////////////////////////////////////////////////////////////////////
-//     Function: SoftToEggConverter::make_polyset
+//     Function: SoftToEggConverter::make_soft_skin
 //       Access: Private
-//  Description: Converts the indicated Soft polyset to a bunch of
-//               EggPolygons and parents them to the indicated egg
-//               group.
+//  Description: make soft skin assignments to the mesh
+//               finally call cleanup_soft_skin to clean it up
 ////////////////////////////////////////////////////////////////////
-void SoftToEggConverter::
-handle_null(SAA_Elem *model, EggGroup *egg_group, SAA_ModelType type, const char *node_name) {
-  const char *name = node_name;
-  SAA_AlgorithmType    algo;
-  
-  SAA_modelGetAlgorithm( &scene, model, &algo );
-  cout << "null algorithm: " << algo << endl;
-  
-  if ( algo == SAA_ALG_INV_KIN ) {
-    //    MakeJoint( &scene, lastJoint, lastAnim,  model, name );
-    cout << "encountered IK root: " << name << endl;
-  }
-  else if ( algo == SAA_ALG_INV_KIN_LEAF ) {
-    //    MakeJoint( &scene, lastJoint, lastAnim, model, name );
-    cout << "encountered IK leaf: " << name << endl;
-  }
-  else if ( algo == SAA_ALG_STANDARD ) {
-    SAA_Boolean isSkeleton = FALSE;
-    cout << "encountered Standard null: " << name << endl;
-
-    SAA_modelIsSkeleton( &scene, model, &isSkeleton );
-
-    // check to see if this NULL is used as a skeleton
-    // or is animated via constraint only ( these nodes are
-    // tagged by the animator with the keyword "joint"
-    // somewhere in the nodes name)
-    if ( isSkeleton || (strstr( name, "joint" ) != NULL) ) {
-      //      MakeJoint( &scene, lastJoint, lastAnim, model, name );
-      cout << "animating Standard null!!!\n";
-    }
-  }
-  else
-    cout << "encountered some other NULL: " << algo << endl;
-
-#if 0 // no need to follow children, _tree already contains all the model nodes
-  // check for children...
-  int numChildren;
-  int thisChild;
-  SAA_Elem *children;
-  
-  SAA_modelGetNbChildren( &scene, model, &numChildren );
-  cout << "Model children: " << numChildren << endl;
-
-  if ( numChildren ) {
-    children = new SAA_Elem[numChildren];
-    SAA_modelGetChildren( &scene, model, numChildren, children );
-    if ( children != NULL ) {
-      for ( thisChild = 0; thisChild < numChildren; thisChild++ ) {
-        cout << "\negging child " << thisChild << "...\n";
-        //        MakeEgg( parent, lastJoint, lastAnim, scene, 
-        //                 &children[thisChild] );
+bool SoftToEggConverter::
+make_soft_skin() {
+  int num_nodes = _tree.get_num_nodes();
+  SoftNodeDesc *node_desc;
+  SAA_Boolean isSkeleton;
+
+  cout << endl << "----------------------------------------------------------------" << endl;
+
+  for (int i = 0; i < num_nodes; i++) {
+    node_desc = _tree.get_node(i);
+    SAA_modelIsSkeleton( &scene, node_desc->get_model(), &isSkeleton );
+
+    if (isSkeleton && node_desc->is_joint()) {
+      // Now that we've added all the polygons (and created all the
+      // vertices), go back through the vertex pool and set up the
+      // appropriate joint membership for each of the vertices.
+
+      // check for envelops
+      int numEnv;
+      SAA_ModelType type;
+      SAA_Elem *envelopes;
+      SAA_Elem *model = node_desc->get_model();
+      EggGroup *joint = NULL;
+      EggVertexPool *vpool;
+
+      SAA_skeletonGetNbEnvelopes( &scene, model, &numEnv );
+      if ( numEnv == 0 ) {
+        cout << "no soft skinning for joint " << node_desc->get_name() << endl;
+        continue;
+      }
+      
+      // it's got envelopes - must be soft skinned
+      cout << endl << "found skeleton part( " << node_desc->get_name() << ")!\n";
+      cout << "numEnv = " << numEnv << endl;
+      // allocate envelope array
+      envelopes = new SAA_Elem[numEnv];
+      if ( envelopes == NULL ) {
+        cout << "Out Of Memory" << endl;
+        exit(1);
+      }
+      int thisEnv;
+      SAA_EnvType envType;
+      bool hasEnvVertices = 0;
+        
+      SAA_skeletonGetEnvelopes( &scene, model, numEnv, envelopes );
+      for ( thisEnv = 0; thisEnv < numEnv; thisEnv++ ) {
+        cout << "env[" << thisEnv << "]: ";
+        SAA_envelopeGetType( &scene, &envelopes[thisEnv], &envType );
+        
+        if ( envType == SAA_ENVTYPE_NONE ) {
+          cout << "envType = none\n";
+        }
+        else if ( envType == SAA_ENVTYPE_FLXLCL ) {
+          cout << "envType = flexible, local\n";
+          hasEnvVertices = 1;
+        }
+        else if ( envType == SAA_ENVTYPE_FLXGLB ) {
+          cout << "envType = flexible, global\n";
+          hasEnvVertices = 1;
+        }
+        else if ( envType == SAA_ENVTYPE_RGDGLB ) {
+          cout << "envType = rigid, global\n";
+          hasEnvVertices = 1;
+        }
+        else {
+          cout << "envType = unknown\n";
+        }
+
+      }
+      if ( !hasEnvVertices )
+        continue;
+
+      SAA_SubElem *envVertices = NULL;
+      int *numEnvVertices;
+      int i,j,k;
+      
+      numEnvVertices = new int[numEnv];
+      
+      if ( numEnvVertices != NULL ) {
+        SAA_envelopeGetNbCtrlVertices( &scene, model, numEnv, envelopes, numEnvVertices );
+        int totalEnvVertices = 0;
+        for( i = 0; i < numEnv; i++ ) {
+          totalEnvVertices += numEnvVertices[i];
+          cout << "numEnvVertices[" << i << "] = " << numEnvVertices[i] << endl;
+        }
+        cout << "total env verts = " << totalEnvVertices << endl;
+        if ( totalEnvVertices == 0 )
+          continue;
+
+        envVertices = new SAA_SubElem[totalEnvVertices];
+        if ( envVertices != NULL ) {
+          result = SAA_envelopeGetCtrlVertices( &scene, model,
+                                                numEnv, envelopes, numEnvVertices, envVertices);
+          if (result != SI_SUCCESS) {
+            cout << "error: GetCtrlVertices\n";
+            exit(1);
+          }
+          // loop through for each envelope
+          for ( i = 0; i < numEnv; i++ ) {
+            float *weights = NULL;
+            int vertArrayOffset = 0;
+            cout << "envelope[" << i << "]: ";
+            weights = new float[numEnvVertices[i]];
+            if ( weights ) {
+              char *envName;
+              int *vpoolMap = NULL;
+              for ( j = 0; j < i; j++ )
+                vertArrayOffset += numEnvVertices[j];
+              cout << "envVertArray offset = " << vertArrayOffset;
+
+              /*              
+              if (vertArrayOffset == totalEnvVertices) {
+                cout << endl;                  vpoolMap = FindClosestTriVert( vpool, globalModelVertices, modelNumVert );
+
+                break;
+              }
+              */
+              
+              // get the weights of the envelope vertices
+              result = SAA_ctrlVertexGetEnvelopeWeights( &scene, model, &envelopes[i], 
+                                                         numEnvVertices[i], 
+                                                         &envVertices[vertArrayOffset], weights ); 
+
+              // Get the name of the envelope model
+              if ( use_prefix ) {
+                // Get the FULL name of the envelope
+                envName = _tree.GetFullName( &scene, &envelopes[i] );
+              }
+              else {
+                // Get the name of the envelope
+                envName = _tree.GetName( &scene, &envelopes[i] );
+              }
+
+              cout << " envelop name is [" << envName << "]" << endl;
+              
+              if (result != SI_SUCCESS) {
+                cout << "warning: this envelop doesn't have any weights\n";
+                continue;
+              }
+
+              result = SAA_modelGetType( &scene, &envelopes[i], &type );
+              if (result != SI_SUCCESS) {
+                cout << "choked on get type\n";
+                exit(1);
+              }
+
+              cout << "envelope model type ";
+              if ( type == SAA_MSMSH )
+                cout << "MESH\n";
+              else if ( type == SAA_MNSRF )
+                cout << "NURBS\n";
+              else
+                cout << "OTHER\n";
+              
+              int *envVtxIndices = NULL;
+              envVtxIndices = new int[numEnvVertices[i]];
+              
+              // Get the envelope vertex indices
+              result = SAA_ctrlVertexGetIndices( &scene, &envelopes[i], numEnvVertices[i], 
+                                                 &envVertices[vertArrayOffset], envVtxIndices );
+              
+              if (result != SI_SUCCESS) {
+                cout << "error: choked on get indices\n";
+                exit(1);
+              }
+
+              // find out how many vertices the model has
+              int modelNumVert;
+              
+              SAA_modelGetNbVertices( &scene, &envelopes[i], &modelNumVert );
+              
+              SAA_DVector *modelVertices = NULL;
+              modelVertices = new SAA_DVector[modelNumVert];
+              
+              // get the model vertices
+              SAA_modelGetVertices( &scene, &envelopes[i],
+                                    SAA_GEOM_ORIGINAL, 0, modelNumVert, 
+                                    modelVertices );
+              
+              // create array of global model coords 
+              SAA_DVector *globalModelVertices = NULL;
+              globalModelVertices = new SAA_DVector[modelNumVert];
+              float matrix[4][4];
+              
+              // tranform local model vert coords to global
+              
+              // first get the global matrix
+              SAA_modelGetMatrix( &scene, &envelopes[i], SAA_COORDSYS_GLOBAL,  matrix );
+              
+              // populate array of global model verts
+              for ( j = 0; j < modelNumVert; j++ ) {
+                _VCT_X_MAT( globalModelVertices[j], 
+                            modelVertices[j], matrix );
+              }
+              
+              // Get the vpool
+              string s_name = envName;
+              SoftNodeDesc *mesh_node = find_node(s_name);
+              if (!mesh_node) {
+                cout << "error: node " << s_name << " not found in tree\n";
+                exit(1);
+              }
+              string vpool_name = s_name + ".verts";
+              DCAST_INTO_R(vpool, mesh_node->get_egg_group()->find_child(vpool_name), NULL);
+
+              // find the mapping of the vertices that match this envelop
+              if (vpool) {
+                cout << "found vpool of size " << vpool->size() << endl;
+                if ( !make_nurbs || (type == SAA_MSMSH) ) {
+                  vpoolMap = FindClosestTriVert( vpool, globalModelVertices, modelNumVert );
+                }
+              }
+              else {
+                cout << "error: vpool " << vpool_name << " not found\n";
+                exit(1);
+              }
+
+              joint = node_desc->get_egg_group();
+              // for every envelope vertex 
+              for (j = 0; j < numEnvVertices[i]; j++) {
+                double scaledWeight =  weights[j]/ 100.0f;
+
+                // make sure its in legal range
+                if (( envVtxIndices[j] < modelNumVert )
+                    && ( envVtxIndices[j] >= 0 )) {
+                  if ( (type == SAA_MNSRF) && make_nurbs ) { 
+                    // assign all referenced control vertices
+                    EggVertex *vert = vpool->get_vertex(envVtxIndices[j]+1);
+                    joint->ref_vertex( vert, scaledWeight );
+                    cout << j << ": adding vref to cv " << envVtxIndices[j] 
+                         << " with weight " << scaledWeight << endl; 
+
+                    /*
+                    envPool->Vertex(envVtxIndices[j])->AddJoint( joint, scaledWeight );
+                    // set flag to show this vertex has
+                    // been assigned
+                    envPool->Vertex(envVtxIndices[j])->multipleJoints = 1;
+                    */
+                  }
+                  else {    
+                    //assign all the tri verts associated
+                    // with this control vertex to joint
+                    cout << j << "--trying to find " << envVtxIndices[j] << endl;
+                    for ( k = 0; k < (int)vpool->size(); k++ ) {
+                      if ( vpoolMap[k] == envVtxIndices[j] ) {
+                        EggVertex *vert = vpool->get_vertex(k+1);
+                        //                        EggVertex *vert = mesh_node->get_vpool()->get_vertex(vpoolMap[k]+1);
+                        if (!vert) {
+                          cout << "possible error: index " << k+1 << ": vert is " << vert << endl;
+                          break;
+                        }
+
+                        joint->ref_vertex(vert, scaledWeight);
+                        cout << j << ": adding vref from cv " << envVtxIndices[j]
+                             << " to vert " << k+1 << " with weight " << scaledWeight
+                             << "(vpool)\n";
+                        /*
+                          envPool->Vertex(k)->AddJoint( joint, scaledWeight );
+                          // set flag to show this vertex has
+                          // been assigned
+                          envPool->Vertex(k)->multipleJoints = 1;
+                        */
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
       }
     }
-    else
-      cout << "Not enough Memory for children...\n";
   }
-  else
-    cout << "Don't descend this branch!\n";
-#endif
+  return true;
 }
-
 #if 0
 ////////////////////////////////////////////////////////////////////
 //     Function: SoftToEggConverter::make_locator
@@ -1259,7 +1535,7 @@ make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
   }
 
   LPoint3d p3d;
-  if (!get_vec3d_attribute(locator, "localPosition", p3d)) {
+  if (!get_vec3d_attribute(locator, "localPosition", p3d _tree.build_node(joint_dag_path))) {
     softegg_cat.error()
       << "Couldn't get position of locator " 
       << dag_path.fullPathName().asChar() << "\n";
@@ -1284,99 +1560,6 @@ make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
 
   egg_group->add_translate(p3d);
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: SoftToEggConverter::get_vertex_weights
-//       Access: Private
-//  Description: 
-////////////////////////////////////////////////////////////////////
-bool SoftToEggConverter::
-get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
-                   pvector<EggGroup *> &joints, MFloatArray &weights) {
-  MStatus status;
-  
-  // Since we are working with a mesh the input attribute that 
-  // creates the mesh is named "inMesh" 
-  // 
-  MObject attr = mesh.attribute("inMesh"); 
-  
-  // Create the plug to the "inMesh" attribute then use the 
-  // DG iterator to walk through the DG, at the node level.
-  // 
-  MPlug history(mesh.object(), attr); 
-  MItDependencyGraph it(history, MFn::kDependencyNode, 
-                        MItDependencyGraph::kUpstream, 
-                        MItDependencyGraph::kDepthFirst, 
-                        MItDependencyGraph::kNodeLevel);
-
-  while (!it.isDone()) {
-    // We will walk along the node level of the DG until we 
-    // spot a skinCluster node.
-    // 
-    MObject c_node = it.thisNode(); 
-    if (c_node.hasFn(MFn::kSkinClusterFilter)) { 
-      // We've found the cluster handle. Try to get the weight
-      // data.
-      // 
-      MFnSkinCluster cluster(c_node, &status); 
-      if (!status) {
-        status.perror("MFnSkinCluster constructor");
-        return false;
-      }
-
-      // Get the set of objects that influence the vertices of this
-      // mesh.  Hopefully these will all be joints.
-      MDagPathArray influence_objects;
-      cluster.influenceObjects(influence_objects, &status); 
-      if (!status) {
-        status.perror("MFnSkinCluster::influenceObjects");
-
-      } else {
-        // Fill up the vector with the corresponding table of egg
-        // groups for each joint.
-        joints.clear();
-        for (unsigned oi = 0; oi < influence_objects.length(); oi++) {
-          MDagPath joint_dag_path = influence_objects[oi];
-          SoftNodeDesc *joint_node_desc = _tree.build_node(joint_dag_path);
-          EggGroup *joint = _tree.get_egg_group(joint_node_desc);
-          joints.push_back(joint);
-        }
-
-        // Now use a component object to retrieve all of the weight
-        // data in one API call.
-        MFnSingleIndexedComponent sic; 
-        MObject sic_object = sic.create(MFn::kMeshVertComponent); 
-        sic.setCompleteData(mesh.numVertices()); 
-        unsigned influence_count; 
-
-        status = cluster.getWeights(dag_path, sic_object, 
-                                    weights, influence_count); 
-        if (!status) {
-          status.perror("MFnSkinCluster::getWeights");
-        } else {
-          if (influence_count != influence_objects.length()) {
-            softegg_cat.error()
-              << "MFnSkinCluster::influenceObjects() returns " 
-              << influence_objects.length()
-              << " objects, but MFnSkinCluster::getWeights() reports "
-              << influence_count << " objects.\n";
-            
-          } else {
-            // We've got the weights and the set of objects.  That's all
-            // we need.
-            return true;
-          }
-        }
-      }
-    }
-
-    it.next();
-  }
-  
-  softegg_cat.error()
-    << "Unable to find a cluster handle for the DG node.\n"; 
-  return false;
-}
 #endif
 
 ////////////////////////////////////////////////////////////////////

+ 10 - 6
pandatool/src/softegg/softToEggConverter.h

@@ -67,6 +67,9 @@ public:
   bool HandleGetopts(int &idx, int argc, char **argv);
   bool DoGetopts(int &argc, char **&argv);
 
+  SoftNodeDesc *find_node(string name);
+  int *FindClosestTriVert( EggVertexPool *vpool, SAA_DVector *vertices, int numVert );
+
   virtual SomethingToEggConverter *make_copy();
   virtual string get_name() const;
   virtual string get_extension() const;
@@ -80,8 +83,9 @@ private:
   bool convert_flip(double start_frame, double end_frame, 
                     double frame_inc, double output_frame_rate);
 
-  bool convert_char_model();
+  bool make_soft_skin();
   bool convert_char_chan();
+  bool convert_char_model();
   bool convert_hierarchy(EggGroupNode *egg_root);
   bool process_model_node(SoftNodeDesc *node_desc);
 
@@ -102,13 +106,12 @@ private:
                         const MFnNurbsCurve &curve,
                         EggGroup *group);
   */
-  void make_polyset(SoftNodeDesc *node_Desc, EggGroup *egg_group, SAA_ModelType type);
-  void handle_null(SAA_Elem *model, EggGroup *egg_group, SAA_ModelType type, const char *node_name);
+  void make_polyset(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type);
   /*
   void make_locator(const MDagPath &dag_path, const MFnDagNode &dag_node,
                     EggGroup *egg_group);
-  bool get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh,
-                          pvector<EggGroup *> &joints, MFloatArray &weights);
+  bool get_vertex_weights(SoftNodeDesc *node_desc, 
+                          pvector<EggGroup *> &joints, vector<float> &weights);
   */
   void set_shader_attributes(SoftNodeDesc *node_desc, EggPrimitive &primitive, char *texName);
   void apply_texture_properties(EggTexture &tex, int uRepeat, int vRepeat);
@@ -124,12 +127,13 @@ private:
   SoftNodeTree _tree;
 
   SI_Error            result;
-  SAA_Scene           scene;
   SAA_Elem            model;
   SAA_Database        database;
 
 public:
 
+  SAA_Scene           scene;
+
   char *_getopts;
   
   // This is argv[0].