DAEUtil.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #include "DAEUtil.h"
  2. /**
  3. * Returns the index of the skeleton in skeletonArray that points to the given node.
  4. *
  5. * @param skeletonArray The array of skeletons to search.
  6. * @param node The target node.
  7. *
  8. * @return The index in skeletonArray or -1 if not found.
  9. */
  10. int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node);
  11. void getJointNames(const domSource* source, std::list<std::string>& list)
  12. {
  13. // BLENDER used name_array
  14. const domName_arrayRef& nameArray = source->getName_array();
  15. if (nameArray.cast())
  16. {
  17. domListOfNames& ids = nameArray->getValue();
  18. size_t jointCount = (size_t)nameArray->getCount();
  19. for (size_t j = 0; j < jointCount; j++)
  20. {
  21. list.push_back(std::string(ids.get(j)));
  22. }
  23. }
  24. else
  25. {
  26. // Seymour used IDREF_array
  27. const domIDREF_arrayRef& idArray = source->getIDREF_array();
  28. if (idArray.cast())
  29. {
  30. xsIDREFS& ids = idArray->getValue();
  31. size_t jointCount = (size_t)idArray->getCount();
  32. for (size_t j = 0; j < jointCount; j++)
  33. {
  34. list.push_back(std::string(ids.get(j).getID()));
  35. }
  36. }
  37. }
  38. }
  39. void getJointNames(const domSkin* skin, std::list<std::string>& list)
  40. {
  41. const domSkin::domJointsRef& joints = skin->getJoints();
  42. const domInputLocal_Array& inputArray = joints->getInput_array();
  43. size_t inputCount = inputArray.getCount();
  44. for (size_t i = 0; i < inputCount; i++)
  45. {
  46. const domInputLocalRef input = inputArray.get(i);
  47. const char* semantic = input->getSemantic();
  48. if (strcmp(semantic, "JOINT") == 0)
  49. {
  50. daeElement* sourceElement = input->getSource().getElement();
  51. if (sourceElement)
  52. {
  53. const domSource* source = static_cast<domSource*>(sourceElement);
  54. getJointNames(source, list);
  55. }
  56. }
  57. }
  58. }
  59. domSource* getInputSource(const domChannelRef& channel)
  60. {
  61. daeElement* element = channel->getSource().getElement();
  62. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  63. {
  64. domSampler* sampler = daeSafeCast<domSampler>(element);
  65. const domInputLocal_Array& inputArray = sampler->getInput_array();
  66. size_t inputArrayCount = inputArray.getCount();
  67. for (size_t i = 0; i < inputArrayCount; i++)
  68. {
  69. const domInputLocalRef& input = inputArray.get(i);
  70. if (strcmp(input->getSemantic(), "INPUT") == 0)
  71. {
  72. daeElement* e = input->getSource().getElement();
  73. if (e && e->getElementType() == COLLADA_TYPE::SOURCE)
  74. {
  75. domSource* source = daeSafeCast<domSource>(e);
  76. assert(source);
  77. return source;
  78. }
  79. }
  80. }
  81. }
  82. return NULL;
  83. }
  84. const domSamplerRef getSampler(const domChannelRef& channel)
  85. {
  86. const domURIFragmentType& uri = channel->getSource();
  87. daeElementRef element = uri.getElement();
  88. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  89. {
  90. const domSamplerRef sampler = daeSafeCast<domSampler>(element);
  91. return sampler;
  92. }
  93. // resolve the source manually by searching for the sampler in the animation that the channel is a child of.
  94. const std::string& id = uri.id();
  95. const daeElementRef& parent = channel->getParent();
  96. if (parent && parent->getElementType() == COLLADA_TYPE::ANIMATION)
  97. {
  98. const domAnimationRef animation = daeSafeCast<domAnimation>(parent);
  99. const domSampler_Array& samplerArray = animation->getSampler_array();
  100. size_t count = samplerArray.getCount();
  101. for (size_t i = 0; i < count; i++)
  102. {
  103. const domSamplerRef& sampler = samplerArray.get(i);
  104. if (id.compare(sampler->getId()) == 0)
  105. {
  106. return sampler;
  107. }
  108. }
  109. }
  110. return NULL;
  111. }
  112. const domSourceRef getSource(const domInputLocalRef& inputLocal, const domAnimationRef& animation)
  113. {
  114. const domURIFragmentType& uri = inputLocal->getSource();
  115. daeElementRef element = uri.getElement();
  116. if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
  117. {
  118. const domSourceRef source = daeSafeCast<domSource>(element);
  119. return source;
  120. }
  121. // Resolve the URI by searching through the animation's list of sources
  122. const std::string& id = uri.id();
  123. const domSource_Array& sourceArray = animation->getSource_array();
  124. size_t count = sourceArray.getCount();
  125. for (size_t i = 0; i < count; i++)
  126. {
  127. const domSourceRef source = sourceArray.get(i);
  128. if (id.compare(source->getId()) == 0)
  129. {
  130. return source;
  131. }
  132. }
  133. return NULL;
  134. }
  135. const domName_arrayRef getSourceNameArray(const domSourceRef& source)
  136. {
  137. const domName_arrayRef& nameArray = source->getName_array();
  138. if (nameArray)
  139. {
  140. return nameArray;
  141. }
  142. daeTArray<daeSmartRef<daeElement>> children;
  143. source->getChildren(children);
  144. size_t childCount = children.getCount();
  145. for (size_t i = 0; i < childCount; i++)
  146. {
  147. const daeElementRef element = children.get(i);
  148. if (element->getElementType() == COLLADA_TYPE::NAME_ARRAY)
  149. {
  150. return daeSafeCast<domName_array>(element);
  151. }
  152. }
  153. return NULL;
  154. }
  155. const domInstance_controller::domSkeletonRef getSkeleton(const domInstance_controllerRef& instanceController)
  156. {
  157. domInstance_controller::domSkeleton_Array& skeletonArray = instanceController->getSkeleton_array();
  158. size_t count = skeletonArray.getCount();
  159. if (count == 0)
  160. {
  161. return NULL;
  162. }
  163. if (count == 1)
  164. {
  165. return skeletonArray.get(0);
  166. }
  167. // Maya sometimes outputs multiple skeleton elements.
  168. // Find the skeleton element that points to the root most node.
  169. const domInstance_controller::domSkeletonRef& currentSkeleton = skeletonArray.get(0);
  170. const daeElementRef element = currentSkeleton->getValue().getElement();
  171. if (element && element->getElementType() == COLLADA_TYPE::NODE)
  172. {
  173. domNode* node = daeSafeCast<domNode>(element);
  174. int index = 0;
  175. bool loop = true;
  176. do
  177. {
  178. daeElementRef parent = node->getParent();
  179. if (parent && parent->getElementType() == COLLADA_TYPE::NODE)
  180. {
  181. domNodeRef parentNode = daeSafeCast<domNode>(parent);
  182. int result = getIndex(skeletonArray, parentNode);
  183. if (result >= 0)
  184. {
  185. index = result;
  186. }
  187. node = parentNode;
  188. }
  189. else
  190. {
  191. loop = false;
  192. }
  193. } while (loop);
  194. if (index >= 0)
  195. {
  196. return skeletonArray.get(index);
  197. }
  198. }
  199. return NULL;
  200. }
  201. bool equalKeyTimes(const domSource* s1, const domSource* s2)
  202. {
  203. // TODO: shouldn't assume that the source has a float array.
  204. const domFloat_arrayRef& f1 = s1->getFloat_array();
  205. const domFloat_arrayRef& f2 = s2->getFloat_array();
  206. if (f1->getCount() == f2->getCount())
  207. {
  208. const domListOfFloats& list1 = f1->getValue();
  209. const domListOfFloats& list2 = f2->getValue();
  210. size_t count = (size_t)f1->getCount();
  211. for (size_t i = 0; i < count; i++)
  212. {
  213. if (list1.get(i) != list2.get(i))
  214. {
  215. return false;
  216. }
  217. }
  218. return true;
  219. }
  220. return false;
  221. }
  222. bool equalKeyTimes(const domChannelRef& c1, const domChannelRef& c2)
  223. {
  224. domSource* s1 = getInputSource(c1);
  225. domSource* s2 = getInputSource(c2);
  226. assert(s1);
  227. assert(s2);
  228. return equalKeyTimes(s1, s2);
  229. }
  230. void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& animation)
  231. {
  232. assert(channel);
  233. assert(animation);
  234. daeElement::removeFromParent(channel);
  235. animation->add(channel); // move channel
  236. daeElementRef element = channel->getSource().getElement();
  237. if (element)
  238. {
  239. domSamplerRef sampler = daeSafeCast<domSampler>(element);
  240. domInputLocal_Array& inputArray = sampler->getInput_array();
  241. size_t inputArrayCount = inputArray.getCount();
  242. for (size_t i = 0; i < inputArrayCount; i++)
  243. {
  244. inputArray = sampler->getInput_array();
  245. const domInputLocalRef& input = inputArray.get(i);
  246. daeElementRef element = input->getSource().getElement();
  247. if (element && element->getElementType() == COLLADA_TYPE::SOURCE)
  248. {
  249. domSourceRef source = daeSafeCast<domSource>(element);
  250. assert(source);
  251. daeElement::removeFromParent(source);
  252. animation->add(source); // move source
  253. }
  254. }
  255. daeElement::removeFromParent(sampler);
  256. animation->add(sampler); // move sampler
  257. }
  258. }
  259. bool isEmptyAnimation(domAnimationRef& animation)
  260. {
  261. return animation->getAnimation_array().getCount() == 0 &&
  262. animation->getChannel_array().getCount() == 0 &&
  263. animation->getSampler_array().getCount() == 0 &&
  264. animation->getSource_array().getCount() == 0;
  265. }
  266. int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node)
  267. {
  268. const std::string nodeId = node->getId();
  269. size_t count = skeletonArray.getCount();
  270. for (size_t i = 0; i < count; i++)
  271. {
  272. const domInstance_controller::domSkeletonRef& skeleton = skeletonArray.get(i);
  273. daeElementRef element = skeleton->getValue().getElement();
  274. if (element->getElementType() == COLLADA_TYPE::NODE)
  275. {
  276. domNodeRef targetNode = daeSafeCast<domNode>(element);
  277. if (nodeId.compare(targetNode->getId()) == 0)
  278. {
  279. return i;
  280. }
  281. }
  282. }
  283. return -1;
  284. }