AnimationState.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. //
  2. // Copyright (c) 2008-2013 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "AnimatedModel.h"
  24. #include "Animation.h"
  25. #include "AnimationState.h"
  26. #include "Deserializer.h"
  27. #include "DrawableEvents.h"
  28. #include "Serializer.h"
  29. #include "DebugNew.h"
  30. namespace Urho3D
  31. {
  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. if (animation_)
  43. {
  44. // Setup a cache for last keyframe of each track
  45. lastKeyFrame_.Resize(animation_->GetNumTracks());
  46. }
  47. for (unsigned i = 0; i < lastKeyFrame_.Size(); ++i)
  48. lastKeyFrame_[i] = 0;
  49. }
  50. AnimationState::AnimationState(Node* node, Animation* animation) :
  51. node_(node),
  52. animation_(animation),
  53. startBone_(0),
  54. looped_(false),
  55. weight_(0.0f),
  56. time_(0.0f),
  57. layer_(0)
  58. {
  59. if (animation_)
  60. {
  61. // Setup a cache for last keyframe of each track
  62. lastKeyFrame_.Resize(animation_->GetNumTracks());
  63. // Setup animation track to scene node mapping
  64. if (node_)
  65. {
  66. const Vector<AnimationTrack>& tracks = animation_->GetTracks();
  67. for (unsigned i = 0; i < tracks.Size(); ++i)
  68. {
  69. const StringHash& nameHash = tracks[i].nameHash_;
  70. if (node_->GetNameHash() == nameHash)
  71. trackToNodeMap_[i] = node_;
  72. else
  73. {
  74. Node* targetNode = node_->GetChild(nameHash, true);
  75. if (targetNode)
  76. trackToNodeMap_[i] = targetNode;
  77. }
  78. }
  79. }
  80. }
  81. for (unsigned i = 0; i < lastKeyFrame_.Size(); ++i)
  82. lastKeyFrame_[i] = 0;
  83. }
  84. AnimationState::~AnimationState()
  85. {
  86. }
  87. void AnimationState::SetStartBone(Bone* startBone)
  88. {
  89. if (!model_ || !animation_)
  90. return;
  91. Skeleton& skeleton = model_->GetSkeleton();
  92. if (!startBone)
  93. {
  94. Bone* rootBone = skeleton.GetRootBone();
  95. if (!rootBone)
  96. return;
  97. startBone = rootBone;
  98. }
  99. // Do not reassign if the start bone did not actually change, and we already have valid bone nodes
  100. if (startBone == startBone_ && !trackToBoneMap_.Empty())
  101. return;
  102. startBone_ = startBone;
  103. trackToBoneMap_.Clear();
  104. if (!startBone->node_)
  105. return;
  106. const Vector<AnimationTrack>& tracks = animation_->GetTracks();
  107. for (unsigned i = 0; i < tracks.Size(); ++i)
  108. {
  109. // Include those tracks that are either the start bone itself, or its children
  110. Bone* trackBone = 0;
  111. const StringHash& nameHash = tracks[i].nameHash_;
  112. if (nameHash == startBone->nameHash_)
  113. trackBone = startBone;
  114. else
  115. {
  116. Node* trackBoneNode = startBone->node_->GetChild(nameHash, true);
  117. if (trackBoneNode)
  118. trackBone = skeleton.GetBone(nameHash);
  119. }
  120. if (trackBone)
  121. trackToBoneMap_[i] = trackBone;
  122. }
  123. model_->MarkAnimationDirty();
  124. }
  125. void AnimationState::SetLooped(bool looped)
  126. {
  127. looped_ = looped;
  128. }
  129. void AnimationState::SetWeight(float weight)
  130. {
  131. weight = Clamp(weight, 0.0f, 1.0f);
  132. if (weight != weight_)
  133. {
  134. weight_ = weight;
  135. if (model_)
  136. model_->MarkAnimationDirty();
  137. }
  138. }
  139. void AnimationState::SetTime(float time)
  140. {
  141. if (!animation_)
  142. return;
  143. time = Clamp(time, 0.0f, animation_->GetLength());
  144. if (time != time_)
  145. {
  146. time_ = time;
  147. if (model_)
  148. model_->MarkAnimationDirty();
  149. }
  150. }
  151. void AnimationState::AddWeight(float delta)
  152. {
  153. if (delta == 0.0f)
  154. return;
  155. SetWeight(GetWeight() + delta);
  156. }
  157. void AnimationState::AddTime(float delta)
  158. {
  159. if (!animation_ || (!model_ && node_))
  160. return;
  161. float length = animation_->GetLength();
  162. if (delta == 0.0f || length == 0.0f)
  163. return;
  164. float oldTime = GetTime();
  165. float time = oldTime + delta;
  166. if (looped_)
  167. {
  168. while (time >= length)
  169. time -= length;
  170. while (time < 0.0f)
  171. time += length;
  172. }
  173. SetTime(time);
  174. // Process animation triggers
  175. if (animation_->GetNumTriggers())
  176. {
  177. if (delta > 0.0f)
  178. {
  179. if (oldTime > time)
  180. oldTime -= length;
  181. }
  182. if (delta < 0.0f)
  183. {
  184. if (time > oldTime)
  185. time -= length;
  186. }
  187. if (oldTime > time)
  188. Swap(oldTime, time);
  189. const Vector<AnimationTriggerPoint>& triggers = animation_->GetTriggers();
  190. for (Vector<AnimationTriggerPoint>::ConstIterator i = triggers.Begin(); i != triggers.End(); ++i)
  191. {
  192. if (oldTime <= i->time_ && time > i->time_)
  193. {
  194. using namespace AnimationTrigger;
  195. Node* senderNode = model_ ? model_->GetNode() : node_;
  196. VariantMap eventData;
  197. eventData[P_NODE] = (void*)senderNode;
  198. eventData[P_NAME] = animation_->GetAnimationName();
  199. eventData[P_TIME] = i->time_;
  200. eventData[P_DATA] = i->data_;
  201. senderNode->SendEvent(E_ANIMATIONTRIGGER, eventData);
  202. }
  203. }
  204. }
  205. }
  206. void AnimationState::SetLayer(unsigned char layer)
  207. {
  208. if (layer != layer_)
  209. {
  210. layer_ = layer;
  211. if (model_)
  212. model_->MarkAnimationOrderDirty();
  213. }
  214. }
  215. Bone* AnimationState::GetStartBone() const
  216. {
  217. return model_ ? startBone_ : 0;
  218. }
  219. float AnimationState::GetLength() const
  220. {
  221. return animation_ ? animation_->GetLength() : 0.0f;
  222. }
  223. void AnimationState::Apply()
  224. {
  225. if (!animation_ || !IsEnabled())
  226. return;
  227. if (model_)
  228. ApplyToModel();
  229. else
  230. ApplyToNodes();
  231. }
  232. void AnimationState::ApplyToModel()
  233. {
  234. // Check first if full weight or blending
  235. if (Equals(weight_, 1.0f))
  236. {
  237. for (HashMap<unsigned, Bone*>::ConstIterator i = trackToBoneMap_.Begin(); i != trackToBoneMap_.End(); ++i)
  238. {
  239. Bone* bone = i->second_;
  240. Node* boneNode = bone->node_;
  241. if (!boneNode || !bone->animated_)
  242. continue;
  243. ApplyTrackToNodeFullWeight(i->first_, boneNode);
  244. }
  245. }
  246. else
  247. {
  248. for (HashMap<unsigned, Bone*>::ConstIterator i = trackToBoneMap_.Begin(); i != trackToBoneMap_.End(); ++i)
  249. {
  250. Bone* bone = i->second_;
  251. Node* boneNode = bone->node_;
  252. if (!boneNode || !bone->animated_)
  253. continue;
  254. ApplyTrackToNodeBlended(i->first_, boneNode);
  255. }
  256. }
  257. }
  258. void AnimationState::ApplyToNodes()
  259. {
  260. // When applying to a node hierarchy, can only use full weight (nothing to blend to)
  261. for (HashMap<unsigned, WeakPtr<Node> >::ConstIterator i = trackToNodeMap_.Begin(); i != trackToNodeMap_.End(); ++i)
  262. {
  263. Node* node = i->second_;
  264. if (!node)
  265. continue;
  266. ApplyTrackToNodeFullWeight(i->first_, node);
  267. }
  268. }
  269. void AnimationState::ApplyTrackToNodeFullWeight(unsigned index, Node* node)
  270. {
  271. const AnimationTrack* track = animation_->GetTrack(index);
  272. if (track->keyFrames_.Empty())
  273. return;
  274. unsigned& frame = lastKeyFrame_[index];
  275. track->GetKeyFrameIndex(time_, frame);
  276. // Check if next frame to interpolate to is valid, or if wrapping is needed (looping animation only)
  277. unsigned nextFrame = frame + 1;
  278. bool interpolate = true;
  279. if (nextFrame >= track->keyFrames_.Size())
  280. {
  281. if (!looped_)
  282. {
  283. nextFrame = frame;
  284. interpolate = false;
  285. }
  286. else
  287. nextFrame = 0;
  288. }
  289. const AnimationKeyFrame* keyFrame = &track->keyFrames_[frame];
  290. unsigned char channelMask = track->channelMask_;
  291. if (!interpolate)
  292. {
  293. // No interpolation, full weight
  294. if (channelMask & CHANNEL_POSITION)
  295. node->SetPosition(keyFrame->position_);
  296. if (channelMask & CHANNEL_ROTATION)
  297. node->SetRotation(keyFrame->rotation_);
  298. if (channelMask & CHANNEL_SCALE)
  299. node->SetScale(keyFrame->scale_);
  300. }
  301. else
  302. {
  303. const AnimationKeyFrame* nextKeyFrame = &track->keyFrames_[nextFrame];
  304. float timeInterval = nextKeyFrame->time_ - keyFrame->time_;
  305. if (timeInterval < 0.0f)
  306. timeInterval += animation_->GetLength();
  307. float t = timeInterval > 0.0f ? (time_ - keyFrame->time_) / timeInterval : 1.0f;
  308. // Interpolation, full weight
  309. if (channelMask & CHANNEL_POSITION)
  310. node->SetPosition(keyFrame->position_.Lerp(nextKeyFrame->position_, t));
  311. if (channelMask & CHANNEL_ROTATION)
  312. node->SetRotation(keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t));
  313. if (channelMask & CHANNEL_SCALE)
  314. node->SetScale(keyFrame->scale_.Lerp(nextKeyFrame->scale_, t));
  315. }
  316. }
  317. void AnimationState::ApplyTrackToNodeBlended(unsigned index, Node* node)
  318. {
  319. const AnimationTrack* track = animation_->GetTrack(index);
  320. if (track->keyFrames_.Empty())
  321. return;
  322. unsigned& frame = lastKeyFrame_[index];
  323. track->GetKeyFrameIndex(time_, frame);
  324. // Check if next frame to interpolate to is valid, or if wrapping is needed (looping animation only)
  325. unsigned nextFrame = frame + 1;
  326. bool interpolate = true;
  327. if (nextFrame >= track->keyFrames_.Size())
  328. {
  329. if (!looped_)
  330. {
  331. nextFrame = frame;
  332. interpolate = false;
  333. }
  334. else
  335. nextFrame = 0;
  336. }
  337. const AnimationKeyFrame* keyFrame = &track->keyFrames_[frame];
  338. unsigned char channelMask = track->channelMask_;
  339. if (!interpolate)
  340. {
  341. // No interpolation, blend between old transform & animation
  342. if (channelMask & CHANNEL_POSITION)
  343. node->SetPosition(node->GetPosition().Lerp(keyFrame->position_, weight_));
  344. if (channelMask & CHANNEL_ROTATION)
  345. node->SetRotation(node->GetRotation().Slerp(keyFrame->rotation_, weight_));
  346. if (channelMask & CHANNEL_SCALE)
  347. node->SetScale(node->GetScale().Lerp(keyFrame->scale_, weight_));
  348. }
  349. else
  350. {
  351. const AnimationKeyFrame* nextKeyFrame = &track->keyFrames_[nextFrame];
  352. float timeInterval = nextKeyFrame->time_ - keyFrame->time_;
  353. if (timeInterval < 0.0f)
  354. timeInterval += animation_->GetLength();
  355. float t = timeInterval > 0.0f ? (time_ - keyFrame->time_) / timeInterval : 1.0f;
  356. // Interpolation, blend between old transform & animation
  357. if (channelMask & CHANNEL_POSITION)
  358. {
  359. node->SetPosition(node->GetPosition().Lerp(
  360. keyFrame->position_.Lerp(nextKeyFrame->position_, t), weight_));
  361. }
  362. if (channelMask & CHANNEL_ROTATION)
  363. {
  364. node->SetRotation(node->GetRotation().Slerp(
  365. keyFrame->rotation_.Slerp(nextKeyFrame->rotation_, t), weight_));
  366. }
  367. if (channelMask & CHANNEL_SCALE)
  368. {
  369. node->SetScale(node->GetScale().Lerp(
  370. keyFrame->scale_.Lerp(nextKeyFrame->scale_, t), weight_));
  371. }
  372. }
  373. }
  374. }