bool AnimationImporter::fillLinearMaxTransformationController( Control* maxController, size_t keyCount, const InputArrayType& inputValues, const OutputArrayType& outputValues, ConversionFunctorType inputConversionFunctor, ConversionFunctor* outputConversionFunctors[]) { SuspendAnimate(); AnimateOn(); for ( size_t i = 0; i < keyCount; ++i) { TimeValue keyTime; if ( inputConversionFunctor ) { keyTime = (TimeValue)((*inputConversionFunctor)((float)(inputValues[i]))); } else { keyTime = (TimeValue)(inputValues[i]); } Matrix3 matrixValue; size_t firstMatrixElement = 16*i; Point4 column; column[ 0 ] = convert(outputConversionFunctors[0], (float)outputValues[firstMatrixElement + 0]); column[ 1 ] = convert(outputConversionFunctors[1], (float)outputValues[firstMatrixElement + 1]); column[ 2 ] = convert(outputConversionFunctors[2], (float)outputValues[firstMatrixElement + 2]); column[ 3 ] = convert(outputConversionFunctors[3], (float)outputValues[firstMatrixElement + 3]); matrixValue.SetColumn(0, column); column[ 0 ] = convert(outputConversionFunctors[4], (float)outputValues[firstMatrixElement + 4]); column[ 1 ] = convert(outputConversionFunctors[5], (float)outputValues[firstMatrixElement + 5]); column[ 2 ] = convert(outputConversionFunctors[6], (float)outputValues[firstMatrixElement + 6]); column[ 3 ] = convert(outputConversionFunctors[7], (float)outputValues[firstMatrixElement + 7]); matrixValue.SetColumn(1, column); column[ 0 ] = convert(outputConversionFunctors[8], (float)outputValues[firstMatrixElement + 8]); column[ 1 ] = convert(outputConversionFunctors[9], (float)outputValues[firstMatrixElement + 9]); column[ 2 ] = convert(outputConversionFunctors[10], (float)outputValues[firstMatrixElement + 10]); column[ 3 ] = convert(outputConversionFunctors[11], (float)outputValues[firstMatrixElement + 11]); matrixValue.SetColumn(2, column); SetXFormPacket matrixValuePacket(matrixValue); maxController->SetValue( keyTime, &matrixValuePacket, 1, CTRL_ABSOLUTE); } ResumeAnimate(); return true; }
void FloatMC::EndCapture(Interval record,TimeValue sampSize, KeyReduceStatus *stat) { // Clear any keys out of the record interval cont->DeleteTime(record,TIME_INCLEFT|TIME_INCRIGHT|TIME_NOSLIDE); // Make keys out of the data SuspendAnimate(); AnimateOn(); for (int i=0; i<sampleCount; i++) { TimeValue t = record.Start() + i * sampSize; cont->SetValue(t,&data[i],1,CTRL_ABSOLUTE); if (i%UPDATE_RATE==0) if (stat->Progress(i)!=KEYREDUCE_CONTINUE) goto abort; } abort: ResumeAnimate(); delete[] data; base = 0.0f; }
//from IUnReplaceableControl Control * EulerExposeControl::GetReplacementClone() { Control *control = NewDefaultRotationController(); if(control) { // set key per frame Interval range =GetCOREInterface()->GetAnimRange(); TimeValue tpf = GetTicksPerFrame(); SuspendAnimate(); AnimateOn(); Quat v; for(TimeValue t= range.Start(); t<=range.End();t+=tpf) { GetValue(t,&v,Interval(t,t)); control->SetValue(t,&v,1,CTRL_ABSOLUTE); } ResumeAnimate(); } return control; }
// REMOVEBIPED void RemoveBiped(INode *bipRoot, Interface *theInterface) { SuspendAnimate(); AnimateOn(); // remember Max's default controllers (for the user) ClassDesc* defaultRotCtrl=GetDefaultController(CTRL_ROTATION_CLASS_ID); ClassDesc* defaultPosCtrl=GetDefaultController(CTRL_POSITION_CLASS_ID); ClassDesc* defaultScaleCtrl=GetDefaultController(CTRL_SCALE_CLASS_ID); // change default controllers to linear to create linear controllers // since we have no tan info DllDir* dllDir=&theInterface->GetDllDir(); ClassDirectory* classDir=&dllDir->ClassDir(); ClassDesc* rotCtrl = classDir->FindClass( SClass_ID(CTRL_ROTATION_CLASS_ID), Class_ID(TCBINTERP_ROTATION_CLASS_ID,0)); // was Class_ID(LININTERP_ROTATION_CLASS_ID,0)); ClassDesc* posCtrl = classDir->FindClass( SClass_ID(CTRL_POSITION_CLASS_ID), Class_ID(LININTERP_POSITION_CLASS_ID, 0)); ClassDesc* scaleCtrl = classDir->FindClass( SClass_ID(CTRL_SCALE_CLASS_ID), Class_ID(LININTERP_SCALE_CLASS_ID, 0)); SetDefaultController(CTRL_ROTATION_CLASS_ID, rotCtrl); SetDefaultController(CTRL_POSITION_CLASS_ID, posCtrl); SetDefaultController(CTRL_SCALE_CLASS_ID, scaleCtrl); ProcessNodeRecurse(bipRoot, nil, theInterface); //deinit ResumeAnimate(); // remember Max's default controllers (for the user) SetDefaultController(CTRL_ROTATION_CLASS_ID, defaultRotCtrl); SetDefaultController(CTRL_POSITION_CLASS_ID, defaultPosCtrl); SetDefaultController(CTRL_SCALE_CLASS_ID, defaultScaleCtrl); }
int CMaxAnimationImport::DoImport( const TCHAR* name, ImpInterface* ii, Interface* i, BOOL suppressPrompts) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HWND window = i->GetMAXHWnd(); CFileDialog fileDialog(TRUE, "xsf", 0, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 0, CWnd::FromHandle(window)); if (fileDialog.DoModal() != IDOK) { return IMPEXP_CANCEL; } CString skeleton = fileDialog.GetPathName(); cal3d::RefPtr<CalCoreSkeleton> skel = CalLoader::loadCoreSkeleton(std::string(skeleton)); if (!skel) { MessageBox( window, "Loading skeleton file failed", "Import Cal3D Animation", MB_OK | MB_ICONERROR); return IMPEXP_FAIL; } cal3d::RefPtr<CalCoreAnimation> anim = CalLoader::loadCoreAnimation(name); if (!anim) { MessageBox( window, "Loading animation file failed", "Import Cal3D Animation", MB_OK | MB_ICONERROR); return IMPEXP_FAIL; } typedef std::list<CalCoreTrack*> CoreTrackList; CoreTrackList& trackList = anim->getListCoreTrack(); for (CoreTrackList::iterator itr = trackList.begin(); itr != trackList.end(); ++itr) { CalCoreTrack* track = *itr; int boneId = track->getCoreBoneId(); CalCoreBone* bone = skel->getCoreBone(boneId); if (!bone) continue; INode* node = i->GetINodeByName(bone->getName().c_str()); if (!node) continue; unsigned kfCount = track->getCoreKeyframeCount(); SuspendAnimate(); AnimateOn(); for (unsigned i = 0; i < kfCount; ++i) { CalCoreKeyframe* kf = track->getCoreKeyframe(i); CalQuaternion kf_q = kf->getRotation(); CalVector kf_v = kf->getTranslation(); TimeValue time = SecToTicks(kf->getTime()); Matrix3 tm; tm.IdentityMatrix(); Quat(kf_q.x, kf_q.y, kf_q.z, kf_q.w).MakeMatrix(tm); tm.SetTrans(Point3(kf_v.x, kf_v.y, kf_v.z)); INode* parent = node->GetParentNode(); if (parent) { tm *= parent->GetNodeTM(time); } node->SetNodeTM(time, tm); } ResumeAnimate(); /* typedef std::map<float, CalCoreKeyframe*> KeyMap; KeyMap& keys = track->getMapCoreKeyframe(); int mapsize = sizeof(keys); int size = keys.size(); int idx = 0; for (KeyMap::iterator mi = keys.begin(); mi != keys.end(); ++mi) { Point3 p; CalCoreKeyframe* kf = mi->second; p.x = kf->getTranslation().x; p.y = kf->getTranslation().y; p.z = kf->getTranslation().z; pos->SetValue(SecToTicks(mi->first), &p); } */ /* IKeyControl* kc = GetKeyControlInterface(pos); if (!kc) continue; typedef std::map<float, CalCoreKeyframe*> KeyMap; KeyMap& keys = track->getMapCoreKeyframe(); kc->SetNumKeys(keys.size()); int idx = 0; for (KeyMap::iterator mi = keys.begin(); mi != keys.end(); ++mi) { ITCBPoint3Key key; key.time = SecToTicks(mi->first); key.tens = 0; key.cont = 0; key.bias = 0; key.easeIn = 25.0; key.easeOut = 25.0; key.val.x = mi->second->getTranslation().x; key.val.y = mi->second->getTranslation().y; key.val.z = mi->second->getTranslation().z; kc->SetKey(idx++, &key); } kc->SortKeys(); */ } return IMPEXP_SUCCESS; }
int CMaxAnimationImport::DoImport( const TCHAR* name, ImpInterface* ii, Interface* i, BOOL suppressPrompts) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HWND window = i->GetMAXHWnd(); CFileDialog fileDialog(TRUE, "xsf", 0, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 0, CWnd::FromHandle(window)); if (fileDialog.DoModal() != IDOK) { return IMPEXP_CANCEL; } CString skeleton = fileDialog.GetPathName(); CalCoreSkeletonPtr skel = CalLoader::loadCoreSkeleton(std::string(skeleton)); if (!skel) { MessageBox( window, "Loading skeleton file failed", "Import Cal3D Animation", MB_OK | MB_ICONERROR); return IMPEXP_FAIL; } CalCoreAnimationPtr anim = CalLoader::loadCoreAnimation(name); if (!anim) { MessageBox( window, "Loading animation file failed", "Import Cal3D Animation", MB_OK | MB_ICONERROR); return IMPEXP_FAIL; } // Get the pose information in the animation const std::vector<CalTransform>& poses = anim->getPoses(); unsigned int num_poses = poses.size() / anim->getTrackCount(); // Calculate the time_per_frame incorrectly since the duration for animations // is stored incorrectly. float time_per_frame = anim->getDuration() / num_poses; // Import each track for (unsigned track_id = 0; track_id < anim->getTrackCount(); ++track_id) { // Get the core bone mapped to the animation int bone_id = anim->getBoneAssignment(track_id); CalCoreBone* bone = skel->getCoreBone(bone_id); if (!bone) continue; // Get the max node for the bone INode* node = i->GetINodeByName(bone->getName().c_str()); if (!node) continue; SuspendAnimate(); AnimateOn(); // Add each pose keyframe in the track float keyframe_time = 0.0f; for (unsigned keyframe_index = 0; keyframe_index < num_poses; ++keyframe_index) { // Get the keyframe data const CalTransform& pose_coord_sys = poses[(keyframe_index * anim->getTrackCount()) + track_id]; const CalVector &kf_v = pose_coord_sys.getTranslation(); const CalQuaternion &kf_q = pose_coord_sys.getRotation(); TimeValue time = SecToTicks(keyframe_time); // Convert to Max math Matrix3 tm; tm.IdentityMatrix(); Quat(kf_q.x, kf_q.y, kf_q.z, kf_q.w).MakeMatrix(tm); tm.SetTrans(Point3(kf_v.x, kf_v.y, kf_v.z)); // Convert the transform to world space INode* parent = node->GetParentNode(); if (parent) { tm *= parent->GetNodeTM(time); } // Set the new transform on the node node->SetNodeTM(time, tm); keyframe_time += time_per_frame; } ResumeAnimate(); /* typedef std::map<float, CalCoreKeyframe*> KeyMap; KeyMap& keys = track->getMapCoreKeyframe(); int mapsize = sizeof(keys); int size = keys.size(); int idx = 0; for (KeyMap::iterator mi = keys.begin(); mi != keys.end(); ++mi) { Point3 p; CalCoreKeyframe* kf = mi->second; p.x = kf->getTranslation().x; p.y = kf->getTranslation().y; p.z = kf->getTranslation().z; pos->SetValue(SecToTicks(mi->first), &p); } */ /* IKeyControl* kc = GetKeyControlInterface(pos); if (!kc) continue; typedef std::map<float, CalCoreKeyframe*> KeyMap; KeyMap& keys = track->getMapCoreKeyframe(); kc->SetNumKeys(keys.size()); int idx = 0; for (KeyMap::iterator mi = keys.begin(); mi != keys.end(); ++mi) { ITCBPoint3Key key; key.time = SecToTicks(mi->first); key.tens = 0; key.cont = 0; key.bias = 0; key.easeIn = 25.0; key.easeOut = 25.0; key.val.x = mi->second->getTranslation().x; key.val.y = mi->second->getTranslation().y; key.val.z = mi->second->getTranslation().z; kc->SetKey(idx++, &key); } kc->SortKeys(); */ } return IMPEXP_SUCCESS; }
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()); }