2
0

AnimationState.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2012 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "AnimatedModel.h"
  25. #include "Animation.h"
  26. #include "AnimationState.h"
  27. #include "Deserializer.h"
  28. #include "Serializer.h"
  29. #include "XMLElement.h"
  30. #include "DebugNew.h"
  31. AnimationState::AnimationState(AnimatedModel* model, Animation* animation) :
  32. model_(model),
  33. animation_(animation),
  34. startBone_(0),
  35. looped_(false),
  36. weight_(0.0f),
  37. time_(0.0f),
  38. layer_(0)
  39. {
  40. SetStartBone(0);
  41. // Setup a cache for last keyframe of each track
  42. lastKeyFrame_.Resize(animation_->GetNumTracks());
  43. for (unsigned i = 0; i < lastKeyFrame_.Size(); ++i)
  44. lastKeyFrame_[i] = 0;
  45. }
  46. AnimationState::~AnimationState()
  47. {
  48. }
  49. void AnimationState::SetStartBone(Bone* startBone)
  50. {
  51. if (!model_)
  52. return;
  53. Skeleton& skeleton = model_->GetSkeleton();
  54. Bone* rootBone = skeleton.GetRootBone();
  55. if (!rootBone)
  56. return;
  57. if (!startBone)
  58. startBone = rootBone;
  59. // Do not reassign if the start bone did not actually change, and we already have valid bone nodes
  60. if (startBone == startBone_ && !trackToBoneMap_.Empty())
  61. return;
  62. startBone_ = startBone;
  63. trackToBoneMap_.Clear();
  64. if (!startBone->node_)
  65. return;
  66. const Vector<AnimationTrack>& tracks = animation_->GetTracks();
  67. for (unsigned i = 0; i < tracks.Size(); ++i)
  68. {
  69. // Include those tracks that are either the start bone itself, or its children
  70. Bone* trackBone = 0;
  71. const StringHash& nameHash = tracks[i].nameHash_;
  72. if (nameHash == startBone->nameHash_)
  73. trackBone = startBone;
  74. else
  75. {
  76. Node* trackBoneNode = startBone->node_->GetChild(nameHash, true);
  77. if (trackBoneNode)
  78. trackBone = skeleton.GetBone(nameHash);
  79. }
  80. if (trackBone)
  81. trackToBoneMap_[i] = trackBone;
  82. }
  83. model_->MarkAnimationDirty();
  84. }
  85. void AnimationState::SetLooped(bool looped)
  86. {
  87. looped_ = looped;
  88. }
  89. void AnimationState::SetWeight(float weight)
  90. {
  91. weight = Clamp(weight, 0.0f, 1.0f);
  92. if (weight != weight_)
  93. {
  94. weight_ = weight;
  95. if (model_)
  96. model_->MarkAnimationDirty();
  97. }
  98. }
  99. void AnimationState::SetTime(float time)
  100. {
  101. time = Clamp(time, 0.0f, animation_->GetLength());
  102. if (time != time_)
  103. {
  104. time_ = time;
  105. if (model_)
  106. model_->MarkAnimationDirty();
  107. }
  108. }
  109. void AnimationState::AddWeight(float delta)
  110. {
  111. if (delta == 0.0f)
  112. return;
  113. SetWeight(GetWeight() + delta);
  114. }
  115. void AnimationState::AddTime(float delta)
  116. {
  117. float length = animation_->GetLength();
  118. if (delta == 0.0f || length == 0.0f)
  119. return;
  120. float time = GetTime() + delta;
  121. if (looped_)
  122. {
  123. while (time >= length)
  124. time -= length;
  125. while (time < 0.0f)
  126. time += length;
  127. }
  128. SetTime(time);
  129. }
  130. void AnimationState::SetLayer(unsigned char layer)
  131. {
  132. if (layer != layer_)
  133. {
  134. layer_ = layer;
  135. if (model_)
  136. model_->MarkAnimationOrderDirty();
  137. }
  138. }
  139. Bone* AnimationState::GetStartBone() const
  140. {
  141. return model_ ? startBone_ : 0;
  142. }
  143. float AnimationState::GetLength() const
  144. {
  145. return animation_->GetLength();
  146. }
  147. void AnimationState::Apply()
  148. {
  149. if (!IsEnabled())
  150. return;
  151. // Check first if full weight or blending
  152. if (weight_ == 1.0f)
  153. {
  154. for (HashMap<unsigned, Bone*>::ConstIterator i = trackToBoneMap_.Begin(); i != trackToBoneMap_.End(); ++i)
  155. {
  156. const AnimationTrack* track = animation_->GetTrack(i->first_);
  157. Bone* bone = i->second_;
  158. Node* boneNode = bone->node_;
  159. if (!boneNode || !bone->animated_ || !track->keyFrames_.Size())
  160. continue;
  161. unsigned& frame = lastKeyFrame_[i->first_];
  162. track->GetKeyFrameIndex(time_, frame);
  163. // Check if next frame to interpolate to is valid, or if wrapping is needed (looping animation only)
  164. unsigned nextFrame = frame + 1;
  165. bool interpolate = true;
  166. if (nextFrame >= track->keyFrames_.Size())
  167. {
  168. if (!looped_)
  169. {
  170. nextFrame = frame;
  171. interpolate = false;
  172. }
  173. else
  174. nextFrame = 0;
  175. }
  176. const AnimationKeyFrame* keyFrame = &track->keyFrames_[frame];
  177. unsigned char channelMask = track->channelMask_;
  178. if (!interpolate)
  179. {
  180. // No interpolation, full weight
  181. if (channelMask & CHANNEL_POSITION)
  182. boneNode->SetPosition(keyFrame->position_);
  183. if (channelMask & CHANNEL_ROTATION)
  184. boneNode->SetRotation(keyFrame->rotation_);
  185. if (channelMask & CHANNEL_SCALE)
  186. boneNode->SetScale(keyFrame->scale_);
  187. }
  188. else
  189. {
  190. const AnimationKeyFrame* nextKeyFrame = &track->keyFrames_[nextFrame];
  191. float timeInterval = nextKeyFrame->time_ - keyFrame->time_;
  192. if (timeInterval < 0.0f)
  193. timeInterval += animation_->GetLength();
  194. float t = timeInterval > 0.0f ? (time_ - keyFrame->time_) / timeInterval : 1.0f;
  195. // Interpolation, full weight
  196. if (channelMask & CHANNEL_POSITION)
  197. boneNode->SetPosition(keyFrame->position_.Lerp(nextKeyFrame->position_, t));
  198. if (channelMask & CHANNEL_ROTATION)
  199. boneNode->SetRotation(keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t));
  200. if (channelMask & CHANNEL_SCALE)
  201. boneNode->SetScale(keyFrame->scale_.Lerp(nextKeyFrame->scale_, t));
  202. }
  203. }
  204. }
  205. else
  206. {
  207. for (HashMap<unsigned, Bone*>::ConstIterator i = trackToBoneMap_.Begin(); i != trackToBoneMap_.End(); ++i)
  208. {
  209. const AnimationTrack* track = animation_->GetTrack(i->first_);
  210. Bone* bone = i->second_;
  211. Node* boneNode = bone->node_;
  212. if (!boneNode || !bone->animated_ || !track->keyFrames_.Size())
  213. continue;
  214. unsigned& frame = lastKeyFrame_[i->first_];
  215. track->GetKeyFrameIndex(time_, frame);
  216. // Check if next frame to interpolate to is valid, or if wrapping is needed (looping animation only)
  217. unsigned nextFrame = frame + 1;
  218. bool interpolate = true;
  219. if (nextFrame >= track->keyFrames_.Size())
  220. {
  221. if (!looped_)
  222. {
  223. nextFrame = frame;
  224. interpolate = false;
  225. }
  226. else
  227. nextFrame = 0;
  228. }
  229. const AnimationKeyFrame* keyFrame = &track->keyFrames_[frame];
  230. unsigned char channelMask = track->channelMask_;
  231. if (!interpolate)
  232. {
  233. // No interpolation, blend between old transform & animation
  234. if (channelMask & CHANNEL_POSITION)
  235. boneNode->SetPosition(boneNode->GetPosition().Lerp(keyFrame->position_, weight_));
  236. if (channelMask & CHANNEL_ROTATION)
  237. boneNode->SetRotation(boneNode->GetRotation().Slerp(keyFrame->rotation_, weight_));
  238. if (channelMask & CHANNEL_SCALE)
  239. boneNode->SetScale(boneNode->GetScale().Lerp(keyFrame->scale_, weight_));
  240. }
  241. else
  242. {
  243. const AnimationKeyFrame* nextKeyFrame = &track->keyFrames_[nextFrame];
  244. float timeInterval = nextKeyFrame->time_ - keyFrame->time_;
  245. if (timeInterval < 0.0f)
  246. timeInterval += animation_->GetLength();
  247. float t = timeInterval > 0.0f ? (time_ - keyFrame->time_) / timeInterval : 1.0f;
  248. // Interpolation, blend between old transform & animation
  249. if (channelMask & CHANNEL_POSITION)
  250. {
  251. boneNode->SetPosition(boneNode->GetPosition().Lerp(
  252. keyFrame->position_.Lerp(nextKeyFrame->position_, t), weight_));
  253. }
  254. if (channelMask & CHANNEL_ROTATION)
  255. {
  256. boneNode->SetRotation(boneNode->GetRotation().Slerp(
  257. keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t), weight_));
  258. }
  259. if (channelMask & CHANNEL_SCALE)
  260. {
  261. boneNode->SetScale(boneNode->GetScale().Lerp(
  262. keyFrame->scale_.Lerp(nextKeyFrame->scale_, t), weight_));
  263. }
  264. }
  265. }
  266. }
  267. }