TRS Animation

Sample에 의해 TRS 애니메이션 정보를 출력해본다. Sampling에 의해 처리 한다는 것은 일정 시간마다 정보를 추출해낸 샘플을 간단한 보간에 의해 애니메이션 처리하는 것이다. Key에 의한 처리보다 정확하지 않다.

Key에 의한 출력방법보다 keyframe의 수가 많아지고 정확도가 떨어지기는 하지만, 게임내에서 복잡한 보간을 처리하지 않고 간단한 보간( Lerp, Slerp)만으로 처리할 수 있는 장점이 있다.

애니메이션 처리가 들어가면서 코드가 복잡해지기 시작 했다.
코드의 흐름을 보고 넘어 가자.

Export()

ExportTRS()

ExportAnimation()

ExportObject()

Export() 재귀호출

맥스상에서의 1초는 4800 Tick이다.
1초에 5프레임만 저장한다면 0.2초 간격으로 정보를 저장 될 것이다.

현재의 노드가 애니메이션이 되는 노드인지 검사 할려면 GetNodeTM()의 두 번째 인자 값이 FOREVER 인지 체크한다. FOREVER이면 애니메이션이 되지 않는 노드이다.

지금 까지는 노드의 GetNode() 나 GetParent() 메트릭스 값을 얻어 오기 위해 틱값을 준다.

추가되거나 바뀐 코드는 다음과 같다.
TimeValue의 단위는 tick이다.

        void ExportTRS(INode* pNode, int iTreeDepth, TimeValue t = 0);

        void ExportAnimation(INode* pNode, int iTreeDepth);

Export() 메소드에  ExportAnimation()이 추가 되었다.

void maxPluginTest::Export(INode* pNode, int iTreeDepth /* = 0 */)

{

    // First step to export: What are we exporting?

    // Here we are going to export the basic scene tree,

    // identifying each node by name.

 

    MCHAR* pNodeName = pNode->GetName();

    int nChildren = pNode->NumberOfChildren();

 

    // Write out this node as [NodeName] : XX Children

    Write(iTreeDepth, "[%s] : %i children", pNodeName, nChildren);

 

    // Write out this nodes local transform

    ExportTRS(pNode, iTreeDepth);

 

    // Write out the animation (if it this node has any)

    ExportAnimation(pNode, iTreeDepth);

 

    // Write out this nodes object properties

    ExportObject(pNode, iTreeDepth);

 

    // Recursively call the children

    iTreeDepth++;

    for (int i = 0; i < nChildren; i++)

    {

        Export(pNode->GetChildNode(i), iTreeDepth);

    }

}

틱 단위의 시간을 넘겨주는게 추가 되었다.

void maxPluginTest::ExportTRS(INode* pNode, int iTreeDepth, TimeValue t /*=0*/)

{

    // Export the nodes TRS at time t (0 by default)

    Matrix3 tmWorld = pNode->GetNodeTM(t);

    Matrix3 tmParent = pNode->GetParentTM(t);

    Matrix3 tmLocal = tmWorld * Inverse(tmParent);

 

    Write(iTreeDepth, tmLocal);

}

5프레임을 틱단위로 바꾼다.

void maxPluginTest::ExportAnimation(INode* pNode, int iTreeDepth)

{

    // How do we know this node is animated?

    // One way to tell is using validity intervals.

    // If the transform is valid forever, it never changes.

    Interval ivNodeValid = FOREVER;

    pNode->GetNodeTM(0, &ivNodeValid);

    if (ivNodeValid == FOREVER) return;

 

    // Get the time range of the scene in max

    Interval ivAnimRange = GetCOREInterface()->GetAnimRange();

 

    // 0.2 초 간격

    const int iSampleFPS = 5;

    TimeValue tIncrement = SecToTicks(1.0f / iSampleFPS);

 

    // Write out the animations duration

    Write(iTreeDepth, "   TRS Anim Start: %fs, Anim End: %fs", TicksToSec(ivAnimRange.Start()), TicksToSec(ivAnimRange.End()));

 

    // Sample the node over the range, writing out iSampleFPS samples per second

    for (TimeValue t = ivAnimRange.Start(); t < ivAnimRange.End(); t += tIncrement)

    {

        Write(iTreeDepth + 1, "SampleTime: %fs", TicksToSec(t));

        ExportTRS(pNode, iTreeDepth + 1, t);

    }

}

결과) 05animation.TXt

소스) maxPluginTest05_animation.zip