AnimationState.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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 "DrawableEvents.h"
  29. #include "Serializer.h"
  30. #include "XMLElement.h"
  31. #include "DebugNew.h"
  32. AnimationState::AnimationState(AnimatedModel* model, Animation* animation) :
  33. model_(model),
  34. animation_(animation),
  35. startBone_(0),
  36. looped_(false),
  37. weight_(0.0f),
  38. time_(0.0f),
  39. layer_(0)
  40. {
  41. SetStartBone(0);
  42. // Setup a cache for last keyframe of each track
  43. lastKeyFrame_.Resize(animation_->GetNumTracks());
  44. for (unsigned i = 0; i < lastKeyFrame_.Size(); ++i)
  45. lastKeyFrame_[i] = 0;
  46. }
  47. AnimationState::~AnimationState()
  48. {
  49. }
  50. void AnimationState::SetStartBone(Bone* startBone)
  51. {
  52. if (!model_)
  53. return;
  54. Skeleton& skeleton = model_->GetSkeleton();
  55. Bone* rootBone = skeleton.GetRootBone();
  56. if (!rootBone)
  57. return;
  58. if (!startBone)
  59. startBone = rootBone;
  60. // Do not reassign if the start bone did not actually change, and we already have valid bone nodes
  61. if (startBone == startBone_ && !trackToBoneMap_.Empty())
  62. return;
  63. startBone_ = startBone;
  64. trackToBoneMap_.Clear();
  65. if (!startBone->node_)
  66. return;
  67. const Vector<AnimationTrack>& tracks = animation_->GetTracks();
  68. for (unsigned i = 0; i < tracks.Size(); ++i)
  69. {
  70. // Include those tracks that are either the start bone itself, or its children
  71. Bone* trackBone = 0;
  72. const StringHash& nameHash = tracks[i].nameHash_;
  73. if (nameHash == startBone->nameHash_)
  74. trackBone = startBone;
  75. else
  76. {
  77. Node* trackBoneNode = startBone->node_->GetChild(nameHash, true);
  78. if (trackBoneNode)
  79. trackBone = skeleton.GetBone(nameHash);
  80. }
  81. if (trackBone)
  82. trackToBoneMap_[i] = trackBone;
  83. }
  84. model_->MarkAnimationDirty();
  85. }
  86. void AnimationState::SetLooped(bool looped)
  87. {
  88. looped_ = looped;
  89. }
  90. void AnimationState::SetWeight(float weight)
  91. {
  92. weight = Clamp(weight, 0.0f, 1.0f);
  93. if (weight != weight_)
  94. {
  95. weight_ = weight;
  96. if (model_)
  97. model_->MarkAnimationDirty();
  98. }
  99. }
  100. void AnimationState::SetTime(float time)
  101. {
  102. time = Clamp(time, 0.0f, animation_->GetLength());
  103. if (time != time_)
  104. {
  105. time_ = time;
  106. if (model_)
  107. model_->MarkAnimationDirty();
  108. }
  109. }
  110. void AnimationState::AddWeight(float delta)
  111. {
  112. if (delta == 0.0f)
  113. return;
  114. SetWeight(GetWeight() + delta);
  115. }
  116. void AnimationState::AddTime(float delta)
  117. {
  118. float length = animation_->GetLength();
  119. if (delta == 0.0f || length == 0.0f)
  120. return;
  121. float oldTime = GetTime();
  122. float time = oldTime + delta;
  123. if (looped_)
  124. {
  125. while (time >= length)
  126. time -= length;
  127. while (time < 0.0f)
  128. time += length;
  129. }
  130. SetTime(time);
  131. // Process animation triggers
  132. if (model_ && animation_->GetNumTriggers())
  133. {
  134. if (delta > 0.0f)
  135. {
  136. if (oldTime > time)
  137. oldTime -= length;
  138. }
  139. if (delta < 0.0f)
  140. {
  141. if (time > oldTime)
  142. time -= length;
  143. }
  144. if (oldTime > time)
  145. Swap(oldTime, time);
  146. const Vector<AnimationTriggerPoint>& triggers = animation_->GetTriggers();
  147. for (Vector<AnimationTriggerPoint>::ConstIterator i = triggers.Begin(); i != triggers.End(); ++i)
  148. {
  149. if (oldTime <= i->time_ && time > i->time_)
  150. {
  151. using namespace AnimationTrigger;
  152. VariantMap eventData;
  153. eventData[P_NODE] = (void*)model_->GetNode();
  154. eventData[P_NAME] = animation_->GetAnimationName();
  155. eventData[P_TIME] = i->time_;
  156. eventData[P_DATA] = i->data_;
  157. model_->GetNode()->SendEvent(E_ANIMATIONTRIGGER, eventData);
  158. }
  159. }
  160. }
  161. }
  162. void AnimationState::SetLayer(unsigned char layer)
  163. {
  164. if (layer != layer_)
  165. {
  166. layer_ = layer;
  167. if (model_)
  168. model_->MarkAnimationOrderDirty();
  169. }
  170. }
  171. Bone* AnimationState::GetStartBone() const
  172. {
  173. return model_ ? startBone_ : 0;
  174. }
  175. float AnimationState::GetLength() const
  176. {
  177. return animation_->GetLength();
  178. }
  179. void AnimationState::Apply()
  180. {
  181. if (!IsEnabled())
  182. return;
  183. // Check first if full weight or blending
  184. if (Equals(weight_, 1.0f))
  185. {
  186. for (HashMap<unsigned, Bone*>::ConstIterator i = trackToBoneMap_.Begin(); i != trackToBoneMap_.End(); ++i)
  187. {
  188. const AnimationTrack* track = animation_->GetTrack(i->first_);
  189. Bone* bone = i->second_;
  190. Node* boneNode = bone->node_;
  191. if (!boneNode || !bone->animated_ || !track->keyFrames_.Size())
  192. continue;
  193. unsigned& frame = lastKeyFrame_[i->first_];
  194. track->GetKeyFrameIndex(time_, frame);
  195. // Check if next frame to interpolate to is valid, or if wrapping is needed (looping animation only)
  196. unsigned nextFrame = frame + 1;
  197. bool interpolate = true;
  198. if (nextFrame >= track->keyFrames_.Size())
  199. {
  200. if (!looped_)
  201. {
  202. nextFrame = frame;
  203. interpolate = false;
  204. }
  205. else
  206. nextFrame = 0;
  207. }
  208. const AnimationKeyFrame* keyFrame = &track->keyFrames_[frame];
  209. unsigned char channelMask = track->channelMask_;
  210. if (!interpolate)
  211. {
  212. // No interpolation, full weight
  213. if (channelMask & CHANNEL_POSITION)
  214. boneNode->SetPosition(keyFrame->position_);
  215. if (channelMask & CHANNEL_ROTATION)
  216. boneNode->SetRotation(keyFrame->rotation_);
  217. if (channelMask & CHANNEL_SCALE)
  218. boneNode->SetScale(keyFrame->scale_);
  219. }
  220. else
  221. {
  222. const AnimationKeyFrame* nextKeyFrame = &track->keyFrames_[nextFrame];
  223. float timeInterval = nextKeyFrame->time_ - keyFrame->time_;
  224. if (timeInterval < 0.0f)
  225. timeInterval += animation_->GetLength();
  226. float t = timeInterval > 0.0f ? (time_ - keyFrame->time_) / timeInterval : 1.0f;
  227. // Interpolation, full weight
  228. if (channelMask & CHANNEL_POSITION)
  229. boneNode->SetPosition(keyFrame->position_.Lerp(nextKeyFrame->position_, t));
  230. if (channelMask & CHANNEL_ROTATION)
  231. boneNode->SetRotation(keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t));
  232. if (channelMask & CHANNEL_SCALE)
  233. boneNode->SetScale(keyFrame->scale_.Lerp(nextKeyFrame->scale_, t));
  234. }
  235. }
  236. }
  237. else
  238. {
  239. for (HashMap<unsigned, Bone*>::ConstIterator i = trackToBoneMap_.Begin(); i != trackToBoneMap_.End(); ++i)
  240. {
  241. const AnimationTrack* track = animation_->GetTrack(i->first_);
  242. Bone* bone = i->second_;
  243. Node* boneNode = bone->node_;
  244. if (!boneNode || !bone->animated_ || !track->keyFrames_.Size())
  245. continue;
  246. unsigned& frame = lastKeyFrame_[i->first_];
  247. track->GetKeyFrameIndex(time_, frame);
  248. // Check if next frame to interpolate to is valid, or if wrapping is needed (looping animation only)
  249. unsigned nextFrame = frame + 1;
  250. bool interpolate = true;
  251. if (nextFrame >= track->keyFrames_.Size())
  252. {
  253. if (!looped_)
  254. {
  255. nextFrame = frame;
  256. interpolate = false;
  257. }
  258. else
  259. nextFrame = 0;
  260. }
  261. const AnimationKeyFrame* keyFrame = &track->keyFrames_[frame];
  262. unsigned char channelMask = track->channelMask_;
  263. if (!interpolate)
  264. {
  265. // No interpolation, blend between old transform & animation
  266. if (channelMask & CHANNEL_POSITION)
  267. boneNode->SetPosition(boneNode->GetPosition().Lerp(keyFrame->position_, weight_));
  268. if (channelMask & CHANNEL_ROTATION)
  269. boneNode->SetRotation(boneNode->GetRotation().Slerp(keyFrame->rotation_, weight_));
  270. if (channelMask & CHANNEL_SCALE)
  271. boneNode->SetScale(boneNode->GetScale().Lerp(keyFrame->scale_, weight_));
  272. }
  273. else
  274. {
  275. const AnimationKeyFrame* nextKeyFrame = &track->keyFrames_[nextFrame];
  276. float timeInterval = nextKeyFrame->time_ - keyFrame->time_;
  277. if (timeInterval < 0.0f)
  278. timeInterval += animation_->GetLength();
  279. float t = timeInterval > 0.0f ? (time_ - keyFrame->time_) / timeInterval : 1.0f;
  280. // Interpolation, blend between old transform & animation
  281. if (channelMask & CHANNEL_POSITION)
  282. {
  283. boneNode->SetPosition(boneNode->GetPosition().Lerp(
  284. keyFrame->position_.Lerp(nextKeyFrame->position_, t), weight_));
  285. }
  286. if (channelMask & CHANNEL_ROTATION)
  287. {
  288. boneNode->SetRotation(boneNode->GetRotation().Slerp(
  289. keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t), weight_));
  290. }
  291. if (channelMask & CHANNEL_SCALE)
  292. {
  293. boneNode->SetScale(boneNode->GetScale().Lerp(
  294. keyFrame->scale_.Lerp(nextKeyFrame->scale_, t), weight_));
  295. }
  296. }
  297. }
  298. }
  299. }