Panda3D
|
00001 // Filename: maxNodeTree.cxx 00002 // Created by: crevilla 00003 // from mayaNodeTree.cxx created by: drose (06Jun03) 00004 // 00005 //////////////////////////////////////////////////////////////////// 00006 // 00007 // PANDA 3D SOFTWARE 00008 // Copyright (c) Carnegie Mellon University. All rights reserved. 00009 // 00010 // All use of this software is subject to the terms of the revised BSD 00011 // license. You should have received a copy of this license along 00012 // with this source code in a file named "LICENSE." 00013 // 00014 //////////////////////////////////////////////////////////////////// 00015 00016 #include "maxEgg.h" 00017 00018 // 3dsmax versions below 9 don't define this. 00019 #ifndef _M 00020 #define _M(s) (s) 00021 #endif 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: MaxNodeTree::Constructor 00025 // Access: Public 00026 // Description: 00027 //////////////////////////////////////////////////////////////////// 00028 MaxNodeTree:: 00029 MaxNodeTree() { 00030 _root = new MaxNodeDesc; 00031 _fps = 0.0; 00032 _export_mesh = false; 00033 _egg_data = (EggData *)NULL; 00034 _egg_root = (EggGroupNode *)NULL; 00035 _skeleton_node = (EggGroupNode *)NULL; 00036 } 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Function: MaxNodeTree::build_node 00040 // Access: Public 00041 // Description: Returns a pointer to the node corresponding to the 00042 // indicated INode object, creating it first if 00043 // necessary. 00044 //////////////////////////////////////////////////////////////////// 00045 MaxNodeDesc *MaxNodeTree:: 00046 build_node(INode *max_node) { 00047 MaxNodeDesc *node_desc = r_build_node(max_node); 00048 node_desc->from_INode(max_node); 00049 if (node_desc->is_node_joint()) 00050 node_desc->_joint_entry = build_joint(max_node, node_desc); 00051 return node_desc; 00052 } 00053 00054 //////////////////////////////////////////////////////////////////// 00055 // Function: MaxNodeTree::build_node 00056 // Access: Public 00057 // Description: Returns a pointer to the node corresponding to the 00058 // indicated INode object, creating it first if 00059 // necessary. 00060 //////////////////////////////////////////////////////////////////// 00061 MaxNodeDesc *MaxNodeTree:: 00062 build_joint(INode *max_node, MaxNodeDesc *node_joint) { 00063 MaxNodeDesc *node_desc = r_build_joint(node_joint, max_node); 00064 node_desc->from_INode(max_node); 00065 node_desc->set_joint(true); 00066 return node_desc; 00067 } 00068 00069 bool MaxNodeTree::node_in_list(ULONG handle, ULONG *list, int len) { 00070 if (!list) return true; 00071 for (int i = 0; i < len; i++) 00072 if (list[i] == handle) return true; 00073 return false; 00074 } 00075 00076 bool MaxNodeTree::is_joint(INode *node) { 00077 Control *c = node->GetTMController(); 00078 return (node->GetBoneNodeOnOff() || //joints 00079 (c && //bipeds 00080 ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) || 00081 (c->ClassID() == BIPBODY_CONTROL_CLASS_ID) || 00082 (c->ClassID() == FOOTPRINT_CLASS_ID)))); 00083 } 00084 00085 bool MaxNodeTree:: 00086 r_build_hierarchy(INode *root, ULONG *selection_list, int len) { 00087 if (node_in_list(root->GetHandle(), selection_list, len)) 00088 build_node(root); 00089 // Export children 00090 for ( int i = 0; i < root->NumberOfChildren(); i++ ) { 00091 // *** Should probably be checking the return value of the following line 00092 r_build_hierarchy(root->GetChildNode(i), selection_list, len); 00093 } 00094 return true; 00095 } 00096 //////////////////////////////////////////////////////////////////// 00097 // Function: MaxNodeTree::build_complete_hierarchy 00098 // Access: Public 00099 // Description: Walks through the complete Max hierarchy and builds 00100 // up the corresponding tree. 00101 //////////////////////////////////////////////////////////////////// 00102 bool MaxNodeTree:: 00103 build_complete_hierarchy(INode *root, ULONG *selection_list, int len) { 00104 00105 // Get the entire Max scene. 00106 if (root == NULL) { 00107 // *** Log an error 00108 return false; 00109 } 00110 00111 bool all_ok = true; 00112 r_build_hierarchy(root, selection_list, len); 00113 00114 if (all_ok) { 00115 _root->check_pseudo_joints(false); 00116 } 00117 00118 return all_ok; 00119 } 00120 00121 //////////////////////////////////////////////////////////////////// 00122 // Function: MaxNodeTree::get_num_nodes 00123 // Access: Public 00124 // Description: Returns the total number of nodes in the hierarchy, 00125 // not counting the root node. 00126 //////////////////////////////////////////////////////////////////// 00127 int MaxNodeTree:: 00128 get_num_nodes() const { 00129 return _nodes.size(); 00130 } 00131 00132 //////////////////////////////////////////////////////////////////// 00133 // Function: MaxNodeTree::get_node 00134 // Access: Public 00135 // Description: Returns the nth node in the hierarchy, in an 00136 // arbitrary ordering. 00137 //////////////////////////////////////////////////////////////////// 00138 MaxNodeDesc *MaxNodeTree:: 00139 get_node(int n) const { 00140 nassertr(n >= 0 && n < (int)_nodes.size(), NULL); 00141 return _nodes[n]; 00142 } 00143 00144 //////////////////////////////////////////////////////////////////// 00145 // Function: MaxNodeTree::clear_egg 00146 // Access: Public 00147 // Description: Removes all of the references to generated egg 00148 // structures from the tree, and prepares the tree for 00149 // generating new egg structures. 00150 //////////////////////////////////////////////////////////////////// 00151 void MaxNodeTree:: 00152 clear_egg(EggData *egg_data, EggGroupNode *egg_root, 00153 EggGroupNode *skeleton_node) { 00154 _root->clear_egg(); 00155 _egg_data = egg_data; 00156 _egg_root = egg_root; 00157 _skeleton_node = skeleton_node; 00158 } 00159 00160 //////////////////////////////////////////////////////////////////// 00161 // Function: MaxNodeTree::get_egg_group 00162 // Access: Public 00163 // Description: Returns the EggGroupNode corresponding to the group 00164 // or joint for the indicated node. Creates the group 00165 // node if it has not already been created. 00166 //////////////////////////////////////////////////////////////////// 00167 EggGroup *MaxNodeTree:: 00168 get_egg_group(MaxNodeDesc *node_desc) { 00169 nassertr(_egg_root != (EggGroupNode *)NULL, NULL); 00170 00171 if (node_desc->_egg_group == (EggGroup *)NULL) { 00172 // We need to make a new group node. 00173 EggGroup *egg_group; 00174 00175 nassertr(node_desc->_parent != (MaxNodeDesc *)NULL, NULL); 00176 egg_group = new EggGroup(node_desc->get_name()); 00177 if (node_desc->is_joint()) { 00178 egg_group->set_group_type(EggGroup::GT_joint); 00179 } 00180 if (node_desc->_parent == _root) { 00181 // The parent is the root. 00182 // Set collision properties for the root if it has them: 00183 if(!_export_mesh) 00184 { 00185 set_collision_tags(node_desc, egg_group); 00186 } 00187 _egg_root->add_child(egg_group); 00188 00189 } else { 00190 // The parent is another node. 00191 // if export mesh, the tag should be added at the second level 00192 if(_export_mesh) 00193 { 00194 if(node_desc->_parent->_parent == _root) 00195 { 00196 set_collision_tags(node_desc, egg_group); 00197 } 00198 } 00199 EggGroup *parent_egg_group = get_egg_group(node_desc->_parent); 00200 parent_egg_group->add_child(egg_group); 00201 } 00202 00203 node_desc->_egg_group = egg_group; 00204 } 00205 00206 return node_desc->_egg_group; 00207 } 00208 00209 //////////////////////////////////////////////////////////////////// 00210 // Function: MaxNodeTree::get_egg_table 00211 // Access: Public 00212 // Description: Returns the EggTable corresponding to the joint 00213 // for the indicated node. Creates the table node if it 00214 // has not already been created. 00215 //////////////////////////////////////////////////////////////////// 00216 EggTable *MaxNodeTree:: 00217 get_egg_table(MaxNodeDesc *node_desc) { 00218 nassertr(_skeleton_node != (EggGroupNode *)NULL, NULL); 00219 nassertr(node_desc->is_joint(), NULL); 00220 00221 if (node_desc->_egg_table == (EggTable *)NULL) { 00222 // We need to make a new table node. 00223 nassertr(node_desc->_parent != (MaxNodeDesc *)NULL, NULL); 00224 00225 EggTable *egg_table = new EggTable(node_desc->get_name()); 00226 node_desc->_anim = new EggXfmSAnim("xform", 00227 _egg_data->get_coordinate_system()); 00228 node_desc->_anim->set_fps(_fps); 00229 egg_table->add_child(node_desc->_anim); 00230 00231 if (!node_desc->_parent->is_joint()) { 00232 // The parent is not a joint; put it at the top. 00233 _skeleton_node->add_child(egg_table); 00234 00235 } else { 00236 // The parent is another joint. 00237 EggTable *parent_egg_table = get_egg_table(node_desc->_parent); 00238 parent_egg_table->add_child(egg_table); 00239 } 00240 00241 node_desc->_egg_table = egg_table; 00242 } 00243 00244 return node_desc->_egg_table; 00245 } 00246 00247 //////////////////////////////////////////////////////////////////// 00248 // Function: MaxNodeTree::get_egg_anim 00249 // Access: Public 00250 // Description: Returns the anim table corresponding to the joint 00251 // for the indicated node. Creates the table node if it 00252 // has not already been created. 00253 //////////////////////////////////////////////////////////////////// 00254 EggXfmSAnim *MaxNodeTree:: 00255 get_egg_anim(MaxNodeDesc *node_desc) 00256 { 00257 get_egg_table(node_desc); 00258 return node_desc->_anim; 00259 } 00260 00261 00262 //////////////////////////////////////////////////////////////////// 00263 // Function: MaxNodeTree::r_build_node 00264 // Access: Private 00265 // Description: The recursive implementation of build_node(). 00266 //////////////////////////////////////////////////////////////////// 00267 MaxNodeDesc *MaxNodeTree:: 00268 r_build_node(INode* max_node) 00269 { 00270 // If we have already encountered this pathname, return the 00271 // corresponding MaxNodeDesc immediately. 00272 00273 ULONG node_handle = 0; 00274 00275 if (max_node) { 00276 node_handle = max_node->GetHandle(); 00277 } 00278 00279 NodesByPath::const_iterator ni = _nodes_by_path.find(node_handle); 00280 if (ni != _nodes_by_path.end()) { 00281 return (*ni).second; 00282 } 00283 00284 // Otherwise, we have to create it. Do this recursively, so we 00285 // create each node along the path. 00286 MaxNodeDesc *node_desc; 00287 00288 if (!max_node) { 00289 // This is the top. 00290 node_desc = _root; 00291 00292 } else { 00293 INode *parent_node; 00294 string local_name = max_node->GetName(); 00295 if (max_node->IsRootNode()) { 00296 parent_node = NULL; 00297 } else { 00298 parent_node = max_node->GetParentNode(); 00299 } 00300 00301 MaxNodeDesc *parent_node_desc = r_build_node(parent_node); 00302 node_desc = new MaxNodeDesc(parent_node_desc, local_name); 00303 _nodes.push_back(node_desc); 00304 } 00305 00306 _nodes_by_path.insert(NodesByPath::value_type(node_handle, node_desc)); 00307 return node_desc; 00308 } 00309 00310 //////////////////////////////////////////////////////////////////// 00311 // Function: MaxNodeTree::r_build_joint 00312 // Access: Private 00313 // Description: The recursive implementation of build_joint(). 00314 //////////////////////////////////////////////////////////////////// 00315 MaxNodeDesc *MaxNodeTree:: 00316 r_build_joint(MaxNodeDesc *node_desc, INode *max_node) 00317 { 00318 MaxNodeDesc *node_joint; 00319 if (node_desc == _root) { 00320 node_joint = new MaxNodeDesc(_root, max_node->GetName()); 00321 _nodes.push_back(node_joint); 00322 return node_joint; 00323 } else if (node_desc->is_node_joint() && node_desc->_joint_entry) { 00324 node_joint = new MaxNodeDesc(node_desc->_joint_entry, max_node->GetName()); 00325 _nodes.push_back(node_joint); 00326 return node_joint; 00327 } else { 00328 return r_build_joint(node_desc->_parent, max_node); 00329 } 00330 } 00331 00332 //////////////////////////////////////////////////////////////////// 00333 // Function: MaxNodeTree::find_node 00334 // Access: Private 00335 // Description: The recursive implementation of build_node(). 00336 //////////////////////////////////////////////////////////////////// 00337 MaxNodeDesc *MaxNodeTree:: 00338 find_node(INode* max_node) 00339 { 00340 // If we have already encountered this pathname, return the 00341 // corresponding MaxNodeDesc immediately. 00342 00343 ULONG node_handle = 0; 00344 00345 if (max_node) { 00346 node_handle = max_node->GetHandle(); 00347 } 00348 00349 NodesByPath::const_iterator ni = _nodes_by_path.find(node_handle); 00350 if (ni != _nodes_by_path.end()) { 00351 return (*ni).second; 00352 } 00353 00354 return NULL; 00355 } 00356 00357 //////////////////////////////////////////////////////////////////// 00358 // Function: MaxNodeTree::find_joint 00359 // Access: Private 00360 // Description: The recursive implementation of build_node(). 00361 //////////////////////////////////////////////////////////////////// 00362 MaxNodeDesc *MaxNodeTree:: 00363 find_joint(INode* max_node) 00364 { 00365 MaxNodeDesc *node = find_node(max_node); 00366 if (!node || (is_joint(max_node) && !node->is_node_joint())) 00367 node = build_node(max_node); 00368 return node->_joint_entry; 00369 } 00370 00371 //////////////////////////////////////////////////////////////////// 00372 // Function: MaxNodeTree::set_collision_tags 00373 // Access: Private 00374 // Description: Sets the corresponding collision tag to the egg_group 00375 // based on the User Defined Tab in the object properties 00376 // panel 00377 //////////////////////////////////////////////////////////////////// 00378 void MaxNodeTree::set_collision_tags(MaxNodeDesc *node_desc, EggGroup *egg_group) { 00379 //Max has huge problems passing strings and bools to Get and SetUserProp 00380 //So instead we have to use Integers. Now we have to check 00381 //for every collide type, then get its collide flags and 00382 //do some number crunching to get the actual flag into the group 00383 00384 int check = 1; //is the value true. This could be anything really 00385 00386 //We have to check each collision type in turn to see if it's true 00387 //Ugly but it works per object, not globaly 00388 if (node_desc->get_max_node()->GetUserPropInt(_M("polyset"), check)) { 00389 //we have a polyset. 00390 if (check == 1) { 00391 egg_group->set_collision_name(node_desc->get_name()); 00392 egg_group->set_cs_type(EggGroup::CST_polyset); 00393 } 00394 } 00395 if (node_desc->get_max_node()->GetUserPropInt(_M("plane"), check)) { 00396 //plane 00397 if (check == 1) { 00398 egg_group->set_collision_name(node_desc->get_name()); 00399 egg_group->set_cs_type(EggGroup::CST_plane); 00400 } 00401 } 00402 if (node_desc->get_max_node()->GetUserPropInt(_M("polygon"), check)) { 00403 //polygon 00404 if (check == 1) { 00405 egg_group->set_collision_name(node_desc->get_name()); 00406 egg_group->set_cs_type(EggGroup::CST_polygon); 00407 } 00408 } 00409 if (node_desc->get_max_node()->GetUserPropInt(_M("sphere"), check)) { 00410 //sphere 00411 if (check == 1) { 00412 egg_group->set_collision_name(node_desc->get_name()); 00413 egg_group->set_cs_type(EggGroup::CST_sphere); 00414 } 00415 } 00416 if (node_desc->get_max_node()->GetUserPropInt(_M("inv-sphere"), check)) { 00417 //invsphere 00418 if (check == 1) { 00419 egg_group->set_collision_name(node_desc->get_name()); 00420 egg_group->set_cs_type(EggGroup::CST_inv_sphere); 00421 } 00422 } 00423 if (node_desc->get_max_node()->GetUserPropInt(_M("invsphere"), check)) { 00424 //invsphere (different spelling) 00425 if (check == 1) { 00426 egg_group->set_collision_name(node_desc->get_name()); 00427 egg_group->set_cs_type(EggGroup::CST_inv_sphere); 00428 } 00429 } 00430 if (node_desc->get_max_node()->GetUserPropInt(_M("tube"), check)) { 00431 //tube 00432 if (check == 1) { 00433 egg_group->set_collision_name(node_desc->get_name()); 00434 egg_group->set_cs_type(EggGroup::CST_tube); 00435 } 00436 } 00437 if (node_desc->get_max_node()->GetUserPropInt(_M("floor-mesh"), check)) { 00438 //floor-mesh 00439 if (check == 1) { 00440 egg_group->set_collision_name(node_desc->get_name()); 00441 egg_group->set_cs_type(EggGroup::CST_floor_mesh); 00442 } 00443 } 00444 00445 if (node_desc->get_max_node()->GetUserPropInt(_M("descend"), check)) { 00446 if (check == 1) { 00447 //we have the descend flag specified 00448 egg_group->set_collide_flags(EggGroup::CF_descend); 00449 } 00450 } 00451 if (node_desc->get_max_node()->GetUserPropInt(_M("event"), check)) { 00452 if (check == 1) { 00453 //we have the event flag specified 00454 egg_group->set_collide_flags(EggGroup::CF_event); 00455 } 00456 } 00457 if (node_desc->get_max_node()->GetUserPropInt(_M("keep"), check)) { 00458 if (check == 1) { 00459 //we have the keep flag specified 00460 egg_group->set_collide_flags(EggGroup::CF_keep); 00461 } 00462 } 00463 if (node_desc->get_max_node()->GetUserPropInt(_M("solid"), check)) { 00464 if (check == 1) { 00465 //we have the solid flag specified 00466 egg_group->set_collide_flags(EggGroup::CF_solid); 00467 } 00468 } 00469 if (node_desc->get_max_node()->GetUserPropInt(_M("center"), check)) { 00470 if (check == 1) { 00471 //we have the center flag specified 00472 egg_group->set_collide_flags(EggGroup::CF_center); 00473 } 00474 } 00475 if (node_desc->get_max_node()->GetUserPropInt(_M("turnstile"), check)) { 00476 if (check == 1) { 00477 //we have the turnstile flag specified 00478 egg_group->set_collide_flags(EggGroup::CF_turnstile); 00479 } 00480 } 00481 if (node_desc->get_max_node()->GetUserPropInt(_M("level"), check)) { 00482 if (check == 1) { 00483 //we have the level flag specified 00484 egg_group->set_collide_flags(EggGroup::CF_level); 00485 } 00486 } 00487 if (node_desc->get_max_node()->GetUserPropInt(_M("intangible"), check)) { 00488 if (check == 1) { 00489 //we have the intangible flag specified 00490 egg_group->set_collide_flags(EggGroup::CF_intangible); 00491 } 00492 } 00493 return; 00494 }