BsSkeleton.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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. : mNumBones(0), mInvBindPoses(nullptr), mBoneInfo(nullptr)
  72. { }
  73. Skeleton::Skeleton(BONE_DESC* bones, UINT32 numBones)
  74. : mNumBones(numBones), mInvBindPoses(bs_newN<Matrix4>(numBones)), mBoneInfo(bs_newN<SkeletonBoneInfo>(numBones))
  75. {
  76. for(UINT32 i = 0; i < numBones; i++)
  77. {
  78. mInvBindPoses[i] = bones[i].invBindPose;
  79. mBoneInfo[i].name = bones[i].name;
  80. mBoneInfo[i].parent = bones[i].parent;
  81. }
  82. }
  83. Skeleton::~Skeleton()
  84. {
  85. if(mInvBindPoses != nullptr)
  86. bs_deleteN(mInvBindPoses, mNumBones);
  87. if (mBoneInfo != nullptr)
  88. bs_deleteN(mBoneInfo, mNumBones);
  89. }
  90. SPtr<Skeleton> Skeleton::create(BONE_DESC* bones, UINT32 numBones)
  91. {
  92. Skeleton* rawPtr = new (bs_alloc<Skeleton>()) Skeleton(bones, numBones);
  93. return bs_shared_ptr<Skeleton>(rawPtr);
  94. }
  95. void Skeleton::getPose(Matrix4* pose, LocalSkeletonPose& localPose, const SkeletonMask& mask,
  96. const AnimationClip& clip, float time, bool loop)
  97. {
  98. bs_frame_mark();
  99. {
  100. FrameVector<AnimationCurveMapping> boneToCurveMapping(mNumBones);
  101. AnimationState state;
  102. state.curves = clip.getCurves();
  103. state.boneToCurveMapping = boneToCurveMapping.data();
  104. state.loop = loop;
  105. state.weight = 1.0f;
  106. state.time = time;
  107. FrameVector<TCurveCache<Vector3>> positionCache(state.curves->position.size());
  108. FrameVector<TCurveCache<Quaternion>> rotationCache(state.curves->rotation.size());
  109. FrameVector<TCurveCache<Vector3>> scaleCache(state.curves->scale.size());
  110. state.positionCaches = positionCache.data();
  111. state.rotationCaches = rotationCache.data();
  112. state.scaleCaches = scaleCache.data();
  113. state.genericCaches = nullptr;
  114. state.disabled = false;
  115. AnimationStateLayer layer;
  116. layer.index = 0;
  117. layer.additive = false;
  118. layer.states = &state;
  119. layer.numStates = 1;
  120. clip.getBoneMapping(*this, state.boneToCurveMapping);
  121. getPose(pose, localPose, mask, &layer, 1);
  122. }
  123. bs_frame_clear();
  124. }
  125. void Skeleton::getPose(Matrix4* pose, LocalSkeletonPose& localPose, const SkeletonMask& mask,
  126. const AnimationStateLayer* layers, UINT32 numLayers)
  127. {
  128. // Note: If more performance is required this method could be optimized with vector instructions
  129. assert(localPose.numBones == mNumBones);
  130. for(UINT32 i = 0; i < mNumBones; i++)
  131. {
  132. localPose.positions[i] = Vector3::ZERO;
  133. localPose.rotations[i] = Quaternion::ZERO;
  134. localPose.scales[i] = Vector3::ONE;
  135. }
  136. bool* hasAnimCurve = bs_stack_alloc<bool>(mNumBones);
  137. bs_zero_out(hasAnimCurve, mNumBones);
  138. // Note: For a possible performance improvement consider keeping an array of only active (non-disabled) bones and
  139. // just iterate over them without mask checks. Possibly also a list of active curve mappings to avoid those checks
  140. // as well.
  141. for(UINT32 i = 0; i < numLayers; i++)
  142. {
  143. const AnimationStateLayer& layer = layers[i];
  144. float invLayerWeight;
  145. if (layer.additive)
  146. {
  147. float weightSum = 0.0f;
  148. for (UINT32 j = 0; j < layer.numStates; j++)
  149. weightSum += layer.states[j].weight;
  150. invLayerWeight = 1.0f / weightSum;
  151. }
  152. else
  153. invLayerWeight = 1.0f;
  154. for (UINT32 j = 0; j < layer.numStates; j++)
  155. {
  156. const AnimationState& state = layer.states[j];
  157. if (state.disabled)
  158. continue;
  159. float normWeight = state.weight * invLayerWeight;
  160. // Early exit for clips that don't contribute (which there could be plenty especially for sequential blends)
  161. if (Math::approxEquals(normWeight, 0.0f))
  162. continue;
  163. for (UINT32 k = 0; k < mNumBones; k++)
  164. {
  165. if (!mask.isEnabled(k))
  166. continue;
  167. const AnimationCurveMapping& mapping = state.boneToCurveMapping[k];
  168. UINT32 curveIdx = mapping.position;
  169. if (curveIdx != (UINT32)-1)
  170. {
  171. const TAnimationCurve<Vector3>& curve = state.curves->position[curveIdx].curve;
  172. localPose.positions[k] += curve.evaluate(state.time, state.positionCaches[curveIdx], state.loop) * normWeight;
  173. localPose.hasOverride[k] = false;
  174. hasAnimCurve[k] = true;
  175. }
  176. curveIdx = mapping.scale;
  177. if (curveIdx != (UINT32)-1)
  178. {
  179. const TAnimationCurve<Vector3>& curve = state.curves->scale[curveIdx].curve;
  180. localPose.scales[k] *= curve.evaluate(state.time, state.scaleCaches[curveIdx], state.loop) * normWeight;
  181. localPose.hasOverride[k] = false;
  182. hasAnimCurve[k] = true;
  183. }
  184. if (layer.additive)
  185. {
  186. curveIdx = mapping.rotation;
  187. if (curveIdx != (UINT32)-1)
  188. {
  189. bool isAssigned = localPose.rotations[k].w != 0.0f;
  190. if (!isAssigned)
  191. localPose.rotations[k] = Quaternion::IDENTITY;
  192. const TAnimationCurve<Quaternion>& curve = state.curves->rotation[curveIdx].curve;
  193. Quaternion value = curve.evaluate(state.time, state.rotationCaches[curveIdx], state.loop);
  194. value = Quaternion::lerp(normWeight, Quaternion::IDENTITY, value);
  195. localPose.rotations[k] *= value;
  196. localPose.hasOverride[k] = false;
  197. hasAnimCurve[k] = true;
  198. }
  199. }
  200. else
  201. {
  202. curveIdx = mapping.rotation;
  203. if (curveIdx != (UINT32)-1)
  204. {
  205. const TAnimationCurve<Quaternion>& curve = state.curves->rotation[curveIdx].curve;
  206. Quaternion value = curve.evaluate(state.time, state.rotationCaches[curveIdx], state.loop) * normWeight;
  207. if (value.dot(localPose.rotations[k]) < 0.0f)
  208. value = -value;
  209. localPose.rotations[k] += value;
  210. localPose.hasOverride[k] = false;
  211. hasAnimCurve[k] = true;
  212. }
  213. }
  214. }
  215. }
  216. }
  217. // Calculate local pose matrices
  218. UINT32 isGlobalBytes = sizeof(bool) * mNumBones;
  219. bool* isGlobal = (bool*)bs_stack_alloc(isGlobalBytes);
  220. memset(isGlobal, 0, isGlobalBytes);
  221. for(UINT32 i = 0; i < mNumBones; i++)
  222. {
  223. bool isAssigned = localPose.rotations[i].w != 0.0f;
  224. if (!isAssigned)
  225. localPose.rotations[i] = Quaternion::IDENTITY;
  226. else
  227. localPose.rotations[i].normalize();
  228. if (localPose.hasOverride[i])
  229. {
  230. isGlobal[i] = true;
  231. continue;
  232. }
  233. pose[i] = Matrix4::TRS(localPose.positions[i], localPose.rotations[i], localPose.scales[i]);
  234. }
  235. // Apply bind pose transforms to non-animated bones (so that any potential child bones are transformed properly)
  236. for(UINT32 i = 0; i < mNumBones; i++)
  237. {
  238. if(hasAnimCurve[i])
  239. continue;
  240. pose[i] = pose[i] * mInvBindPoses[i].inverseAffine();
  241. }
  242. // Calculate global poses
  243. // Note: For a possible performance improvement consider sorting bones in such order so that parents (and overrides)
  244. // always come before children, we no isGlobal check is needed.
  245. std::function<void(UINT32)> calcGlobal = [&](UINT32 boneIdx)
  246. {
  247. UINT32 parentBoneIdx = mBoneInfo[boneIdx].parent;
  248. if (parentBoneIdx == (UINT32)-1)
  249. {
  250. isGlobal[boneIdx] = true;
  251. return;
  252. }
  253. if (!isGlobal[parentBoneIdx])
  254. calcGlobal(parentBoneIdx);
  255. pose[boneIdx] = pose[parentBoneIdx] * pose[boneIdx];
  256. isGlobal[boneIdx] = true;
  257. };
  258. for (UINT32 i = 0; i < mNumBones; i++)
  259. {
  260. if (!isGlobal[i])
  261. calcGlobal(i);
  262. }
  263. for (UINT32 i = 0; i < mNumBones; i++)
  264. pose[i] = pose[i] * mInvBindPoses[i];
  265. bs_stack_free(isGlobal);
  266. bs_stack_free(hasAnimCurve);
  267. }
  268. UINT32 Skeleton::getRootBoneIndex() const
  269. {
  270. for (UINT32 i = 0; i < mNumBones; i++)
  271. {
  272. if (mBoneInfo[i].parent == (UINT32)-1)
  273. return i;
  274. }
  275. return (UINT32)-1;
  276. }
  277. SPtr<Skeleton> Skeleton::createEmpty()
  278. {
  279. Skeleton* rawPtr = new (bs_alloc<Skeleton>()) Skeleton();
  280. SPtr<Skeleton> newSkeleton = bs_shared_ptr<Skeleton>(rawPtr);
  281. return newSkeleton;
  282. }
  283. RTTITypeBase* Skeleton::getRTTIStatic()
  284. {
  285. return SkeletonRTTI::instance();
  286. }
  287. RTTITypeBase* Skeleton::getRTTI() const
  288. {
  289. return getRTTIStatic();
  290. }
  291. }