SkelAnimCtrl.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include "SkelAnimCtrl.h"
  2. #include "SkelAnim.h"
  3. #include "SkelNode.h"
  4. #include "Skeleton.h"
  5. #include "App.h"
  6. #include "MainRenderer.h"
  7. //======================================================================================================================
  8. // SkelAnimCtrl =
  9. //======================================================================================================================
  10. SkelAnimCtrl::SkelAnimCtrl( SkelNode* skelNode_ ):
  11. Controller(CT_SKEL_ANIM),
  12. skelNode( skelNode_ )
  13. {
  14. heads.resize( skelNode->skeleton->bones.size() );
  15. tails.resize( skelNode->skeleton->bones.size() );
  16. boneRotations.resize( skelNode->skeleton->bones.size() );
  17. boneTranslations.resize( skelNode->skeleton->bones.size() );
  18. }
  19. //======================================================================================================================
  20. // interpolate =
  21. //======================================================================================================================
  22. void SkelAnimCtrl::interpolate( SkelAnim* animation, float frame )
  23. {
  24. DEBUG_ERR( frame >= animation->framesNum );
  25. // calculate the t (used in slerp and lerp) using the keyframs and the frame and
  26. // calc the lPose and rPose witch indicate the pose ids in witch the frame lies between
  27. const Vec<uint>& keyframes = animation->keyframes;
  28. float t = 0.0;
  29. uint lPose = 0, rPose = 0;
  30. for( uint j=0; j<keyframes.size(); j++ )
  31. {
  32. if( (float)keyframes[j] == frame )
  33. {
  34. lPose = rPose = j;
  35. t = 0.0;
  36. break;
  37. }
  38. else if( (float)keyframes[j] > frame )
  39. {
  40. lPose = j-1;
  41. rPose = j;
  42. t = ( frame - (float)keyframes[lPose] ) / float( keyframes[rPose] - keyframes[lPose] );
  43. break;
  44. }
  45. }
  46. // now for all bones update bone's poses
  47. DEBUG_ERR( boneRotations.size()<1 );
  48. for( uint i=0; i<boneRotations.size(); i++ )
  49. {
  50. const SkelAnim::BoneAnim& banim = animation->bones[i];
  51. Mat3& localRot = boneRotations[i];
  52. Vec3& localTransl = boneTranslations[i];
  53. // if the bone has animations then slerp and lerp to find the rotation and translation
  54. if( banim.keyframes.size() != 0 )
  55. {
  56. const SkelAnim::BonePose& lBpose = banim.keyframes[lPose];
  57. const SkelAnim::BonePose& rBpose = banim.keyframes[rPose];
  58. // rotation
  59. const Quat& q0 = lBpose.rotation;
  60. const Quat& q1 = rBpose.rotation;
  61. localRot = Mat3( q0.slerp(q1, t) );
  62. // translation
  63. const Vec3& v0 = lBpose.translation;
  64. const Vec3& v1 = rBpose.translation;
  65. localTransl = v0.lerp( v1, t );
  66. }
  67. // else put the idents
  68. else
  69. {
  70. localRot = Mat3::getIdentity();
  71. localTransl = Vec3( 0.0, 0.0, 0.0 );
  72. }
  73. }
  74. }
  75. //======================================================================================================================
  76. // updateBoneTransforms =
  77. //======================================================================================================================
  78. void SkelAnimCtrl::updateBoneTransforms()
  79. {
  80. uint queue[ 128 ];
  81. uint head = 0, tail = 0;
  82. // put the roots
  83. for( uint i=0; i<skelNode->skeleton->bones.size(); i++ )
  84. if( skelNode->skeleton->bones[i].parent == NULL )
  85. queue[tail++] = i; // queue push
  86. // loop
  87. while( head != tail ) // while queue not empty
  88. {
  89. uint boneId = queue[head++]; // queue pop
  90. const Skeleton::Bone& boned = skelNode->skeleton->bones[boneId];
  91. // bone.final_transform = MA * ANIM * MAi
  92. // where MA is bone matrix at armature space and ANIM the interpolated transformation.
  93. combineTransformations( boneTranslations[boneId], boneRotations[boneId],
  94. boned.tslSkelSpaceInv, boned.rotSkelSpaceInv,
  95. boneTranslations[boneId], boneRotations[boneId] );
  96. combineTransformations( boned.tslSkelSpace, boned.rotSkelSpace,
  97. boneTranslations[boneId], boneRotations[boneId],
  98. boneTranslations[boneId], boneRotations[boneId] );
  99. // and finaly add the parent's transform
  100. if( boned.parent )
  101. {
  102. // bone.final_final_transform = parent.transf * bone.final_transform
  103. combineTransformations( boneTranslations[boned.parent->id], boneRotations[boned.parent->id],
  104. boneTranslations[boneId], boneRotations[boneId],
  105. boneTranslations[boneId], boneRotations[boneId] );
  106. }
  107. // now add the bone's childes
  108. for( uint i=0; i<boned.childsNum; i++ )
  109. queue[tail++] = boned.childs[i]->id;
  110. }
  111. }
  112. //======================================================================================================================
  113. // deform =
  114. //======================================================================================================================
  115. void SkelAnimCtrl::deform()
  116. {
  117. Skeleton* skeleton = skelNode->skeleton;
  118. for( uint i=0; i<skeleton->bones.size(); i++ )
  119. {
  120. const Mat3& rot = boneRotations[ i ];
  121. const Vec3& transl = boneTranslations[ i ];
  122. heads[i] = skeleton->bones[i].head.getTransformed( transl, rot );
  123. tails[i] = skeleton->bones[i].tail.getTransformed( transl, rot );
  124. }
  125. }
  126. //======================================================================================================================
  127. // update =
  128. //======================================================================================================================
  129. void SkelAnimCtrl::update( float )
  130. {
  131. frame += step;
  132. if( frame > skelAnim->framesNum ) // if the crnt is finished then play the next or loop the crnt
  133. {
  134. frame = 0.0;
  135. }
  136. interpolate( skelAnim, frame );
  137. updateBoneTransforms();
  138. if( app->getMainRenderer()->dbg.isShowSkeletonsEnabled() )
  139. {
  140. deform();
  141. }
  142. }