SkinComponent.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Scene/Components/SkinComponent.h>
  6. #include <AnKi/Scene/SceneNode.h>
  7. #include <AnKi/Scene/SceneGraph.h>
  8. #include <AnKi/Resource/SkeletonResource.h>
  9. #include <AnKi/Resource/AnimationResource.h>
  10. #include <AnKi/Resource/ResourceManager.h>
  11. #include <AnKi/Util/BitSet.h>
  12. namespace anki {
  13. ANKI_SCENE_COMPONENT_STATICS(SkinComponent)
  14. SkinComponent::SkinComponent(SceneNode* node)
  15. : SceneComponent(node, getStaticClassId())
  16. , m_node(node)
  17. {
  18. }
  19. SkinComponent::~SkinComponent()
  20. {
  21. m_boneTrfs[0].destroy(m_node->getAllocator());
  22. m_boneTrfs[1].destroy(m_node->getAllocator());
  23. m_animationTrfs.destroy(m_node->getAllocator());
  24. }
  25. Error SkinComponent::loadSkeletonResource(CString fname)
  26. {
  27. ANKI_CHECK(m_node->getSceneGraph().getResourceManager().loadResource(fname, m_skeleton));
  28. m_boneTrfs[0].destroy(m_node->getAllocator());
  29. m_boneTrfs[1].destroy(m_node->getAllocator());
  30. m_animationTrfs.destroy(m_node->getAllocator());
  31. m_boneTrfs[0].create(m_node->getAllocator(), m_skeleton->getBones().getSize(), Mat4::getIdentity());
  32. m_boneTrfs[1].create(m_node->getAllocator(), m_skeleton->getBones().getSize(), Mat4::getIdentity());
  33. m_animationTrfs.create(m_node->getAllocator(), m_skeleton->getBones().getSize(),
  34. {Vec3(0.0f), Quat::getIdentity(), 1.0f});
  35. return Error::kNone;
  36. }
  37. void SkinComponent::playAnimation(U32 track, AnimationResourcePtr anim, const AnimationPlayInfo& info)
  38. {
  39. const Second animDuration = anim->getDuration();
  40. m_tracks[track].m_anim = anim;
  41. m_tracks[track].m_absoluteStartTime = m_absoluteTime + info.m_startTime;
  42. m_tracks[track].m_relativeTimePassed = 0.0;
  43. if(info.m_repeatTimes > 0.0)
  44. {
  45. m_tracks[track].m_blendInTime = min(animDuration * info.m_repeatTimes, info.m_blendInTime);
  46. m_tracks[track].m_blendOutTime = min(animDuration * info.m_repeatTimes, info.m_blendOutTime);
  47. }
  48. else
  49. {
  50. m_tracks[track].m_blendInTime = info.m_blendInTime;
  51. m_tracks[track].m_blendOutTime = 0.0; // Irrelevant
  52. }
  53. m_tracks[track].m_repeatTimes = info.m_repeatTimes;
  54. }
  55. Error SkinComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
  56. {
  57. ANKI_ASSERT(info.m_node == m_node);
  58. updated = false;
  59. if(!m_skeleton.isCreated())
  60. {
  61. return Error::kNone;
  62. }
  63. const Second dt = info.m_dt;
  64. Vec4 minExtend(kMaxF32, kMaxF32, kMaxF32, 0.0f);
  65. Vec4 maxExtend(kMinF32, kMinF32, kMinF32, 0.0f);
  66. BitSet<128> bonesAnimated(false);
  67. for(Track& track : m_tracks)
  68. {
  69. if(!track.m_anim.isCreated())
  70. {
  71. continue;
  72. }
  73. if(track.m_absoluteStartTime > m_absoluteTime)
  74. {
  75. // Hasn't started yet
  76. continue;
  77. }
  78. const Second clipDuration = track.m_anim->getDuration();
  79. const Second animationDuration = track.m_repeatTimes * clipDuration;
  80. if(track.m_repeatTimes > 0.0 && track.m_relativeTimePassed > animationDuration)
  81. {
  82. // Animation finished
  83. continue;
  84. }
  85. updated = true;
  86. const Second animTime = track.m_relativeTimePassed;
  87. track.m_relativeTimePassed += dt;
  88. // Iterate the animation channels and interpolate
  89. for(U32 i = 0; i < track.m_anim->getChannels().getSize(); ++i)
  90. {
  91. const AnimationChannel& channel = track.m_anim->getChannels()[i];
  92. const Bone* bone = m_skeleton->tryFindBone(channel.m_name.toCString());
  93. if(!bone)
  94. {
  95. ANKI_SCENE_LOGW("Animation is referencing unknown bone \"%s\"", &channel.m_name[0]);
  96. continue;
  97. }
  98. const U32 boneIdx = bone->getIndex();
  99. // Interpolate
  100. Vec3 position;
  101. Quat rotation;
  102. F32 scale;
  103. track.m_anim->interpolate(i, animTime, position, rotation, scale);
  104. // Blend with previous track
  105. if(bonesAnimated.get(boneIdx) && (track.m_blendInTime > 0.0 || track.m_blendOutTime > 0.0))
  106. {
  107. F32 blendInFactor;
  108. if(track.m_blendInTime > 0.0)
  109. {
  110. blendInFactor = min(1.0f, F32(animTime / track.m_blendInTime));
  111. }
  112. else
  113. {
  114. blendInFactor = 1.0f;
  115. }
  116. F32 blendOutFactor;
  117. if(track.m_blendOutTime > 0.0)
  118. {
  119. blendOutFactor = min(1.0f, F32((animationDuration - animTime) / track.m_blendOutTime));
  120. }
  121. else
  122. {
  123. blendOutFactor = 1.0f;
  124. }
  125. const F32 factor = blendInFactor * blendOutFactor;
  126. if(factor < 1.0f)
  127. {
  128. const Trf& prevTrf = m_animationTrfs[boneIdx];
  129. position = linearInterpolate(prevTrf.m_translation, position, factor);
  130. rotation = prevTrf.m_rotation.slerp(rotation, factor);
  131. scale = linearInterpolate(prevTrf.m_scale, scale, factor);
  132. }
  133. }
  134. // Store
  135. bonesAnimated.set(boneIdx);
  136. m_animationTrfs[boneIdx] = {position, rotation, scale};
  137. }
  138. }
  139. // Always update the 1st time
  140. updated = updated || (m_absoluteTime == 0.0);
  141. if(updated)
  142. {
  143. m_prevBoneTrfs = m_crntBoneTrfs;
  144. m_crntBoneTrfs = m_crntBoneTrfs ^ 1;
  145. // Walk the bone hierarchy to add additional transforms
  146. visitBones(m_skeleton->getRootBone(), Mat4::getIdentity(), bonesAnimated, minExtend, maxExtend);
  147. const Vec4 e(kEpsilonf, kEpsilonf, kEpsilonf, 0.0f);
  148. m_boneBoundingVolume.setMin(minExtend - e);
  149. m_boneBoundingVolume.setMax(maxExtend + e);
  150. }
  151. else
  152. {
  153. m_prevBoneTrfs = m_crntBoneTrfs;
  154. }
  155. m_absoluteTime += dt;
  156. return Error::kNone;
  157. }
  158. void SkinComponent::visitBones(const Bone& bone, const Mat4& parentTrf, const BitSet<128>& bonesAnimated,
  159. Vec4& minExtend, Vec4& maxExtend)
  160. {
  161. Mat4 outMat;
  162. if(bonesAnimated.get(bone.getIndex()))
  163. {
  164. const Trf& t = m_animationTrfs[bone.getIndex()];
  165. outMat = parentTrf * Mat4(t.m_translation.xyz1(), Mat3(t.m_rotation), t.m_scale);
  166. }
  167. else
  168. {
  169. outMat = parentTrf * bone.getTransform();
  170. }
  171. m_boneTrfs[m_crntBoneTrfs][bone.getIndex()] = outMat * bone.getVertexTransform();
  172. // Update volume
  173. const Vec4 bonePos = outMat * Vec4(0.0f, 0.0f, 0.0f, 1.0f);
  174. minExtend = minExtend.min(bonePos.xyz0());
  175. maxExtend = maxExtend.max(bonePos.xyz0());
  176. for(const Bone* child : bone.getChildren())
  177. {
  178. visitBones(*child, outMat, bonesAnimated, minExtend, maxExtend);
  179. }
  180. }
  181. } // end namespace anki