BsSkeleton.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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 "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. // Note: For a possible performance improvement consider keeping an array of only active (non-disabled) bones and
  137. // just iterate over them without mask checks. Possibly also a list of active curve mappings to avoid those checks
  138. // as well.
  139. for(UINT32 i = 0; i < numLayers; i++)
  140. {
  141. const AnimationStateLayer& layer = layers[i];
  142. float invLayerWeight;
  143. if (layer.additive)
  144. {
  145. float weightSum = 0.0f;
  146. for (UINT32 j = 0; j < layer.numStates; j++)
  147. weightSum += layer.states[j].weight;
  148. invLayerWeight = 1.0f / weightSum;
  149. }
  150. else
  151. invLayerWeight = 1.0f;
  152. for (UINT32 j = 0; j < layer.numStates; j++)
  153. {
  154. const AnimationState& state = layer.states[j];
  155. if (state.disabled)
  156. continue;
  157. float normWeight = state.weight * invLayerWeight;
  158. // Early exit for clips that don't contribute (which there could be plenty especially for sequential blends)
  159. if (Math::approxEquals(normWeight, 0.0f))
  160. continue;
  161. for (UINT32 k = 0; k < mNumBones; k++)
  162. {
  163. if (!mask.isEnabled(k))
  164. continue;
  165. const AnimationCurveMapping& mapping = state.boneToCurveMapping[k];
  166. UINT32 curveIdx = mapping.position;
  167. if (curveIdx != (UINT32)-1)
  168. {
  169. const TAnimationCurve<Vector3>& curve = state.curves->position[curveIdx].curve;
  170. localPose.positions[k] += curve.evaluate(state.time, state.positionCaches[curveIdx], state.loop) * normWeight;
  171. localPose.hasOverride[k] = false;
  172. }
  173. }
  174. for (UINT32 k = 0; k < mNumBones; k++)
  175. {
  176. if (!mask.isEnabled(k))
  177. continue;
  178. const AnimationCurveMapping& mapping = state.boneToCurveMapping[k];
  179. UINT32 curveIdx = mapping.scale;
  180. if (curveIdx != (UINT32)-1)
  181. {
  182. const TAnimationCurve<Vector3>& curve = state.curves->scale[curveIdx].curve;
  183. localPose.scales[k] *= curve.evaluate(state.time, state.scaleCaches[curveIdx], state.loop) * normWeight;
  184. localPose.hasOverride[k] = false;
  185. }
  186. }
  187. if(layer.additive)
  188. {
  189. for (UINT32 k = 0; k < mNumBones; k++)
  190. {
  191. if (!mask.isEnabled(k))
  192. continue;
  193. const AnimationCurveMapping& mapping = state.boneToCurveMapping[k];
  194. UINT32 curveIdx = mapping.rotation;
  195. if (curveIdx != (UINT32)-1)
  196. {
  197. bool isAssigned = localPose.rotations[k].w != 0.0f;
  198. if (!isAssigned)
  199. localPose.rotations[k] = Quaternion::IDENTITY;
  200. const TAnimationCurve<Quaternion>& curve = state.curves->rotation[curveIdx].curve;
  201. Quaternion value = curve.evaluate(state.time, state.rotationCaches[curveIdx], state.loop);
  202. value = Quaternion::lerp(normWeight, Quaternion::IDENTITY, value);
  203. localPose.rotations[k] *= value;
  204. localPose.hasOverride[k] = false;
  205. }
  206. }
  207. }
  208. else
  209. {
  210. for (UINT32 k = 0; k < mNumBones; k++)
  211. {
  212. if (!mask.isEnabled(k))
  213. continue;
  214. const AnimationCurveMapping& mapping = state.boneToCurveMapping[k];
  215. UINT32 curveIdx = mapping.rotation;
  216. if (curveIdx != (UINT32)-1)
  217. {
  218. const TAnimationCurve<Quaternion>& curve = state.curves->rotation[curveIdx].curve;
  219. Quaternion value = curve.evaluate(state.time, state.rotationCaches[curveIdx], state.loop) * normWeight;
  220. if (value.dot(localPose.rotations[k]) < 0.0f)
  221. value = -value;
  222. localPose.rotations[k] += value;
  223. localPose.hasOverride[k] = false;
  224. }
  225. }
  226. }
  227. }
  228. }
  229. // Calculate local pose matrices
  230. UINT32 isGlobalBytes = sizeof(bool) * mNumBones;
  231. bool* isGlobal = (bool*)bs_stack_alloc(isGlobalBytes);
  232. memset(isGlobal, 0, isGlobalBytes);
  233. for(UINT32 i = 0; i < mNumBones; i++)
  234. {
  235. bool isAssigned = localPose.rotations[i].w != 0.0f;
  236. if (!isAssigned)
  237. localPose.rotations[i] = Quaternion::IDENTITY;
  238. else
  239. localPose.rotations[i].normalize();
  240. if (localPose.hasOverride[i])
  241. {
  242. isGlobal[i] = true;
  243. continue;
  244. }
  245. pose[i] = Matrix4::TRS(localPose.positions[i], localPose.rotations[i], localPose.scales[i]);
  246. }
  247. // Calculate global poses
  248. // Note: For a possible performance improvement consider sorting bones in such order so that parents (and overrides)
  249. // always come before children, we no isGlobal check is needed.
  250. std::function<void(UINT32)> calcGlobal = [&](UINT32 boneIdx)
  251. {
  252. UINT32 parentBoneIdx = mBoneInfo[boneIdx].parent;
  253. if (parentBoneIdx == (UINT32)-1)
  254. {
  255. isGlobal[boneIdx] = true;
  256. return;
  257. }
  258. if (!isGlobal[parentBoneIdx])
  259. calcGlobal(parentBoneIdx);
  260. pose[boneIdx] = pose[parentBoneIdx] * pose[boneIdx];
  261. isGlobal[boneIdx] = true;
  262. };
  263. for (UINT32 i = 0; i < mNumBones; i++)
  264. {
  265. if (!isGlobal[i])
  266. calcGlobal(i);
  267. }
  268. for (UINT32 i = 0; i < mNumBones; i++)
  269. pose[i] = pose[i] * mInvBindPoses[i];
  270. bs_stack_free(isGlobal);
  271. }
  272. UINT32 Skeleton::getRootBoneIndex() const
  273. {
  274. for (UINT32 i = 0; i < mNumBones; i++)
  275. {
  276. if (mBoneInfo[i].parent == (UINT32)-1)
  277. return i;
  278. }
  279. return (UINT32)-1;
  280. }
  281. SPtr<Skeleton> Skeleton::createEmpty()
  282. {
  283. Skeleton* rawPtr = new (bs_alloc<Skeleton>()) Skeleton();
  284. SPtr<Skeleton> newSkeleton = bs_shared_ptr<Skeleton>(rawPtr);
  285. return newSkeleton;
  286. }
  287. RTTITypeBase* Skeleton::getRTTIStatic()
  288. {
  289. return SkeletonRTTI::instance();
  290. }
  291. RTTITypeBase* Skeleton::getRTTI() const
  292. {
  293. return getRTTIStatic();
  294. }
  295. }