Animation3D.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #include "Animation3D.h"
  2. #include "Model3D.h"
  3. using namespace Framework;
  4. // create an animation for a specific bone
  5. // \param boneId the id of the bone
  6. // \param originPos the position of the bone at the beginning of the animation
  7. // \param originRot the rotation of the bone at the beginning of the animation
  8. BoneAnimation::BoneAnimation(
  9. int boneId, Vec3<float> originPos, Vec3<float> originRot)
  10. : ReferenceCounter(),
  11. boneId(boneId),
  12. frameCount(1),
  13. maxTime(0.0),
  14. loop(0)
  15. {
  16. frames = new KeyFrame[1];
  17. frames[0].time = 0.0;
  18. frames[0].pos = originPos;
  19. frames[0].rot = originRot;
  20. current = frames[0];
  21. }
  22. // destructor
  23. BoneAnimation::~BoneAnimation()
  24. {
  25. delete[] frames;
  26. }
  27. // make the animation to a loop that starts again if the end is reached
  28. void BoneAnimation::setLoop(bool loop)
  29. {
  30. this->loop = loop;
  31. }
  32. //! adds a keyframe
  33. //! \param time the time in seconds since the start of the animation at
  34. //! which the bone should have the given position and rotation relative
  35. //! to its parent bone \param pos the position of the bone \param rot
  36. //! the rotation of the bone
  37. void BoneAnimation::addKeyFrame(double time, Vec3<float> pos, Vec3<float> rot)
  38. {
  39. if (time < 0)
  40. throw "Illegal argument exception: time of a keyframe can not be lower "
  41. "than 0";
  42. if (maxTime < time) maxTime = time;
  43. frameCount++;
  44. KeyFrame* tmp = new KeyFrame[frameCount];
  45. bool added = 0;
  46. for (int i = 0; i < frameCount; i++)
  47. {
  48. if (i < frameCount - 1 && frames[i - (int)added].time <= time)
  49. {
  50. tmp[i] = frames[i];
  51. }
  52. else
  53. {
  54. if (!added)
  55. {
  56. tmp[i].time = time;
  57. tmp[i].pos = pos;
  58. tmp[i].rot = rot;
  59. added = 1;
  60. }
  61. else
  62. {
  63. tmp[i] = frames[i - 1];
  64. }
  65. }
  66. }
  67. delete[] frames;
  68. frames = tmp;
  69. }
  70. // adds a keyframe that is the same as the last keyframe with the time time
  71. // \returns true if the keyframe was added successfully, false if time is maller
  72. // than the current length of the animation
  73. bool BoneAnimation::doNothingUntil(double time)
  74. {
  75. if (time > maxTime)
  76. {
  77. KeyFrame& last = frames[frameCount - 1];
  78. addKeyFrame(time, last.pos, last.rot);
  79. }
  80. return 0;
  81. }
  82. // calculates the positions and rotation at the next time
  83. // \param time the passed time in seconds since the last call
  84. void BoneAnimation::tick(double time)
  85. {
  86. if (frameCount <= 1) return;
  87. current.time += time;
  88. if (loop)
  89. {
  90. while (current.time >= maxTime)
  91. {
  92. current.time -= maxTime;
  93. }
  94. }
  95. else if (current.time > maxTime)
  96. {
  97. current.time = maxTime;
  98. }
  99. int last = -1;
  100. int next = -1;
  101. for (int i = 0; i < frameCount; i++)
  102. {
  103. last = next;
  104. next = i;
  105. if (frames[i].time > current.time)
  106. {
  107. break;
  108. }
  109. }
  110. float timePart = (float)(current.time - frames[last].time);
  111. current.pos
  112. = frames[last].pos + (frames[next].pos - frames[last].pos) * timePart;
  113. current.rot
  114. = frames[last].rot + (frames[next].rot - frames[last].rot) * timePart;
  115. }
  116. //! applys the animation on a given skeleton
  117. //! \param zS: the sceleton
  118. void BoneAnimation::apply(Skeleton* zSkelett) const
  119. {
  120. Bone* zK = zSkelett->zBone(boneId);
  121. if (zK)
  122. {
  123. zK->setPosition(current.pos);
  124. zK->setRotation(current.rot);
  125. }
  126. }
  127. // returns true if the animation has reached the last keyframe and does
  128. // not loop
  129. bool BoneAnimation::isFinished() const
  130. {
  131. return current.time >= maxTime;
  132. }
  133. // returns the bone id this animation is for
  134. int BoneAnimation::getBoneId() const
  135. {
  136. return boneId;
  137. }
  138. // returns the maximum time of the animation
  139. double BoneAnimation::getMaxTime() const
  140. {
  141. return maxTime;
  142. }
  143. //! Constructor
  144. SkeletonAnimation::SkeletonAnimation()
  145. : ReferenceCounter(),
  146. loop(0)
  147. {}
  148. // make the animation to a loop that starts again if the end is reached
  149. void SkeletonAnimation::setLoop(bool loop)
  150. {
  151. this->loop = loop;
  152. for (BoneAnimation* animation : subAnimations)
  153. {
  154. animation->setLoop(loop);
  155. }
  156. }
  157. // adds an animation for a specific bone
  158. // \param boneId the bone id
  159. // \param originPos the position of the bone at the beginning of the animation
  160. // \param originRot the rotation of the bone at the beginning of the animation
  161. bool SkeletonAnimation::addAnimation(
  162. int boneId, Vec3<float> originPos, Vec3<float> originRot)
  163. {
  164. for (BoneAnimation* animation : subAnimations)
  165. {
  166. if (animation->getBoneId() == boneId)
  167. {
  168. return 0;
  169. }
  170. }
  171. subAnimations.add(new BoneAnimation(boneId, originPos, originRot));
  172. return 1;
  173. }
  174. //! adds a keyframe for a specific bone of the sceleton
  175. //! \param kId id of the bone
  176. //! \param time the time in seconds since the start of the animation at
  177. //! which the bone should have the given position and rotation relative
  178. //! to its parent bone \param pos the position of the bone \param rot
  179. //! the rotation of the bone
  180. bool SkeletonAnimation::addKeyFrame(
  181. int boneId, double time, Vec3<float> pos, Vec3<float> rot)
  182. {
  183. for (BoneAnimation* animation : subAnimations)
  184. {
  185. if (animation->getBoneId() == boneId)
  186. {
  187. animation->addKeyFrame(time, pos, rot);
  188. return 1;
  189. }
  190. }
  191. return 0;
  192. }
  193. //! applys the animation on a given skeleton
  194. //! \param zS: the sceleton
  195. void SkeletonAnimation::apply(Skeleton* zS) const
  196. {
  197. for (BoneAnimation* animation : subAnimations)
  198. {
  199. animation->apply(zS);
  200. }
  201. }
  202. // calculates the positions and rotation at the next time
  203. // \param time the passed time in seconds since the last call
  204. void SkeletonAnimation::tick(double time)
  205. {
  206. for (BoneAnimation* animation : subAnimations)
  207. {
  208. animation->tick(time);
  209. }
  210. }
  211. // returns true if the animation has reached the last keyframe and does
  212. // not loop
  213. bool SkeletonAnimation::isFinished() const
  214. {
  215. for (BoneAnimation* animation : subAnimations)
  216. {
  217. if (!animation->isFinished()) return 0;
  218. }
  219. return 1;
  220. }
  221. // returns the maximum time of the animation
  222. double SkeletonAnimation::getMaxTime() const
  223. {
  224. double max = 0;
  225. for (BoneAnimation* animation : subAnimations)
  226. {
  227. max = MAX(animation->getMaxTime(), max);
  228. }
  229. return max;
  230. }
  231. // returns the animation for a specific bone or 0 if it does not exist
  232. BoneAnimation* SkeletonAnimation::zAnimation(int boneId) const
  233. {
  234. for (BoneAnimation* animation : subAnimations)
  235. {
  236. if (animation->getBoneId() == boneId) return animation;
  237. }
  238. return 0;
  239. }