ABOUT ME

-

  • 상하체 애니메이션 분리
    Programming/DirectX12 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)번째 뼈는 하체 애니메이션 변환 행렬을 채워서 셰이더로 보내준다.

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

     

     

     

     

     

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

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

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

     

     

     

     

     

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

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

    댓글