DAEOptimizer.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "DAEOptimizer.h"
  2. #include <algorithm>
  3. #include "StringUtil.h"
  4. DAEOptimizer::DAEOptimizer(domCOLLADA* dom)
  5. {
  6. _dom = dom;
  7. }
  8. DAEOptimizer::~DAEOptimizer()
  9. {
  10. }
  11. void DAEOptimizer::combineAnimations(const std::string& nodeId, const std::string& animationId)
  12. {
  13. std::list<domChannelRef> channels;
  14. daeSIDResolver resolver(_dom, nodeId.c_str());
  15. daeElement* element = resolver.getElement();
  16. if (element && element->getElementType() == COLLADA_TYPE::NODE)
  17. {
  18. domNodeRef node = daeSafeCast<domNode>(resolver.getElement());
  19. getAnimationChannels(node, channels);
  20. }
  21. // Get the <library_animations>
  22. domLibrary_animations_Array& animationsLibraryArray = _dom->getLibrary_animations_array();
  23. assert(animationsLibraryArray.getCount() > 0);
  24. domLibrary_animationsRef& animationsLibrary = animationsLibraryArray.get(0);
  25. // Add a new animation
  26. domAnimationRef animation = daeSafeCast<domAnimation>(animationsLibrary->createAndPlace("animation"));
  27. assert(animation);
  28. animation->setId(animationId.c_str());
  29. // TODO: Make sure that there doesn't already exist an animation with this ID.
  30. // Move each of the channels to this animation
  31. for (std::list<domChannelRef>::iterator i = channels.begin(); i != channels.end(); i++)
  32. {
  33. moveChannelAndSouresToAnimation(*i, animation);
  34. }
  35. // Clean up the empty animations
  36. deleteEmptyAnimations();
  37. }
  38. void DAEOptimizer::getAnimationChannels(const domNodeRef& node, std::list<domChannelRef>& channels)
  39. {
  40. assert(node->getId());
  41. std::string nodeIdSlash (node->getId());
  42. nodeIdSlash.append("/");
  43. domCOLLADA* root = (domCOLLADA*)node->getDocument()->getDomRoot();
  44. domLibrary_animations_Array& animationLibrary = root->getLibrary_animations_array();
  45. size_t animationLibraryCount = animationLibrary.getCount();
  46. for (size_t i = 0; i < animationLibraryCount; i++)
  47. {
  48. domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
  49. domAnimation_Array& animationArray = animationsRef->getAnimation_array();
  50. size_t animationCount = animationArray.getCount();
  51. for (size_t j = 0; j < animationCount; j++)
  52. {
  53. domAnimationRef& animationRef = animationArray.get(j);
  54. domChannel_Array& channelArray = animationRef->getChannel_array();
  55. size_t channelArrayCount = channelArray.getCount();
  56. for (size_t k = 0; k < channelArrayCount; k++)
  57. {
  58. domChannelRef& channel = channelArray.get(k);
  59. const char* target = channel->getTarget();
  60. // TODO: Assumes only one target per channel?
  61. if (startsWith(target, nodeIdSlash.c_str()))
  62. {
  63. channels.push_back(channel);
  64. }
  65. }
  66. }
  67. }
  68. // Recursively do the same for all nodes
  69. daeTArray< daeSmartRef<daeElement> > children;
  70. node->getChildren(children);
  71. size_t childCount = children.getCount();
  72. for (size_t i = 0; i < childCount; i++)
  73. {
  74. daeElementRef childElement = children[i];
  75. if (childElement->getElementType() == COLLADA_TYPE::NODE)
  76. {
  77. domNodeRef childNode = daeSafeCast<domNode>(childElement);
  78. getAnimationChannels(childNode, channels);
  79. }
  80. }
  81. }
  82. void DAEOptimizer::deleteEmptyAnimations()
  83. {
  84. std::list<domAnimationRef> animations;
  85. // Get the list of empty animations
  86. domLibrary_animations_Array& animationLibrary = _dom->getLibrary_animations_array();
  87. size_t animationLibraryCount = animationLibrary.getCount();
  88. for (size_t i = 0; i < animationLibraryCount; i++)
  89. {
  90. domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
  91. domAnimation_Array& animationArray = animationsRef->getAnimation_array();
  92. size_t animationCount = animationArray.getCount();
  93. for (size_t j = 0; j < animationCount; j++)
  94. {
  95. domAnimationRef& animation = animationArray.get(j);
  96. if (isEmptyAnimation(animation))
  97. {
  98. animations.push_back(animation);
  99. }
  100. }
  101. }
  102. // Delete all of the empty animations
  103. for (std::list<domAnimationRef>::iterator i = animations.begin(); i != animations.end(); i++)
  104. {
  105. daeElement::removeFromParent(*i);
  106. }
  107. }