1 //****************************************************************************//
2 // mixer.cpp                                                                  //
3 // Copyright (C) 2001, 2002 Bruno 'Beosil' Heidelberger                       //
4 //****************************************************************************//
5 // This library is free software; you can redistribute it and/or modify it    //
6 // under the terms of the GNU Lesser General Public License as published by   //
7 // the Free Software Foundation; either version 2.1 of the License, or (at    //
8 // your option) any later version.                                            //
9 //****************************************************************************//
10 
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14 
15 //****************************************************************************//
16 // Includes                                                                   //
17 //****************************************************************************//
18 
19 #include "cal3d/error.h"
20 #include "cal3d/mixer.h"
21 #include "cal3d/coremodel.h"
22 #include "cal3d/corebone.h"
23 #include "cal3d/coreanimation.h"
24 #include "cal3d/coretrack.h"
25 #include "cal3d/corekeyframe.h"
26 #include "cal3d/model.h"
27 #include "cal3d/skeleton.h"
28 #include "cal3d/bone.h"
29 #include "cal3d/animation.h"
30 #include "cal3d/animation_action.h"
31 #include "cal3d/animation_cycle.h"
32 
33  /*****************************************************************************/
34 /** Constructs the mixer instance.
35   *
36   * This function is the default constructor of the mixer instance.
37   *****************************************************************************/
38 
CalMixer(CalModel * pModel)39 CalMixer::CalMixer(CalModel* pModel)
40 {
41   assert(pModel);
42 
43   m_pModel = pModel;
44 
45   // build the animation table
46   int coreAnimationCount = m_pModel->getCoreModel()->getCoreAnimationCount();
47 
48   m_vectorAnimation.reserve(coreAnimationCount);
49   CalAnimation* null = 0;
50   m_vectorAnimation.insert(m_vectorAnimation.begin(), coreAnimationCount, null);
51 
52   // set the animation time/duration values to default
53   m_animationTime = 0.0f;
54   m_animationDuration = 0.0f;
55   m_timeFactor = 1.0f;
56 }
57 
58  /*****************************************************************************/
59 /** Destructs the mixer instance.
60   *
61   * This function is the destructor of the mixer instance.
62   *****************************************************************************/
63 
~CalMixer()64 CalMixer::~CalMixer()
65 {
66   // destroy all active animation actions
67   while(!m_listAnimationAction.empty())
68   {
69     CalAnimationAction *pAnimationAction = m_listAnimationAction.front();
70     m_listAnimationAction.pop_front();
71 
72     delete pAnimationAction;
73   }
74 
75   // destroy all active animation cycles
76   while(!m_listAnimationCycle.empty())
77   {
78     CalAnimationCycle *pAnimationCycle;
79     pAnimationCycle = m_listAnimationCycle.front();
80     m_listAnimationCycle.pop_front();
81 
82     delete pAnimationCycle;
83   }
84 
85   // clear the animation table
86   m_vectorAnimation.clear();
87 
88   m_pModel = 0;
89 }
90 
91 ///
92 /// Examines the given animation and if the first and last keyframe of a given track
93 /// do not match up, the first key frame is duplicated and added to the end of the track
94 /// to ensure smooth looping.
95 ///
addExtraKeyframeForLoopedAnim(CalCoreAnimation * pCoreAnimation)96 static void addExtraKeyframeForLoopedAnim(CalCoreAnimation* pCoreAnimation)
97 {
98 	std::list<CalCoreTrack*>& listCoreTrack = pCoreAnimation->getListCoreTrack();
99 
100    if(listCoreTrack.size() == 0)
101 		 return;
102 
103 	CalCoreTrack *coreTrack = listCoreTrack.front();
104   if(coreTrack == 0)
105 		 return;
106 
107 	CalCoreKeyframe *lastKeyframe = coreTrack->getCoreKeyframe(coreTrack->getCoreKeyframeCount()-1);
108 	if(lastKeyframe == 0)
109 		 return;
110 
111 	if(lastKeyframe->getTime() < pCoreAnimation->getDuration())
112 	{
113 		std::list<CalCoreTrack *>::iterator itr;
114     for(itr=listCoreTrack.begin();itr!=listCoreTrack.end();++itr)
115 		{
116 			coreTrack = *itr;
117 
118 			CalCoreKeyframe *firstKeyframe = coreTrack->getCoreKeyframe(0);
119       CalCoreKeyframe *newKeyframe = new CalCoreKeyframe();
120 
121       newKeyframe->setTranslation(firstKeyframe->getTranslation());
122       newKeyframe->setRotation(firstKeyframe->getRotation());
123       newKeyframe->setTime(pCoreAnimation->getDuration());
124 
125       coreTrack->addCoreKeyframe(newKeyframe);
126 		}
127 	}
128 }
129 
130  /*****************************************************************************/
131 /** Interpolates the weight of an animation cycle.
132   *
133   * This function interpolates the weight of an animation cycle to a new value
134   * in a given amount of time. If the specified animation cycle is not active
135   * yet, it is activated.
136   *
137   * @param id The ID of the animation cycle that should be blended.
138   * @param weight The weight to interpolate the animation cycle to.
139   * @param delay The time in seconds until the new weight should be reached.
140   *
141   * @return One of the following values:
142   *         \li \b true if successful
143   *         \li \b false if an error happend
144   *****************************************************************************/
145 
blendCycle(int id,float weight,float delay)146 bool CalMixer::blendCycle(int id, float weight, float delay)
147 {
148   if((id < 0) || (id >= (int)m_vectorAnimation.size()))
149   {
150     CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__);
151     return false;
152   }
153 
154   // get the animation for the given id
155   CalAnimation *pAnimation = m_vectorAnimation[id];
156 
157   // create a new animation instance if it is not active yet
158   if(pAnimation == 0)
159   {
160     // take the fast way out if we are trying to clear an inactive animation
161     if(weight == 0.0f) return true;
162 
163     // get the core animation
164     CalCoreAnimation *pCoreAnimation = m_pModel->getCoreModel()->getCoreAnimation(id);
165     if(pCoreAnimation == 0) return false;
166 
167     // Ensure that the animation's first and last key frame match for proper
168     // looping.
169     ::addExtraKeyframeForLoopedAnim(pCoreAnimation);
170 
171     // allocate a new animation cycle instance
172     CalAnimationCycle *pAnimationCycle = new CalAnimationCycle(pCoreAnimation);
173     if(pAnimationCycle == 0)
174     {
175       CalError::setLastError(CalError::MEMORY_ALLOCATION_FAILED, __FILE__, __LINE__);
176       return false;
177     }
178 
179     // insert new animation into the tables
180     m_vectorAnimation[id] = pAnimationCycle;
181     m_listAnimationCycle.push_front(pAnimationCycle);
182 
183     // blend the animation
184     return pAnimationCycle->blend(weight, delay);
185   }
186 
187   // check if this is really a animation cycle instance
188   if(pAnimation->getType() != CalAnimation::TYPE_CYCLE)
189   {
190       CalError::setLastError(CalError::INVALID_ANIMATION_TYPE, __FILE__, __LINE__);
191       return false;
192   }
193 
194   // clear the animation cycle from the active vector if the target weight is zero
195   if(weight == 0.0f)
196   {
197       m_vectorAnimation[id] = 0;
198   }
199 
200   // cast it to an animation cycle
201   CalAnimationCycle *pAnimationCycle;
202   pAnimationCycle = (CalAnimationCycle *)pAnimation;
203 
204   // blend the animation cycle
205   pAnimationCycle->blend(weight, delay);
206   pAnimationCycle->checkCallbacks(0,m_pModel);
207   return true;
208 }
209 
210  /*****************************************************************************/
211 /** Fades an animation cycle out.
212   *
213   * This function fades an animation cycle out in a given amount of time.
214   *
215   * @param id The ID of the animation cycle that should be faded out.
216   * @param delay The time in seconds until the the animation cycle is
217   *              completely removed.
218   *
219   * @return One of the following values:
220   *         \li \b true if successful
221   *         \li \b false if an error happend
222   *****************************************************************************/
223 
clearCycle(int id,float delay)224 bool CalMixer::clearCycle(int id, float delay)
225 {
226   // check if the animation id is valid
227   if((id < 0) || (id >= (int)m_vectorAnimation.size()))
228   {
229     CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__);
230     return false;
231   }
232 
233   // get the animation for the given id
234   CalAnimation *pAnimation;
235   pAnimation = m_vectorAnimation[id];
236 
237   // we can only clear cycles that are active
238   if(pAnimation == 0) return true;
239 
240   // check if this is really a animation cycle instance
241   if(pAnimation->getType() != CalAnimation::TYPE_CYCLE)
242   {
243       CalError::setLastError(CalError::INVALID_ANIMATION_TYPE, __FILE__, __LINE__);
244       return false;
245   }
246 
247   // clear the animation cycle from the active vector
248   m_vectorAnimation[id] = 0;
249 
250   // cast it to an animation cycle
251   CalAnimationCycle *pAnimationCycle;
252   pAnimationCycle = (CalAnimationCycle *)pAnimation;
253 
254   // set animation cycle to async state
255   pAnimationCycle->setAsync(m_animationTime, m_animationDuration);
256 
257   // blend the animation cycle
258   pAnimationCycle->blend(0.0f, delay);
259   pAnimationCycle->checkCallbacks(0, m_pModel);
260   return true;
261 }
262 
263 /*****************************************************************************/
264 /** Executes an animation action.
265   *
266   * This function executes an animation action.
267   *
268   * @param id The ID of the animation action that should be blended.
269   * @param delayIn The time in seconds until the animation action reaches the
270   *                full weight from the beginning of its execution.
271   * @param delayOut The time in seconds in which the animation action reaches
272   *                 zero weight at the end of its execution.
273   * @param weightTarget The weight to interpolate the animation action to.
274   * @param autoLock     This prevents the Action from being reset and removed
275   *                     on the last keyframe if true.
276   *
277   * @return One of the following values:
278   *         \li \b true if successful
279   *         \li \b false if an error happend
280   *****************************************************************************/
executeAction(int id,float delayIn,float delayOut,float weightTarget,bool autoLock)281 bool CalMixer::executeAction(int id, float delayIn, float delayOut, float weightTarget, bool autoLock)
282 {
283   // get the core animation
284   CalCoreAnimation *pCoreAnimation;
285   pCoreAnimation = m_pModel->getCoreModel()->getCoreAnimation(id);
286   if(pCoreAnimation == 0)
287   {
288     return false;
289   }
290 
291   // allocate a new animation action instance
292   CalAnimationAction *pAnimationAction = new CalAnimationAction(pCoreAnimation);
293   if(pAnimationAction == 0)
294   {
295     CalError::setLastError(CalError::MEMORY_ALLOCATION_FAILED, __FILE__, __LINE__);
296     return false;
297   }
298 
299   // insert new animation into the table
300   m_listAnimationAction.push_front(pAnimationAction);
301 
302   // execute the animation
303   pAnimationAction->execute(delayIn, delayOut, weightTarget, autoLock);
304   pAnimationAction->checkCallbacks(0, m_pModel);
305   return true;
306 }
307 
308 /*****************************************************************************/
309 /** Clears an active animation action.
310   *
311   * This function removes an animation action from the blend list.  This is
312   * particularly useful with auto-locked actions on their last frame.
313   *
314   * @param id The ID of the animation action that should be removed.
315   *
316   * @return One of the following values:
317   *         \li \b true if successful
318   *         \li \b false if an error happened or action was not found
319   *****************************************************************************/
removeAction(int id)320 bool CalMixer::removeAction(int id)
321 {
322   // get the core animation
323   CalCoreAnimation *pCoreAnimation;
324   pCoreAnimation = m_pModel->getCoreModel()->getCoreAnimation(id);
325   if(pCoreAnimation == 0)
326   {
327     return false;
328   }
329 
330   // update all active animation actions of this model
331   std::list<CalAnimationAction *>::iterator iteratorAnimationAction;
332   iteratorAnimationAction = m_listAnimationAction.begin();
333 
334   while(iteratorAnimationAction != m_listAnimationAction.end())
335   {
336     // find the specified action and remove it
337     if((*iteratorAnimationAction)->getCoreAnimation() == pCoreAnimation )
338     {
339         // found, so remove
340       (*iteratorAnimationAction)->completeCallbacks(m_pModel);
341       delete (*iteratorAnimationAction);
342       iteratorAnimationAction = m_listAnimationAction.erase(iteratorAnimationAction);
343       return true;
344     }
345     iteratorAnimationAction++;
346   }
347   return false;
348 }
349 
350  /*****************************************************************************/
351 /** Updates all active animations.
352   *
353   * This function updates all active animations of the mixer instance for a
354   * given amount of time.
355   *
356   * @param deltaTime The elapsed time in seconds since the last update.
357   *****************************************************************************/
358 
updateAnimation(float deltaTime)359 void CalMixer::updateAnimation(float deltaTime)
360 {
361   // update the current animation time
362   if(m_animationDuration == 0.0f)
363   {
364     m_animationTime = 0.0f;
365   }
366   else
367   {
368     m_animationTime += deltaTime * m_timeFactor;
369     if(m_animationTime >= m_animationDuration || m_animationTime<0)
370     {
371       m_animationTime = (float) fmod(m_animationTime, m_animationDuration);
372     }
373 	if (m_animationTime < 0)
374       m_animationTime += m_animationDuration;
375 
376   }
377 
378   // update all active animation actions of this model
379   std::list<CalAnimationAction *>::iterator iteratorAnimationAction;
380   iteratorAnimationAction = m_listAnimationAction.begin();
381 
382   while(iteratorAnimationAction != m_listAnimationAction.end())
383   {
384     // update and check if animation action is still active
385     if((*iteratorAnimationAction)->update(deltaTime))
386     {
387       (*iteratorAnimationAction)->checkCallbacks((*iteratorAnimationAction)->getTime(),m_pModel);
388       ++iteratorAnimationAction;
389     }
390     else
391     {
392       // animation action has ended, destroy and remove it from the animation list
393       (*iteratorAnimationAction)->completeCallbacks(m_pModel);
394       delete (*iteratorAnimationAction);
395       iteratorAnimationAction = m_listAnimationAction.erase(iteratorAnimationAction);
396     }
397   }
398 
399   // todo: update all active animation poses of this model
400 
401   // update the weight of all active animation cycles of this model
402   std::list<CalAnimationCycle *>::iterator iteratorAnimationCycle;
403   iteratorAnimationCycle = m_listAnimationCycle.begin();
404 
405   float accumulatedWeight, accumulatedDuration;
406   accumulatedWeight = 0.0f;
407   accumulatedDuration = 0.0f;
408 
409   while(iteratorAnimationCycle != m_listAnimationCycle.end())
410   {
411     // update and check if animation cycle is still active
412     if((*iteratorAnimationCycle)->update(deltaTime))
413     {
414       // check if it is in sync. if yes, update accumulated weight and duration
415       if((*iteratorAnimationCycle)->getState() == CalAnimation::STATE_SYNC)
416       {
417         accumulatedWeight += (*iteratorAnimationCycle)->getWeight();
418         accumulatedDuration += (*iteratorAnimationCycle)->getWeight() * (*iteratorAnimationCycle)->getCoreAnimation()->getDuration();
419       }
420 
421       (*iteratorAnimationCycle)->checkCallbacks(m_animationTime,m_pModel);
422       ++iteratorAnimationCycle;
423     }
424     else
425     {
426       // animation cycle has ended, destroy and remove it from the animation list
427       (*iteratorAnimationCycle)->completeCallbacks(m_pModel);
428       delete (*iteratorAnimationCycle);
429       iteratorAnimationCycle = m_listAnimationCycle.erase(iteratorAnimationCycle);
430     }
431   }
432 
433   // adjust the global animation cycle duration
434   if(accumulatedWeight > 0.0f)
435   {
436     m_animationDuration = accumulatedDuration / accumulatedWeight;
437   }
438   else
439   {
440     m_animationDuration = 0.0f;
441   }
442 }
443 
updateSkeleton()444 void CalMixer::updateSkeleton()
445 {
446   // get the skeleton we need to update
447   CalSkeleton *pSkeleton;
448   pSkeleton = m_pModel->getSkeleton();
449   if(pSkeleton == 0) return;
450 
451   // clear the skeleton state
452   pSkeleton->clearState();
453 
454   // get the bone vector of the skeleton
455   std::vector<CalBone *>& vectorBone = pSkeleton->getVectorBone();
456 
457   // loop through all animation actions
458   std::list<CalAnimationAction *>::iterator iteratorAnimationAction;
459   for(iteratorAnimationAction = m_listAnimationAction.begin(); iteratorAnimationAction != m_listAnimationAction.end(); ++iteratorAnimationAction)
460   {
461     // get the core animation instance
462     CalCoreAnimation *pCoreAnimation;
463     pCoreAnimation = (*iteratorAnimationAction)->getCoreAnimation();
464 
465     // get the list of core tracks of above core animation
466     std::list<CalCoreTrack *>& listCoreTrack = pCoreAnimation->getListCoreTrack();
467 
468     // loop through all core tracks of the core animation
469     std::list<CalCoreTrack *>::iterator iteratorCoreTrack;
470     for(iteratorCoreTrack = listCoreTrack.begin(); iteratorCoreTrack != listCoreTrack.end(); ++iteratorCoreTrack)
471     {
472       // get the appropriate bone of the track
473       CalBone *pBone;
474       pBone = vectorBone[(*iteratorCoreTrack)->getCoreBoneId()];
475 
476       // get the current translation and rotation
477       CalVector translation;
478       CalQuaternion rotation;
479       (*iteratorCoreTrack)->getState((*iteratorAnimationAction)->getTime(), translation, rotation);
480 
481       // blend the bone state with the new state
482       pBone->blendState((*iteratorAnimationAction)->getWeight(), translation, rotation);
483     }
484   }
485 
486   // lock the skeleton state
487   pSkeleton->lockState();
488 
489   // loop through all animation cycles
490   std::list<CalAnimationCycle *>::iterator iteratorAnimationCycle;
491   for(iteratorAnimationCycle = m_listAnimationCycle.begin(); iteratorAnimationCycle != m_listAnimationCycle.end(); ++iteratorAnimationCycle)
492   {
493     // get the core animation instance
494     CalCoreAnimation *pCoreAnimation;
495     pCoreAnimation = (*iteratorAnimationCycle)->getCoreAnimation();
496 
497     // calculate adjusted time
498     float animationTime;
499     if((*iteratorAnimationCycle)->getState() == CalAnimation::STATE_SYNC)
500     {
501       if(m_animationDuration == 0.0f)
502       {
503         animationTime = 0.0f;
504       }
505       else
506       {
507         animationTime = m_animationTime * pCoreAnimation->getDuration() / m_animationDuration;
508       }
509     }
510     else
511     {
512       animationTime = (*iteratorAnimationCycle)->getTime();
513     }
514 
515     // get the list of core tracks of above core animation
516     std::list<CalCoreTrack *>& listCoreTrack = pCoreAnimation->getListCoreTrack();
517 
518     // loop through all core tracks of the core animation
519     std::list<CalCoreTrack *>::iterator iteratorCoreTrack;
520     for(iteratorCoreTrack = listCoreTrack.begin(); iteratorCoreTrack != listCoreTrack.end(); ++iteratorCoreTrack)
521     {
522       // get the appropriate bone of the track
523       CalBone *pBone;
524       pBone = vectorBone[(*iteratorCoreTrack)->getCoreBoneId()];
525 
526       // get the current translation and rotation
527       CalVector translation;
528       CalQuaternion rotation;
529       (*iteratorCoreTrack)->getState(animationTime, translation, rotation);
530 
531       // blend the bone state with the new state
532       pBone->blendState((*iteratorAnimationCycle)->getWeight(), translation, rotation);
533     }
534   }
535 
536   // lock the skeleton state
537   pSkeleton->lockState();
538 
539   // let the skeleton calculate its final state
540   pSkeleton->calculateState();
541 }
542 
543 /*****************************************************************************/
544 /** Returns the animation time.
545   *
546   * This function returns the animation time of the mixer instance.
547   *
548   * @return The animation time in seconds.
549   *****************************************************************************/
550 
getAnimationTime() const551 float CalMixer::getAnimationTime() const
552 {
553 	return m_animationTime;
554 }
555 
556 /*****************************************************************************/
557 /** Returns the animation duration.
558   *
559   * This function returns the animation duration of the mixer instance.
560   *
561   * @return The animation duration in seconds.
562   *****************************************************************************/
563 
getAnimationDuration() const564 float CalMixer::getAnimationDuration() const
565 {
566 	return m_animationDuration;
567 }
568 
569 /*****************************************************************************/
570 /** Sets the animation time.
571   *
572   * This function sets the animation time of the mixer instance.
573   *
574   *****************************************************************************/
575 
setAnimationTime(float animationTime)576 void CalMixer::setAnimationTime(float animationTime)
577 {
578 	m_animationTime=animationTime;
579 }
580 
581 /*****************************************************************************/
582 /** Set the time factor.
583   *
584   * This function sets the time factor of the mixer instance.
585   * this time factor affect only sync animation
586   *
587   *****************************************************************************/
588 
setTimeFactor(float timeFactor)589 void CalMixer::setTimeFactor(float timeFactor)
590 {
591     m_timeFactor = timeFactor;
592 }
593 
594 /*****************************************************************************/
595 /** Get the time factor.
596   *
597   * This function return the time factor of the mixer instance.
598   *
599   *****************************************************************************/
600 
getTimeFactor() const601 float CalMixer::getTimeFactor() const
602 {
603     return m_timeFactor;
604 }
605 
606 /*****************************************************************************/
607 /** Get the model.
608   *
609   * This function return the CalModel of the mixer instance.
610   *
611   *****************************************************************************/
612 
getCalModel()613 CalModel *CalMixer::getCalModel()
614 {
615     return m_pModel;
616 }
617 
618 /*****************************************************************************/
619 /** Get the animation vector.
620   *
621   * This function return the animation vector of the mixer instance.
622   *
623   *****************************************************************************/
624 
getAnimationVector()625 std::vector<CalAnimation *> & CalMixer::getAnimationVector()
626 {
627     return m_vectorAnimation;
628 }
629 
630 /*****************************************************************************/
631 /** Get the list of the action animation.
632   *
633   * This function return the list of the action animation of the mixer instance.
634   *
635   *****************************************************************************/
636 
getAnimationActionList()637 std::list<CalAnimationAction *> & CalMixer::getAnimationActionList()
638 {
639     return m_listAnimationAction;
640 }
641 
642 /*****************************************************************************/
643 /** Get the list of the cycle animation.
644   *
645   * This function return the list of the cycle animation of the mixer instance.
646   *
647   *****************************************************************************/
648 
getAnimationCycle()649 std::list<CalAnimationCycle *> & CalMixer::getAnimationCycle()
650 {
651     return m_listAnimationCycle;
652 }
653 
654 //****************************************************************************//
655