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