SkinComponent.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright (C) 2009-present, 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. SkinComponent::SkinComponent(SceneNode* node)
  14. : SceneComponent(node, kClassType)
  15. {
  16. }
  17. SkinComponent::~SkinComponent()
  18. {
  19. }
  20. SkinComponent& SkinComponent::setSkeletonFilename(CString fname)
  21. {
  22. SkeletonResourcePtr newRsrc;
  23. if(ResourceManager::getSingleton().loadResource(fname, newRsrc))
  24. {
  25. ANKI_SCENE_LOGE("Failed to load skeleton");
  26. }
  27. else
  28. {
  29. m_resourceDirty = !m_resource || (m_resource->getUuid() != newRsrc->getUuid());
  30. m_resource = std::move(newRsrc);
  31. }
  32. return *this;
  33. }
  34. CString SkinComponent::getSkeletonFilename() const
  35. {
  36. return (m_resource) ? m_resource->getFilename() : "*Error*";
  37. }
  38. void SkinComponent::playAnimation(U32 trackIdx, AnimationResourcePtr anim, const AnimationPlayInfo& info)
  39. {
  40. const Second animDuration = anim->getDuration();
  41. Track& track = m_tracks[trackIdx];
  42. track.m_anim = anim;
  43. track.m_absoluteStartTime = m_absoluteTime + info.m_startTime;
  44. track.m_relativeTimePassed = 0.0;
  45. if(info.m_repeatTimes > 0.0)
  46. {
  47. track.m_blendInTime = min(animDuration * info.m_repeatTimes, info.m_blendInTime);
  48. track.m_blendOutTime = min(animDuration * info.m_repeatTimes, info.m_blendOutTime);
  49. }
  50. else
  51. {
  52. track.m_blendInTime = info.m_blendInTime;
  53. track.m_blendOutTime = 0.0; // Irrelevant
  54. }
  55. track.m_repeatTimes = info.m_repeatTimes;
  56. track.m_animationSpeedScale = max(0.1f, info.m_animationSpeedScale);
  57. }
  58. void SkinComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
  59. {
  60. m_boneTransformsReallocatedThisFrame = false;
  61. if(m_resourceDirty || !isValid()) [[unlikely]]
  62. {
  63. // Cleanup
  64. m_boneTrfs[0].destroy();
  65. m_boneTrfs[1].destroy();
  66. m_animationTrfs.destroy();
  67. GpuSceneBuffer::getSingleton().deferredFree(m_gpuSceneBoneTransforms);
  68. m_boneTransformsReallocatedThisFrame = true;
  69. }
  70. if(!isValid()) [[unlikely]]
  71. {
  72. return;
  73. }
  74. // Always update two frames because of the bone transforms buffer
  75. const Bool updatedLastFrame = m_updatedLastFrame;
  76. const Bool resourceDirty = m_resourceDirty;
  77. m_resourceDirty = false;
  78. Bool animationRun = false;
  79. if(resourceDirty) [[unlikely]]
  80. {
  81. // Create
  82. const U32 boneCount = m_resource->getBones().getSize();
  83. m_boneTrfs[0].resize(boneCount, Mat3x4::getIdentity());
  84. m_boneTrfs[1].resize(boneCount, Mat3x4::getIdentity());
  85. m_animationTrfs.resize(boneCount, Trf{Vec3(0.0f), Quat::getIdentity(), 1.0f});
  86. m_gpuSceneBoneTransforms = GpuSceneBuffer::getSingleton().allocate(sizeof(Mat4) * boneCount * 2, 4);
  87. m_boneTransformsReallocatedThisFrame = true;
  88. }
  89. const Second dt = info.m_dt;
  90. Vec4 minExtend(kMaxF32, kMaxF32, kMaxF32, 0.0f);
  91. Vec4 maxExtend(kMinF32, kMinF32, kMinF32, 0.0f);
  92. BitSet<128> bonesAnimated(false);
  93. for(Track& track : m_tracks)
  94. {
  95. if(!track.m_anim.isCreated())
  96. {
  97. continue;
  98. }
  99. if(track.m_absoluteStartTime > m_absoluteTime)
  100. {
  101. // Hasn't started yet
  102. continue;
  103. }
  104. const Second clipDuration = track.m_anim->getDuration();
  105. const Second animationDuration = track.m_repeatTimes * clipDuration;
  106. if(track.m_repeatTimes > 0.0 && track.m_relativeTimePassed > animationDuration)
  107. {
  108. // Animation finished
  109. continue;
  110. }
  111. animationRun = true;
  112. const Second animTime = track.m_relativeTimePassed;
  113. track.m_relativeTimePassed += dt * Second(track.m_animationSpeedScale);
  114. // Iterate the animation channels and interpolate
  115. for(U32 i = 0; i < track.m_anim->getChannels().getSize(); ++i)
  116. {
  117. const AnimationChannel& channel = track.m_anim->getChannels()[i];
  118. const Bone* bone = m_resource->tryFindBone(channel.m_name.toCString());
  119. if(!bone)
  120. {
  121. ANKI_SCENE_LOGW("Animation is referencing unknown bone \"%s\"", &channel.m_name[0]);
  122. continue;
  123. }
  124. const U32 boneIdx = bone->getIndex();
  125. // Interpolate
  126. Vec3 position;
  127. Quat rotation;
  128. F32 scale;
  129. track.m_anim->interpolate(i, animTime, position, rotation, scale);
  130. // Blend with previous track
  131. if(bonesAnimated.get(boneIdx) && (track.m_blendInTime > 0.0 || track.m_blendOutTime > 0.0))
  132. {
  133. F32 blendInFactor;
  134. if(track.m_blendInTime > 0.0)
  135. {
  136. blendInFactor = min(1.0f, F32(animTime / track.m_blendInTime));
  137. }
  138. else
  139. {
  140. blendInFactor = 1.0f;
  141. }
  142. F32 blendOutFactor;
  143. if(track.m_blendOutTime > 0.0)
  144. {
  145. blendOutFactor = min(1.0f, F32((animationDuration - animTime) / track.m_blendOutTime));
  146. }
  147. else
  148. {
  149. blendOutFactor = 1.0f;
  150. }
  151. const F32 factor = blendInFactor * blendOutFactor;
  152. if(factor < 1.0f)
  153. {
  154. const Trf& prevTrf = m_animationTrfs[boneIdx];
  155. position = linearInterpolate(prevTrf.m_translation, position, factor);
  156. rotation = prevTrf.m_rotation.slerp(rotation, factor);
  157. scale = linearInterpolate(prevTrf.m_scale, scale, factor);
  158. }
  159. }
  160. // Store
  161. bonesAnimated.set(boneIdx);
  162. m_animationTrfs[boneIdx] = {position, rotation, scale};
  163. }
  164. }
  165. if(updatedLastFrame || resourceDirty || animationRun)
  166. {
  167. m_prevBoneTrfs = m_crntBoneTrfs;
  168. m_crntBoneTrfs = m_crntBoneTrfs ^ 1;
  169. // Walk the bone hierarchy to add additional transforms
  170. visitBones(m_resource->getRootBone(), Mat3x4::getIdentity(), bonesAnimated, minExtend, maxExtend);
  171. const Vec4 e(kEpsilonf, kEpsilonf, kEpsilonf, 0.0f);
  172. m_boneBoundingVolume.setMin(minExtend - e);
  173. m_boneBoundingVolume.setMax(maxExtend + e);
  174. // Update the GPU scene
  175. const U32 boneCount = m_resource->getBones().getSize();
  176. DynamicArray<Mat3x4, MemoryPoolPtrWrapper<StackMemoryPool>> trfs(info.m_framePool);
  177. trfs.resize(boneCount * 2);
  178. for(U32 i = 0; i < boneCount; ++i)
  179. {
  180. trfs[i * 2 + 0] = getBoneTransforms()[i];
  181. trfs[i * 2 + 1] = getPreviousFrameBoneTransforms()[i];
  182. }
  183. GpuSceneMicroPatcher::getSingleton().newCopy(m_gpuSceneBoneTransforms, trfs.getSizeInBytes(), trfs.getBegin());
  184. }
  185. else
  186. {
  187. m_prevBoneTrfs = m_crntBoneTrfs;
  188. }
  189. m_absoluteTime += dt;
  190. updated = updatedLastFrame || resourceDirty || animationRun;
  191. m_updatedLastFrame = resourceDirty || animationRun;
  192. }
  193. void SkinComponent::visitBones(const Bone& bone, const Mat3x4& parentTrf, const BitSet<128>& bonesAnimated, Vec4& minExtend, Vec4& maxExtend)
  194. {
  195. Mat3x4 outMat;
  196. if(bonesAnimated.get(bone.getIndex()))
  197. {
  198. const Trf& t = m_animationTrfs[bone.getIndex()];
  199. outMat = parentTrf.combineTransformations(Mat3x4(t.m_translation.xyz, Mat3(t.m_rotation), Vec3(t.m_scale)));
  200. }
  201. else
  202. {
  203. outMat = parentTrf.combineTransformations(bone.getTransform());
  204. }
  205. m_boneTrfs[m_crntBoneTrfs][bone.getIndex()] = outMat.combineTransformations(bone.getVertexTransform());
  206. // Update volume
  207. const Vec3 bonePos = outMat * Vec4(0.0f, 0.0f, 0.0f, 1.0f);
  208. minExtend = minExtend.min(bonePos.xyz0);
  209. maxExtend = maxExtend.max(bonePos.xyz0);
  210. for(const Bone* child : bone.getChildren())
  211. {
  212. visitBones(*child, outMat, bonesAnimated, minExtend, maxExtend);
  213. }
  214. }
  215. Error SkinComponent::serialize(SceneSerializer& serializer)
  216. {
  217. ANKI_SERIALIZE(m_resource, 1);
  218. for(Track& track : m_tracks)
  219. {
  220. ANKI_SERIALIZE(track.m_anim, 1);
  221. ANKI_SERIALIZE(track.m_absoluteStartTime, 1);
  222. ANKI_SERIALIZE(track.m_relativeTimePassed, 1);
  223. ANKI_SERIALIZE(track.m_blendInTime, 1);
  224. ANKI_SERIALIZE(track.m_blendOutTime, 1);
  225. ANKI_SERIALIZE(track.m_repeatTimes, 1);
  226. ANKI_SERIALIZE(track.m_animationSpeedScale, 1);
  227. }
  228. return Error::kNone;
  229. }
  230. } // end namespace anki