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
|