DAEUtil.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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. int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node);
  15. void getAnimationChannels(const domNodeRef& node, std::list<domChannelRef>& channels)
  16. {
  17. assert(node->getId());
  18. std::string nodeIdSlash (node->getId());
  19. nodeIdSlash.append("/");
  20. domCOLLADA* root = (domCOLLADA*)node->getDocument()->getDomRoot();
  21. domLibrary_animations_Array& animationLibrary = root->getLibrary_animations_array();
  22. size_t animationLibraryCount = animationLibrary.getCount();
  23. for (size_t i = 0; i < animationLibraryCount; ++i)
  24. {
  25. domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
  26. domAnimation_Array& animationArray = animationsRef->getAnimation_array();
  27. size_t animationCount = animationArray.getCount();
  28. for (size_t j = 0; j < animationCount; ++j)
  29. {
  30. domAnimationRef& animationRef = animationArray.get(j);
  31. domChannel_Array& channelArray = animationRef->getChannel_array();
  32. size_t channelArrayCount = channelArray.getCount();
  33. for (size_t k = 0; k < channelArrayCount; ++k)
  34. {
  35. domChannelRef& channel = channelArray.get(k);
  36. const char* target = channel->getTarget();
  37. // TODO: Assumes only one target per channel?
  38. if (startsWith(target, nodeIdSlash.c_str()))
  39. {
  40. channels.push_back(channel);
  41. }
  42. }
  43. }
  44. }
  45. // Recursively do the same for all nodes
  46. daeTArray< daeSmartRef<daeElement> > children;
  47. node->getChildren(children);
  48. size_t childCount = children.getCount();
  49. for (size_t i = 0; i < childCount; ++i)
  50. {
  51. daeElementRef childElement = children[i];
  52. if (childElement->getElementType() == COLLADA_TYPE::NODE)
  53. {
  54. domNodeRef childNode = daeSafeCast<domNode>(childElement);
  55. getAnimationChannels(childNode, channels);
  56. }
  57. }
  58. }
  59. void getJointNames(const domSourceRef source, std::vector<std::string>& list)
  60. {
  61. // BLENDER used name_array
  62. const domName_arrayRef& nameArray = source->getName_array();
  63. if (nameArray.cast())
  64. {
  65. domListOfNames& ids = nameArray->getValue();
  66. size_t jointCount = (size_t)nameArray->getCount();
  67. for (size_t j = 0; j < jointCount; ++j)
  68. {
  69. list.push_back(std::string(ids.get(j)));
  70. }
  71. }
  72. else
  73. {
  74. // Seymour used IDREF_array
  75. const domIDREF_arrayRef& idArray = source->getIDREF_array();
  76. if (idArray.cast())
  77. {
  78. xsIDREFS& ids = idArray->getValue();
  79. size_t jointCount = (size_t)idArray->getCount();
  80. for (size_t j = 0; j < jointCount; ++j)
  81. {
  82. list.push_back(std::string(ids.get(j).getID()));
  83. }
  84. }
  85. }
  86. }
  87. void getJointNames(const domSkin* skin, std::vector<std::string>& list)
  88. {
  89. const domSkin::domJointsRef& joints = skin->getJoints();
  90. const domInputLocal_Array& inputArray = joints->getInput_array();
  91. size_t inputCount = inputArray.getCount();
  92. for (size_t i = 0; i < inputCount; ++i)
  93. {
  94. const domInputLocalRef input = inputArray.get(i);
  95. const char* semantic = input->getSemantic();
  96. if (strcmp(semantic, "JOINT") == 0)
  97. {
  98. daeElement* sourceElement = input->getSource().getElement();
  99. if (sourceElement)
  100. {
  101. const domSourceRef source = daeSafeCast<domSource>(sourceElement);
  102. getJointNames(source, list);
  103. }
  104. }
  105. }
  106. }
  107. domSource* getInputSource(const domChannelRef& channel)
  108. {
  109. daeElement* element = channel->getSource().getElement();
  110. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  111. {
  112. domSampler* sampler = daeSafeCast<domSampler>(element);
  113. const domInputLocal_Array& inputArray = sampler->getInput_array();
  114. size_t inputArrayCount = inputArray.getCount();
  115. for (size_t i = 0; i < inputArrayCount; ++i)
  116. {
  117. const domInputLocalRef& input = inputArray.get(i);
  118. if (strcmp(input->getSemantic(), "INPUT") == 0)
  119. {
  120. daeElement* e = input->getSource().getElement();
  121. if (e && e->getElementType() == COLLADA_TYPE::SOURCE)
  122. {
  123. domSource* source = daeSafeCast<domSource>(e);
  124. assert(source);
  125. return source;
  126. }
  127. }
  128. }
  129. }
  130. return NULL;
  131. }
  132. const domSamplerRef getSampler(const domChannelRef& channel)
  133. {
  134. const domURIFragmentType& uri = channel->getSource();
  135. daeElementRef element = uri.getElement();
  136. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  137. {
  138. const domSamplerRef sampler = daeSafeCast<domSampler>(element);
  139. return sampler;
  140. }
  141. // resolve the source manually by searching for the sampler in the animation that the channel is a child of.
  142. const std::string& id = uri.id();
  143. const daeElementRef& parent = channel->getParent();
  144. if (parent && parent->getElementType() == COLLADA_TYPE::ANIMATION)
  145. {
  146. const domAnimationRef animation = daeSafeCast<domAnimation>(parent);
  147. const domSampler_Array& samplerArray = animation->getSampler_array();
  148. size_t count = samplerArray.getCount();
  149. for (size_t i = 0; i < count; ++i)
  150. {
  151. const domSamplerRef& sampler = samplerArray.get(i);
  152. if (id.compare(sampler->getId()) == 0)
  153. {
  154. return sampler;
  155. }
  156. }
  157. }
  158. return NULL;
  159. }
  160. const domSourceRef getSource(const domInputLocalRef& inputLocal, const domAnimationRef& animation)
  161. {
  162. const domURIFragmentType& uri = inputLocal->getSource();
  163. daeElementRef element = uri.getElement();
  164. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  165. {
  166. const domSourceRef source = daeSafeCast<domSource>(element);
  167. return source;
  168. }
  169. // Resolve the URI by searching through the animation's list of sources
  170. const std::string& id = uri.id();
  171. const domSource_Array& sourceArray = animation->getSource_array();
  172. size_t count = sourceArray.getCount();
  173. for (size_t i = 0; i < count; ++i)
  174. {
  175. const domSourceRef source = sourceArray.get(i);
  176. if (id.compare(source->getId()) == 0)
  177. {
  178. return source;
  179. }
  180. }
  181. return NULL;
  182. }
  183. const domName_arrayRef getSourceNameArray(const domSourceRef& source)
  184. {
  185. const domName_arrayRef& nameArray = source->getName_array();
  186. if (nameArray)
  187. {
  188. return nameArray;
  189. }
  190. daeTArray<daeSmartRef<daeElement> > children;
  191. source->getChildren(children);
  192. size_t childCount = children.getCount();
  193. for (size_t i = 0; i < childCount; ++i)
  194. {
  195. const daeElementRef element = children.get(i);
  196. if (element->getElementType() == COLLADA_TYPE::NAME_ARRAY)
  197. {
  198. return daeSafeCast<domName_array>(element);
  199. }
  200. }
  201. return NULL;
  202. }
  203. const domInstance_controller::domSkeletonRef getSkeleton(const domInstance_controllerRef& instanceController)
  204. {
  205. domInstance_controller::domSkeleton_Array& skeletonArray = instanceController->getSkeleton_array();
  206. size_t count = skeletonArray.getCount();
  207. if (count == 0)
  208. {
  209. return NULL;
  210. }
  211. if (count == 1)
  212. {
  213. return skeletonArray.get(0);
  214. }
  215. // Maya sometimes outputs multiple skeleton elements.
  216. // Find the skeleton element that points to the root most node.
  217. const domInstance_controller::domSkeletonRef& currentSkeleton = skeletonArray.get(0);
  218. const daeElementRef element = currentSkeleton->getValue().getElement();
  219. if (element && element->getElementType() == COLLADA_TYPE::NODE)
  220. {
  221. domNode* node = daeSafeCast<domNode>(element);
  222. int index = 0;
  223. bool loop = true;
  224. do
  225. {
  226. daeElementRef parent = node->getParent();
  227. if (parent && parent->getElementType() == COLLADA_TYPE::NODE)
  228. {
  229. domNodeRef parentNode = daeSafeCast<domNode>(parent);
  230. int result = getIndex(skeletonArray, parentNode);
  231. if (result >= 0)
  232. {
  233. index = result;
  234. }
  235. node = parentNode;
  236. }
  237. else
  238. {
  239. loop = false;
  240. }
  241. } while (loop);
  242. if (index >= 0)
  243. {
  244. return skeletonArray.get(index);
  245. }
  246. }
  247. return NULL;
  248. }
  249. bool equalKeyTimes(const domSource* s1, const domSource* s2)
  250. {
  251. // TODO: shouldn't assume that the source has a float array.
  252. const domFloat_arrayRef& f1 = s1->getFloat_array();
  253. const domFloat_arrayRef& f2 = s2->getFloat_array();
  254. if (f1->getCount() == f2->getCount())
  255. {
  256. const domListOfFloats& list1 = f1->getValue();
  257. const domListOfFloats& list2 = f2->getValue();
  258. size_t count = (size_t)f1->getCount();
  259. for (size_t i = 0; i < count; ++i)
  260. {
  261. if (list1.get(i) != list2.get(i))
  262. {
  263. return false;
  264. }
  265. }
  266. return true;
  267. }
  268. return false;
  269. }
  270. bool equalKeyTimes(const domChannelRef& c1, const domChannelRef& c2)
  271. {
  272. domSource* s1 = getInputSource(c1);
  273. domSource* s2 = getInputSource(c2);
  274. assert(s1);
  275. assert(s2);
  276. return equalKeyTimes(s1, s2);
  277. }
  278. void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& animation)
  279. {
  280. assert(channel);
  281. assert(animation);
  282. daeElement::removeFromParent(channel);
  283. animation->add(channel); // move channel
  284. daeElementRef element = channel->getSource().getElement();
  285. if (element)
  286. {
  287. domSamplerRef sampler = daeSafeCast<domSampler>(element);
  288. domInputLocal_Array& inputArray = sampler->getInput_array();
  289. size_t inputArrayCount = inputArray.getCount();
  290. for (size_t i = 0; i < inputArrayCount; ++i)
  291. {
  292. inputArray = sampler->getInput_array();
  293. const domInputLocalRef& input = inputArray.get(i);
  294. daeElementRef element = input->getSource().getElement();
  295. if (element && element->getElementType() == COLLADA_TYPE::SOURCE)
  296. {
  297. domSourceRef source = daeSafeCast<domSource>(element);
  298. assert(source);
  299. daeElement::removeFromParent(source);
  300. animation->add(source); // move source
  301. }
  302. }
  303. daeElement::removeFromParent(sampler);
  304. animation->add(sampler); // move sampler
  305. }
  306. }
  307. bool isEmptyAnimation(domAnimationRef& animation)
  308. {
  309. return animation->getAnimation_array().getCount() == 0 &&
  310. animation->getChannel_array().getCount() == 0 &&
  311. animation->getSampler_array().getCount() == 0 &&
  312. animation->getSource_array().getCount() == 0;
  313. }
  314. int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node)
  315. {
  316. const std::string nodeId = node->getId();
  317. size_t count = skeletonArray.getCount();
  318. for (size_t i = 0; i < count; ++i)
  319. {
  320. const domInstance_controller::domSkeletonRef& skeleton = skeletonArray.get(i);
  321. daeElementRef element = skeleton->getValue().getElement();
  322. if (element->getElementType() == COLLADA_TYPE::NODE)
  323. {
  324. domNodeRef targetNode = daeSafeCast<domNode>(element);
  325. if (nodeId.compare(targetNode->getId()) == 0)
  326. {
  327. return i;
  328. }
  329. }
  330. }
  331. return -1;
  332. }
  333. }