| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- // Filename: maxNodeTree.cxx
- // Created by: crevilla
- // from mayaNodeTree.cxx created by: drose (06Jun03)
- //
- ////////////////////////////////////////////////////////////////////
- //
- // PANDA 3D SOFTWARE
- // Copyright (c) Carnegie Mellon University. All rights reserved.
- //
- // All use of this software is subject to the terms of the revised BSD
- // license. You should have received a copy of this license along
- // with this source code in a file named "LICENSE."
- //
- ////////////////////////////////////////////////////////////////////
- #include "maxNodeTree.h"
- #include "eggGroup.h"
- #include "eggTable.h"
- #include "eggXfmSAnim.h"
- #include "eggData.h"
- #ifdef MAX5
- //Disable the "Too many actual parameters in istdplug.h" warning in Max5
- #pragma warning(push)
- #pragma warning(disable: 4002)
- #include "max_pre_include.h"
- #endif
- #include "Max.h"
- #ifdef MAX5
- #include "max_post_include.h"
- #pragma warning(pop)
- #endif
- #include "maxToEggConverter.h"
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::Constructor
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- MaxNodeTree::
- MaxNodeTree() {
- _root = new MaxNodeDesc;
- _fps = 0.0;
- _egg_data = (EggData *)NULL;
- _egg_root = (EggGroupNode *)NULL;
- _skeleton_node = (EggGroupNode *)NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::build_node
- // Access: Public
- // Description: Returns a pointer to the node corresponding to the
- // indicated INode object, creating it first if
- // necessary.
- ////////////////////////////////////////////////////////////////////
- MaxNodeDesc *MaxNodeTree::
- build_node(INode *max_node) {
- MaxNodeDesc *node_desc = r_build_node(max_node);
- node_desc->from_INode(max_node);
- if (node_desc->is_node_joint())
- node_desc->_joint_entry = build_joint(max_node, node_desc);
- return node_desc;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::build_node
- // Access: Public
- // Description: Returns a pointer to the node corresponding to the
- // indicated INode object, creating it first if
- // necessary.
- ////////////////////////////////////////////////////////////////////
- MaxNodeDesc *MaxNodeTree::
- build_joint(INode *max_node, MaxNodeDesc *node_joint) {
- MaxNodeDesc *node_desc = r_build_joint(node_joint, max_node);
- node_desc->from_INode(max_node);
- node_desc->set_joint(true);
- return node_desc;
- }
- bool MaxNodeTree::node_in_list(ULONG handle, ULONG *list, int len) {
- if (!list) return true;
- for (int i = 0; i < len; i++)
- if (list[i] == handle) return true;
- return false;
- }
- bool MaxNodeTree::is_joint(INode *node) {
- Control *c = node->GetTMController();
- return (node->GetBoneNodeOnOff() || //joints
- (c && //bipeds
- ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
- (c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
- (c->ClassID() == FOOTPRINT_CLASS_ID))));
- }
- bool MaxNodeTree::
- r_build_hierarchy(INode *root, ULONG *selection_list, int len) {
- if (node_in_list(root->GetHandle(), selection_list, len))
- build_node(root);
- // Export children
- for ( int i = 0; i < root->NumberOfChildren(); i++ ) {
- // *** Should probably be checking the return value of the following line
- r_build_hierarchy(root->GetChildNode(i), selection_list, len);
- }
- return true;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::build_complete_hierarchy
- // Access: Public
- // Description: Walks through the complete Max hierarchy and builds
- // up the corresponding tree.
- ////////////////////////////////////////////////////////////////////
- bool MaxNodeTree::
- build_complete_hierarchy(INode *root, ULONG *selection_list, int len) {
- // Get the entire Max scene.
- if (root == NULL) {
- // *** Log an error
- return false;
- }
-
- bool all_ok = true;
- r_build_hierarchy(root, selection_list, len);
- if (all_ok) {
- _root->check_pseudo_joints(false);
- }
- Logger::Log( MTEC, Logger::SAT_MEDIUM_LEVEL,
- "finished building complete hierarchy" );
-
- return all_ok;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::build_selected_hierarchy
- // Access: Public
- // Description: Walks through the selected subset of the Max
- // hierarchy (or the complete hierarchy, if nothing is
- // selected) and builds up the corresponding tree.
- ////////////////////////////////////////////////////////////////////
- bool MaxNodeTree::
- build_selected_hierarchy(INode *root) {
- // *** Write this later when it's time to do selection
- /*
- MStatus status;
- MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
- if (!status) {
- status.perror("MItDag constructor");
- return false;
- }
- // Get only the selected geometry.
- MSelectionList selection;
- status = MGlobal::getActiveSelectionList(selection);
- if (!status) {
- status.perror("MGlobal::getActiveSelectionList");
- return false;
- }
-
- // Get the selected geometry only if the selection is nonempty;
- // otherwise, get the whole scene anyway.
- if (selection.isEmpty()) {
- mayaegg_cat.info()
- << "Selection list is empty.\n";
- return build_complete_hierarchy();
- }
- */
- bool all_ok = true;
- /*
- unsigned int length = selection.length();
- for (unsigned int i = 0; i < length; i++) {
- MDagPath root_path;
- status = selection.getDagPath(i, root_path);
- if (!status) {
- status.perror("MSelectionList::getDagPath");
- } else {
- // Now traverse through the selected dag path and all nested
- // dag paths.
- dag_iterator.reset(root_path);
- while (!dag_iterator.isDone()) {
- MDagPath dag_path;
- status = dag_iterator.getPath(dag_path);
- if (!status) {
- status.perror("MItDag::getPath");
- } else {
- build_node(dag_path);
- }
-
- dag_iterator.next();
- }
- }
- }
- if (all_ok) {
- _root->check_pseudo_joints(false);
- }
- */
- return all_ok;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::get_num_nodes
- // Access: Public
- // Description: Returns the total number of nodes in the hierarchy,
- // not counting the root node.
- ////////////////////////////////////////////////////////////////////
- int MaxNodeTree::
- get_num_nodes() const {
- return _nodes.size();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::get_node
- // Access: Public
- // Description: Returns the nth node in the hierarchy, in an
- // arbitrary ordering.
- ////////////////////////////////////////////////////////////////////
- MaxNodeDesc *MaxNodeTree::
- get_node(int n) const {
- nassertr(n >= 0 && n < (int)_nodes.size(), NULL);
- return _nodes[n];
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::clear_egg
- // Access: Public
- // Description: Removes all of the references to generated egg
- // structures from the tree, and prepares the tree for
- // generating new egg structures.
- ////////////////////////////////////////////////////////////////////
- void MaxNodeTree::
- clear_egg(EggData *egg_data, EggGroupNode *egg_root,
- EggGroupNode *skeleton_node) {
- _root->clear_egg();
- _egg_data = egg_data;
- _egg_root = egg_root;
- _skeleton_node = skeleton_node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::get_egg_group
- // Access: Public
- // Description: Returns the EggGroupNode corresponding to the group
- // or joint for the indicated node. Creates the group
- // node if it has not already been created.
- ////////////////////////////////////////////////////////////////////
- EggGroup *MaxNodeTree::
- get_egg_group(MaxNodeDesc *node_desc) {
- nassertr(_egg_root != (EggGroupNode *)NULL, NULL);
- if (node_desc->_egg_group == (EggGroup *)NULL) {
- // We need to make a new group node.
- EggGroup *egg_group;
- nassertr(node_desc->_parent != (MaxNodeDesc *)NULL, NULL);
- egg_group = new EggGroup(node_desc->get_name());
- if (node_desc->is_joint()) {
- egg_group->set_group_type(EggGroup::GT_joint);
- }
- 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);
- }
- // *** This is probably something that a Max plugin would need to be
- // written for. May want to ask Disney about it
- /*
- if (node_desc->has_dag_path()) {
- // 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);
- }
- // 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" has meaning only to this converter.
- if (egg_group->has_object_type("vertex-color")) {
- egg_group->remove_object_type("vertex-color");
- MaxEggGroupUserData *user_data = new MaxEggGroupUserData;
- user_data->_vertex_color = true;
- egg_group->set_user_data(user_data);
- }
- }
- */
- node_desc->_egg_group = egg_group;
- }
- return node_desc->_egg_group;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::get_egg_table
- // Access: Public
- // Description: Returns the EggTable corresponding to the joint
- // for the indicated node. Creates the table node if it
- // has not already been created.
- ////////////////////////////////////////////////////////////////////
- EggTable *MaxNodeTree::
- get_egg_table(MaxNodeDesc *node_desc) {
- nassertr(_skeleton_node != (EggGroupNode *)NULL, NULL);
- nassertr(node_desc->is_joint(), NULL);
- if (node_desc->_egg_table == (EggTable *)NULL) {
- // We need to make a new table node.
- nassertr(node_desc->_parent != (MaxNodeDesc *)NULL, NULL);
- EggTable *egg_table = new EggTable(node_desc->get_name());
- node_desc->_anim = new EggXfmSAnim("xform",
- _egg_data->get_coordinate_system());
- 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);
- } 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;
- }
- return node_desc->_egg_table;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::get_egg_anim
- // Access: Public
- // Description: Returns the anim table corresponding to the joint
- // for the indicated node. Creates the table node if it
- // has not already been created.
- ////////////////////////////////////////////////////////////////////
- EggXfmSAnim *MaxNodeTree::
- get_egg_anim(MaxNodeDesc *node_desc)
- {
- get_egg_table(node_desc);
- return node_desc->_anim;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::r_build_node
- // Access: Private
- // Description: The recursive implementation of build_node().
- ////////////////////////////////////////////////////////////////////
- MaxNodeDesc *MaxNodeTree::
- r_build_node(INode* max_node)
- {
- // If we have already encountered this pathname, return the
- // corresponding MaxNodeDesc immediately.
-
- ULONG node_handle = 0;
-
- if (max_node) {
- node_handle = max_node->GetHandle();
- }
- NodesByPath::const_iterator ni = _nodes_by_path.find(node_handle);
- if (ni != _nodes_by_path.end()) {
- return (*ni).second;
- }
- // Otherwise, we have to create it. Do this recursively, so we
- // create each node along the path.
- MaxNodeDesc *node_desc;
- if (!max_node) {
- // This is the top.
- node_desc = _root;
- } else {
- INode *parent_node;
- string local_name = max_node->GetName();
- if (max_node->IsRootNode()) {
- parent_node = NULL;
- } else {
- parent_node = max_node->GetParentNode();
- }
- MaxNodeDesc *parent_node_desc = r_build_node(parent_node);
- node_desc = new MaxNodeDesc(parent_node_desc, local_name);
- _nodes.push_back(node_desc);
- }
- _nodes_by_path.insert(NodesByPath::value_type(node_handle, node_desc));
- return node_desc;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::r_build_joint
- // Access: Private
- // Description: The recursive implementation of build_joint().
- ////////////////////////////////////////////////////////////////////
- MaxNodeDesc *MaxNodeTree::
- r_build_joint(MaxNodeDesc *node_desc, INode *max_node)
- {
- MaxNodeDesc *node_joint;
- if (node_desc == _root) {
- node_joint = new MaxNodeDesc(_root, max_node->GetName());
- _nodes.push_back(node_joint);
- return node_joint;
- } else if (node_desc->is_node_joint() && node_desc->_joint_entry) {
- node_joint = new MaxNodeDesc(node_desc->_joint_entry, max_node->GetName());
- _nodes.push_back(node_joint);
- return node_joint;
- } else {
- return r_build_joint(node_desc->_parent, max_node);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::find_node
- // Access: Private
- // Description: The recursive implementation of build_node().
- ////////////////////////////////////////////////////////////////////
- MaxNodeDesc *MaxNodeTree::
- find_node(INode* max_node)
- {
- // If we have already encountered this pathname, return the
- // corresponding MaxNodeDesc immediately.
-
- ULONG node_handle = 0;
-
- if (max_node) {
- node_handle = max_node->GetHandle();
- }
- NodesByPath::const_iterator ni = _nodes_by_path.find(node_handle);
- if (ni != _nodes_by_path.end()) {
- return (*ni).second;
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: MaxNodeTree::find_joint
- // Access: Private
- // Description: The recursive implementation of build_node().
- ////////////////////////////////////////////////////////////////////
- MaxNodeDesc *MaxNodeTree::
- find_joint(INode* max_node)
- {
- MaxNodeDesc *node = find_node(max_node);
- if (!node || (is_joint(max_node) && !node->is_node_joint()))
- node = build_node(max_node);
- return node->_joint_entry;
- }
|