//------------------------------------------------------------------------------//
// 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;
}
示例#2
0
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();
}