Key Animation

Key에 의한 애니메이션은 Sample에 의해 TRS 애니메이션 보다 맥스의 값과 비슷하지만, 실시간으로 계산해야 하는 부담이 있다( 하드웨어 발전으로 인해 최근에는 크게 부담이 없다.). 또한 보간에 대한 정보를 얻기 맥스 SDK 개발자로 등록이 되어 있어야 한다.

맥스에서 지원하는보간 방법은 크게 Tension / Continutiy /Bias (TCB),  베지어,  선형 3가지가 있다.
이들 세가지  형의 컨트롤 정보를 저장하는것에 대해 논의 할 것이다.

기존 Sample에 의해 익스포트 하던 ExportAnimation() 메쏘드를 ExportAnimationSample()로 바꾸고 Key에 의해 지원 되는 애니메이션 정보는 ExportAnimationKeys()에 의해 익스포트 한다. ExportAnimation() 메쏘드 안에서 bSample에 의해 ExportAnimationSample이나 ExportAnimationKeys를 선택한다.

pSubCtrls[0], pSubCtrls[1], pSubCtrls[2]에 의해 위치, 회전, 크기 컨트롤이 정해진다.

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

{

    ............................................

    Control* pNodeCtrl = pNode->GetTMController();

    Control* pSubCtrls[3];

    pSubCtrls[0] = pNodeCtrl->GetPositionController();

    pSubCtrls[1] = pNodeCtrl->GetRotationController();

    pSubCtrls[2] = pNodeCtrl->GetScaleController();

    .............................................

    if (bSample)

    {

        ExportAnimationSample(pNode, iTreeDepth);

    }

    else

    {

        Write(iTreeDepth, "TRS Export: ");

        ExportAnimationKeys(pSubCtrls[0], "Position", iTreeDepth + 1);

        ExportAnimationKeys(pSubCtrls[1], "Rotation", iTreeDepth + 1);

        ExportAnimationKeys(pSubCtrls[2], "Scale", iTreeDepth + 1);

    }

}

맥스 API는 IKeyControl 클래스를 제공한다. 이 클래스는 개발자가 컨트롤러의 키를 추가, 삭제, 검색, 업데이트 할 수 있도록 TCB, 베지어 그리고 선형 키프레임 컨트롤러 인터페이스를 제공한다.

IKeyControl 메쏘드는 사용은 \MAXSDK\INCLUDE\ISTDPLUG.H에 있다. IKeyControl 인터페이스를 얻을려면 다음의 매크로를 사용한다.

#define GetKeyControlInterface(pAnim)
((IKeyControl*)pAnim->GetInterface(I_KEYCONTROL))

이것을 매크로를 사용하면 아래와 같다.

IKeyControl *ikc = GetKeyControlInterface(pAnim)

pAnim은 Animatable 클래스의 포인터로 Animatable 클래스는 애니메이션 되는 모든 오브젝트의 서브 클래스이다.  ikc가 NULL이면 노드이거나 데이터에 접근하는 인터페이스를 제공하지 않는다.

3DSMAX  Class의 계층도는 PDF

3DSMAX  Class의 계층도는 StarUML

void IKeyControl::GetKey(int i,IKey *key)에 의해  key값을 찾는다. key  값은 ClassID에 의해 사용 용도가 달라진다. IKeyControl 에 의해 지원 되는 세가지 컨트롤 타입과 다섯가지의 데이터 형이 있다.

Tension/Continuity/Bias

Bezier

Linear

Class ITCBFloatKey

Class IBezFloatKey

Class ILinFloatKey

Class ITCBPoint3Key

Class IBezPoint3Key

Class ILinPoint3Key

Class ITCBRotKey

 

Class ILinRotKey

 

Class IBezQuatKey

 

Class ITCBScaleKey

Class IBezScaleKey

Class ILinScaleKey

아래 코드를 보면 Class_ID에 의해 ExportAnimation 관련 처리를 별도로 호출해 주고 있다.

        Class_ID clid = pAnim->ClassID();

        switch(clid.PartA())

        {

        case LININTERP_FLOAT_CLASS_ID:

            ExportAnimationKeyLinear<ILinFloatKey>(iKeyControl, iTreeDepth);

            break;

        case LININTERP_POSITION_CLASS_ID:

            ExportAnimationKeyLinear<ILinPoint3Key>(iKeyControl, iTreeDepth);

            break;

        case LININTERP_ROTATION_CLASS_ID:

            ExportAnimationKeyLinear<ILinRotKey>(iKeyControl, iTreeDepth);

            break;

        case LININTERP_SCALE_CLASS_ID:

            ExportAnimationKeyLinear<ILinScaleKey>(iKeyControl, iTreeDepth);

            break;

 

        case HYBRIDINTERP_FLOAT_CLASS_ID:

            ExportAnimationKeyBezier<IBezFloatKey>(iKeyControl, iTreeDepth);

            break;

        case HYBRIDINTERP_POSITION_CLASS_ID:

            ExportAnimationKeyBezier<IBezPoint3Key>(iKeyControl, iTreeDepth);

            break;

        case HYBRIDINTERP_ROTATION_CLASS_ID:

            // The HYBRIDINTERP rotation class is unique in that it doesn't use

            // bezier interpolation: We export this as a simple linear key

            ExportAnimationKeyLinear<IBezQuatKey>(iKeyControl, iTreeDepth);

            break;

        case HYBRIDINTERP_SCALE_CLASS_ID:

            ExportAnimationKeyBezier<IBezScaleKey>(iKeyControl, iTreeDepth);

            break;

 

        case TCBINTERP_FLOAT_CLASS_ID:

            ExportAnimationKeyTCB<ITCBFloatKey>(iKeyControl, iTreeDepth);

            break;

        case TCBINTERP_POSITION_CLASS_ID:

            ExportAnimationKeyTCB<ITCBPoint3Key>(iKeyControl, iTreeDepth);

            break;

        case TCBINTERP_ROTATION_CLASS_ID:

            ExportAnimationKeyTCB<ITCBRotKey>(iKeyControl, iTreeDepth);

            break;

        case TCBINTERP_SCALE_CLASS_ID:

            ExportAnimationKeyTCB<ITCBScaleKey>(iKeyControl, iTreeDepth);

            break;

 

        default:

            // If we hit this, we need to update our exporter to support this controller.

            Write(iTreeDepth, "ERROR: Unknown class exported under KeyFrames: (0x%X, 0x%X)", clid.PartA(), clid.PartB());

            break;

        }

Class_ID에 의해 불려지는 메쏘드 예를 들면 아래와 같다. WriteValue()는 오버로딩된 메쏘드로 다섯가지 데이터형으로 다섯가지의 WriteValue() 메쏘드가 있다.

template<class KeyType>

void maxPluginTest::ExportAnimationKeyLinear(IKeyControl* iKeyControl, int iTreeDepth)

{

    Write(iTreeDepth, "  Linear Interpolation");

    KeyType ioKey;

    for (int i = 0; i < iKeyControl->GetNumKeys(); i++)

    {

        iKeyControl->GetKey(i, &ioKey);

        Write(iTreeDepth, "Key at time %fs:", TicksToSec(ioKey.time));

        WriteValue(iTreeDepth, "    Value: ", ioKey.val);

        //WriteValue()는 오버로딩 메쏘드로 세번째 인자 val에 의해,

        //float, Point, Quat, AngAxis, ScaleValue 다섯개의 데이타 타입이다.

    }

}

 

void maxPluginTest::WriteValue(int indent, const char* pMsg, const Point3& val)

{

    Write(indent, "%sPoint3(%f, %f, %f)", pMsg, val.x, val.y, val.z);

}

베지어 보간 코드는 <MaxDebugRoot>\Core\INTERP.CPP에 있고 TCB 보간은 <MaxDebugRoot>\Core\TCBINTRP.CPP에 있다. 이 코드는 비 등록 개발자는 불가능 하다.  
디버그 SDK에서 더 상세한 설명을 위해서는 고급 디버그 주제 섹션을 참고한다.

 

 

결과) 06key_animation.TXT

소스) maxPluginTest06_keyanimation.zip