/** * @brief * Returns whether or not the given controller has any key control interface (x, y, z) */ bool PLTools::HasKeyControlInterface(Control &cController) { // X Control *pXController = cController.GetXController(); if (pXController) { IKeyControl *pKeyControl = GetKeyControlInterface(pXController); if (pKeyControl && pKeyControl->GetNumKeys()) return true; // There's at least one key control interface } // Y Control *pYController = cController.GetYController(); if (pYController) { IKeyControl *pKeyControl = GetKeyControlInterface(pYController); if (pKeyControl && pKeyControl->GetNumKeys()) return true; // There's at least one key control interface } // Z Control *pZController = cController.GetZController(); if (pZController) { IKeyControl *pKeyControl = GetKeyControlInterface(pZController); if (pKeyControl && pKeyControl->GetNumKeys()) return true; // There's at least one key control interface } // Funny... but 'scale controller' (unlike position and rotation) seam to have their own way... IKeyControl *pKeyControl = GetKeyControlInterface(&cController); if (pKeyControl && pKeyControl->GetNumKeys()) return true; // There's at least one key control interface // There are no key control interfaces return false; }
// ADJUSTROTKEYS void AdjustRotKeys(INode *node) { Control *controller = node->GetTMController(); Control *rotControl = controller->GetRotationController(); IKeyControl *rotKeyCont = GetKeyControlInterface(rotControl); int numKeys = rotKeyCont->GetNumKeys(); for(int i = 0; i < numKeys; i++) { ITCBKey key; rotKeyCont->GetKey(i, &key); key.cont = 0; rotKeyCont->SetKey(i, &key); } }
Interval AnimExportUtil::getKeyFramedRotationRange( INode* node3ds, Interval animRange ) { require( node3ds->GetTMController() ); TimeValue start = animRange.Start(); TimeValue end = animRange.End(); // target defines rotation if ( node3ds->GetTarget() ) return Interval( start, start ); Control* cont = node3ds->GetTMController()->GetRotationController(); IKeyControl* ikeys = cont ? GetKeyControlInterface( cont ) : 0; if ( ikeys ) { ITCBRotKey key1; IBezQuatKey key2; ILinRotKey key3; IKey* keyp = 0; if ( cont->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0) ) keyp = &key1; else if ( cont->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0) ) keyp = &key2; else if ( cont->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0) ) keyp = &key3; if ( keyp ) { if ( 0 == ikeys->GetNumKeys() ) return Interval( start, start ); ikeys->GetKey( 0, keyp ); start = keyp->time; ikeys->GetKey( ikeys->GetNumKeys()-1, keyp ); end = keyp->time; } } return Interval( start, end ); }
/** * This method will add all the position keys found in the controller to * the animation path. */ void OSGExp::exportPosKeys(osg::AnimationPath* animationPath, Control* cont){ if (!cont) return; int i; IKeyControl *ikc = GetKeyControlInterface(cont); // TCB position if (ikc && cont->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) { int numKeys; if (numKeys = ikc->GetNumKeys()) { for (i=0; i<numKeys; i++) { ITCBPoint3Key key; ikc->GetKey(i, &key); ; // NOT SUPPORTED YET } } } // Bezier position else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)){ int numKeys; if(numKeys = ikc->GetNumKeys()){ for (i=0; i<numKeys; i++) { IBezPoint3Key key; ikc->GetKey(i, &key); ; // NOT SUPPORTED YET } } } // Linear position else if (ikc && cont->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) { int numKeys; if(numKeys = ikc->GetNumKeys()){ for (i=0; i<numKeys; i++) { ILinPoint3Key key; ikc->GetKey(i, &key); addControlPos(animationPath, (key.time/(float)TIME_TICKSPERSEC),key.val); } } } }
void GR2ImportImpl::ImportRotation(Control* c, TransformTrack& track, float time, GR2Array<granny_real32>& defaultKeys) { if (RotationCurveData* rotData = dynamic_cast<RotationCurveData*>(track.OrientationCurve.ToPointer())) { if (rotData->GetKeyType() == QUADRATIC_KEY) { if (Control *subCtrl = MakeRotation(c, Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID,0), Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID,0))) { IKeyControl *keys = GetKeyControlInterface(subCtrl); if (keys) { NWArray<float> times = rotData->GetKnots(); NWArray<Quat> points = rotData->GetQuatData(); if (times.size() == 0 && points.size() != 0) times = defaultKeys; keys->SetNumKeys(times.size()); for (int i=0; i<times.size(); ++i) { Quat q = points[i]; q.w = -q.w; IBezQuatKey rKey; memset(&rKey, 0, sizeof(rKey)); rKey.time = TimeToFrame(times[i] + time); SetInTanType(rKey.flags, BEZKEY_SLOW); SetOutTanType(rKey.flags, BEZKEY_SLOW); rKey.val = q; keys->SetKey(i, &rKey); } keys->SortKeys(); } } } else if (rotData->GetKeyType() == XYZ_ROTATION_KEY) { if (Control *subCtrl = MakeRotation(c, Class_ID(EULER_CONTROL_CLASS_ID,0), Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID,0))) { IKeyControl *xkeys = GetKeyControlInterface(subCtrl->GetXController()); IKeyControl *ykeys = GetKeyControlInterface(subCtrl->GetYController()); IKeyControl *zkeys = GetKeyControlInterface(subCtrl->GetZController()); if (xkeys && ykeys && zkeys) { NWArray<float> times = rotData->GetKnots(); NWArray<Point3> points = rotData->GetPoint3Data(); if (times.size() == 0 && points.size() != 0) times = defaultKeys; xkeys->SetNumKeys(times.size()); ykeys->SetNumKeys(times.size()); zkeys->SetNumKeys(times.size()); for (int i=0; i<times.size(); ++i) { Point3 &p = points[i]; //Quat q; Point3 p; //EulerToQuat(points[i], q); //q = invQ * q; //QuatToEuler(q, p); IBezFloatKey rKey; memset(&rKey, 0, sizeof(rKey)); rKey.time = TimeToFrame(times[i] + time); SetInTanType(rKey.flags, BEZKEY_SLOW); SetOutTanType(rKey.flags, BEZKEY_SLOW); rKey.val = p.x; xkeys->SetKey(i, &rKey); rKey.val = p.y; ykeys->SetKey(i, &rKey); rKey.val = p.z; zkeys->SetKey(i, &rKey); } xkeys->SortKeys(); ykeys->SortKeys(); zkeys->SortKeys(); } } } } }
void GR2ImportImpl::ImportPosition(Control* c, TransformTrack& track, float time, GR2Array<granny_real32>& defaultKeys) { // Better use linear for now if (Control *subCtrl = MakePositionXYZ(c, Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID,0))) { IKeyControl *xkeys = GetKeyControlInterface(subCtrl->GetXController()); IKeyControl *ykeys = GetKeyControlInterface(subCtrl->GetYController()); IKeyControl *zkeys = GetKeyControlInterface(subCtrl->GetZController()); if (xkeys && ykeys && zkeys) { if (Point3CurveData* posData = dynamic_cast<Point3CurveData*>(track.PositionCurve.ToPointer())) { NWArray<float> times = posData->GetKnots(); NWArray<Point3> points = posData->GetPoint3Data(); if (times.size() == 0 && points.size() != 0) times = defaultKeys; xkeys->SetNumKeys(times.size()); ykeys->SetNumKeys(times.size()); zkeys->SetNumKeys(times.size()); for (int i=0; i<times.size(); ++i) { IBezFloatKey rKey; memset(&rKey, 0, sizeof(rKey)); rKey.time = TimeToFrame(times[i] + time); SetInTanType(rKey.flags, BEZKEY_SLOW); SetOutTanType(rKey.flags, BEZKEY_SLOW); rKey.val = points[i].x; xkeys->SetKey(i, &rKey); rKey.val = points[i].y; ykeys->SetKey(i, &rKey); rKey.val = points[i].z; zkeys->SetKey(i, &rKey); } xkeys->SortKeys(); ykeys->SortKeys(); zkeys->SortKeys(); } } } }
void AsciiExp::DumpScaleKeys(Control* cont, int indentLevel) { if (!cont) return; int i; TSTR indent = GetIndent(indentLevel); IKeyControl *ikc = GetKeyControlInterface(cont); if (ikc && cont->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) { int numKeys = ikc->GetNumKeys(); if (numKeys != 0) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_SCALE_TCB); for (i=0; i<numKeys; i++) { ITCBScaleKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_TCB_SCALE_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%s\t%s\t%s\n"), Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } } else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) { int numKeys = ikc->GetNumKeys(); if (numKeys != 0) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_SCALE_BEZIER); for (i=0; i<numKeys; i++) { IBezScaleKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_BEZIER_SCALE_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%d\n"), Format(key.intan), Format(key.outtan), key.flags); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } } else if (ikc && cont->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) { int numKeys = ikc->GetNumKeys(); if (numKeys != 0) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_SCALE_LINEAR); for (i=0; i<numKeys; i++) { ILinScaleKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), ID_SCALE_KEY, key.time, Format(key.val)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } } }
void AsciiExp::DumpRotKeys(Control* cont, int indentLevel) { if (!cont) return; int i; TSTR indent = GetIndent(indentLevel); IKeyControl *ikc = GetKeyControlInterface(cont); if (ikc && cont->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)) { int numKeys = ikc->GetNumKeys(); if (numKeys != 0) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_ROT_TCB); for (i=0; i<numKeys; i++) { ITCBRotKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_TCB_ROT_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%s\t%s\t%s\n"), Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } } else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)) { int numKeys = ikc->GetNumKeys(); if (numKeys != 0) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_ROT_BEZIER); for (i=0; i<numKeys; i++) { IBezQuatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), // Quaternions are converted to AngAxis when written to file ID_ROT_KEY, key.time, Format(key.val)); // There is no intan/outtan for Quat Rotations } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } } else if (ikc && cont->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) { int numKeys = ikc->GetNumKeys(); if (numKeys != 0) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_ROT_LINEAR); for (i=0; i<numKeys; i++) { ILinRotKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), // Quaternions are converted to AngAxis when written to file ID_ROT_KEY, key.time, Format(key.val)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } } }
// Output float keys if this is a known float controller that // supports key operations. Otherwise we will sample the controller // once for each frame to get the value. void AsciiExp::DumpFloatKeys(Control* cont, int indentLevel) { if (!cont) return; int i; TSTR indent = GetIndent(indentLevel); IKeyControl *ikc = NULL; // If the user wants us to always sample, we will ignore the KeyControlInterface if (!GetAlwaysSample()) ikc = GetKeyControlInterface(cont); // TCB float if (ikc && cont->ClassID() == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_TCB); for (i=0; i<ikc->GetNumKeys(); i++) { ITCBFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_TCB_FLOAT_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%s\t%s\t%s\n"), Format(key.tens), Format(key.cont), Format(key.bias), Format(key.easeIn), Format(key.easeOut)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } // Bezier float else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_BEZIER); for (i=0; i<ikc->GetNumKeys(); i++) { IBezFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s"), indent.data(), ID_BEZIER_FLOAT_KEY, key.time, Format(key.val)); _ftprintf(pStream, _T("\t%s\t%s\t%d\n"), Format(key.intan), Format(key.outtan), key.flags); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } else if (ikc && cont->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID, 0)) { _ftprintf(pStream, _T("%s\t\t%s {\n"), indent.data(), ID_CONTROL_FLOAT_LINEAR); for (i=0; i<ikc->GetNumKeys(); i++) { ILinFloatKey key; ikc->GetKey(i, &key); _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), ID_FLOAT_KEY, key.time, Format(key.val)); } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } else { // Unknown controller, no key interface or sample on demand - // This might be a procedural controller or something else we // don't know about. The last resort is to get the value from the // controller at every n frames. TSTR name; cont->GetClassName(name); TSTR className = FixupName(name); Interface14 *iface = GetCOREInterface14(); UINT codepage = iface-> DefaultTextSaveCodePage(true); const char* className_locale = className.ToCP(codepage); _ftprintf(pStream, _T("%s\t\t%s \"%hs\" {\n"), indent.data(), ID_CONTROL_FLOAT_SAMPLE, className_locale); // If it is animated at all... if (cont->IsAnimated()) { // Get the range of the controller animation Interval range; // Get range of full animation Interval animRange = ip->GetAnimRange(); TimeValue t = cont->GetTimeRange(TIMERANGE_ALL).Start(); float value; // While we are inside the animation... while (animRange.InInterval(t)) { // Sample the controller range = FOREVER; cont->GetValue(t, &value, range); // Set time to start of controller validity interval t = range.Start(); // Output the sample _ftprintf(pStream, _T("%s\t\t\t%s %d\t%s\n"), indent.data(), ID_FLOAT_KEY, t, Format(value)); // If the end of the controller validity is beyond the // range of the animation if (range.End() > cont->GetTimeRange(TIMERANGE_ALL).End()) { break; } else { t = (range.End()/GetTicksPerFrame()+GetKeyFrameStep()) * GetTicksPerFrame(); } } } _ftprintf(pStream, _T("%s\t\t}\n"), indent.data()); } }
void XsiExp::DumpScaleKeys( INode * node, int indentLevel) { Control * cont = node->GetTMController()->GetScaleController(); IKeyControl * ikc = GetKeyControlInterface(cont); INode * parent = node->GetParentNode(); if (!cont || !parent || (parent && parent->IsRootNode()) || !ikc) { // no controller or root node return; } int numKeys = ikc->GetNumKeys(); if (numKeys <= 1) { return; } Object * obj = node->EvalWorldState(0).obj; BOOL isBone = obj && obj->ClassID() == Class_ID(BONE_CLASS_ID, 0) ? TRUE : FALSE; // anim keys header TSTR indent = GetIndent(indentLevel); fprintf(pStream,"%s\tSI_AnimationKey {\n", indent.data()); fprintf(pStream,"%s\t\t1;\n", indent.data()); // 1 means scale keys fprintf(pStream,"%s\t\t%d;\n", indent.data(), numKeys); int t, delta = GetTicksPerFrame(); Matrix3 matrix; AffineParts ap; for (int i = 0; i < numKeys; i++) { // get the key's time if (cont->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) { ITCBRotKey key; ikc->GetKey(i, &key); t = key.time; } else if (cont->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) { IBezQuatKey key; ikc->GetKey(i, &key); t = key.time; } else if (cont->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) { ILinRotKey key; ikc->GetKey(i, &key); t = key.time; } // sample the node's matrix matrix = node->GetNodeTM(t) * Inverse(node->GetParentTM(t)); if (!isBone) { matrix = matrix * topMatrix; } decomp_affine(matrix, &ap); fprintf(pStream, "%s\t\t%d; 3; %.6f, %.6f, %.6f;;%s\n", indent.data(), t / delta, ap.k.x, ap.k.z, ap.k.y, i == numKeys - 1 ? ";\n" : ","); } // anim keys close fprintf(pStream,"%s\t}\n\n", indent.data()); }
void KeyTest() { int i, numKeys; INode * n; Control * c; Quat newQuat, prevQuat; IKeyControl* ikeys; ITCBPoint3Key tcbPosKey; ITCBRotKey tcbRotKey; ITCBScaleKey tcbScaleKey; IBezPoint3Key bezPosKey; IBezQuatKey bezRotKey; IBezScaleKey bezScaleKey; ILinPoint3Key linPosKey; ILinRotKey linRotKey; ILinScaleKey linScaleKey; // Get the first node in the selection set if (!CMaxEnv::singleton().m_pInterace->GetSelNodeCount()) return; n = CMaxEnv::singleton().m_pInterace->GetSelNode(0); // --- Process the position keys --- c = n->GetTMController()->GetPositionController(); ikeys = GetKeyControlInterface(c); if (!ikeys) { // No interface available to access the keys... // Just sample the controller to get the position // data at each key... SampleController(n, c); return; } numKeys = ikeys->GetNumKeys(); DebugPrint(_T("\nThere are %d position key(s)"), numKeys); if (c->ClassID() == Class_ID(TCBINTERP_POSITION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &tcbPosKey); //DebugPrint(_T("\nTCB Position Key: %d=(%.1f, %.1f, %.1f)"), // i, tcbPosKey.val.x, tcbPosKey.val.y, tcbPosKey.val.z); } } else if (c->ClassID() == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &bezPosKey); //DebugPrint(_T("\nBezier Position Key: %d=(%.1f, %.1f, %.1f)"), // i, bezPosKey.val.x, bezPosKey.val.y, bezPosKey.val.z); } } else if (c->ClassID() == Class_ID(LININTERP_POSITION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &linPosKey); //DebugPrint(_T("\nLinear Position Key: %d=(%.1f, %.1f, %.1f)"), // i, linPosKey.val.x, linPosKey.val.y, linPosKey.val.z); } } // --- Process the rotation keys --- c = n->GetTMController()->GetRotationController(); ikeys = GetKeyControlInterface(c); if (!ikeys) return; numKeys = ikeys->GetNumKeys(); //DebugPrint(_T("\nThere are %d rotation key(s)"), numKeys); if (c->ClassID() == Class_ID(TCBINTERP_ROTATION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &tcbRotKey); newQuat = QFromAngAxis(tcbRotKey.val.angle, tcbRotKey.val.axis); if (i) newQuat = prevQuat * newQuat; prevQuat = newQuat; //DebugPrint(_T("\nTCB Rotation Key: %d=(%.1f, %.1f, %.1f, %.1f)"), // i, newQuat.x, newQuat.y, newQuat.z, newQuat.w); } } else if (c->ClassID() == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &bezRotKey); newQuat = bezRotKey.val; if (i) newQuat = prevQuat * newQuat; prevQuat = newQuat; //DebugPrint(_T("\nBezier Rotation Key: %d=(%.1f, %.1f, %.1f, %.1f)"), // i, newQuat.x, newQuat.y, newQuat.z, newQuat.w); } } else if (c->ClassID() == Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &linRotKey); newQuat = linRotKey.val; if (i) newQuat = prevQuat * newQuat; prevQuat = newQuat; //DebugPrint(_T("\nLinear Rotation Key: %d=(%.1f, %.1f, %.1f, %.1f)"), // i, newQuat.x, newQuat.y, newQuat.z, newQuat.w); } } // --- Process the scale keys --- c = n->GetTMController()->GetScaleController(); ikeys = GetKeyControlInterface(c); if (!ikeys) return; numKeys = ikeys->GetNumKeys(); //DebugPrint(_T("\nThere are %d scale key(s)"), numKeys); if (c->ClassID() == Class_ID(TCBINTERP_SCALE_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &tcbScaleKey); //DebugPrint(_T("\nTCB Scale Key: %2d=(%.1f, %.1f, %.1f)"), // i, tcbScaleKey.val.s.x, tcbScaleKey.val.s.y, // tcbScaleKey.val.s.z); } } else if (c->ClassID() == Class_ID(HYBRIDINTERP_SCALE_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &bezScaleKey); //DebugPrint(_T("\nBezier Scale Key: %2d=(%.1f, %.1f, %.1f)"), // i, bezScaleKey.val.s.x, bezScaleKey.val.s.y, // bezScaleKey.val.s.z); } } else if (c->ClassID() == Class_ID(LININTERP_SCALE_CLASS_ID, 0)) { for (i = 0; i < numKeys; i++) { ikeys->GetKey(i, &linScaleKey); DebugPrint(_T("\nLinear Scale Key: %2d=(%.1f, %.1f, %.1f)"), i, linScaleKey.val.s.x, linScaleKey.val.s.y, linScaleKey.val.s.z); } } }
//BOOL TbsAnimObj::IsKnownController(Control* cont) //{ // ulong partA, partB; // // if (!cont) // return FALSE; // ////Listed below are the first ULONG of the 8 byte ID. ////The second ULONG is 0 for all built-in classes (unless noted otherwise). ////For example a Class_ID for a TriObject would read: ////Class_ID(TRIOBJ_CLASS_ID, 0); ////Note that only built-in classes should have the second ULONG equal to 0. ////All plug-in developers should use both ULONGs. // // // // ClassID는 두개의 ULONG변수로 구성되며 내장된 클래스들은 모두 두번째 // // 변수는 0의 값을 갖고 있다. // // 단, 개발자의 플로그인은 두번째 값을 갖게 된다. // partA = cont->ClassID().PartA(); // partB = cont->ClassID().PartB(); // // if (partB != 0x00) // return FALSE; // // switch (partA) { // case TCBINTERP_POSITION_CLASS_ID: // case TCBINTERP_ROTATION_CLASS_ID: // case TCBINTERP_SCALE_CLASS_ID: // case HYBRIDINTERP_POSITION_CLASS_ID: // case HYBRIDINTERP_ROTATION_CLASS_ID: // case HYBRIDINTERP_SCALE_CLASS_ID: // case LININTERP_POSITION_CLASS_ID: // case LININTERP_ROTATION_CLASS_ID: // case LININTERP_SCALE_CLASS_ID: // return TRUE; // } // // return FALSE; //} void TbsAnimObj::DumpFloatKeys(Control* cont, TMesh* pMesh) { if (!cont) return; int i; IKeyControl *ikc = NULL; ikc = GetKeyControlInterface(cont); TAnimTrack Anim; // TCB float if (ikc && cont->ClassID() == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0)) { for (i=0; i<ikc->GetNumKeys(); i++) { ITCBFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->m_VisTrack.push_back( Anim ); } } // Bezier float else if (ikc && cont->ClassID() == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID, 0)) { for (i=0; i<ikc->GetNumKeys(); i++) { IBezFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->m_VisTrack.push_back( Anim ); } } else if (ikc && cont->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID, 0)) { for (i=0; i<ikc->GetNumKeys(); i++) { ILinFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->m_VisTrack.push_back( Anim ); } } else { TSTR name; cont->GetClassName(name); // If it is animated at all... if (cont->IsAnimated()) { // Get the range of the controller animation Interval range; // Get range of full animation Interval animRange = m_p3dsMax->GetAnimRange(); TimeValue t = cont->GetTimeRange(TIMERANGE_ALL).Start(); float value; // While we are inside the animation... while (animRange.InInterval(t)) { // Sample the controller range = FOREVER; cont->GetValue(t, &value, range); // Set time to start of controller validity interval t = range.Start(); Anim.iTick = t; Anim.vValue.x = value; pMesh->m_VisTrack.push_back( Anim ); if (range.End() > cont->GetTimeRange(TIMERANGE_ALL).End()) { break; } else { //t = (range.End()/GetTicksPerFrame()+GetKeyFrameStep()) * GetTicksPerFrame(); t = (range.End()/GetTicksPerFrame()) * GetTicksPerFrame(); } } } } }
// 2. 加载骨骼数据 void M2Importer::importBoneObject() { // Bone Group Header Node INode* groupHeadNode = createGroupHeaderNode(); groupHeadNode->SetGroupHead(TRUE); groupHeadNode->SetGroupMember(FALSE); if (m_modelHeader->nameLength > 1) { TCHAR* modelName = (TCHAR*)(m_m2FileData + m_modelHeader->nameOfs); TCHAR boneGroupName[256]; sprintf(boneGroupName, "%s_bone", modelName); groupHeadNode->SetName(boneGroupName); } else groupHeadNode->SetName("BoneGroup"); // Bone // 一个Bone构造一个Node, 并且加入到组中 ModelBoneDef* boneData = (ModelBoneDef*)(m_m2FileData + m_modelHeader->ofsBones); m_boneNodeList.reserve(m_modelHeader->nBones); for (unsigned int i = 0; i < m_modelHeader->nBones; ++i) { ModelBoneDef& boneDef = boneData[i]; // create bone node HelperObject* obj = (HelperObject*)CreateInstance(HELPER_CLASS_ID, Class_ID(BONE_CLASS_ID, 0)); ImpNode* node = m_impInterface->CreateNode(); TCHAR boneName[256]; sprintf(boneName, "bone_%02d", i); node->SetName(boneName); node->SetPivot(*(Point3*)&(boneDef.pivot)); node->Reference(obj); m_impInterface->AddNodeToScene(node); // 设置变换矩阵 Matrix3 tm; tm.IdentityMatrix(); tm.SetTrans(*(Point3*)&(boneDef.pivot)); node->SetTransform(0, tm); // 添加到组 INode* realINode = node->GetINode(); realINode->SetGroupHead(FALSE); realINode->SetGroupMember(TRUE); groupHeadNode->AttachChild(realINode); // 设置Bone父子关系 realINode->ShowBone(2); m_boneNodeList.push_back(realINode); if (boneDef.parent != -1) { INode* parentNode = m_boneNodeList[boneDef.parent]; parentNode->AttachChild(realINode); } realINode->EvalWorldState(0); } // 导入每根骨骼的关键桢数据 for (unsigned int i = 0; i < m_modelHeader->nBones; ++i) { ModelBoneDef& boneDef = boneData[i]; INode* realINode = m_boneNodeList[i]; Control* tmControl = realINode->GetTMController(); // Position if (boneDef.translation.nKeys) { // 设置动画控制器为线性控制器 Control* posControl = createPositionController(); tmControl->SetPositionController(posControl); unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.translation.ofsTimes); Point3* keyData = (Point3*)(m_m2FileData + boneDef.translation.ofsKeys); // 设置动画时间范围 bool animRangeChanged = false; Interval animRange = m_maxInterface->GetAnimRange(); for (unsigned int j = 0; j < boneDef.translation.nKeys; ++j) { if (timeData[j] < animRange.Start()) { animRange.SetStart(timeData[j]); animRangeChanged = true; } else if (timeData[j] > animRange.End()) { animRange.SetEnd(timeData[j]); animRangeChanged = true; } } if (animRangeChanged) m_maxInterface->SetAnimRange(animRange); // 设置动画关键桢数据 Control* xControl = posControl->GetXController(); IKeyControl* xKeyControl = GetKeyControlInterface(xControl); xKeyControl->SetNumKeys(boneDef.translation.nKeys); Control* yControl = posControl->GetYController(); IKeyControl* yKeyControl = GetKeyControlInterface(yControl); yKeyControl->SetNumKeys(boneDef.translation.nKeys); Control* zControl = posControl->GetZController(); IKeyControl* zKeyControl = GetKeyControlInterface(zControl); zKeyControl->SetNumKeys(boneDef.translation.nKeys); for (unsigned int j = 0; j < boneDef.translation.nKeys; ++j) { // X AnyKey bufX; ILinFloatKey* keyX = reinterpret_cast<ILinFloatKey*>((IKey*)bufX); keyX->time = timeData[j]; keyX->val = keyData[j].x; xKeyControl->AppendKey(keyX); // Y AnyKey bufY; ILinFloatKey* keyY = reinterpret_cast<ILinFloatKey*>((IKey*)bufY); keyY->time = timeData[j]; keyY->val = keyData[j].y; yKeyControl->AppendKey(keyY); // Z AnyKey bufZ; ILinFloatKey* keyZ = reinterpret_cast<ILinFloatKey*>((IKey*)bufZ); keyZ->time = timeData[j]; keyZ->val = keyData[j].z; zKeyControl->AppendKey(keyZ); } } /* // Rotation if (boneDef.rotation.nKeys) { Control* rotControl = createRotationController(); tmControl->SetRotationController(rotControl); unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.rotation.ofsTimes); Quat* keyData = (Quat*)(m_m2FileData + boneDef.rotation.ofsKeys); // 设置动画时间范围 bool animRangeChanged = false; Interval animRange = m_maxInterface->GetAnimRange(); for (unsigned int j = 0; j < boneDef.rotation.nKeys; ++j) { if (timeData[j] < animRange.Start()) { animRange.SetStart(timeData[j]); animRangeChanged = true; } else if (timeData[j] > animRange.End()) { animRange.SetEnd(timeData[j]); animRangeChanged = true; } } if (animRangeChanged) m_maxInterface->SetAnimRange(animRange); // 设置动画关键桢数据 IKeyControl* keyControl = GetKeyControlInterface(rotControl); keyControl->SetNumKeys(boneDef.rotation.nKeys); for (unsigned int j = 0; j < boneDef.rotation.nKeys; ++j) { AnyKey buf; ILinRotKey* key = reinterpret_cast<ILinRotKey*>((IKey*)buf); key->time = timeData[j]; key->val = keyData[j]; keyControl->AppendKey(key); } } */ // Scaling if (boneDef.scaling.nKeys) { Control* scaControl = createScaleController(); tmControl->SetScaleController(scaControl); unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.scaling.ofsTimes); Point3* keyData = (Point3*)(m_m2FileData + boneDef.scaling.ofsKeys); // 设置动画时间范围 bool animRangeChanged = false; Interval animRange = m_maxInterface->GetAnimRange(); for (unsigned int j = 0; j < boneDef.scaling.nKeys; ++j) { if (timeData[j] < animRange.Start()) { animRange.SetStart(timeData[j]); animRangeChanged = true; } else if (timeData[j] > animRange.End()) { animRange.SetEnd(timeData[j]); animRangeChanged = true; } } if (animRangeChanged) m_maxInterface->SetAnimRange(animRange); // 设置动画关键桢数据 IKeyControl* keyControl = GetKeyControlInterface(scaControl); keyControl->SetNumKeys(boneDef.scaling.nKeys); for (unsigned int j = 0; j < boneDef.scaling.nKeys; ++j) { AnyKey buf; ILinScaleKey* key = reinterpret_cast<ILinScaleKey*>((IKey*)buf); key->time = timeData[j]; key->val = ScaleValue(keyData[j]); keyControl->AppendKey(key); } } } }
void bgAnimMax::DumpFloatKeys(Control* pControl, bgMesh* pMesh) { if (!pControl) return; int i; bgAnimTrack Anim; IKeyControl *ikc = NULL; ikc = GetKeyControlInterface(pControl); if (ikc && pControl->ClassID() == Class_ID(TCBINTERP_FLOAT_CLASS_ID, 0)) { for (i = 0; i < ikc->GetNumKeys(); i++) { ITCBFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->AlpTrack.push_back(Anim); } } else if (ikc && pControl->ClassID() == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID, 0)) { for (i = 0; i < ikc->GetNumKeys(); i++) { IBezFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->AlpTrack.push_back(Anim); } } else if (ikc && pControl->ClassID() == Class_ID(LININTERP_FLOAT_CLASS_ID, 0)) { for (i = 0; i < ikc->GetNumKeys(); i++) { ILinFloatKey key; ikc->GetKey(i, &key); Anim.iTick = key.time; Anim.vValue.x = key.val; pMesh->AlpTrack.push_back(Anim); } } else { TSTR name; pControl->GetClassName(name); if (pControl->IsAnimated()) { float value; Interval range; Interval animRange = m_p3DMax->GetAnimRange(); TimeValue t = pControl->GetTimeRange(TIMERANGE_ALL).Start(); while (animRange.InInterval(t)) { range = FOREVER; pControl->GetValue(t, &value, range); t = range.Start(); Anim.iTick = t; Anim.vValue.x = value; pMesh->AlpTrack.push_back(Anim); if (range.End() > pControl->GetTimeRange(TIMERANGE_ALL).End()) { break; } else { t = (range.End() / GetTicksPerFrame()) * GetTicksPerFrame(); } } } } }
void RandKeysUtil::Apply() { BOOL timeMode = iu->GetMajorMode()==TVMODE_EDITTIME; BOOL fcurveMode = iu->GetMajorMode()==TVMODE_EDITFCURVE; Interval iv = iu->GetTimeSelection(); if (!doTime && !doVal) return; theHold.Begin(); // Turn animation on SuspendAnimate(); AnimateOn(); for (int i=0; i<iu->GetNumTracks(); i++) { if ((timeMode||fcurveMode) && !iu->IsSelected(i)) continue; // Get Interfaces Animatable *anim = iu->GetAnim(i); Animatable *client = iu->GetClient(i); int subNum = iu->GetSubNum(i); Control *cont = GetControlInterface(anim); IKeyControl *ikc = GetKeyControlInterface(anim); IKey *key = GetKeyPointer(anim->SuperClassID(),anim->ClassID()); if (!ikc || !cont || !key) continue; if (fcurveMode && !anim->IsCurveSelected()) continue; // Get the param dim float min = negVal, max = posVal; ParamDimension *dim = client->GetParamDimension(subNum); if (dim) { min = dim->UnConvert(min); max = dim->UnConvert(max); } for (int j=0; j<ikc->GetNumKeys(); j++) { // Get the key data ikc->GetKey(j,key); // Check if it's selected if (timeMode && !iv.InInterval(key->time)) continue; if (!timeMode && !(key->flags&IKEY_SELECTED)) continue; // Randomize time if (doTime) { key->time = (int)CompRand( float(key->time-negTime), float(key->time+posTime)); ikc->SetKey(j,key); } } if (doTime) ikc->SortKeys(); for (j=0; j<ikc->GetNumKeys(); j++) { // Get the key data ikc->GetKey(j,key); // Check if it's selected if (timeMode && !iv.InInterval(key->time)) continue; if (!timeMode && !(key->flags&IKEY_SELECTED)) continue; // Randomize value if (doVal) { Point3 pt, ang; Point4 p4; float f; Quat q; ScaleValue s; BOOL doX, doY, doZ, doW; doX = doY = doZ = doW = TRUE; if (!fcurveMode) { if (!(key->flags&IKEY_XSEL)) doX = FALSE; if (!(key->flags&IKEY_YSEL)) doY = FALSE; if (!(key->flags&IKEY_ZSEL)) doZ = FALSE; if (!(key->flags&IKEY_WSEL)) doW = FALSE; } switch (anim->SuperClassID()) { case CTRL_FLOAT_CLASS_ID: cont->GetValue(key->time,&f,FOREVER); f = CompRand(f-min,f+max); cont->SetValue(key->time,&f); break; case CTRL_POSITION_CLASS_ID: case CTRL_POINT3_CLASS_ID: cont->GetValue(key->time,&pt,FOREVER); if (doX) pt.x = CompRand(pt.x-min,pt.x+max); if (doY) pt.y = CompRand(pt.y-min,pt.y+max); if (doZ) pt.z = CompRand(pt.z-min,pt.z+max); cont->SetValue(key->time,&pt); break; case CTRL_POINT4_CLASS_ID: cont->GetValue(key->time,&p4,FOREVER); if (doX) p4.x = CompRand(p4.x-min,p4.x+max); if (doY) p4.y = CompRand(p4.y-min,p4.y+max); if (doZ) p4.z = CompRand(p4.z-min,p4.z+max); if (doW) p4.w = CompRand(p4.w-min,p4.w+max); cont->SetValue(key->time,&p4); break; case CTRL_ROTATION_CLASS_ID: cont->GetValue(key->time,&q,FOREVER); QuatToEuler(q, ang); ang.x = CompRand(ang.x-min,ang.x+max); ang.y = CompRand(ang.y-min,ang.y+max); ang.z = CompRand(ang.z-min,ang.z+max); EulerToQuat(ang,q); cont->SetValue(key->time,&q); break; case CTRL_SCALE_CLASS_ID: cont->GetValue(key->time,&s,FOREVER); if (doX) s.s.x = CompRand(s.s.x-min,s.s.x+max); if (doY) s.s.y = CompRand(s.s.y-min,s.s.y+max); if (doZ) s.s.z = CompRand(s.s.z-min,s.s.z+max); cont->SetValue(key->time,&s); break; } } } } ResumeAnimate(); theHold.Accept(GetString(IDS_RB_RANDOMIZEKEYS)); ip->RedrawViews(ip->GetTime()); }