diff --git a/pandatool/src/softegg/softNodeDesc.cxx b/pandatool/src/softegg/softNodeDesc.cxx index 9c57db5044..fb95110edd 100755 --- a/pandatool/src/softegg/softNodeDesc.cxx +++ b/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,23 +457,9 @@ 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"; - //get SAA orientation - SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, - &p, &h, &r ); - - //get SAA translation - SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, - &x, &y, &z ); - - //get SAA scaling - SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_GLOBAL, - &i, &j, &k ); - } - else { + // if ( global ) { + if (_parent->is_joint() && !stec.flatten && !scale_joint ) { cout << "using local matrix\n"; //get SAA orientation @@ -348,6 +473,20 @@ get_joint_transform(SAA_Scene *scene, EggGroup *egg_group, EggXfmSAnim *anim) { //get SAA scaling SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_LOCAL, &i, &j, &k ); + } else { + cout << " using global matrix\n"; + + //get SAA orientation + SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, + &p, &h, &r ); + + //get SAA translation + SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, + &x, &y, &z ); + + //get SAA scaling + SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_GLOBAL, + &i, &j, &k ); } cout << "\nanim data: " << i << " " << j << " " << k << endl; @@ -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; } + // // // diff --git a/pandatool/src/softegg/softNodeDesc.h b/pandatool/src/softegg/softNodeDesc.h index ff8f1377ad..4cb9c94737 100755 --- a/pandatool/src/softegg/softNodeDesc.h +++ b/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; } diff --git a/pandatool/src/softegg/softNodeTree.cxx b/pandatool/src/softegg/softNodeTree.cxx index f1d91a87d5..059dc5c8e8 100755 --- a/pandatool/src/softegg/softNodeTree.cxx +++ b/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; } - // // // diff --git a/pandatool/src/softegg/softNodeTree.h b/pandatool/src/softegg/softNodeTree.h index 2d7154cdc0..9c6d0164e9 100755 --- a/pandatool/src/softegg/softNodeTree.h +++ b/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 *); diff --git a/pandatool/src/softegg/softToEggConverter.cxx b/pandatool/src/softegg/softToEggConverter.cxx index 6dd741e943..695be093c5 100755 --- a/pandatool/src/softegg/softToEggConverter.cxx +++ b/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(""); 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; + } +} + +//////////////////////////////////////////////////////////////////// +// 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; - pvector joints; - MFloatArray weights; - if (_animation_convert == AC_model) { - got_weights = - get_vertex_weights(dag_path, mesh, joints, weights); } + return vertMap; +} - 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); +//////////////////////////////////////////////////////////////////// +// Function: SoftToEggConverter::make_soft_skin +// Access: Private +// Description: make soft skin assignments to the mesh +// finally call cleanup_soft_skin to clean it up +//////////////////////////////////////////////////////////////////// +bool SoftToEggConverter:: +make_soft_skin() { + int num_nodes = _tree.get_num_nodes(); + SoftNodeDesc *node_desc; + SAA_Boolean isSkeleton; - 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); + cout << endl << "----------------------------------------------------------------" << endl; - 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); + 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; + */ + } + } + } + } + } + } } } } } } -#endif - } + return true; } -//////////////////////////////////////////////////////////////////// -// Function: SoftToEggConverter::make_polyset -// Access: Private -// Description: Converts the indicated Soft polyset to a bunch of -// EggPolygons and parents them to the indicated egg -// group. -//////////////////////////////////////////////////////////////////// -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] ); - } - } - else - cout << "Not enough Memory for children...\n"; - } - else - cout << "Don't descend this branch!\n"; -#endif -} - #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 &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 //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/softegg/softToEggConverter.h b/pandatool/src/softegg/softToEggConverter.h index 8cd3a790fd..335d961d85 100755 --- a/pandatool/src/softegg/softToEggConverter.h +++ b/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 &joints, MFloatArray &weights); + bool get_vertex_weights(SoftNodeDesc *node_desc, + pvector &joints, vector &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].