Advertisement
IonutCava

AnimationLoader

Apr 28th, 2012
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.29 KB | None | 0 0
  1. #include "Headers/AnimationController.h"
  2. #include "Core/Math/Headers/Quaternion.h"
  3. #include "Hardware/Video/GFXDevice.h"
  4. #include <assimp/scene.h>
  5. using namespace boost;
  6.  
  7. /// there is some type of alignment issue with my mat4 and the aimatrix4x4 class, so the copy must be manually
  8. void TransformMatrix(mat4<F32>& out,const aiMatrix4x4& in){
  9.     if(GFX_DEVICE.getApi() == Direct3D){
  10.         out.element(1,1)=in.a1; out.element(2,1)=in.b1; out.element(3,1)=in.c1; out.element(4,1)=in.d1;
  11.         out.element(1,2)=in.a2; out.element(2,2)=in.b2; out.element(3,2)=in.c2; out.element(4,2)=in.d2;
  12.         out.element(1,3)=in.a3; out.element(2,3)=in.b3; out.element(3,3)=in.c3; out.element(4,3)=in.d3;
  13.         out.element(1,4)=in.a4; out.element(2,4)=in.b4; out.element(3,4)=in.c4; out.element(4,4)=in.d4;
  14.     }else{
  15.         memcpy(out.mat,&in,sizeof(F32) * 16);
  16.     }
  17. }
  18.  
  19. mat4<F32> MultiplyMatAPIDependent(mat4<F32>& a, mat4<F32>& b){
  20.     mat4<F32> ret;
  21.     (GFX_DEVICE.getApi() == Direct3D) ? ret = a * b : ret = b * a;
  22.     return ret;
  23. }
  24.  
  25. // ------------------------------------------------------------------------------------------------
  26. /// Evaluates the animation tracks for a given time stamp.
  27. void AnimationEvaluator::Evaluate( F32 pTime,unordered_map<std::string, Bone*>& bones) {
  28.  
  29.     pTime *= TicksPerSecond;
  30.    
  31.     F32 time = 0.0f;
  32.     if( Duration > 0.0)
  33.         time = fmod( pTime, Duration);
  34.  
  35.     // calculate the transformations for each animation channel
  36.     for( U32 a = 0; a < Channels.size(); a++){
  37.         const AnimationChannel* channel = &Channels[a];
  38.         unordered_map<std::string, Bone*>::iterator bonenode = bones.find(channel->Name);
  39.  
  40.         if(bonenode == bones.end()) {
  41.             D_PRINT_FN("did not find the bone node [ %s ]",channel->Name.c_str());
  42.             continue;
  43.         }
  44.  
  45.         // ******** Position *****
  46.         aiVector3D presentPosition( 0, 0, 0);
  47.         if( channel->mPositionKeys.size() > 0){
  48.             // Look for present frame number.
  49.             //Search from last position if time is after the last time, else from beginning
  50.             // Should be much quicker than always looking from start for the average use case.
  51.             U32 frame = (time >= mLastTime) ? tuple_get_impl<0>(mLastPositions[a]): 0;
  52.             while( frame < channel->mPositionKeys.size() - 1){
  53.                 if( time < channel->mPositionKeys[frame+1].mTime){
  54.                     break;
  55.                 }
  56.                 frame++;
  57.             }
  58.  
  59.             // interpolate between this frame's value and next frame's value
  60.             U32 nextFrame = (frame + 1) % channel->mPositionKeys.size();
  61.    
  62.             const aiVectorKey& key = channel->mPositionKeys[frame];
  63.             const aiVectorKey& nextKey = channel->mPositionKeys[nextFrame];
  64.             D32 diffTime = nextKey.mTime - key.mTime;
  65.             if( diffTime < 0.0)
  66.                 diffTime += Duration;
  67.             if( diffTime > 0) {
  68.                 F32 factor = F32( (time - key.mTime) / diffTime);
  69.                 presentPosition = key.mValue + (nextKey.mValue - key.mValue) * factor;
  70.             } else {
  71.                 presentPosition = key.mValue;
  72.             }
  73.             tuple_get_impl<0>(mLastPositions[a]) = frame;
  74.         }
  75.         // ******** Rotation *********
  76.         aiQuaternion presentRotation( 1, 0, 0, 0);
  77.         if( channel->mRotationKeys.size() > 0)
  78.         {
  79.             U32 frame = (time >= mLastTime) ? tuple_get_impl<1>(mLastPositions[a]) : 0;
  80.             while( frame < channel->mRotationKeys.size()  - 1){
  81.                 if( time < channel->mRotationKeys[frame+1].mTime)
  82.                     break;
  83.                 frame++;
  84.             }
  85.  
  86.             // interpolate between this frame's value and next frame's value
  87.             U32 nextFrame = (frame + 1) % channel->mRotationKeys.size() ;
  88.  
  89.             const aiQuatKey& key = channel->mRotationKeys[frame];
  90.             const aiQuatKey& nextKey = channel->mRotationKeys[nextFrame];
  91.             D32 diffTime = nextKey.mTime - key.mTime;
  92.             if( diffTime < 0.0) diffTime += Duration;
  93.             if( diffTime > 0) {
  94.                 F32 factor = F32( (time - key.mTime) / diffTime);
  95.                 aiQuaternion::Interpolate( presentRotation, key.mValue,
  96.                                nextKey.mValue, factor);
  97.             } else presentRotation = key.mValue;
  98.             tuple_get_impl<1>(mLastPositions[a]) = frame;
  99.         }
  100.  
  101.         // ******** Scaling **********
  102.         aiVector3D presentScaling( 1, 1, 1);
  103.         if( channel->mScalingKeys.size() > 0) {
  104.             U32 frame = (time >= mLastTime) ? tuple_get_impl<2>(mLastPositions[a]) : 0;
  105.             while( frame < channel->mScalingKeys.size() - 1){
  106.                 if( time < channel->mScalingKeys[frame+1].mTime)
  107.                     break;
  108.                 frame++;
  109.             }
  110.  
  111.             presentScaling = channel->mScalingKeys[frame].mValue;
  112.             tuple_get_impl<2>(mLastPositions[a]) = frame;
  113.         }
  114.  
  115.             aiMatrix4x4 mat = aiMatrix4x4( presentRotation.GetMatrix());
  116.  
  117.             mat.a1 *= presentScaling.x; mat.b1 *= presentScaling.x; mat.c1 *= presentScaling.x;
  118.             mat.a2 *= presentScaling.y; mat.b2 *= presentScaling.y; mat.c2 *= presentScaling.y;
  119.             mat.a3 *= presentScaling.z; mat.b3 *= presentScaling.z; mat.c3 *= presentScaling.z;
  120.             mat.a4 = presentPosition.x; mat.b4 = presentPosition.y; mat.c4 = presentPosition.z;
  121.         /// Transpose matrix for D3D
  122.         if(GFX_DEVICE.getApi() == Direct3D){
  123.             mat.Transpose();
  124.         }
  125.         TransformMatrix(bonenode->second->_localTransform, mat);
  126.     }
  127.     mLastTime = time;
  128. }
  129.  
  130. /// this will build the skeleton based on the scene passed to it and CLEAR EVERYTHING
  131. void AnimationController::Init(const aiScene* pScene){
  132.     if(!pScene->HasAnimations()) return;
  133.     Release();
  134.    
  135.     Skeleton = CreateBoneTree( pScene->mRootNode, NULL);
  136.     ExtractAnimations(pScene);
  137.    
  138.     for (U32 i = 0; i < pScene->mNumMeshes;++i){
  139.         const aiMesh* mesh = pScene->mMeshes[i];
  140.         //Skip points and lines ... for now -Ionut
  141.         //ToDo: Fix this -Ionut
  142.         if(mesh->mPrimitiveTypes == aiPrimitiveType_LINE ||
  143.             mesh->mPrimitiveTypes == aiPrimitiveType_POINT ||
  144.             mesh->mNumVertices == 0)
  145.                 continue;
  146.  
  147.         for (U32 n = 0; n < mesh->mNumBones;++n){
  148.             const aiBone* bone = mesh->mBones[n];
  149.             unordered_map<std::string, Bone*>::iterator found = BonesByName.find(bone->mName.data);
  150.             if(found != BonesByName.end()){// FOUND IT!!! woohoo, make sure its not already in the bone list
  151.                 bool skip = false;
  152.                 for(size_t j(0); j< Bones.size(); j++){
  153.                     std::string bname = bone->mName.data;
  154.                     if(Bones[j]->_name == bname) {
  155.                         // already inserted
  156.                         skip = true;
  157.                         break;
  158.                     }
  159.                 }
  160.                 if(!skip){// only insert the bone if it has not already been inserted
  161.                     std::string tes = found->second->_name;
  162.                     TransformMatrix(found->second->_offset, bone->mOffsetMatrix);
  163.                     ///Transpose for D3D
  164.                     if(GFX_DEVICE.getApi() == Direct3D){
  165.                         // transpose their matrix to get in the correct format
  166.                         found->second->_offset.transpose(found->second->_offset);
  167.                     }
  168.                     Bones.push_back(found->second);
  169.                 }
  170.             }
  171.         }
  172.     }
  173.  
  174.     Transforms.resize( Bones.size());
  175.     F32 timestep = 1.0f/30.0f;// 30 per second
  176.     for(size_t i(0); i< Animations.size(); i++){// pre calculate the animations
  177.         SetAnimIndex(i);
  178.         F32 dt = 0;
  179.         for(F32 ticks = 0; ticks < Animations[i].Duration;
  180.             ticks += Animations[i].TicksPerSecond/30.0f){
  181.             dt +=timestep;
  182.             Calculate(dt);
  183.             Animations[i].Transforms.push_back(std::vector<mat4<F32> >());
  184.             std::vector<mat4<F32> >& trans = Animations[i].Transforms.back();
  185.             for( size_t a = 0; a < Transforms.size(); ++a){
  186.  
  187.                 mat4<F32> rotationmat = MultiplyMatAPIDependent(Bones[a]->_offset,Bones[a]->_globalTransform);
  188.  
  189.                 trans.push_back(rotationmat);
  190.             }
  191.  
  192.         }
  193.     }
  194.     D_PRINT_FN("Finished loading animations with [ %d ] bones", Bones.size());
  195. }
  196.  
  197. // ------------------------------------------------------------------------------------------------
  198. /// Calculates the bone matrices for the given mesh.
  199. void AnimationController::CalcBoneMatrices(){
  200.     for( size_t a = 0; a < Transforms.size(); ++a){
  201.         Transforms[a] =  MultiplyMatAPIDependent(Bones[a]->_offset, Bones[a]->_globalTransform);
  202.         /*
  203.         mat4<F32> rotationmat = Transforms[a];
  204.         quat q;
  205.         q.frommatrix(rotationmat);
  206.        
  207.         vec4<F32> dual[2] ;
  208.         UQTtoUDQ( dual, q, Transforms[a].row3_v);
  209.         QuatTransforms[a].row0_v =dual[0];
  210.         QuatTransforms[a].row1_v =dual[1];
  211.         */
  212.     }
  213.  
  214. }
  215.  
  216. // ------------------------------------------------------------------------------------------------
  217. /// Recursively creates an internal node structure matching the current scene and animation.
  218. Bone* AnimationController::CreateBoneTree( aiNode* pNode, Bone* pParent){
  219.     Bone* internalNode = New Bone();// create a node
  220.     internalNode->_name = pNode->mName.data;// get the name of the bone
  221.     //set the parent, in the case this is theroot node, it will be null
  222.     internalNode->_parent = pParent;
  223.  
  224.  
  225.     BonesByName[internalNode->_name] = internalNode;// use the name as a key
  226.     TransformMatrix(internalNode->_localTransform, pNode->mTransformation);
  227.  
  228.     ///Transpose for D3D
  229.     if(GFX_DEVICE.getApi() == Direct3D){
  230.         internalNode->_localTransform.transpose(internalNode->_localTransform);
  231.     }
  232.  
  233.     internalNode->_originalLocalTransform = internalNode->_localTransform;// a copy saved
  234.     CalculateBoneToWorldTransform(internalNode);
  235.  
  236.     // continue for all child nodes and assign the created internal nodes as our children
  237.     for( U32 a = 0; a < pNode->mNumChildren; a++){// recursivly call this function on all children
  238.         internalNode->_children.push_back(CreateBoneTree( pNode->mChildren[a], internalNode));
  239.     }
  240.     return internalNode;
  241. }
  242.  
  243. // ------------------------------------------------------------------------------------------------
  244. /// Calculates the global transformation matrix for the given internal node
  245. void AnimationController::CalculateBoneToWorldTransform(Bone* child){
  246.     child->_globalTransform = child->_localTransform;
  247.     Bone* parent = child->_parent;
  248.     while( parent ){// this will climb the nodes up along through the parents concentating all the matrices to get the Object to World transform, or in this case, the Bone To World transform
  249.         ///For OpenGL : _global = _global * _local;
  250.         ///For Direct3D: _global = _local * _global;
  251.         child->_globalTransform = MultiplyMatAPIDependent(parent->_localTransform,child->_globalTransform);
  252.         parent  = parent->_parent;// get the parent of the bone we are working on
  253.     }
  254. }
  255.  
  256.  
  257. ////--------------------------------- SHADER CODE --------------------///
  258.     ///w - weight value
  259.     float finalWeight = 1.0f - ( boneWeight.x + boneWeight.y + boneWeight.z );
  260.  
  261.     mat4 matTransform  = boneTransforms[int(boneIndex.x)] * boneWeight.x;
  262.          matTransform += boneTransforms[int(boneIndex.y)] * boneWeight.y;
  263.          matTransform += boneTransforms[int(boneIndex.z)] * boneWeight.z;
  264.          matTransform += boneTransforms[int(boneIndex.w)] * finalWeight;
  265.  
  266.     position = mul( matTransform, position);
  267.     normal   = mul( matTransform, vec4(normal.xyz,0.0));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement