Programming/DirectX12

상하체 애니메이션 분리

LaivY 2022. 3. 1. 22:19

Graduation Project

문제점

if (animationInfo->state == PLAY) // 프레임 진행
{
    Animation ani{};
    if (parentMesh)
        ani = parentMesh->GetAnimations().at(animationInfo->currAnimationName);
    else
        ani = m_animations.at(animationInfo->currAnimationName);
    const float frame{ animationInfo->currTimer / (1.0f / 24.0f) };
    const UINT currFrame{ min(static_cast<UINT>(floorf(frame)), ani.length - 1) };
    const UINT nextFrame{ min(static_cast<UINT>(ceilf(frame)), ani.length - 1) };
    const float t{ frame - static_cast<int>(frame) };

    for (int i = start; i < ani.joints.size(); ++i)
    {
        m_pcbMesh->boneTransformMatrix[i] = Matrix::Interpolate(
        	ani.joints[i].animationTransformMatrix[currFrame],
            	ani.joints[i].animationTransformMatrix[nextFrame],
            	t);
    }
    object->OnAnimation(frame, ani.length, FALSE);
}

기존 클라이언트에서 애니메이션 코드는 위와 같았다.

뼈의 애니메이션 변환 행렬을 최신화 해주는 코드이고 프레임과 프레임 사이를 보간해서 결정한다.

 

 

 

 

 

재장전 애니메이션

애니메이션은 잘 작동한다.

하지만 문제가 하나 있었다. 움직이면서 장전할 수가 없는 것이다.

 

따라서 상체와 하체 따로 애니메이션을 하는 것으로

상체는 재장전하고 하체는 걷는 애니메이션을 할 수 있도록 구현하고자 했다.

 

 

 

 

 

해결 방법

if (AnimationInfo* upperAnimationInfo{ object->GetUpperAnimationInfo() })
{
    start = 20; // 상체는 0~19번 뼈
    if (upperAnimationInfo->state == PLAY)
    {
        Animation animation{};
        if (parentMesh)
            animation = parentMesh->GetAnimations().at(upperAnimationInfo->currAnimationName);
        else
            animation = m_animations.at(upperAnimationInfo->currAnimationName);
        const float frame{ upperAnimationInfo->currTimer / (1.0f / 24.0f) };
        const UINT currFrame{ min(static_cast<UINT>(floorf(frame)), animation.length - 1) };
        const UINT nextFrame{ min(static_cast<UINT>(ceilf(frame)), animation.length - 1) };
        const float t{ frame - static_cast<int>(frame) };

        for (int i = 0; i < start; ++i)
        {
            m_pcbMesh->boneTransformMatrix[i] = Matrix::Interpolate(animation.joints[i].animationTransformMatrix[currFrame],
                                                                    animation.joints[i].animationTransformMatrix[nextFrame],
                                                                    t);
        }
        object->OnAnimation(frame, animation.length, TRUE);
    }
    ...
}

기존에는 애니메이션 정보를 한 개만 갖고있었지만

상체를 따로 애니메이션해주기 위해 두 개로 늘렸다.

 

0~19번 뼈는 상체 애니메이션 변환 행렬로,

나머지 20~(마지막 - 1)번째 뼈는 하체 애니메이션 변환 행렬을 채워서 셰이더로 보내준다.

마지막 뼈는 총의 애니메이션 변환 행렬을 갖고있다.

 

 

 

 

 

움직이면서 재장전하는 애니메이션

총은 아직 하체 애니메이션을 따라가서 어색하게 보인다.

하지만 어렵지않게 고칠 수 있다.

 

 

 

 

 

총을 포함한 상체 애니메이션

총도 상체 애니메이션에 맞게 잘 움직인다.