softNodeTree.cxx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. // Filename: softNodeTree.cxx
  2. // Created by: masad (26Sep03)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2003, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://www.panda3d.org/license.txt .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. ////////////////////////////////////////////////////////////////////
  19. // Includes
  20. ////////////////////////////////////////////////////////////////////
  21. #include "softNodeTree.h"
  22. #include "softEggGroupUserData.h"
  23. #include "config_softegg.h"
  24. #include "eggGroup.h"
  25. #include "eggTable.h"
  26. #include "eggXfmSAnim.h"
  27. #include "eggData.h"
  28. #include "dcast.h"
  29. #include <SAA.h>
  30. ////////////////////////////////////////////////////////////////////
  31. // Function: SoftNodeTree::Constructor
  32. // Access: Public
  33. // Description:
  34. ////////////////////////////////////////////////////////////////////
  35. SoftNodeTree::
  36. SoftNodeTree() {
  37. // _root = new SoftNodeDesc;
  38. _root = NULL;
  39. _fps = 0.0;
  40. _egg_data = (EggData *)NULL;
  41. _egg_root = (EggGroupNode *)NULL;
  42. _skeleton_node = (EggGroupNode *)NULL;
  43. }
  44. ////////////////////////////////////////////////////////////////////
  45. // Function: GetName
  46. // Access: Public
  47. // Description: Given an element, return a copy of the element's
  48. // name WITHOUT prefix.
  49. ////////////////////////////////////////////////////////////////////
  50. char *SoftNodeTree::
  51. GetName( SAA_Scene *scene, SAA_Elem *element ) {
  52. int nameLen;
  53. char *name;
  54. // get the name
  55. SAA_elementGetNameLength( scene, element, &nameLen );
  56. name = new char[++nameLen];
  57. SAA_elementGetName( scene, element, nameLen, name );
  58. return name;
  59. }
  60. ////////////////////////////////////////////////////////////////////
  61. // Function: GetFullName
  62. // Access: Public
  63. // Description: Given an element, return a copy of the element's
  64. // name complete with prefix.
  65. ////////////////////////////////////////////////////////////////////
  66. char *SoftNodeTree::
  67. GetFullName( SAA_Scene *scene, SAA_Elem *element )
  68. {
  69. int nameLen, prefixLen;
  70. char *name, *prefix;
  71. // get the name length
  72. SAA_elementGetNameLength( scene, element, &nameLen );
  73. // get the prefix length
  74. SAA_elementGetPrefixLength( scene, element, &prefixLen );
  75. // allocate the array to hold name
  76. name = new char[++nameLen];
  77. // allocate the array to hold prefix and length + hyphen
  78. prefix = new char[++prefixLen + nameLen + 4];
  79. // get the name
  80. SAA_elementGetName( scene, element, nameLen, name );
  81. // get the prefix
  82. SAA_elementGetPrefix( scene, element, prefixLen, prefix );
  83. // add 'em together
  84. strcat(prefix, "-");
  85. strcat(prefix, name);
  86. // return string
  87. return prefix;
  88. }
  89. ////////////////////////////////////////////////////////////////////
  90. // Function: SoftNodeTree::build_node
  91. // Access: Public
  92. // Description: Returns a pointer to the node corresponding to the
  93. // indicated dag_path object, creating it first if
  94. // necessary.
  95. ////////////////////////////////////////////////////////////////////
  96. SoftNodeDesc *SoftNodeTree::
  97. build_node(SAA_Elem *model, const char *name) {
  98. string node_name = name;
  99. SoftNodeDesc *node_desc = r_build_node(node_name);
  100. node_desc->set_model(model);
  101. return node_desc;
  102. }
  103. ////////////////////////////////////////////////////////////////////
  104. // Function: SoftNodeTree::build_complete_hierarchy
  105. // Access: Public
  106. // Description: Walks through the complete Soft hierarchy and builds
  107. // up the corresponding tree.
  108. ////////////////////////////////////////////////////////////////////
  109. bool SoftNodeTree::
  110. build_complete_hierarchy(SAA_Scene &scene, SAA_Database &database, char **root_name) {
  111. SI_Error status;
  112. // Get the entire Soft scene.
  113. int numModels;
  114. SAA_Elem *models;
  115. SAA_sceneGetNbModels( &scene, &numModels );
  116. cout << "Scene has " << numModels << " model(s)...\n";
  117. // This while loop walks through the entire Soft hierarchy, one
  118. // node at a time.
  119. bool all_ok = true;
  120. if ( numModels ) {
  121. // allocate array of models
  122. models = (SAA_Elem *) new SAA_Elem[numModels];
  123. if ( models != NULL ) {
  124. if ((status = SAA_sceneGetModels( &scene, numModels, models )) != SI_SUCCESS) {
  125. return false;
  126. }
  127. for ( int i = 0; i < numModels; i++ ) {
  128. int level;
  129. status = SAA_elementGetHierarchyLevel( &scene, &models[i], &level );
  130. cout << "level " << level << endl;
  131. char *name = GetName(&scene, &models[i]);
  132. if ( !level ) {
  133. // this is the root node, so this should be the name of the model
  134. *root_name = name;
  135. }
  136. SoftNodeDesc *node_desc = build_node(&models[i], name);
  137. cout << "status is " << status << "\n";
  138. }
  139. }
  140. }
  141. # if 0
  142. if (all_ok) {
  143. _root->check_pseudo_joints(false);
  144. }
  145. #endif
  146. return all_ok;
  147. }
  148. #if 0
  149. ////////////////////////////////////////////////////////////////////
  150. // Function: SoftNodeTree::build_selected_hierarchy
  151. // Access: Public
  152. // Description: Walks through the selected subset of the Soft
  153. // hierarchy (or the complete hierarchy, if nothing is
  154. // selected) and builds up the corresponding tree.
  155. ////////////////////////////////////////////////////////////////////
  156. bool SoftNodeTree::
  157. build_selected_hierarchy(char *scene_name) {
  158. MStatus status;
  159. MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
  160. if (!status) {
  161. status.perror("MItDag constructor");
  162. return false;
  163. }
  164. // Get only the selected geometry.
  165. MSelectionList selection;
  166. status = MGlobal::getActiveSelectionList(selection);
  167. if (!status) {
  168. status.perror("MGlobal::getActiveSelectionList");
  169. return false;
  170. }
  171. // Get the selected geometry only if the selection is nonempty;
  172. // otherwise, get the whole scene anyway.
  173. if (selection.isEmpty()) {
  174. softegg_cat.info()
  175. << "Selection list is empty.\n";
  176. return build_complete_hierarchy();
  177. }
  178. bool all_ok = true;
  179. unsigned int length = selection.length();
  180. for (unsigned int i = 0; i < length; i++) {
  181. MDagPath root_path;
  182. status = selection.getDagPath(i, root_path);
  183. if (!status) {
  184. status.perror("MSelectionList::getDagPath");
  185. } else {
  186. // Now traverse through the selected dag path and all nested
  187. // dag paths.
  188. dag_iterator.reset(root_path);
  189. while (!dag_iterator.isDone()) {
  190. MDagPath dag_path;
  191. status = dag_iterator.getPath(dag_path);
  192. if (!status) {
  193. status.perror("MItDag::getPath");
  194. } else {
  195. build_node(dag_path);
  196. }
  197. dag_iterator.next();
  198. }
  199. }
  200. }
  201. if (all_ok) {
  202. _root->check_pseudo_joints(false);
  203. }
  204. return all_ok;
  205. }
  206. #endif
  207. ////////////////////////////////////////////////////////////////////
  208. // Function: SoftNodeTree::get_num_nodes
  209. // Access: Public
  210. // Description: Returns the total number of nodes in the hierarchy,
  211. // not counting the root node.
  212. ////////////////////////////////////////////////////////////////////
  213. int SoftNodeTree::
  214. get_num_nodes() const {
  215. return _nodes.size();
  216. }
  217. ////////////////////////////////////////////////////////////////////
  218. // Function: SoftNodeTree::get_node
  219. // Access: Public
  220. // Description: Returns the nth node in the hierarchy, in an
  221. // arbitrary ordering.
  222. ////////////////////////////////////////////////////////////////////
  223. SoftNodeDesc *SoftNodeTree::
  224. get_node(int n) const {
  225. nassertr(n >= 0 && n < (int)_nodes.size(), NULL);
  226. return _nodes[n];
  227. }
  228. ////////////////////////////////////////////////////////////////////
  229. // Function: SoftNodeTree::clear_egg
  230. // Access: Public
  231. // Description: Removes all of the references to generated egg
  232. // structures from the tree, and prepares the tree for
  233. // generating new egg structures.
  234. ////////////////////////////////////////////////////////////////////
  235. void SoftNodeTree::
  236. clear_egg(EggData *egg_data, EggGroupNode *egg_root,
  237. EggGroupNode *skeleton_node) {
  238. // _root->clear_egg();
  239. _egg_data = egg_data;
  240. _egg_root = egg_root;
  241. _skeleton_node = skeleton_node;
  242. }
  243. ////////////////////////////////////////////////////////////////////
  244. // Function: SoftNodeTree::get_egg_group
  245. // Access: Public
  246. // Description: Returns the EggGroupNode corresponding to the group
  247. // or joint for the indicated node. Creates the group
  248. // node if it has not already been created.
  249. ////////////////////////////////////////////////////////////////////
  250. EggGroup *SoftNodeTree::
  251. get_egg_group(SoftNodeDesc *node_desc) {
  252. nassertr(_egg_root != (EggGroupNode *)NULL, NULL);
  253. if (node_desc->_egg_group == (EggGroup *)NULL) {
  254. // We need to make a new group node.
  255. EggGroup *egg_group;
  256. egg_group = new EggGroup(node_desc->get_name());
  257. if (node_desc->is_joint()) {
  258. egg_group->set_group_type(EggGroup::GT_joint);
  259. }
  260. // For now lets add this group to egg_root.
  261. _egg_root->add_child(egg_group);
  262. #if 0
  263. SoftEggGroupUserData *parent_user_data = NULL;
  264. if (node_desc->_parent == _root) {
  265. // The parent is the root.
  266. _egg_root->add_child(egg_group);
  267. } else {
  268. // The parent is another node.
  269. EggGroup *parent_egg_group = get_egg_group(node_desc->_parent);
  270. parent_egg_group->add_child(egg_group);
  271. if (parent_egg_group->has_user_data()) {
  272. DCAST_INTO_R(parent_user_data, parent_egg_group->get_user_data(), NULL);
  273. }
  274. }
  275. if (node_desc->has_models()) {
  276. // Check for an object type setting, from Oliver's plug-in.
  277. MObject dag_object = node_desc->get_dag_path().node();
  278. string object_type;
  279. if (get_enum_attribute(dag_object, "eggObjectTypes1", object_type)) {
  280. egg_group->add_object_type(object_type);
  281. }
  282. if (get_enum_attribute(dag_object, "eggObjectTypes2", object_type)) {
  283. egg_group->add_object_type(object_type);
  284. }
  285. if (get_enum_attribute(dag_object, "eggObjectTypes3", object_type)) {
  286. egg_group->add_object_type(object_type);
  287. }
  288. // Is the node flagged to be invisible? If it is, and is has no
  289. // other egg flags, it is implicitly tagged "backstage", so it
  290. // won't get converted. (But it might be an invisible collision
  291. // solid, which is why we do this only if it has no other egg
  292. // flags.)
  293. bool visible = true;
  294. get_bool_attribute(dag_object, "visibility", visible);
  295. if (!visible && egg_group->get_num_object_types() == 0) {
  296. egg_group->add_object_type("backstage");
  297. }
  298. // We treat the object type "billboard" as a special case: we
  299. // apply this one right away and also flag the group as an
  300. // instance.
  301. if (egg_group->has_object_type("billboard")) {
  302. egg_group->remove_object_type("billboard");
  303. egg_group->set_group_type(EggGroup::GT_instance);
  304. egg_group->set_billboard_type(EggGroup::BT_axis);
  305. } else if (egg_group->has_object_type("billboard-point")) {
  306. egg_group->remove_object_type("billboard-point");
  307. egg_group->set_group_type(EggGroup::GT_instance);
  308. egg_group->set_billboard_type(EggGroup::BT_point_camera_relative);
  309. }
  310. // We also treat the object type "dcs" and "model" as a special
  311. // case, so we can test for these flags later.
  312. if (egg_group->has_object_type("dcs")) {
  313. egg_group->remove_object_type("dcs");
  314. egg_group->set_dcs_type(EggGroup::DC_default);
  315. }
  316. if (egg_group->has_object_type("model")) {
  317. egg_group->remove_object_type("model");
  318. egg_group->set_model_flag(true);
  319. }
  320. // And "vertex-color" and "double-sided" have meaning only to
  321. // this converter.
  322. SoftEggGroupUserData *user_data;
  323. if (parent_user_data == (SoftEggGroupUserData *)NULL) {
  324. user_data = new SoftEggGroupUserData;
  325. } else {
  326. // Inherit the flags from above.
  327. user_data = new SoftEggGroupUserData(*parent_user_data);
  328. }
  329. if (egg_group->has_object_type("vertex-color")) {
  330. egg_group->remove_object_type("vertex-color");
  331. user_data->_vertex_color = true;
  332. }
  333. if (egg_group->has_object_type("double-sided")) {
  334. egg_group->remove_object_type("double-sided");
  335. user_data->_double_sided = true;
  336. }
  337. egg_group->set_user_data(user_data);
  338. }
  339. #endif
  340. // EggUserData *user_data = new EggUserData;
  341. // egg_group->set_user_data(user_data);
  342. node_desc->_egg_group = egg_group;
  343. }
  344. return node_desc->_egg_group;
  345. }
  346. #if 0
  347. ////////////////////////////////////////////////////////////////////
  348. // Function: SoftNodeTree::get_egg_table
  349. // Access: Public
  350. // Description: Returns the EggTable corresponding to the joint
  351. // for the indicated node. Creates the table node if it
  352. // has not already been created.
  353. ////////////////////////////////////////////////////////////////////
  354. EggTable *SoftNodeTree::
  355. get_egg_table(SoftNodeDesc *node_desc) {
  356. nassertr(_skeleton_node != (EggGroupNode *)NULL, NULL);
  357. nassertr(node_desc->is_joint(), NULL);
  358. if (node_desc->_egg_table == (EggTable *)NULL) {
  359. // We need to make a new table node.
  360. nassertr(node_desc->_parent != (SoftNodeDesc *)NULL, NULL);
  361. EggTable *egg_table = new EggTable(node_desc->get_name());
  362. node_desc->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system());
  363. node_desc->_anim->set_fps(_fps);
  364. egg_table->add_child(node_desc->_anim);
  365. if (!node_desc->_parent->is_joint()) {
  366. // The parent is not a joint; put it at the top.
  367. _skeleton_node->add_child(egg_table);
  368. } else {
  369. // The parent is another joint.
  370. EggTable *parent_egg_table = get_egg_table(node_desc->_parent);
  371. parent_egg_table->add_child(egg_table);
  372. }
  373. node_desc->_egg_table = egg_table;
  374. }
  375. return node_desc->_egg_table;
  376. }
  377. ////////////////////////////////////////////////////////////////////
  378. // Function: SoftNodeTree::get_egg_anim
  379. // Access: Public
  380. // Description: Returns the anim table corresponding to the joint
  381. // for the indicated node. Creates the table node if it
  382. // has not already been created.
  383. ////////////////////////////////////////////////////////////////////
  384. EggXfmSAnim *SoftNodeTree::
  385. get_egg_anim(SoftNodeDesc *node_desc) {
  386. get_egg_table(node_desc);
  387. return node_desc->_anim;
  388. }
  389. #endif
  390. ////////////////////////////////////////////////////////////////////
  391. // Function: SoftNodeTree::r_build_node
  392. // Access: Private
  393. // Description: The recursive implementation of build_node().
  394. ////////////////////////////////////////////////////////////////////
  395. SoftNodeDesc *SoftNodeTree::
  396. r_build_node(const string &name) {
  397. // Otherwise, we have to create it. Do this recursively, so we
  398. // create each node along the path.
  399. SoftNodeDesc *node_desc;
  400. node_desc = new SoftNodeDesc(name);
  401. _nodes.push_back(node_desc);
  402. return node_desc;
  403. }
  404. //
  405. //
  406. //