You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

247 lines
8.8 KiB

  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (assimp)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2012, assimp team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the assimp team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the assimp team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file SceneAnimator.cpp
  35. * @brief Implementation of the utility class SceneAnimator
  36. */
  37. #include "stdafx.h"
  38. #include "assimp_view.h"
  39. using namespace AssimpView;
  40. // ------------------------------------------------------------------------------------------------
  41. // Constructor for a given scene.
  42. SceneAnimator::SceneAnimator( const aiScene* pScene, size_t pAnimIndex)
  43. {
  44. mScene = pScene;
  45. mCurrentAnimIndex = -1;
  46. mAnimEvaluator = NULL;
  47. mRootNode = NULL;
  48. // build the nodes-for-bones table
  49. for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
  50. {
  51. const aiMesh* mesh = pScene->mMeshes[i];
  52. for (unsigned int n = 0; n < mesh->mNumBones;++n)
  53. {
  54. const aiBone* bone = mesh->mBones[n];
  55. mBoneNodesByName[bone->mName.data] = pScene->mRootNode->FindNode(bone->mName);
  56. }
  57. }
  58. // changing the current animation also creates the node tree for this animation
  59. SetAnimIndex( pAnimIndex);
  60. }
  61. // ------------------------------------------------------------------------------------------------
  62. // Destructor
  63. SceneAnimator::~SceneAnimator()
  64. {
  65. delete mRootNode;
  66. delete mAnimEvaluator;
  67. }
  68. // ------------------------------------------------------------------------------------------------
  69. // Sets the animation to use for playback.
  70. void SceneAnimator::SetAnimIndex( size_t pAnimIndex)
  71. {
  72. // no change
  73. if( pAnimIndex == mCurrentAnimIndex)
  74. return;
  75. // kill data of the previous anim
  76. delete mRootNode; mRootNode = NULL;
  77. delete mAnimEvaluator; mAnimEvaluator = NULL;
  78. mNodesByName.clear();
  79. mCurrentAnimIndex = pAnimIndex;
  80. // create the internal node tree. Do this even in case of invalid animation index
  81. // so that the transformation matrices are properly set up to mimic the current scene
  82. mRootNode = CreateNodeTree( mScene->mRootNode, NULL);
  83. // invalid anim index
  84. if( mCurrentAnimIndex >= mScene->mNumAnimations)
  85. return;
  86. // create an evaluator for this animation
  87. mAnimEvaluator = new AnimEvaluator( mScene->mAnimations[mCurrentAnimIndex]);
  88. }
  89. // ------------------------------------------------------------------------------------------------
  90. // Calculates the node transformations for the scene.
  91. void SceneAnimator::Calculate( double pTime)
  92. {
  93. // invalid anim
  94. if( !mAnimEvaluator)
  95. return;
  96. // calculate current local transformations
  97. mAnimEvaluator->Evaluate( pTime);
  98. // and update all node transformations with the results
  99. UpdateTransforms( mRootNode, mAnimEvaluator->GetTransformations());
  100. }
  101. // ------------------------------------------------------------------------------------------------
  102. // Retrieves the most recent local transformation matrix for the given node.
  103. const aiMatrix4x4& SceneAnimator::GetLocalTransform( const aiNode* node) const
  104. {
  105. NodeMap::const_iterator it = mNodesByName.find( node);
  106. if( it == mNodesByName.end())
  107. return mIdentityMatrix;
  108. return it->second->mLocalTransform;
  109. }
  110. // ------------------------------------------------------------------------------------------------
  111. // Retrieves the most recent global transformation matrix for the given node.
  112. const aiMatrix4x4& SceneAnimator::GetGlobalTransform( const aiNode* node) const
  113. {
  114. NodeMap::const_iterator it = mNodesByName.find( node);
  115. if( it == mNodesByName.end())
  116. return mIdentityMatrix;
  117. return it->second->mGlobalTransform;
  118. }
  119. // ------------------------------------------------------------------------------------------------
  120. // Calculates the bone matrices for the given mesh.
  121. const std::vector<aiMatrix4x4>& SceneAnimator::GetBoneMatrices( const aiNode* pNode, size_t pMeshIndex /* = 0 */)
  122. {
  123. ai_assert( pMeshIndex < pNode->mNumMeshes);
  124. size_t meshIndex = pNode->mMeshes[pMeshIndex];
  125. ai_assert( meshIndex < mScene->mNumMeshes);
  126. const aiMesh* mesh = mScene->mMeshes[meshIndex];
  127. // resize array and initialise it with identity matrices
  128. mTransforms.resize( mesh->mNumBones, aiMatrix4x4());
  129. // calculate the mesh's inverse global transform
  130. aiMatrix4x4 globalInverseMeshTransform = GetGlobalTransform( pNode);
  131. globalInverseMeshTransform.Inverse();
  132. // Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose
  133. // Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform
  134. for( size_t a = 0; a < mesh->mNumBones; ++a)
  135. {
  136. const aiBone* bone = mesh->mBones[a];
  137. const aiMatrix4x4& currentGlobalTransform = GetGlobalTransform( mBoneNodesByName[ bone->mName.data ]);
  138. mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone->mOffsetMatrix;
  139. }
  140. // and return the result
  141. return mTransforms;
  142. }
  143. // ------------------------------------------------------------------------------------------------
  144. // Recursively creates an internal node structure matching the current scene and animation.
  145. SceneAnimNode* SceneAnimator::CreateNodeTree( aiNode* pNode, SceneAnimNode* pParent)
  146. {
  147. // create a node
  148. SceneAnimNode* internalNode = new SceneAnimNode( pNode->mName.data);
  149. internalNode->mParent = pParent;
  150. mNodesByName[pNode] = internalNode;
  151. // copy its transformation
  152. internalNode->mLocalTransform = pNode->mTransformation;
  153. CalculateGlobalTransform( internalNode);
  154. // find the index of the animation track affecting this node, if any
  155. if( mCurrentAnimIndex < mScene->mNumAnimations)
  156. {
  157. internalNode->mChannelIndex = -1;
  158. const aiAnimation* currentAnim = mScene->mAnimations[mCurrentAnimIndex];
  159. for( unsigned int a = 0; a < currentAnim->mNumChannels; a++)
  160. {
  161. if( currentAnim->mChannels[a]->mNodeName.data == internalNode->mName)
  162. {
  163. internalNode->mChannelIndex = a;
  164. break;
  165. }
  166. }
  167. }
  168. // continue for all child nodes and assign the created internal nodes as our children
  169. for( unsigned int a = 0; a < pNode->mNumChildren; a++)
  170. {
  171. SceneAnimNode* childNode = CreateNodeTree( pNode->mChildren[a], internalNode);
  172. internalNode->mChildren.push_back( childNode);
  173. }
  174. return internalNode;
  175. }
  176. // ------------------------------------------------------------------------------------------------
  177. // Recursively updates the internal node transformations from the given matrix array
  178. void SceneAnimator::UpdateTransforms( SceneAnimNode* pNode, const std::vector<aiMatrix4x4>& pTransforms)
  179. {
  180. // update node local transform
  181. if( pNode->mChannelIndex != -1)
  182. {
  183. ai_assert( pNode->mChannelIndex < pTransforms.size());
  184. pNode->mLocalTransform = pTransforms[pNode->mChannelIndex];
  185. }
  186. // update global transform as well
  187. CalculateGlobalTransform( pNode);
  188. // continue for all children
  189. for( std::vector<SceneAnimNode*>::iterator it = pNode->mChildren.begin(); it != pNode->mChildren.end(); ++it)
  190. UpdateTransforms( *it, pTransforms);
  191. }
  192. // ------------------------------------------------------------------------------------------------
  193. // Calculates the global transformation matrix for the given internal node
  194. void SceneAnimator::CalculateGlobalTransform( SceneAnimNode* pInternalNode)
  195. {
  196. // concatenate all parent transforms to get the global transform for this node
  197. pInternalNode->mGlobalTransform = pInternalNode->mLocalTransform;
  198. SceneAnimNode* node = pInternalNode->mParent;
  199. while( node)
  200. {
  201. pInternalNode->mGlobalTransform = node->mLocalTransform * pInternalNode->mGlobalTransform;
  202. node = node->mParent;
  203. }
  204. }