DAEUtil.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. #include "Base.h"
  2. #include "DAEUtil.h"
  3. #include "StringUtil.h"
  4. namespace gameplay
  5. {
  6. /**
  7. * Returns the index of the skeleton in skeletonArray that points to the given node.
  8. *
  9. * @param skeletonArray The array of skeletons to search.
  10. * @param node The target node.
  11. *
  12. * @return The index in skeletonArray or -1 if not found.
  13. */
  14. static int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node);
  15. /**
  16. * Gets all of the animation channels that target the given node and appends them to the list.
  17. *
  18. * @param animationRef The animation to search in.
  19. * @param nodeIdSlash The node's id with a forward slash appended to it.
  20. * @param channels The list of channels to append to.
  21. */
  22. static void getAnimationChannels(const domAnimationRef& animationRef, const std::string& nodeIdSlash, std::list<domChannelRef>& channels);
  23. void getAnimationChannels(const domNodeRef& node, std::list<domChannelRef>& channels)
  24. {
  25. assert(node->getId());
  26. std::string nodeIdSlash (node->getId());
  27. nodeIdSlash.append("/");
  28. domCOLLADA* root = (domCOLLADA*)node->getDocument()->getDomRoot();
  29. domLibrary_animations_Array& animationLibrary = root->getLibrary_animations_array();
  30. size_t animationLibraryCount = animationLibrary.getCount();
  31. for (size_t i = 0; i < animationLibraryCount; ++i)
  32. {
  33. domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
  34. domAnimation_Array& animationArray = animationsRef->getAnimation_array();
  35. size_t animationCount = animationArray.getCount();
  36. for (size_t j = 0; j < animationCount; ++j)
  37. {
  38. domAnimationRef& animationRef = animationArray.get(j);
  39. getAnimationChannels(animationRef, nodeIdSlash, channels);
  40. }
  41. }
  42. // Recursively do the same for all nodes
  43. daeTArray< daeSmartRef<daeElement> > children;
  44. node->getChildren(children);
  45. size_t childCount = children.getCount();
  46. for (size_t i = 0; i < childCount; ++i)
  47. {
  48. daeElementRef childElement = children[i];
  49. if (childElement->getElementType() == COLLADA_TYPE::NODE)
  50. {
  51. domNodeRef childNode = daeSafeCast<domNode>(childElement);
  52. getAnimationChannels(childNode, channels);
  53. }
  54. }
  55. }
  56. void getJointNames(const domSourceRef source, std::vector<std::string>& list)
  57. {
  58. // BLENDER used name_array
  59. const domName_arrayRef& nameArray = source->getName_array();
  60. if (nameArray.cast())
  61. {
  62. domListOfNames& ids = nameArray->getValue();
  63. size_t jointCount = (size_t)nameArray->getCount();
  64. for (size_t j = 0; j < jointCount; ++j)
  65. {
  66. list.push_back(std::string(ids.get(j)));
  67. }
  68. }
  69. else
  70. {
  71. // Seymour used IDREF_array
  72. const domIDREF_arrayRef& idArray = source->getIDREF_array();
  73. if (idArray.cast())
  74. {
  75. xsIDREFS& ids = idArray->getValue();
  76. size_t jointCount = (size_t)idArray->getCount();
  77. for (size_t j = 0; j < jointCount; ++j)
  78. {
  79. list.push_back(std::string(ids.get(j).getID()));
  80. }
  81. }
  82. }
  83. }
  84. void getJointNames(const domSkin* skin, std::vector<std::string>& list)
  85. {
  86. const domSkin::domJointsRef& joints = skin->getJoints();
  87. const domInputLocal_Array& inputArray = joints->getInput_array();
  88. size_t inputCount = inputArray.getCount();
  89. for (size_t i = 0; i < inputCount; ++i)
  90. {
  91. const domInputLocalRef input = inputArray.get(i);
  92. const char* semantic = input->getSemantic();
  93. if (strcmp(semantic, "JOINT") == 0)
  94. {
  95. daeElement* sourceElement = input->getSource().getElement();
  96. if (sourceElement)
  97. {
  98. const domSourceRef source = daeSafeCast<domSource>(sourceElement);
  99. getJointNames(source, list);
  100. }
  101. }
  102. }
  103. }
  104. domSource* getInputSource(const domChannelRef& channel)
  105. {
  106. daeElement* element = channel->getSource().getElement();
  107. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  108. {
  109. domSampler* sampler = daeSafeCast<domSampler>(element);
  110. const domInputLocal_Array& inputArray = sampler->getInput_array();
  111. size_t inputArrayCount = inputArray.getCount();
  112. for (size_t i = 0; i < inputArrayCount; ++i)
  113. {
  114. const domInputLocalRef& input = inputArray.get(i);
  115. if (strcmp(input->getSemantic(), "INPUT") == 0)
  116. {
  117. daeElement* e = input->getSource().getElement();
  118. if (e && e->getElementType() == COLLADA_TYPE::SOURCE)
  119. {
  120. domSource* source = daeSafeCast<domSource>(e);
  121. assert(source);
  122. return source;
  123. }
  124. }
  125. }
  126. }
  127. return NULL;
  128. }
  129. const domSamplerRef getSampler(const domChannelRef& channel)
  130. {
  131. const domURIFragmentType& uri = channel->getSource();
  132. daeElementRef element = uri.getElement();
  133. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  134. {
  135. const domSamplerRef sampler = daeSafeCast<domSampler>(element);
  136. return sampler;
  137. }
  138. // resolve the source manually by searching for the sampler in the animation that the channel is a child of.
  139. const std::string& id = uri.id();
  140. const daeElementRef& parent = channel->getParent();
  141. if (parent && parent->getElementType() == COLLADA_TYPE::ANIMATION)
  142. {
  143. const domAnimationRef animation = daeSafeCast<domAnimation>(parent);
  144. const domSampler_Array& samplerArray = animation->getSampler_array();
  145. size_t count = samplerArray.getCount();
  146. for (size_t i = 0; i < count; ++i)
  147. {
  148. const domSamplerRef& sampler = samplerArray.get(i);
  149. if (id.compare(sampler->getId()) == 0)
  150. {
  151. return sampler;
  152. }
  153. }
  154. }
  155. return NULL;
  156. }
  157. const domSourceRef getSource(const domInputLocalRef& inputLocal, const domAnimationRef& animation)
  158. {
  159. const domURIFragmentType& uri = inputLocal->getSource();
  160. daeElementRef element = uri.getElement();
  161. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  162. {
  163. const domSourceRef source = daeSafeCast<domSource>(element);
  164. return source;
  165. }
  166. // Resolve the URI by searching through the animation's list of sources
  167. const std::string& id = uri.id();
  168. const domSource_Array& sourceArray = animation->getSource_array();
  169. size_t count = sourceArray.getCount();
  170. for (size_t i = 0; i < count; ++i)
  171. {
  172. const domSourceRef source = sourceArray.get(i);
  173. if (id.compare(source->getId()) == 0)
  174. {
  175. return source;
  176. }
  177. }
  178. return NULL;
  179. }
  180. const domName_arrayRef getSourceNameArray(const domSourceRef& source)
  181. {
  182. const domName_arrayRef& nameArray = source->getName_array();
  183. if (nameArray)
  184. {
  185. return nameArray;
  186. }
  187. daeTArray<daeSmartRef<daeElement> > children;
  188. source->getChildren(children);
  189. size_t childCount = children.getCount();
  190. for (size_t i = 0; i < childCount; ++i)
  191. {
  192. const daeElementRef element = children.get(i);
  193. if (element->getElementType() == COLLADA_TYPE::NAME_ARRAY)
  194. {
  195. return daeSafeCast<domName_array>(element);
  196. }
  197. }
  198. return NULL;
  199. }
  200. const domInstance_controller::domSkeletonRef getSkeleton(const domInstance_controllerRef& instanceController)
  201. {
  202. domInstance_controller::domSkeleton_Array& skeletonArray = instanceController->getSkeleton_array();
  203. size_t count = skeletonArray.getCount();
  204. if (count == 0)
  205. {
  206. return NULL;
  207. }
  208. if (count == 1)
  209. {
  210. return skeletonArray.get(0);
  211. }
  212. // Maya sometimes outputs multiple skeleton elements.
  213. // Find the skeleton element that points to the root most node.
  214. const domInstance_controller::domSkeletonRef& currentSkeleton = skeletonArray.get(0);
  215. const daeElementRef element = currentSkeleton->getValue().getElement();
  216. if (element && element->getElementType() == COLLADA_TYPE::NODE)
  217. {
  218. domNode* node = daeSafeCast<domNode>(element);
  219. int index = 0;
  220. bool loop = true;
  221. do
  222. {
  223. daeElementRef parent = node->getParent();
  224. if (parent && parent->getElementType() == COLLADA_TYPE::NODE)
  225. {
  226. domNodeRef parentNode = daeSafeCast<domNode>(parent);
  227. int result = getIndex(skeletonArray, parentNode);
  228. if (result >= 0)
  229. {
  230. index = result;
  231. }
  232. node = parentNode;
  233. }
  234. else
  235. {
  236. loop = false;
  237. }
  238. } while (loop);
  239. if (index >= 0)
  240. {
  241. return skeletonArray.get(index);
  242. }
  243. }
  244. return NULL;
  245. }
  246. domNode* getRootJointNode(const domSkin* skin)
  247. {
  248. std::vector<std::string> names;
  249. getJointNames(skin, names);
  250. daeSIDResolver resolver(const_cast<domSkin*>(skin)->getDocument()->getDomRoot(), names[0].c_str());
  251. daeElement* element = resolver.getElement();
  252. if (element && element->getElementType() == COLLADA_TYPE::NODE)
  253. {
  254. domNode* node = daeSafeCast<domNode>(resolver.getElement());
  255. return node;
  256. }
  257. return NULL;
  258. }
  259. bool equalKeyTimes(const domSource* s1, const domSource* s2)
  260. {
  261. // TODO: shouldn't assume that the source has a float array.
  262. const domFloat_arrayRef& f1 = s1->getFloat_array();
  263. const domFloat_arrayRef& f2 = s2->getFloat_array();
  264. if (f1->getCount() == f2->getCount())
  265. {
  266. const domListOfFloats& list1 = f1->getValue();
  267. const domListOfFloats& list2 = f2->getValue();
  268. size_t count = (size_t)f1->getCount();
  269. for (size_t i = 0; i < count; ++i)
  270. {
  271. if (list1.get(i) != list2.get(i))
  272. {
  273. return false;
  274. }
  275. }
  276. return true;
  277. }
  278. return false;
  279. }
  280. bool equalKeyTimes(const domChannelRef& c1, const domChannelRef& c2)
  281. {
  282. domSource* s1 = getInputSource(c1);
  283. domSource* s2 = getInputSource(c2);
  284. assert(s1);
  285. assert(s2);
  286. return equalKeyTimes(s1, s2);
  287. }
  288. void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& animation)
  289. {
  290. assert(channel);
  291. assert(animation);
  292. daeElement::removeFromParent(channel);
  293. animation->add(channel); // move channel
  294. daeElementRef element = channel->getSource().getElement();
  295. if (element)
  296. {
  297. domSamplerRef sampler = daeSafeCast<domSampler>(element);
  298. domInputLocal_Array& inputArray = sampler->getInput_array();
  299. size_t inputArrayCount = inputArray.getCount();
  300. for (size_t i = 0; i < inputArrayCount; ++i)
  301. {
  302. inputArray = sampler->getInput_array();
  303. const domInputLocalRef& input = inputArray.get(i);
  304. daeElementRef element = input->getSource().getElement();
  305. if (element && element->getElementType() == COLLADA_TYPE::SOURCE)
  306. {
  307. domSourceRef source = daeSafeCast<domSource>(element);
  308. assert(source);
  309. daeElement::removeFromParent(source);
  310. animation->add(source); // move source
  311. }
  312. }
  313. daeElement::removeFromParent(sampler);
  314. animation->add(sampler); // move sampler
  315. }
  316. }
  317. bool isEmptyAnimation(domAnimationRef& animation)
  318. {
  319. return animation->getAnimation_array().getCount() == 0 &&
  320. animation->getChannel_array().getCount() == 0 &&
  321. animation->getSampler_array().getCount() == 0 &&
  322. animation->getSource_array().getCount() == 0;
  323. }
  324. int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node)
  325. {
  326. const std::string nodeId = node->getId();
  327. size_t count = skeletonArray.getCount();
  328. for (size_t i = 0; i < count; ++i)
  329. {
  330. const domInstance_controller::domSkeletonRef& skeleton = skeletonArray.get(i);
  331. daeElementRef element = skeleton->getValue().getElement();
  332. if (element->getElementType() == COLLADA_TYPE::NODE)
  333. {
  334. domNodeRef targetNode = daeSafeCast<domNode>(element);
  335. if (nodeId.compare(targetNode->getId()) == 0)
  336. {
  337. return i;
  338. }
  339. }
  340. }
  341. return -1;
  342. }
  343. void getAnimationChannels(const domAnimationRef& animationRef, const std::string& nodeIdSlash, std::list<domChannelRef>& channels)
  344. {
  345. domChannel_Array& channelArray = animationRef->getChannel_array();
  346. size_t channelArrayCount = channelArray.getCount();
  347. for (size_t k = 0; k < channelArrayCount; ++k)
  348. {
  349. domChannelRef& channel = channelArray.get(k);
  350. const char* target = channel->getTarget();
  351. // TODO: Assumes only one target per channel?
  352. if (startsWith(target, nodeIdSlash.c_str()))
  353. {
  354. channels.push_back(channel);
  355. }
  356. }
  357. // This animation could have child animations.
  358. const domAnimation_Array& animationArray = animationRef->getAnimation_array();
  359. unsigned int animationCount = animationArray.getCount();
  360. for (size_t i = 0; i < animationCount; ++i)
  361. {
  362. getAnimationChannels(animationArray[i], nodeIdSlash, channels);
  363. }
  364. }
  365. domVisual_scene* getVisualScene(const domCOLLADA::domSceneRef& domScene)
  366. {
  367. daeElement* scene = domScene->getInstance_visual_scene()->getUrl().getElement();
  368. if (scene->getElementType() == COLLADA_TYPE::VISUAL_SCENE)
  369. {
  370. return static_cast<domVisual_scene*>(scene);
  371. }
  372. // DAE_FBX sometimes doesn't export an ID. In that case, see if there is only one visual scene and use that.
  373. // Most of the time there is only one visual scene.
  374. domCOLLADA* root = (domCOLLADA*)domScene->getDocument()->getDomRoot();
  375. domLibrary_visual_scenes_Array& visualSceneLibrary = root->getLibrary_visual_scenes_array();
  376. size_t visualSceneLibraryCount = visualSceneLibrary.getCount();
  377. for (size_t i = 0; i < visualSceneLibraryCount; ++i)
  378. {
  379. domLibrary_visual_scenesRef scenesRef = visualSceneLibrary.get(i);
  380. domVisual_scene_Array visualScenes = scenesRef->getVisual_scene_array();
  381. size_t visualSceneCount = visualScenes.getCount();
  382. for (size_t j = 0; j < visualSceneCount; ++j)
  383. {
  384. domVisual_sceneRef visualScene = visualScenes.get(j);
  385. return visualScene.cast();
  386. }
  387. }
  388. return NULL;
  389. }
  390. }