maxNodeTree.cxx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. // Filename: maxNodeTree.cxx
  2. // Created by: crevilla
  3. // from mayaNodeTree.cxx created by: drose (06Jun03)
  4. //
  5. ////////////////////////////////////////////////////////////////////
  6. //
  7. // PANDA 3D SOFTWARE
  8. // Copyright (c) Carnegie Mellon University. All rights reserved.
  9. //
  10. // All use of this software is subject to the terms of the revised BSD
  11. // license. You should have received a copy of this license along
  12. // with this source code in a file named "LICENSE."
  13. //
  14. ////////////////////////////////////////////////////////////////////
  15. #include "maxNodeTree.h"
  16. #include "eggGroup.h"
  17. #include "eggTable.h"
  18. #include "eggXfmSAnim.h"
  19. #include "eggData.h"
  20. #ifdef MAX5
  21. //Disable the "Too many actual parameters in istdplug.h" warning in Max5
  22. #pragma warning(push)
  23. #pragma warning(disable: 4002)
  24. #include "max_pre_include.h"
  25. #endif
  26. #include "Max.h"
  27. #ifdef MAX5
  28. #include "max_post_include.h"
  29. #pragma warning(pop)
  30. #endif
  31. #include "maxToEggConverter.h"
  32. ////////////////////////////////////////////////////////////////////
  33. // Function: MaxNodeTree::Constructor
  34. // Access: Public
  35. // Description:
  36. ////////////////////////////////////////////////////////////////////
  37. MaxNodeTree::
  38. MaxNodeTree() {
  39. _root = new MaxNodeDesc;
  40. _fps = 0.0;
  41. _egg_data = (EggData *)NULL;
  42. _egg_root = (EggGroupNode *)NULL;
  43. _skeleton_node = (EggGroupNode *)NULL;
  44. }
  45. ////////////////////////////////////////////////////////////////////
  46. // Function: MaxNodeTree::build_node
  47. // Access: Public
  48. // Description: Returns a pointer to the node corresponding to the
  49. // indicated INode object, creating it first if
  50. // necessary.
  51. ////////////////////////////////////////////////////////////////////
  52. MaxNodeDesc *MaxNodeTree::
  53. build_node(INode *max_node) {
  54. MaxNodeDesc *node_desc = r_build_node(max_node);
  55. node_desc->from_INode(max_node);
  56. if (node_desc->is_node_joint())
  57. node_desc->_joint_entry = build_joint(max_node, node_desc);
  58. return node_desc;
  59. }
  60. ////////////////////////////////////////////////////////////////////
  61. // Function: MaxNodeTree::build_node
  62. // Access: Public
  63. // Description: Returns a pointer to the node corresponding to the
  64. // indicated INode object, creating it first if
  65. // necessary.
  66. ////////////////////////////////////////////////////////////////////
  67. MaxNodeDesc *MaxNodeTree::
  68. build_joint(INode *max_node, MaxNodeDesc *node_joint) {
  69. MaxNodeDesc *node_desc = r_build_joint(node_joint, max_node);
  70. node_desc->from_INode(max_node);
  71. node_desc->set_joint(true);
  72. return node_desc;
  73. }
  74. bool MaxNodeTree::node_in_list(ULONG handle, ULONG *list, int len) {
  75. if (!list) return true;
  76. for (int i = 0; i < len; i++)
  77. if (list[i] == handle) return true;
  78. return false;
  79. }
  80. bool MaxNodeTree::is_joint(INode *node) {
  81. Control *c = node->GetTMController();
  82. return (node->GetBoneNodeOnOff() || //joints
  83. (c && //bipeds
  84. ((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
  85. (c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
  86. (c->ClassID() == FOOTPRINT_CLASS_ID))));
  87. }
  88. bool MaxNodeTree::
  89. r_build_hierarchy(INode *root, ULONG *selection_list, int len) {
  90. if (node_in_list(root->GetHandle(), selection_list, len))
  91. build_node(root);
  92. // Export children
  93. for ( int i = 0; i < root->NumberOfChildren(); i++ ) {
  94. // *** Should probably be checking the return value of the following line
  95. r_build_hierarchy(root->GetChildNode(i), selection_list, len);
  96. }
  97. return true;
  98. }
  99. ////////////////////////////////////////////////////////////////////
  100. // Function: MaxNodeTree::build_complete_hierarchy
  101. // Access: Public
  102. // Description: Walks through the complete Max hierarchy and builds
  103. // up the corresponding tree.
  104. ////////////////////////////////////////////////////////////////////
  105. bool MaxNodeTree::
  106. build_complete_hierarchy(INode *root, ULONG *selection_list, int len) {
  107. // Get the entire Max scene.
  108. if (root == NULL) {
  109. // *** Log an error
  110. return false;
  111. }
  112. bool all_ok = true;
  113. r_build_hierarchy(root, selection_list, len);
  114. if (all_ok) {
  115. _root->check_pseudo_joints(false);
  116. }
  117. Logger::Log( MTEC, Logger::SAT_MEDIUM_LEVEL,
  118. "finished building complete hierarchy" );
  119. return all_ok;
  120. }
  121. ////////////////////////////////////////////////////////////////////
  122. // Function: MaxNodeTree::build_selected_hierarchy
  123. // Access: Public
  124. // Description: Walks through the selected subset of the Max
  125. // hierarchy (or the complete hierarchy, if nothing is
  126. // selected) and builds up the corresponding tree.
  127. ////////////////////////////////////////////////////////////////////
  128. bool MaxNodeTree::
  129. build_selected_hierarchy(INode *root) {
  130. // *** Write this later when it's time to do selection
  131. /*
  132. MStatus status;
  133. MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
  134. if (!status) {
  135. status.perror("MItDag constructor");
  136. return false;
  137. }
  138. // Get only the selected geometry.
  139. MSelectionList selection;
  140. status = MGlobal::getActiveSelectionList(selection);
  141. if (!status) {
  142. status.perror("MGlobal::getActiveSelectionList");
  143. return false;
  144. }
  145. // Get the selected geometry only if the selection is nonempty;
  146. // otherwise, get the whole scene anyway.
  147. if (selection.isEmpty()) {
  148. mayaegg_cat.info()
  149. << "Selection list is empty.\n";
  150. return build_complete_hierarchy();
  151. }
  152. */
  153. bool all_ok = true;
  154. /*
  155. unsigned int length = selection.length();
  156. for (unsigned int i = 0; i < length; i++) {
  157. MDagPath root_path;
  158. status = selection.getDagPath(i, root_path);
  159. if (!status) {
  160. status.perror("MSelectionList::getDagPath");
  161. } else {
  162. // Now traverse through the selected dag path and all nested
  163. // dag paths.
  164. dag_iterator.reset(root_path);
  165. while (!dag_iterator.isDone()) {
  166. MDagPath dag_path;
  167. status = dag_iterator.getPath(dag_path);
  168. if (!status) {
  169. status.perror("MItDag::getPath");
  170. } else {
  171. build_node(dag_path);
  172. }
  173. dag_iterator.next();
  174. }
  175. }
  176. }
  177. if (all_ok) {
  178. _root->check_pseudo_joints(false);
  179. }
  180. */
  181. return all_ok;
  182. }
  183. ////////////////////////////////////////////////////////////////////
  184. // Function: MaxNodeTree::get_num_nodes
  185. // Access: Public
  186. // Description: Returns the total number of nodes in the hierarchy,
  187. // not counting the root node.
  188. ////////////////////////////////////////////////////////////////////
  189. int MaxNodeTree::
  190. get_num_nodes() const {
  191. return _nodes.size();
  192. }
  193. ////////////////////////////////////////////////////////////////////
  194. // Function: MaxNodeTree::get_node
  195. // Access: Public
  196. // Description: Returns the nth node in the hierarchy, in an
  197. // arbitrary ordering.
  198. ////////////////////////////////////////////////////////////////////
  199. MaxNodeDesc *MaxNodeTree::
  200. get_node(int n) const {
  201. nassertr(n >= 0 && n < (int)_nodes.size(), NULL);
  202. return _nodes[n];
  203. }
  204. ////////////////////////////////////////////////////////////////////
  205. // Function: MaxNodeTree::clear_egg
  206. // Access: Public
  207. // Description: Removes all of the references to generated egg
  208. // structures from the tree, and prepares the tree for
  209. // generating new egg structures.
  210. ////////////////////////////////////////////////////////////////////
  211. void MaxNodeTree::
  212. clear_egg(EggData *egg_data, EggGroupNode *egg_root,
  213. EggGroupNode *skeleton_node) {
  214. _root->clear_egg();
  215. _egg_data = egg_data;
  216. _egg_root = egg_root;
  217. _skeleton_node = skeleton_node;
  218. }
  219. ////////////////////////////////////////////////////////////////////
  220. // Function: MaxNodeTree::get_egg_group
  221. // Access: Public
  222. // Description: Returns the EggGroupNode corresponding to the group
  223. // or joint for the indicated node. Creates the group
  224. // node if it has not already been created.
  225. ////////////////////////////////////////////////////////////////////
  226. EggGroup *MaxNodeTree::
  227. get_egg_group(MaxNodeDesc *node_desc) {
  228. nassertr(_egg_root != (EggGroupNode *)NULL, NULL);
  229. if (node_desc->_egg_group == (EggGroup *)NULL) {
  230. // We need to make a new group node.
  231. EggGroup *egg_group;
  232. nassertr(node_desc->_parent != (MaxNodeDesc *)NULL, NULL);
  233. egg_group = new EggGroup(node_desc->get_name());
  234. if (node_desc->is_joint()) {
  235. egg_group->set_group_type(EggGroup::GT_joint);
  236. }
  237. if (node_desc->_parent == _root) {
  238. // The parent is the root.
  239. _egg_root->add_child(egg_group);
  240. } else {
  241. // The parent is another node.
  242. EggGroup *parent_egg_group = get_egg_group(node_desc->_parent);
  243. parent_egg_group->add_child(egg_group);
  244. }
  245. // *** This is probably something that a Max plugin would need to be
  246. // written for. May want to ask Disney about it
  247. /*
  248. if (node_desc->has_dag_path()) {
  249. // Check for an object type setting, from Oliver's plug-in.
  250. MObject dag_object = node_desc->get_dag_path().node();
  251. string object_type;
  252. if (get_enum_attribute(dag_object, "eggObjectTypes1", object_type)) {
  253. egg_group->add_object_type(object_type);
  254. }
  255. if (get_enum_attribute(dag_object, "eggObjectTypes2", object_type)) {
  256. egg_group->add_object_type(object_type);
  257. }
  258. if (get_enum_attribute(dag_object, "eggObjectTypes3", object_type)) {
  259. egg_group->add_object_type(object_type);
  260. }
  261. // We treat the object type "billboard" as a special case: we
  262. // apply this one right away and also flag the group as an
  263. // instance.
  264. if (egg_group->has_object_type("billboard")) {
  265. egg_group->remove_object_type("billboard");
  266. egg_group->set_group_type(EggGroup::GT_instance);
  267. egg_group->set_billboard_type(EggGroup::BT_axis);
  268. } else if (egg_group->has_object_type("billboard-point")) {
  269. egg_group->remove_object_type("billboard-point");
  270. egg_group->set_group_type(EggGroup::GT_instance);
  271. egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
  272. }
  273. // We also treat the object type "dcs" and "model" as a special
  274. // case, so we can test for these flags later.
  275. if (egg_group->has_object_type("dcs")) {
  276. egg_group->remove_object_type("dcs");
  277. egg_group->set_dcs_type(EggGroup::DC_default);
  278. }
  279. if (egg_group->has_object_type("model")) {
  280. egg_group->remove_object_type("model");
  281. egg_group->set_model_flag(true);
  282. }
  283. // And "vertex-color" has meaning only to this converter.
  284. if (egg_group->has_object_type("vertex-color")) {
  285. egg_group->remove_object_type("vertex-color");
  286. MaxEggGroupUserData *user_data = new MaxEggGroupUserData;
  287. user_data->_vertex_color = true;
  288. egg_group->set_user_data(user_data);
  289. }
  290. }
  291. */
  292. node_desc->_egg_group = egg_group;
  293. }
  294. return node_desc->_egg_group;
  295. }
  296. ////////////////////////////////////////////////////////////////////
  297. // Function: MaxNodeTree::get_egg_table
  298. // Access: Public
  299. // Description: Returns the EggTable corresponding to the joint
  300. // for the indicated node. Creates the table node if it
  301. // has not already been created.
  302. ////////////////////////////////////////////////////////////////////
  303. EggTable *MaxNodeTree::
  304. get_egg_table(MaxNodeDesc *node_desc) {
  305. nassertr(_skeleton_node != (EggGroupNode *)NULL, NULL);
  306. nassertr(node_desc->is_joint(), NULL);
  307. if (node_desc->_egg_table == (EggTable *)NULL) {
  308. // We need to make a new table node.
  309. nassertr(node_desc->_parent != (MaxNodeDesc *)NULL, NULL);
  310. EggTable *egg_table = new EggTable(node_desc->get_name());
  311. node_desc->_anim = new EggXfmSAnim("xform",
  312. _egg_data->get_coordinate_system());
  313. node_desc->_anim->set_fps(_fps);
  314. egg_table->add_child(node_desc->_anim);
  315. if (!node_desc->_parent->is_joint()) {
  316. // The parent is not a joint; put it at the top.
  317. _skeleton_node->add_child(egg_table);
  318. } else {
  319. // The parent is another joint.
  320. EggTable *parent_egg_table = get_egg_table(node_desc->_parent);
  321. parent_egg_table->add_child(egg_table);
  322. }
  323. node_desc->_egg_table = egg_table;
  324. }
  325. return node_desc->_egg_table;
  326. }
  327. ////////////////////////////////////////////////////////////////////
  328. // Function: MaxNodeTree::get_egg_anim
  329. // Access: Public
  330. // Description: Returns the anim table corresponding to the joint
  331. // for the indicated node. Creates the table node if it
  332. // has not already been created.
  333. ////////////////////////////////////////////////////////////////////
  334. EggXfmSAnim *MaxNodeTree::
  335. get_egg_anim(MaxNodeDesc *node_desc)
  336. {
  337. get_egg_table(node_desc);
  338. return node_desc->_anim;
  339. }
  340. ////////////////////////////////////////////////////////////////////
  341. // Function: MaxNodeTree::r_build_node
  342. // Access: Private
  343. // Description: The recursive implementation of build_node().
  344. ////////////////////////////////////////////////////////////////////
  345. MaxNodeDesc *MaxNodeTree::
  346. r_build_node(INode* max_node)
  347. {
  348. // If we have already encountered this pathname, return the
  349. // corresponding MaxNodeDesc immediately.
  350. ULONG node_handle = 0;
  351. if (max_node) {
  352. node_handle = max_node->GetHandle();
  353. }
  354. NodesByPath::const_iterator ni = _nodes_by_path.find(node_handle);
  355. if (ni != _nodes_by_path.end()) {
  356. return (*ni).second;
  357. }
  358. // Otherwise, we have to create it. Do this recursively, so we
  359. // create each node along the path.
  360. MaxNodeDesc *node_desc;
  361. if (!max_node) {
  362. // This is the top.
  363. node_desc = _root;
  364. } else {
  365. INode *parent_node;
  366. string local_name = max_node->GetName();
  367. if (max_node->IsRootNode()) {
  368. parent_node = NULL;
  369. } else {
  370. parent_node = max_node->GetParentNode();
  371. }
  372. MaxNodeDesc *parent_node_desc = r_build_node(parent_node);
  373. node_desc = new MaxNodeDesc(parent_node_desc, local_name);
  374. _nodes.push_back(node_desc);
  375. }
  376. _nodes_by_path.insert(NodesByPath::value_type(node_handle, node_desc));
  377. return node_desc;
  378. }
  379. ////////////////////////////////////////////////////////////////////
  380. // Function: MaxNodeTree::r_build_joint
  381. // Access: Private
  382. // Description: The recursive implementation of build_joint().
  383. ////////////////////////////////////////////////////////////////////
  384. MaxNodeDesc *MaxNodeTree::
  385. r_build_joint(MaxNodeDesc *node_desc, INode *max_node)
  386. {
  387. MaxNodeDesc *node_joint;
  388. if (node_desc == _root) {
  389. node_joint = new MaxNodeDesc(_root, max_node->GetName());
  390. _nodes.push_back(node_joint);
  391. return node_joint;
  392. } else if (node_desc->is_node_joint() && node_desc->_joint_entry) {
  393. node_joint = new MaxNodeDesc(node_desc->_joint_entry, max_node->GetName());
  394. _nodes.push_back(node_joint);
  395. return node_joint;
  396. } else {
  397. return r_build_joint(node_desc->_parent, max_node);
  398. }
  399. }
  400. ////////////////////////////////////////////////////////////////////
  401. // Function: MaxNodeTree::find_node
  402. // Access: Private
  403. // Description: The recursive implementation of build_node().
  404. ////////////////////////////////////////////////////////////////////
  405. MaxNodeDesc *MaxNodeTree::
  406. find_node(INode* max_node)
  407. {
  408. // If we have already encountered this pathname, return the
  409. // corresponding MaxNodeDesc immediately.
  410. ULONG node_handle = 0;
  411. if (max_node) {
  412. node_handle = max_node->GetHandle();
  413. }
  414. NodesByPath::const_iterator ni = _nodes_by_path.find(node_handle);
  415. if (ni != _nodes_by_path.end()) {
  416. return (*ni).second;
  417. }
  418. return NULL;
  419. }
  420. ////////////////////////////////////////////////////////////////////
  421. // Function: MaxNodeTree::find_joint
  422. // Access: Private
  423. // Description: The recursive implementation of build_node().
  424. ////////////////////////////////////////////////////////////////////
  425. MaxNodeDesc *MaxNodeTree::
  426. find_joint(INode* max_node)
  427. {
  428. MaxNodeDesc *node = find_node(max_node);
  429. if (!node || (is_joint(max_node) && !node->is_node_joint()))
  430. node = build_node(max_node);
  431. return node->_joint_entry;
  432. }