//------------------------------------------------------------------------------// // Export the skeleton from a Maxscript call --// //------------------------------------------------------------------------------// bool CMaxInterface::ExportSkeletonFromMaxscriptCall(const std::string& strFilename, bool bShowUI) { // build a skeleton candidate CSkeletonCandidate skeletonCandidate; if(!skeletonCandidate.CreateFromInterfaceFromMaxScriptCall()) return false; //Does the user wants to see the UI and select the bones himself ? if (bShowUI) { // show export wizard sheet CSkeletonExportSheet sheet(_T("Cal3D Skeleton Export"), GetMainWnd()); sheet.SetSkeletonCandidate(&skeletonCandidate); sheet.SetWizardMode(); if(sheet.DoModal() != ID_WIZFINISH) return true; } // build the selected ids of the bone candidates int selectedCount = skeletonCandidate.BuildSelectedId(); if(selectedCount == 0) { theExporter.SetLastError("No bones selected to export.", __FILE__, __LINE__); return false; } // create the core skeleton instance CalCoreSkeletonPtr coreSkeleton = new CalCoreSkeleton; // get bone candidate vector std::vector<CBoneCandidate *>& vectorBoneCandidate = skeletonCandidate.GetVectorBoneCandidate(); // start the progress info StartProgressInfo("Exporting to skeleton file..."); size_t boneCandidateId; int selectedId; for(boneCandidateId = 0, selectedId = 0; boneCandidateId < vectorBoneCandidate.size(); boneCandidateId++) { // get the bone candidate CBoneCandidate *pBoneCandidate; pBoneCandidate = vectorBoneCandidate[boneCandidateId]; // only export selected bone candidates if(pBoneCandidate->IsSelected()) { // update the progress info SetProgressInfo(int(100.0f * (selectedId + 1) / selectedCount)); selectedId++; // allocate new core bone instance CalCoreBone *pCoreBone = new CalCoreBone(pBoneCandidate->GetNode()->GetName()); // get the parent id of the bone candidate int parentId; parentId = skeletonCandidate.GetParentSelectedId(boneCandidateId); // set the parentId pCoreBone->setParentId(parentId); // get the translation and the rotation of the bone candidate CalVector translation; CalQuaternion rotation; skeletonCandidate.GetTranslationAndRotation(boneCandidateId, -1.0f, translation, rotation); // set the translation and rotation pCoreBone->setTranslation(translation); pCoreBone->setRotation(rotation); // get the bone space translation and the rotation of the bone candidate CalVector translationBoneSpace; CalQuaternion rotationBoneSpace; skeletonCandidate.GetTranslationAndRotationBoneSpace(boneCandidateId, -1.0f, translationBoneSpace, rotationBoneSpace); // set the bone space translation and rotation pCoreBone->setTranslationBoneSpace(translationBoneSpace); pCoreBone->setRotationBoneSpace(rotationBoneSpace); // set the core skeleton of the core bone instance pCoreBone->setCoreSkeleton(coreSkeleton.get()); // add the core bone to the core skeleton instance int boneId; boneId = coreSkeleton->addCoreBone(pCoreBone); // adjust child list of parent bone if(parentId != -1) { // get parent core bone CalCoreBone *pParentCoreBone; pParentCoreBone = coreSkeleton->getCoreBone(parentId); if(pParentCoreBone == 0) { theExporter.SetLastError(CalError::getLastErrorText(), __FILE__, __LINE__); delete pCoreBone; StopProgressInfo(); return false; } // add this core bone to the child list of the parent bone pParentCoreBone->addChildId(boneId); } } } // stop the progress info StopProgressInfo(); // save core skeleton to the file if(!CalSaver::saveCoreSkeleton(strFilename, coreSkeleton.get())) { theExporter.SetLastError(CalError::getLastErrorText(), __FILE__, __LINE__); return false; } return true; }
void SGP_MaxInterface::GetTracks( int nNodeCount, INode** nodes, Track** tracks ) { StartProgressInfo(_M("Get node track...")); TimeValue nStartTick = GetStartTick(); TimeValue nEndTick = GetEndTick(); int nTickPerFrame = GetTickPerFrame(); int nFrameCount = 0; for( TimeValue t = nStartTick; t <= nEndTick; t += nTickPerFrame ) nFrameCount++; for( int i = 0; i < nNodeCount; i++ ) { tracks[i]->vectorVisible.resize( nFrameCount ); tracks[i]->vectorTrans.resize( nFrameCount ); tracks[i]->vectorRot.resize( nFrameCount ); tracks[i]->vectorScale.resize( nFrameCount ); Matrix3 matrix = nodes[i]->GetObjTMAfterWSM ( 0 ); bool bMirror = DotProd ( CrossProd ( matrix.GetRow ( 0 ), matrix.GetRow ( 1 ) ), matrix.GetRow ( 2 ) ) < 0.0 ? true : false; tracks[i]->bMirror = bMirror; } TimeValue t = nStartTick; for( int nFrameId = 0; nFrameId < nFrameCount; nFrameId++, t += nTickPerFrame ) { SetProgressInfo( 100.0f*nFrameId/nFrameCount ); for( int nNodeId = 0; nNodeId < nNodeCount; nNodeId++ ) { INode* pNode = nodes[nNodeId]; Track* pTrack = tracks[nNodeId]; Matrix3 tm = pNode->GetNodeTM(t); // The coordinate system of 3DMax9 is Right-X Up-Z Screenin-Y // But coordinate system of SGP Engine is like D3D Right-X Up-Y Screenin-Z // Node Transform Matrix should be swaped. /* If your matrix looks like this: { rx, ry, rz, 0 } { ux, uy, uz, 0 } { lx, ly, lz, 0 } { px, py, pz, 1 } To change it from left to right or right to left, flip it like this: { rx, rz, ry, 0 } { lx, lz, ly, 0 } { ux, uz, uy, 0 } { px, pz, py, 1 } */ Point3 Row0 = tm.GetRow(0); Point3 Row1 = tm.GetRow(1); Point3 Row2 = tm.GetRow(2); Point3 Row3 = tm.GetRow(3); sgp::swapVariables( Row0.y, Row0.z ); sgp::swapVariables( Row1.x, Row2.x ); sgp::swapVariables( Row1.y, Row2.z ); sgp::swapVariables( Row1.z, Row2.y ); sgp::swapVariables( Row3.y, Row3.z ); tm.SetRow(0, Row0); tm.SetRow(1, Row1); tm.SetRow(2, Row2); tm.SetRow(3, Row3); Point3 trans; Quat quat; Point3 scale; { // calculate the translation component Point3 p; p = tm.GetTrans(); trans.x = p.x; trans.y = p.y; trans.z = p.z; scale.x = tm.GetRow(0).Length(); scale.y = tm.GetRow(1).Length(); scale.z = tm.GetRow(2).Length(); tm.NoScale(); // calculate the rotation component Quat q(tm); if( tracks[nNodeId]->bMirror ) { float m[4][3]; memcpy( m, &tm, sizeof(float)*4*3 ); m[0][0] *= -1; m[1][0] *= -1; m[2][0] *= -1; Matrix3 mm(m); Quat q0(mm); q = q0; } quat.x = q.x; quat.y = q.y; quat.z = q.z; quat.w = q.w; } pTrack->vectorTrans.getReference(nFrameId) = trans; pTrack->vectorRot.getReference(nFrameId) = quat; pTrack->vectorScale.getReference(nFrameId) = scale; float fv = pNode->GetVisibility( t ); if( fv == 0 ) pTrack->vectorVisible.getReference(nFrameId) = false; else pTrack->vectorVisible.getReference(nFrameId) = true; } } StopProgressInfo(); }