Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Precompiled Header [ALWAYS ON TOP IN CPP]
- #include "stdafx.h"
- #include "ModelAnimator.h"
- #include "../Diagnostics/Logger.h"
- ModelAnimator::ModelAnimator(MeshFilter* pMeshFilter) :
- m_pMeshFilter(pMeshFilter),
- m_Transforms(vector<XMFLOAT4X4>()),
- m_IsPlaying(false),
- m_Reversed(false),
- m_ClipSet(false),
- m_TickCount(0),
- m_AnimationSpeed(1.0f)
- {
- SetAnimation(0);
- }
- ModelAnimator::~ModelAnimator()
- {
- }
- void ModelAnimator::SetAnimation(UINT clipNumber)
- {
- //Set m_ClipSet to false
- m_ClipSet = false;
- //Check if clipNumber is smaller than the actual m_AnimationClips vector size
- if (clipNumber >= m_pMeshFilter->m_AnimationClips.size() || clipNumber < 0)
- {
- // Call Reset
- Reset();
- // Log a warning with an appropriate message
- Logger::LogWarning(L"Could Not Set Animation Clip Number");
- // return
- return;
- }
- //else
- // Retrieve the AnimationClip from the m_AnimationClips vector based on the given clipNumber
- // Call SetAnimation(AnimationClip clip)
- SetAnimation(m_pMeshFilter->m_AnimationClips[clipNumber]);
- }
- void ModelAnimator::SetAnimation(wstring clipName)
- {
- //Set m_ClipSet to false
- m_ClipSet = false;
- //Iterate the m_AnimationClips vector and search for an AnimationClip with the given name (clipName)
- auto found = find_if(m_pMeshFilter->m_AnimationClips.begin(), m_pMeshFilter->m_AnimationClips.end(),
- [clipName](AnimationClip a)
- {
- return clipName == a.Name;
- });
- //If found,
- if (found != m_pMeshFilter->m_AnimationClips.end())
- {
- // Call SetAnimation(Animation Clip) with the found clip
- SetAnimation(*found);
- return;
- }
- //Else
- // Call Reset
- Reset();
- // Log a warning with an appropriate message
- Logger::LogWarning(L"Could Not Find Animation Clip With This Name: " + clipName);
- }
- void ModelAnimator::SetAnimation(AnimationClip clip)
- {
- //Set m_ClipSet to true
- m_ClipSet = true;
- //Set m_CurrentClip
- m_CurrentClip = clip;
- //Call Reset(false)
- Reset(false);
- }
- void ModelAnimator::Reset(bool pause)
- {
- //If pause is true, set m_IsPlaying to false
- if (pause == true)
- {
- m_IsPlaying = false;
- }
- //Set m_TickCount to zero
- m_TickCount = 0;
- //Set m_AnimationSpeed to 1.0f
- m_AnimationSpeed = 1.0f;
- //If m_ClipSet is true
- if (m_ClipSet == true)
- {
- // Retrieve the BoneTransform from the first Key from the current clip (m_CurrentClip)
- auto idk = m_CurrentClip.Keys[0].BoneTransforms;
- // Refill the m_Transforms vector with the new BoneTransforms (have a look at vector::assign)
- m_Transforms.assign(idk.begin(), idk.end());
- }
- //Else
- else
- {
- // Create an IdentityMatrix
- // Refill the m_Transforms vector with this IdenityMatrix (Amount = BoneCount) (have a look at vector::assign)
- XMFLOAT4X4 idm =
- { 1,0,0,0,
- 0,1,0,0,
- 0,0,1,0,
- 0,0,0,1 };
- m_Transforms.assign(m_pMeshFilter->m_BoneCount, idm);
- }
- }
- void ModelAnimator::Update(const GameContext& gameContext)
- {
- //We only update the transforms if the animation is running and the clip is set
- if (m_IsPlaying && m_ClipSet)
- {
- //1.
- //Calculate the passedTicks (see the lab document)
- auto passedTicks = gameContext.pGameTime->GetElapsed()* m_CurrentClip.TicksPerSecond * m_AnimationSpeed;
- //Make sure that the passedTicks stay between the m_CurrentClip.Duration bounds (fmod)
- passedTicks = fmod(passedTicks, m_CurrentClip.Duration);
- //2.
- //IF m_Reversed is true
- if (m_Reversed == true)
- {
- // Subtract passedTicks from m_TickCount
- m_TickCount -= passedTicks;
- // If m_TickCount is smaller than zero, add m_CurrentClip.Duration to m_TickCount
- m_TickCount += m_TickCount < 0 ? m_CurrentClip.Duration : 0;
- }
- else //ELSE
- {
- // Add passedTicks to m_TickCount
- m_TickCount += passedTicks;
- // if m_TickCount is bigger than the clip duration, subtract the duration from m_TickCount
- m_TickCount -= m_TickCount > m_CurrentClip.Duration ? m_CurrentClip.Duration : 0;
- }
- //3.
- //Find the enclosing keys
- AnimationKey keyA = m_CurrentClip.Keys[0], keyB = m_CurrentClip.Keys[0];
- //Iterate all the keys of the clip and find the following keys:
- //keyA > Closest Key with Tick before/smaller than m_TickCount
- //keyB > Closest Key with Tick after/bigger than m_TickCount
- for (size_t i = 0; i < m_CurrentClip.Keys.size(); i++)
- {
- auto curr = m_CurrentClip.Keys[i];
- if (curr.Tick < m_TickCount && curr.Tick > keyA.Tick)
- {
- keyA = curr;
- keyB = m_CurrentClip.Keys[i+1];
- }
- }
- //4.
- //Interpolate between keys
- //Figure out the BlendFactor (See lab document)
- float blend = (m_TickCount - keyA.Tick) / keyB.Tick;
- //Clear the m_Transforms vector
- m_Transforms.clear();
- //FOR every boneTransform in a key (So for every bone)
- auto bones = GetBoneTransforms();
- for (int i = 0; i < keyA.BoneTransforms.size(); ++i)
- {
- // Retrieve the transform from keyA (transformA)
- auto transformA = keyA.BoneTransforms[i];
- // Retrieve the transform from keyB (transformB)
- auto transformB = keyB.BoneTransforms[i];
- // Decompose both transforms
- // Lerp between all the transformations (Position, Scale, Rotation)
- // Compose a transformation matrix with the lerp-results
- // Add the resulting matrix to the m_Transforms vector
- XMVECTOR scaleA, posA, rotA,
- scaleB, posB, rotB,
- scaleC, posC, rotC;
- XMMatrixDecompose(&scaleA, &rotA, &posA, XMLoadFloat4x4(&transformA));
- XMMatrixDecompose(&scaleB, &rotB, &posB, XMLoadFloat4x4(&transformB));
- scaleC = XMVectorLerp(scaleA, scaleB, blend);
- posC = XMVectorLerp(posA, posB, blend);
- rotC = XMQuaternionSlerp(rotA, rotB, blend);
- XMFLOAT4X4 mat;
- XMStoreFloat4x4(
- &mat,
- XMMatrixScalingFromVector(scaleC)*
- XMMatrixRotationQuaternion(rotC) *
- XMMatrixTranslationFromVector(posC)
- );
- m_Transforms.push_back(mat);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement