现在的位置: 首页 > 综合 > 正文

Dx高级动画制作 关键帧动画源码

2014年10月09日 ⁄ 综合 ⁄ 共 14476字 ⁄ 字号 评论关闭

#include "SkeletalAnim.h"    
   
cAnimation::cAnimation()   
{   
  m_Name = NULL;   
  m_Bone = NULL;   
  m_Next = NULL;   
   
  m_NumTranslationKeys = 0;   
  m_NumScaleKeys       = 0;   
  m_NumRotationKeys    = 0;   
  m_NumMatrixKeys      = 0;   
   
  m_TranslationKeys = NULL;   
  m_ScaleKeys       = NULL;   
  m_RotationKeys    = NULL;   
  m_MatrixKeys      = NULL;   
}   
   
cAnimation::~cAnimation()   
{   
  delete [] m_Name; m_Name = NULL;   
  delete m_Next;    m_Next = NULL;   
  delete [] m_TranslationKeys;   
  delete [] m_ScaleKeys;   
  delete [] m_RotationKeys;   
  delete [] m_MatrixKeys;   
}   
   
cAnimationSet::cAnimationSet()   
{   
  m_Name          = NULL;   
  m_Length        = 0;   
  m_Next          = NULL;   
  m_NumAnimations = 0;   
  m_Animations    = NULL;   
}   
   
cAnimationSet::~cAnimationSet()   
{   
  delete [] m_Name;    m_Name = NULL;   
  delete m_Next;       m_Next = NULL;   
  delete m_Animations; m_Animations = NULL;   
}   
   
cAnimationCollection::cAnimationCollection()   
{   
  m_NumAnimationSets = 0;   
  m_AnimationSets    = NULL;   
}   
   
cAnimationCollection::~cAnimationCollection()   
{   
  Free();   
}   
   
BOOL cAnimationCollection::ParseObject(                     \   
                   IDirectXFileData *pDataObj,                \   
                   IDirectXFileData *pParentDataObj,          \   
                   DWORD Depth,                               \   
                   void **Data, BOOL Reference)   
{   
  const GUID *Type = GetObjectGUID(pDataObj);   
  DWORD i;   
   
  // Check if template is AnimationSet type    
  if(*Type == TID_D3DRMAnimationSet) {   
   
    // Create and link in a cAnimationSet object    
    cAnimationSet *AnimSet = new cAnimationSet();   
    AnimSet->m_Next = m_AnimationSets;   
    m_AnimationSets = AnimSet;   
   
    // Increase # of animation sets    
    m_NumAnimationSets++;   
   
    // Set animation set name    
    AnimSet->m_Name = GetObjectName(pDataObj);   
  }   
   
  // Check if template is Animation type    
  if(*Type == TID_D3DRMAnimation && m_AnimationSets) {   
   
    // Add a cAnimation class to top-level cAnimationSet    
    cAnimation *Anim = new cAnimation();   
    Anim->m_Next = m_AnimationSets->m_Animations;   
    m_AnimationSets->m_Animations = Anim;   
   
    // Increase # of animations    
    m_AnimationSets->m_NumAnimations++;   
  }   
   
  // Check if a frame reference inside animation template    
  if(*Type == TID_D3DRMFrame && Reference == TRUE &&          \   
                             m_AnimationSets &&               \   
                             m_AnimationSets->m_Animations) {   
   
    // Make sure parent object is an Animation template    
    if(pParentDataObj && *GetObjectGUID(pParentDataObj) ==  \   
                                        TID_D3DRMAnimation) {   
   
      // Get name of frame and store it as animation    
      m_AnimationSets->m_Animations->m_Name =                 \   
                                  GetObjectName(pDataObj);   
    }   
   
    // Don't process child of reference frames    
    return TRUE;   
  }   
   
  // Check if template is AnimationKey type    
  if(*Type == TID_D3DRMAnimationKey && m_AnimationSets &&     \   
                            m_AnimationSets->m_Animations) {   
   
    // Get a pointer to top-level animation object    
    cAnimation *Anim = m_AnimationSets->m_Animations;   
   
    // Get a data pointer    
    DWORD *DataPtr = (DWORD*)GetObjectData(pDataObj, NULL);   
   
    // Get key type    
    DWORD Type = *DataPtr++;   
   
    // Get # of keys to follow    
    DWORD NumKeys = *DataPtr++;   
   
    // Branch based on key type    
    switch(Type) {   
      case 0: // Rotation    
        delete [] Anim->m_RotationKeys;   
        Anim->m_NumRotationKeys = NumKeys;   
        Anim->m_RotationKeys = new                            \   
                             cAnimationQuaternionKey[NumKeys];   
        for(i=0;i<NumKeys;i++) {   
          // Get time    
          Anim->m_RotationKeys[i].m_Time = *DataPtr++;   
          if(Anim->m_RotationKeys[i].m_Time >                 \   
                                   m_AnimationSets->m_Length)   
            m_AnimationSets->m_Length =                       \   
                              Anim->m_RotationKeys[i].m_Time;   
   
          // Skip # keys to follow (should be 4)    
          DataPtr++;   
   
          // Get rotational values    
          float *fPtr = (float*)DataPtr;   
          Anim->m_RotationKeys[i].m_quatKey.w = *fPtr++;   
          Anim->m_RotationKeys[i].m_quatKey.x = *fPtr++;   
          Anim->m_RotationKeys[i].m_quatKey.y = *fPtr++;   
          Anim->m_RotationKeys[i].m_quatKey.z = *fPtr++;   
          DataPtr+=4;   
        }   
        break;   
   
      case 1: // Scaling    
        delete [] Anim->m_ScaleKeys;   
        Anim->m_NumScaleKeys = NumKeys;   
        Anim->m_ScaleKeys = new cAnimationVectorKey[NumKeys];   
        for(i=0;i<NumKeys;i++) {   
          // Get time    
          Anim->m_ScaleKeys[i].m_Time = *DataPtr++;   
          if(Anim->m_ScaleKeys[i].m_Time >                    \   
                                   m_AnimationSets->m_Length)   
            m_AnimationSets->m_Length =                       \   
                                 Anim->m_ScaleKeys[i].m_Time;   
   
          // Skip # keys to follow (should be 3)    
          DataPtr++;   
   
          // Get scale values    
          D3DXVECTOR3 *vecPtr = (D3DXVECTOR3*)DataPtr;   
          Anim->m_ScaleKeys[i].m_vecKey = *vecPtr;   
          DataPtr+=3;   
        }   
        break;   
   
      case 2: // Translation    
        delete [] Anim->m_TranslationKeys;   
        Anim->m_NumTranslationKeys = NumKeys;   
        Anim->m_TranslationKeys = new                         \   
                                cAnimationVectorKey[NumKeys];   
        for(i=0;i<NumKeys;i++) {   
          // Get time    
          Anim->m_TranslationKeys[i].m_Time = *DataPtr++;   
          if(Anim->m_TranslationKeys[i].m_Time >              \   
                                   m_AnimationSets->m_Length)   
            m_AnimationSets->m_Length =                       \   
                           Anim->m_TranslationKeys[i].m_Time;   
   
          // Skip # keys to follow (should be 3)    
          DataPtr++;   
   
          // Get translation values    
          D3DXVECTOR3 *vecPtr = (D3DXVECTOR3*)DataPtr;   
          Anim->m_TranslationKeys[i].m_vecKey = *vecPtr;   
          DataPtr+=3;   
        }   
        break;   
   
      case 4: // Transformation matrix    
        delete [] Anim->m_MatrixKeys;   
        Anim->m_NumMatrixKeys = NumKeys;   
        Anim->m_MatrixKeys = new cAnimationMatrixKey[NumKeys];   
        for(i=0;i<NumKeys;i++) {   
          // Get time    
          Anim->m_MatrixKeys[i].m_Time = *DataPtr++;   
   
          if(Anim->m_MatrixKeys[i].m_Time >                   \   
                                  m_AnimationSets->m_Length)   
            m_AnimationSets->m_Length =                       \   
                               Anim->m_MatrixKeys[i].m_Time;   
   
          // Skip # keys to follow (should be 16)    
          DataPtr++;   
   
          // Get matrix values    
          D3DXMATRIX *mPtr = (D3DXMATRIX *)DataPtr;   
          Anim->m_MatrixKeys[i].m_matKey = *mPtr;   
          DataPtr += 16;   
        }   
        break;   
    }   
  }   
   
  return ParseChildObjects(pDataObj, Depth, Data, Reference);   
}   
   
BOOL cAnimationCollection::Load(char *Filename)   
{   
  // Free a prior loaded collection    
  Free();   
   
  // Parse the file    
  return Parse(Filename);   
}   
   
void cAnimationCollection::Free()   
{   
  m_NumAnimationSets = 0;   
  delete m_AnimationSets; m_AnimationSets = NULL;   
}   
   
void cAnimationCollection::Map(D3DXFRAME_EX *RootFrame)   
{   
  // Go through each animation set    
  cAnimationSet *AnimSet = m_AnimationSets;   
  while(AnimSet != NULL) {   
   
    // Go through each animation object    
    cAnimation *Anim = AnimSet->m_Animations;   
    while(Anim != NULL) {   
   
      // Go through all frames and look for match    
      Anim->m_Bone = RootFrame->Find(Anim->m_Name);   
   
      // Go to next animation object    
      Anim = Anim->m_Next;   
    }   
   
    // Go to next animation set object    
    AnimSet = AnimSet->m_Next;   
  }   
}   
   
void cAnimationCollection::Update(char *AnimationSetName,     \   
                                  DWORD Time, BOOL Loop)   
{   
  cAnimationSet *AnimSet = m_AnimationSets;   
   
  // Look for matching animation set name if used    
  if(AnimationSetName) {   
   
    // Find matching animation set name    
    while(AnimSet != NULL) {   
   
      // Break when match found    
      if(!stricmp(AnimSet->m_Name, AnimationSetName))   
        break;   
   
      // Go to next animation set object    
      AnimSet = AnimSet->m_Next;   
    }   
  }   
   
  // Return no set found    
  if(AnimSet == NULL)   
    return;   
   
  // Bounds time to animation length    
  if(Time > AnimSet->m_Length)   
    Time = (Loop==TRUE)?Time%(AnimSet->m_Length+1):AnimSet->m_Length;   
   
  // Go through each animation    
  cAnimation *Anim = AnimSet->m_Animations;   
  while(Anim) {   
   
    // Only process if it's attached to a bone    
    if(Anim->m_Bone) {   
   
      // Reset transformation    
      D3DXMatrixIdentity(&Anim->m_Bone->TransformationMatrix);   
   
      // Apply various matrices to transformation    
   
      // Scaling    
      if(Anim->m_NumScaleKeys && Anim->m_ScaleKeys) {   
   
        // Loop for matching scale key    
        DWORD Key1 = 0, Key2 = 0;   
        for(DWORD i=0;i<Anim->m_NumScaleKeys;i++) {   
          if(Time >= Anim->m_ScaleKeys[i].m_Time)   
            Key1 = i;   
        }   
   
        // Get 2nd key number    
        Key2 = (Key1>=(Anim->m_NumScaleKeys-1))?Key1:Key1+1;   
   
        // Get difference in keys' times    
        DWORD TimeDiff = Anim->m_ScaleKeys[Key2].m_Time-   
                         Anim->m_ScaleKeys[Key1].m_Time;   
        if(!TimeDiff)   
          TimeDiff = 1;   
   
        // Calculate a scalar value to use    
        float Scalar = (float)(Time - Anim->m_ScaleKeys[Key1].m_Time) / (float)TimeDiff;   
   
        // Calculate interpolated scale values    
        D3DXVECTOR3 vecScale = Anim->m_ScaleKeys[Key2].m_vecKey -    
                               Anim->m_ScaleKeys[Key1].m_vecKey;   
        vecScale *= Scalar;   
        vecScale += Anim->m_ScaleKeys[Key1].m_vecKey;   
   
        // Create scale matrix and combine with transformation    
        D3DXMATRIX matScale;   
        D3DXMatrixScaling(&matScale, vecScale.x, vecScale.y, vecScale.z);   
        Anim->m_Bone->TransformationMatrix *= matScale;   
      }   
   
      // Rotation    
      if(Anim->m_NumRotationKeys && Anim->m_RotationKeys) {   
   
        // Loop for matching rotation key    
        DWORD Key1 = 0, Key2 = 0;   
        for(DWORD i=0;i<Anim->m_NumRotationKeys;i++) {   
          if(Time >= Anim->m_RotationKeys[i].m_Time)   
            Key1 = i;   
        }   
   
        // Get 2nd key number    
        Key2 = (Key1>=(Anim->m_NumRotationKeys-1))?Key1:Key1+1;   
   
        // Get difference in keys' times    
        DWORD TimeDiff = Anim->m_RotationKeys[Key2].m_Time-   
                         Anim->m_RotationKeys[Key1].m_Time;   
        if(!TimeDiff)   
          TimeDiff = 1;   
   
        // Calculate a scalar value to use    
        float Scalar = (float)(Time - Anim->m_RotationKeys[Key1].m_Time) / (float)TimeDiff;   
   
        // slerp rotation values    
        D3DXQUATERNION quatRotation;   
        D3DXQuaternionSlerp(&quatRotation,   
                            &Anim->m_RotationKeys[Key1].m_quatKey,   
                            &Anim->m_RotationKeys[Key2].m_quatKey,   
                            Scalar);   
   
        // Create rotation matrix and combine with transformation    
        D3DXMATRIX matRotation;   
        D3DXMatrixRotationQuaternion(&matRotation, &quatRotation);   
        Anim->m_Bone->TransformationMatrix *= matRotation;   
      }   
   
      // Translation    
      if(Anim->m_NumTranslationKeys && Anim->m_TranslationKeys) {   
   
        // Loop for matching translation key    
        DWORD Key1 = 0, Key2 = 0;   
        for(DWORD i=0;i<Anim->m_NumTranslationKeys;i++) {   
          if(Time >= Anim->m_TranslationKeys[i].m_Time)   
            Key1 = i;   
        }   
   
        // Get 2nd key number    
        Key2 = (Key1>=(Anim->m_NumTranslationKeys-1))?Key1:Key1+1;   
   
        // Get difference in keys' times    
        DWORD TimeDiff = Anim->m_TranslationKeys[Key2].m_Time-   
                         Anim->m_TranslationKeys[Key1].m_Time;   
        if(!TimeDiff)   
          TimeDiff = 1;   
   
        // Calculate a scalar value to use    
        float Scalar = (float)(Time - Anim->m_TranslationKeys[Key1].m_Time) / (float)TimeDiff;   
   
        // Calculate interpolated vector values    
        D3DXVECTOR3 vecPos = Anim->m_TranslationKeys[Key2].m_vecKey -    
                             Anim->m_TranslationKeys[Key1].m_vecKey;   
        vecPos *= Scalar;   
        vecPos += Anim->m_TranslationKeys[Key1].m_vecKey;   
   
        // Create translation matrix and combine with transformation    
        D3DXMATRIX matTranslation;   
        D3DXMatrixTranslation(&matTranslation, vecPos.x, vecPos.y, vecPos.z);   
        Anim->m_Bone->TransformationMatrix *= matTranslation;   
      }   
   
      // Matrix    
      if(Anim->m_NumMatrixKeys && Anim->m_MatrixKeys) {   
        // Loop for matching matrix key    
        DWORD Key1 = 0, Key2 = 0;   
        for(DWORD i=0;i<Anim->m_NumMatrixKeys;i++) {   
          if(Time >= Anim->m_MatrixKeys[i].m_Time)   
            Key1 = i;   
        }   
   
        // Get 2nd key number    
        Key2 = (Key1>=(Anim->m_NumMatrixKeys-1))?Key1:Key1+1;   
   
        // Get difference in keys' times    
        DWORD TimeDiff = Anim->m_MatrixKeys[Key2].m_Time-   
                         Anim->m_MatrixKeys[Key1].m_Time;   
        if(!TimeDiff)   
          TimeDiff = 1;   
   
        // Calculate a scalar value to use    
        float Scalar = (float)(Time - Anim->m_MatrixKeys[Key1].m_Time) / (float)TimeDiff;   
   
        // Calculate interpolated matrix    
        D3DXMATRIX matDiff = Anim->m_MatrixKeys[Key2].m_matKey -    
                             Anim->m_MatrixKeys[Key1].m_matKey;   
        matDiff *= Scalar;   
        matDiff += Anim->m_MatrixKeys[Key1].m_matKey;   
   
        // Combine with transformation    
        Anim->m_Bone->TransformationMatrix *= matDiff;   
      }   
    }   
   
    // Go to next animation    
    Anim = Anim->m_Next;   
  }   
}   

抱歉!评论已关闭.