AnimationClip.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. #include "Base.h"
  2. #include "AnimationClip.h"
  3. #include "Animation.h"
  4. #include "AnimationTarget.h"
  5. #include "Game.h"
  6. #include "Quaternion.h"
  7. namespace gameplay
  8. {
  9. int AnimationClip::_crazyCounter = 0;
  10. AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long startTime, unsigned long endTime)
  11. : _id(id), _animation(animation), _startTime(startTime), _endTime(endTime), _duration(_endTime - _startTime), _repeatCount(1.0f),
  12. _activeDuration(_duration * _repeatCount), _speed(1.0f), _isPlaying(false), _timeStarted(0), _elapsedTime(0), _runningTime(0),
  13. _channelPriority(NULL), _crossFadeToClip(NULL), _crossFadeStart(0), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f),
  14. _isFadingOutStarted(false), _isFadingOut(false), _isFadingIn(false), _beginListeners(NULL), _endListeners(NULL)
  15. {
  16. assert(0 <= startTime && startTime <= animation->_duration && 0 <= endTime && endTime <= animation->_duration);
  17. unsigned int channelCount = _animation->_channels.size();
  18. _channelPriority = new unsigned int[channelCount];
  19. for (unsigned int i = 0; i < channelCount; i++)
  20. {
  21. _values.push_back(new AnimationValue(_animation->_channels[i]->_curve->getComponentCount()));
  22. _channelPriority[i] = 0;
  23. }
  24. }
  25. AnimationClip::~AnimationClip()
  26. {
  27. // Explicitly stop this clip if it's currently playing so it gets removed from the controller
  28. if (_isPlaying)
  29. {
  30. stop();
  31. }
  32. std::vector<AnimationValue*>::iterator valueIter = _values.begin();
  33. while (valueIter != _values.end())
  34. {
  35. SAFE_DELETE(*valueIter);
  36. valueIter++;
  37. }
  38. SAFE_DELETE(_crossFadeToClip);
  39. SAFE_DELETE(_channelPriority);
  40. SAFE_DELETE(_beginListeners);
  41. SAFE_DELETE(_endListeners);
  42. }
  43. const char* AnimationClip::getID() const
  44. {
  45. return _id.c_str();
  46. }
  47. Animation* AnimationClip::getAnimation() const
  48. {
  49. return _animation;
  50. }
  51. unsigned long AnimationClip::getStartTime() const
  52. {
  53. return _startTime;
  54. }
  55. unsigned long AnimationClip::getEndTime() const
  56. {
  57. return _endTime;
  58. }
  59. unsigned long AnimationClip::getElaspedTime() const
  60. {
  61. return _elapsedTime;
  62. }
  63. void AnimationClip::setRepeatCount(float repeatCount)
  64. {
  65. assert(repeatCount == REPEAT_INDEFINITE || repeatCount > 0.0f);
  66. _repeatCount = repeatCount;
  67. if (repeatCount == REPEAT_INDEFINITE)
  68. {
  69. _activeDuration = _duration;
  70. }
  71. else
  72. {
  73. _activeDuration = _repeatCount * _duration;
  74. }
  75. }
  76. float AnimationClip::getRepeatCount() const
  77. {
  78. return _repeatCount;
  79. }
  80. void AnimationClip::setActiveDuration(unsigned long duration)
  81. {
  82. if (duration == REPEAT_INDEFINITE)
  83. {
  84. _repeatCount = REPEAT_INDEFINITE;
  85. _activeDuration = _duration;
  86. }
  87. else
  88. {
  89. _activeDuration = _duration;
  90. _repeatCount = (float) _activeDuration / (float) _duration;
  91. }
  92. }
  93. unsigned long AnimationClip::getActiveDuration() const
  94. {
  95. if (_repeatCount == REPEAT_INDEFINITE)
  96. return REPEAT_INDEFINITE;
  97. return _activeDuration;
  98. }
  99. void AnimationClip::setSpeed(float speed)
  100. {
  101. _speed = speed;
  102. }
  103. float AnimationClip::getSpeed() const
  104. {
  105. return _speed;
  106. }
  107. void AnimationClip::setBlendWeight(float blendWeight)
  108. {
  109. _blendWeight = blendWeight;
  110. }
  111. float AnimationClip::getBlendWeight() const
  112. {
  113. return _blendWeight;
  114. }
  115. bool AnimationClip::isPlaying() const
  116. {
  117. return _isPlaying;
  118. }
  119. void AnimationClip::play()
  120. {
  121. _animation->_controller->schedule(this);
  122. _timeStarted = Game::getGameTime();
  123. }
  124. void AnimationClip::stop()
  125. {
  126. _animation->_controller->unschedule(this);
  127. if (_isPlaying)
  128. {
  129. _isPlaying = false;
  130. onEnd();
  131. }
  132. }
  133. void AnimationClip::crossFade(AnimationClip* clip, unsigned long duration)
  134. {
  135. assert(clip);
  136. if (clip->_isPlaying && clip->_isFadingOut)
  137. {
  138. clip->_isFadingOut = false;
  139. clip->_crossFadeToClip->_isFadingIn = false;
  140. SAFE_RELEASE(clip->_crossFadeToClip);
  141. }
  142. // If I already have a clip I'm fading too.. release it.
  143. if (_crossFadeToClip)
  144. SAFE_RELEASE(_crossFadeToClip);
  145. // Assign the clip we're fading to, and increase its ref count.
  146. _crossFadeToClip = clip;
  147. _crossFadeToClip->addRef();
  148. // Set the fade in clip to fading in, and set the duration of the fade in.
  149. _crossFadeToClip->_isFadingIn = true;
  150. // Set this clip to fade out, and reset the elapsed time for the fade out.
  151. _isFadingOut = true;
  152. _crossFadeOutElapsed = 0;
  153. _crossFadeOutDuration = duration;
  154. _crossFadeStart = (Game::getGameTime() - _timeStarted);
  155. _isFadingOutStarted = true;
  156. if (!_isPlaying)
  157. play();
  158. _crossFadeToClip->play();
  159. }
  160. void AnimationClip::addBeginListener(AnimationClip::Listener* listener)
  161. {
  162. if (!_beginListeners)
  163. _beginListeners = new std::vector<Listener*>;
  164. _beginListeners->push_back(listener);
  165. }
  166. void AnimationClip::addEndListener(AnimationClip::Listener* listener)
  167. {
  168. if (!_endListeners)
  169. _endListeners = new std::vector<Listener*>;
  170. _endListeners->push_back(listener);
  171. }
  172. bool AnimationClip::update(unsigned long elapsedTime)
  173. {
  174. float speed = _speed;
  175. if (!_isPlaying)
  176. {
  177. onBegin();
  178. _elapsedTime = Game::getGameTime() - _timeStarted;
  179. _runningTime = _elapsedTime * speed;
  180. }
  181. else
  182. {
  183. // Update elapsed time.
  184. _elapsedTime += elapsedTime;
  185. _runningTime += elapsedTime * speed;
  186. }
  187. float percentComplete = 0.0f;
  188. // Check to see if clip is complete.
  189. if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0 && _runningTime >= (long) _activeDuration) || (_speed < 0 && _runningTime <= 0)))
  190. {
  191. _isPlaying = false;
  192. if (_speed >= 0)
  193. {
  194. percentComplete = _activeDuration % _duration; // Get's the fractional part of the final repeat.
  195. if (percentComplete == 0.0f)
  196. percentComplete = _duration;
  197. }
  198. else
  199. {
  200. percentComplete = 0.0f; // If we are negative speed, the end value should be 0.
  201. }
  202. }
  203. else
  204. {
  205. // Gets portion/fraction of the repeat.
  206. percentComplete = (float) (_runningTime % _duration);
  207. }
  208. // Add back in start time, and divide by the total animation's duration to get the actual percentage complete
  209. percentComplete = (float)(_startTime + percentComplete) / (float) _animation->_duration;
  210. if (_isFadingOut)
  211. {
  212. if (_isFadingOutStarted) // Calculate elapsed time since the fade out begin.
  213. {
  214. _crossFadeOutElapsed = (_elapsedTime - _crossFadeStart) * speed;
  215. _isFadingOutStarted = false;
  216. }
  217. else
  218. {
  219. // continue tracking elapsed time.
  220. _crossFadeOutElapsed += elapsedTime * speed;
  221. }
  222. if (_crossFadeOutElapsed < _crossFadeOutDuration)
  223. {
  224. float tempBlendWeight = (float) (_crossFadeOutDuration - _crossFadeOutElapsed) / (float) _crossFadeOutDuration;
  225. _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight);
  226. // adjust the clip your blending to's weight to be a percentage of your current blend weight
  227. if (_isFadingIn)
  228. {
  229. _crossFadeToClip->_blendWeight *= _blendWeight;
  230. _blendWeight -= _crossFadeToClip->_blendWeight;
  231. }
  232. else
  233. {
  234. _blendWeight = tempBlendWeight;
  235. }
  236. }
  237. else
  238. { // Fade done.
  239. _crossFadeToClip->_blendWeight = 1.0f;
  240. if (_isFadingIn)
  241. _crossFadeToClip->_blendWeight *= _blendWeight;
  242. _crossFadeToClip->_isFadingIn = false;
  243. SAFE_RELEASE(_crossFadeToClip);
  244. _blendWeight = 0.0f;
  245. _isFadingOut = false;
  246. _isPlaying = false;
  247. }
  248. }
  249. // Evaluate this clip.
  250. Animation::Channel* channel = NULL;
  251. AnimationValue* value = NULL;
  252. AnimationTarget* target = NULL;
  253. unsigned int channelCount = _animation->_channels.size();
  254. for (unsigned int i = 0; i < channelCount; i++)
  255. {
  256. channel = _animation->_channels[i];
  257. target = channel->_target;
  258. value = _values[i];
  259. // Get the current value.
  260. target->getAnimationPropertyValue(channel->_propertyId, value);
  261. // My channel priority has changed if my priority is greater than the active animation count.
  262. if (target->_reassignPriorities)
  263. {
  264. _channelPriority[i] = target->getPriority();
  265. }
  266. if (_blendWeight != 0.0f)
  267. {
  268. // Evaluate point on Curve.
  269. channel->_curve->evaluate(percentComplete, value->_interpolatedValue);
  270. if (channel->_curve->_quaternionOffsetsCount == 0)
  271. {
  272. if (_channelPriority[i] == 1)
  273. {
  274. unsigned int componentCount = value->_componentCount;
  275. for (unsigned int j = 0; j < componentCount; j++)
  276. {
  277. if (_blendWeight != 1.0f)
  278. value->_interpolatedValue[j] *= _blendWeight;
  279. value->_currentValue[j] = value->_interpolatedValue[j];
  280. }
  281. }
  282. else
  283. {
  284. unsigned int componentCount = value->_componentCount;
  285. for (unsigned int j = 0; j < componentCount; j++)
  286. {
  287. if (_blendWeight != 1.0f)
  288. value->_interpolatedValue[j] *= _blendWeight;
  289. value->_currentValue[j] += value->_interpolatedValue[j];
  290. }
  291. }
  292. }
  293. else
  294. { //We have Quaternions!!!
  295. unsigned int j = 0;
  296. unsigned int quaternionOffsetIndex = 0;
  297. unsigned int quaternionOffset = 0;
  298. if (_channelPriority[i] == 1)
  299. {
  300. do {
  301. quaternionOffset = channel->_curve->_quaternionOffsets[quaternionOffsetIndex];
  302. while (j < quaternionOffset)
  303. {
  304. if (_blendWeight != 1.0f)
  305. value->_interpolatedValue[j] *= _blendWeight;
  306. value->_currentValue[j] = value->_interpolatedValue[j];
  307. j++;
  308. }
  309. // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
  310. Quaternion* interpolatedQuaternion = (Quaternion*) (value->_interpolatedValue + j);
  311. Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
  312. // If we have a blend weight, we apply it by slerping from the identity to our interpolated value at the given weight.
  313. if (_blendWeight != 1.0f)
  314. Quaternion::slerp(Quaternion::identity(), *interpolatedQuaternion, _blendWeight, interpolatedQuaternion);
  315. // Add in contribution.
  316. currentQuaternion->set(*interpolatedQuaternion);
  317. // Increase by 4.
  318. j += 4;
  319. quaternionOffsetIndex++;
  320. } while (quaternionOffsetIndex < channel->_curve->_quaternionOffsetsCount);
  321. unsigned int componentCount = value->_componentCount;
  322. // Handle remaining scalar values.
  323. while (j < componentCount)
  324. {
  325. if (_blendWeight != 1.0f)
  326. value->_interpolatedValue[j] *= _blendWeight;
  327. value->_currentValue[j] = value->_interpolatedValue[j];
  328. j++;
  329. }
  330. }
  331. else
  332. {
  333. do {
  334. quaternionOffset = channel->_curve->_quaternionOffsets[quaternionOffsetIndex];
  335. while (j < quaternionOffset)
  336. {
  337. if (_blendWeight != 1.0f)
  338. value->_interpolatedValue[j] *= _blendWeight;
  339. value->_currentValue[j] += value->_interpolatedValue[j];
  340. j++;
  341. }
  342. // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
  343. Quaternion* interpolatedQuaternion = (Quaternion*) (value->_interpolatedValue + j);
  344. Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
  345. // If we have a blend weight, we apply it by slerping from the identity to our interpolated value at the given weight.
  346. if (_blendWeight != 1.0f)
  347. Quaternion::slerp(Quaternion::identity(), *interpolatedQuaternion, _blendWeight, interpolatedQuaternion);
  348. // Add in contribution.
  349. currentQuaternion->multiply(*interpolatedQuaternion);
  350. // Increase by 4.
  351. j += 4;
  352. quaternionOffsetIndex++;
  353. } while (quaternionOffsetIndex < channel->_curve->_quaternionOffsetsCount);
  354. unsigned int componentCount = value->_componentCount;
  355. // Handle remaining scalar values.
  356. while (j < componentCount)
  357. {
  358. if (_blendWeight != 1.0f)
  359. value->_interpolatedValue[j] *= _blendWeight;
  360. value->_currentValue[j] += value->_interpolatedValue[j];
  361. j++;
  362. }
  363. }
  364. }
  365. }
  366. else if (_channelPriority[i] == 1)
  367. {
  368. if (channel->_curve->_quaternionOffsetsCount == 0)
  369. {
  370. memset(value->_currentValue, 0.0f, value->_componentCount);
  371. }
  372. else
  373. {
  374. unsigned int j = 0;
  375. unsigned int quaternionOffset = 0;
  376. unsigned int quaternionOffsetIndex = 0;
  377. do {
  378. quaternionOffset = channel->_curve->_quaternionOffsets[quaternionOffsetIndex];
  379. while (j < quaternionOffset)
  380. {
  381. value->_currentValue[j] = 0.0f;
  382. j++;
  383. }
  384. // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
  385. Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
  386. // Set it to identity.
  387. currentQuaternion->setIdentity();
  388. // Increase by 4.
  389. j += 4;
  390. quaternionOffsetIndex++;
  391. } while (quaternionOffsetIndex < channel->_curve->_quaternionOffsetsCount);
  392. unsigned int componentCount = value->_componentCount;
  393. // Handle remaining scalar values.
  394. while (j < componentCount)
  395. {
  396. value->_currentValue[j] = 0.0f;
  397. j++;
  398. }
  399. }
  400. }
  401. // Set the animation value on the target property.
  402. target->setAnimationPropertyValue(channel->_propertyId, value);
  403. }
  404. // When ended. Probably should move to it's own method so we can call it when the clip is ended early.
  405. if (!_isPlaying)
  406. {
  407. onEnd();
  408. }
  409. return !_isPlaying;
  410. }
  411. void AnimationClip::onBegin()
  412. {
  413. // Initialize animation to play.
  414. _isPlaying = true;
  415. _elapsedTime = 0;
  416. if (_speed > 0)
  417. {
  418. _runningTime = 0;
  419. }
  420. else
  421. {
  422. _runningTime = _activeDuration;
  423. }
  424. AnimationTarget* target = NULL;
  425. unsigned int channelCount = _animation->_channels.size();
  426. // Sets the starting value.
  427. for (unsigned int i = 0; i < channelCount; i++)
  428. {
  429. target = _animation->_channels[i]->_target;
  430. target->increaseActiveAnimationCount();
  431. _channelPriority[i] = target->getPriority();
  432. }
  433. // Notify begin listeners.. if any.
  434. if (_beginListeners)
  435. {
  436. std::vector<Listener*>::iterator listener = _beginListeners->begin();
  437. while (listener != _beginListeners->end())
  438. {
  439. (*listener)->animationEvent(this, Listener::BEGIN);
  440. listener++;
  441. }
  442. }
  443. }
  444. void AnimationClip::onEnd()
  445. {
  446. AnimationTarget* target = NULL;
  447. unsigned int channelCount = _animation->_channels.size();
  448. for (unsigned int i = 0; i < channelCount; i++)
  449. {
  450. target = _animation->_channels[i]->_target;
  451. // Decrease active animation count on target and reset the channel priority
  452. target->decreaseActiveAnimationCount();
  453. _channelPriority[i] = 0;
  454. }
  455. _blendWeight = 1.0f;
  456. _timeStarted = 0;
  457. // Notify end listeners if any.
  458. if (_endListeners)
  459. {
  460. std::vector<Listener*>::iterator listener = _endListeners->begin();
  461. while (listener != _endListeners->end())
  462. {
  463. (*listener)->animationEvent(this, Listener::END);
  464. listener++;
  465. }
  466. }
  467. }
  468. }