BsSkeleton.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Animation/BsSkeleton.h"
  4. #include "Animation/BsAnimationClip.h"
  5. #include "Animation/BsSkeletonMask.h"
  6. #include "Private/RTTI/BsSkeletonRTTI.h"
  7. namespace bs
  8. {
  9. LocalSkeletonPose::LocalSkeletonPose()
  10. : positions(nullptr), rotations(nullptr), scales(nullptr), hasOverride(nullptr), numBones(0)
  11. { }
  12. LocalSkeletonPose::LocalSkeletonPose(UINT32 numBones)
  13. : numBones(numBones)
  14. {
  15. UINT32 elementSize = sizeof(Vector3) * 2 + sizeof(Quaternion) + sizeof(bool);
  16. UINT8* buffer = (UINT8*)bs_alloc(elementSize * numBones);
  17. positions = (Vector3*)buffer;
  18. buffer += sizeof(Vector3) * numBones;
  19. rotations = (Quaternion*)buffer;
  20. buffer += sizeof(Quaternion) * numBones;
  21. scales = (Vector3*)buffer;
  22. buffer += sizeof(Vector3) * numBones;
  23. hasOverride = (bool*)buffer;
  24. }
  25. LocalSkeletonPose::LocalSkeletonPose(UINT32 numPos, UINT32 numRot, UINT32 numScale)
  26. : hasOverride(nullptr), numBones(0)
  27. {
  28. UINT32 bufferSize = sizeof(Vector3) * numPos + sizeof(Quaternion) * numRot + sizeof(Vector3) * numScale;
  29. UINT8* buffer = (UINT8*)bs_alloc(bufferSize);
  30. positions = (Vector3*)buffer;
  31. buffer += sizeof(Vector3) * numPos;
  32. rotations = (Quaternion*)buffer;
  33. buffer += sizeof(Quaternion) * numRot;
  34. scales = (Vector3*)buffer;
  35. }
  36. LocalSkeletonPose::LocalSkeletonPose(LocalSkeletonPose&& other)
  37. : positions(other.positions), rotations(other.rotations), scales(other.scales), hasOverride(other.hasOverride)
  38. , numBones(other.numBones)
  39. {
  40. other.positions = nullptr;
  41. other.rotations = nullptr;
  42. other.scales = nullptr;
  43. other.hasOverride = nullptr;
  44. other.numBones = 0;
  45. }
  46. LocalSkeletonPose::~LocalSkeletonPose()
  47. {
  48. if (positions != nullptr)
  49. bs_free(positions);
  50. }
  51. LocalSkeletonPose& LocalSkeletonPose::operator=(LocalSkeletonPose&& other)
  52. {
  53. if (this != &other)
  54. {
  55. if (positions != nullptr)
  56. bs_free(positions);
  57. positions = other.positions;
  58. rotations = other.rotations;
  59. scales = other.scales;
  60. hasOverride = other.hasOverride;
  61. numBones = other.numBones;
  62. other.positions = nullptr;
  63. other.rotations = nullptr;
  64. other.scales = nullptr;
  65. other.hasOverride = nullptr;
  66. other.numBones = 0;
  67. }
  68. return *this;
  69. }
  70. Skeleton::Skeleton()
  71. { }
  72. Skeleton::Skeleton(BONE_DESC* bones, UINT32 numBones)
  73. : mNumBones(numBones), mBoneTransforms(bs_newN<Transform>(numBones)), mInvBindPoses(bs_newN<Matrix4>(numBones))
  74. , mBoneInfo(bs_newN<SkeletonBoneInfo>(numBones))
  75. {
  76. for(UINT32 i = 0; i < numBones; i++)
  77. {
  78. mBoneTransforms[i] = bones[i].localTfrm;
  79. mInvBindPoses[i] = bones[i].invBindPose;
  80. mBoneInfo[i].name = bones[i].name;
  81. mBoneInfo[i].parent = bones[i].parent;
  82. }
  83. }
  84. Skeleton::~Skeleton()
  85. {
  86. if(mBoneTransforms != nullptr)
  87. bs_deleteN(mBoneTransforms, mNumBones);
  88. if(mInvBindPoses != nullptr)
  89. bs_deleteN(mInvBindPoses, mNumBones);
  90. if (mBoneInfo != nullptr)
  91. bs_deleteN(mBoneInfo, mNumBones);
  92. }
  93. SPtr<Skeleton> Skeleton::create(BONE_DESC* bones, UINT32 numBones)
  94. {
  95. Skeleton* rawPtr = new (bs_alloc<Skeleton>()) Skeleton(bones, numBones);
  96. return bs_shared_ptr<Skeleton>(rawPtr);
  97. }
  98. void Skeleton::getPose(Matrix4* pose, LocalSkeletonPose& localPose, const SkeletonMask& mask,
  99. const AnimationClip& clip, float time, bool loop)
  100. {
  101. bs_frame_mark();
  102. {
  103. FrameVector<AnimationCurveMapping> boneToCurveMapping(mNumBones);
  104. AnimationState state;
  105. state.curves = clip.getCurves();
  106. state.boneToCurveMapping = boneToCurveMapping.data();
  107. state.loop = loop;
  108. state.weight = 1.0f;
  109. state.time = time;
  110. FrameVector<TCurveCache<Vector3>> positionCache(state.curves->position.size());
  111. FrameVector<TCurveCache<Quaternion>> rotationCache(state.curves->rotation.size());
  112. FrameVector<TCurveCache<Vector3>> scaleCache(state.curves->scale.size());
  113. state.positionCaches = positionCache.data();
  114. state.rotationCaches = rotationCache.data();
  115. state.scaleCaches = scaleCache.data();
  116. state.genericCaches = nullptr;
  117. state.disabled = false;
  118. AnimationStateLayer layer;
  119. layer.index = 0;
  120. layer.additive = false;
  121. layer.states = &state;
  122. layer.numStates = 1;
  123. clip.getBoneMapping(*this, state.boneToCurveMapping);
  124. getPose(pose, localPose, mask, &layer, 1);
  125. }
  126. bs_frame_clear();
  127. }
  128. void Skeleton::getPose(Matrix4* pose, LocalSkeletonPose& localPose, const SkeletonMask& mask,
  129. const AnimationStateLayer* layers, UINT32 numLayers)
  130. {
  131. // Note: If more performance is required this method could be optimized with vector instructions
  132. assert(localPose.numBones == mNumBones);
  133. for(UINT32 i = 0; i < mNumBones; i++)
  134. {
  135. localPose.positions[i] = Vector3::ZERO;
  136. localPose.rotations[i] = Quaternion::ZERO;
  137. localPose.scales[i] = Vector3::ONE;
  138. }
  139. // Note: For a possible performance improvement consider keeping an array of only active (non-disabled) bones and
  140. // just iterate over them without mask checks. Possibly also a list of active curve mappings to avoid those checks
  141. // as well.
  142. for(UINT32 i = 0; i < numLayers; i++)
  143. {
  144. const AnimationStateLayer& layer = layers[i];
  145. float invLayerWeight;
  146. if (layer.additive)
  147. {
  148. float weightSum = 0.0f;
  149. for (UINT32 j = 0; j < layer.numStates; j++)
  150. weightSum += layer.states[j].weight;
  151. invLayerWeight = 1.0f / weightSum;
  152. }
  153. else
  154. invLayerWeight = 1.0f;
  155. for (UINT32 j = 0; j < layer.numStates; j++)
  156. {
  157. const AnimationState& state = layer.states[j];
  158. if (state.disabled)
  159. continue;
  160. float normWeight = state.weight * invLayerWeight;
  161. // Early exit for clips that don't contribute (which there could be plenty especially for sequential blends)
  162. if (Math::approxEquals(normWeight, 0.0f))
  163. continue;
  164. for (UINT32 k = 0; k < mNumBones; k++)
  165. {
  166. if (!mask.isEnabled(k))
  167. continue;
  168. bool hasAnimCurve = false;
  169. const AnimationCurveMapping& mapping = state.boneToCurveMapping[k];
  170. UINT32 curveIdx = mapping.position;
  171. if (curveIdx != (UINT32)-1)
  172. {
  173. const TAnimationCurve<Vector3>& curve = state.curves->position[curveIdx].curve;
  174. localPose.positions[k] += curve.evaluate(state.time, state.positionCaches[curveIdx], state.loop) * normWeight;
  175. localPose.hasOverride[k] = false;
  176. hasAnimCurve = true;
  177. }
  178. curveIdx = mapping.scale;
  179. if (curveIdx != (UINT32)-1)
  180. {
  181. const TAnimationCurve<Vector3>& curve = state.curves->scale[curveIdx].curve;
  182. localPose.scales[k] *= curve.evaluate(state.time, state.scaleCaches[curveIdx], state.loop) * normWeight;
  183. localPose.hasOverride[k] = false;
  184. hasAnimCurve = true;
  185. }
  186. if (layer.additive)
  187. {
  188. curveIdx = mapping.rotation;
  189. if (curveIdx != (UINT32)-1)
  190. {
  191. bool isAssigned = localPose.rotations[k].w != 0.0f;
  192. if (!isAssigned)
  193. localPose.rotations[k] = Quaternion::IDENTITY;
  194. const TAnimationCurve<Quaternion>& curve = state.curves->rotation[curveIdx].curve;
  195. Quaternion value = curve.evaluate(state.time, state.rotationCaches[curveIdx], state.loop);
  196. value = Quaternion::lerp(normWeight, Quaternion::IDENTITY, value);
  197. localPose.rotations[k] *= value;
  198. localPose.hasOverride[k] = false;
  199. hasAnimCurve = true;
  200. }
  201. }
  202. else
  203. {
  204. curveIdx = mapping.rotation;
  205. if (curveIdx != (UINT32)-1)
  206. {
  207. const TAnimationCurve<Quaternion>& curve = state.curves->rotation[curveIdx].curve;
  208. Quaternion value = curve.evaluate(state.time, state.rotationCaches[curveIdx], state.loop) * normWeight;
  209. if (value.dot(localPose.rotations[k]) < 0.0f)
  210. value = -value;
  211. localPose.rotations[k] += value;
  212. localPose.hasOverride[k] = false;
  213. hasAnimCurve = true;
  214. }
  215. }
  216. // If no animation for this bone, apply its default transform
  217. // (Even if this bone isn't used for the skin, the child bones need to inherit this transform)
  218. if(!hasAnimCurve)
  219. {
  220. localPose.positions[k] = mBoneTransforms[k].getPosition();
  221. localPose.rotations[k] = mBoneTransforms[k].getRotation();
  222. localPose.scales[k] = mBoneTransforms[k].getScale();
  223. }
  224. }
  225. }
  226. }
  227. // Calculate local pose matrices
  228. UINT32 isGlobalBytes = sizeof(bool) * mNumBones;
  229. bool* isGlobal = (bool*)bs_stack_alloc(isGlobalBytes);
  230. memset(isGlobal, 0, isGlobalBytes);
  231. for(UINT32 i = 0; i < mNumBones; i++)
  232. {
  233. bool isAssigned = localPose.rotations[i].w != 0.0f;
  234. if (!isAssigned)
  235. localPose.rotations[i] = Quaternion::IDENTITY;
  236. else
  237. localPose.rotations[i].normalize();
  238. if (localPose.hasOverride[i])
  239. {
  240. isGlobal[i] = true;
  241. continue;
  242. }
  243. pose[i] = Matrix4::TRS(localPose.positions[i], localPose.rotations[i], localPose.scales[i]);
  244. }
  245. // Calculate global poses
  246. // Note: For a possible performance improvement consider sorting bones in such order so that parents (and overrides)
  247. // always come before children, we no isGlobal check is needed.
  248. std::function<void(UINT32)> calcGlobal = [&](UINT32 boneIdx)
  249. {
  250. UINT32 parentBoneIdx = mBoneInfo[boneIdx].parent;
  251. if (parentBoneIdx == (UINT32)-1)
  252. {
  253. isGlobal[boneIdx] = true;
  254. return;
  255. }
  256. if (!isGlobal[parentBoneIdx])
  257. calcGlobal(parentBoneIdx);
  258. pose[boneIdx] = pose[parentBoneIdx] * pose[boneIdx];
  259. isGlobal[boneIdx] = true;
  260. };
  261. for (UINT32 i = 0; i < mNumBones; i++)
  262. {
  263. if (!isGlobal[i])
  264. calcGlobal(i);
  265. }
  266. for (UINT32 i = 0; i < mNumBones; i++)
  267. pose[i] = pose[i] * mInvBindPoses[i];
  268. bs_stack_free(isGlobal);
  269. }
  270. UINT32 Skeleton::getRootBoneIndex() const
  271. {
  272. for (UINT32 i = 0; i < mNumBones; i++)
  273. {
  274. if (mBoneInfo[i].parent == (UINT32)-1)
  275. return i;
  276. }
  277. return (UINT32)-1;
  278. }
  279. SPtr<Skeleton> Skeleton::createEmpty()
  280. {
  281. Skeleton* rawPtr = new (bs_alloc<Skeleton>()) Skeleton();
  282. SPtr<Skeleton> newSkeleton = bs_shared_ptr<Skeleton>(rawPtr);
  283. return newSkeleton;
  284. }
  285. RTTITypeBase* Skeleton::getRTTIStatic()
  286. {
  287. return SkeletonRTTI::instance();
  288. }
  289. RTTITypeBase* Skeleton::getRTTI() const
  290. {
  291. return getRTTIStatic();
  292. }
  293. }