Пример #1
0
// ***************************************************************************
bool CExportNel::getNELUnHeritFatherScale(INode &node)
{
	// Default.
	bool	ret= false;


	/* If my parent exist, and if my parent is a BipedNode, always suppose I must unherit scale.
		This is because Biped NodeTM always have a Scale 1,1,1. Hence Sons bones do not herit scale.
	*/
	INode	*parentNode= node.GetParentNode();
	if(parentNode && isBipedNode(*parentNode) )
	{
		ret= true;
	}
	// Else, test the std way.
	else
	{
		// Get the TM controler
		Control *c;
		c = node.GetTMController();

		// If a TM controler exist
		if (c)
		{
			// Get the inherit flags
			DWORD flags=c->GetInheritanceFlags();

			// Unherit scale if all scale inherit flags are cleared
			ret= (flags&(INHERIT_SCL_X|INHERIT_SCL_Y|INHERIT_SCL_Z))!=0;
		}
	}

	return ret;
}
Пример #2
0
// ***************************************************************************
bool CExportNel::isBipedNode(INode &node)
{
	bool	ret= false;
	Control	*c= node.GetTMController();
	if( c && (
		c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID ||
		c->ClassID() == BIPBODY_CONTROL_CLASS_ID ))
		ret= true;

	return ret;
}
Пример #3
0
void SkeletonExporter::export_camera(INode *node)
{
  Control *c;
  int size_key;
  float camera_znear, camera_zfar;
  CameraState cs;
//  Interval valid = FOREVER;
  ObjectState os;
  CameraObject *cam;
  GenCamera *gencam;
  float roll0;
  Matrix3 mat;
  Point3 row;

  os = node->EvalWorldState(0);
  cam = (CameraObject *)os.obj;
  gencam = (GenCamera *)os.obj;
  if (gencam->Type() != TARGETED_CAMERA)
  {
	 fprintf(fTXT, "Only targeted camera are supported!\n\n");
	 return;
  }

  fprintf(fTXT, "Targeted camera found\n");
  write_chunk_header(fA3D, TARGETED_CAMERA_ID, node->GetName(), 40);
  if (makeRAY) write_chunk_header(fRAY, TARGETED_CAMERA_ID, node->GetName(), 40);

  INode* target = node->GetTarget();
  fprintf(fTXT, "Name : %s\n", node->GetName());
  cam->EvalCameraState(0, FOREVER, &cs);

  // ------------------  salviamo znear e zfar  ----------------------
  camera_znear=2;
  camera_zfar=2000;
  if (cs.manualClip)
  {
	camera_znear=cs.hither;
	camera_zfar=cs.yon;
  }
  fprintf(fTXT, "Znear = %f \n", camera_znear);
  fwrite(&camera_znear, sizeof(float), 1, fA3D);
  if (makeRAY) fwrite(&camera_znear, sizeof(float), 1, fRAY);
  fprintf(fTXT, "Zfar = %f \n", camera_zfar);
  fwrite(&camera_zfar, sizeof(float), 1, fA3D);
  if (makeRAY) fwrite(&camera_zfar, sizeof(float), 1, fRAY);

  // -----------------  salviamo l'angolo di FOV  --------------------
  fprintf(fTXT, "FOV (rad) = %f \n", cs.fov);
  fwrite(&cs.fov, sizeof(float), 1, fA3D);
  if (makeRAY) fwrite(&cs.fov, sizeof(float), 1, fRAY);

  // ------------------  salviamo l'angolo di roll  ------------------
  c=node->GetTMController()->GetRollController();
  c->GetValue(0, &roll0, FOREVER);	
  fprintf(fTXT, "Roll (rad) = %f \n", roll0);
  fwrite(&roll0, sizeof(float), 1, fA3D);
  if (makeRAY) fwrite(&roll0, sizeof(float), 1, fRAY);

  // salviamo la posizione nel mondo
  mat = node->GetNodeTM(0);
  row = mat.GetRow(3);
  fprintf(fTXT, "Camera world position : x=%f, y=%f, z=%f\n", row.x, row.y, row.z);
  write_point3(&row, fA3D);
  if (makeRAY) write_point3(&row, fRAY);

  // ---------  salviamo la posizione del target nel mondo  ----------
  if (target)
  {
    mat = target->GetNodeTM(0);
    row = mat.GetRow(3);
    fprintf(fTXT, "Target world position : x=%f, y=%f, z=%f\n", row.x, row.y, row.z);
    write_point3(&row, fA3D);
    if (makeRAY) write_point3(&row, fRAY);
  }

  
  // esportiamo l'animazione della posizione della camera
  // se ci sono un numero di key > 0
  c=node->GetTMController()->GetPositionController();
  if ((c) && (c->NumKeys()>0))
  {
	 if (IsTCBControl(c)) size_key=36;
	 else
	 if (IsBezierControl(c)) size_key=40;
	 else size_key=16;
	 fprintf(fTXT, "Camera position track present.");
     write_chunk_header(fA3D, POSITION_TRACK_ID,
	                    node->GetName(), 1+2+4+c->NumKeys()*size_key);
     export_point3_track(c, 1, fA3D);
     if (makeRAY) write_chunk_header(fRAY, POSITION_TRACK_ID,
	                    node->GetName(), 1+2+4+c->NumKeys()*size_key);
     if (makeRAY) export_point3_track(c, 1, fRAY);
  }

  // -----  esportiamo l'animazione della posizione del target  ------
  if (target)
  {
    c=target->GetTMController()->GetPositionController();
    if ((c) && (c->NumKeys()>0))
	{
	  if (IsTCBControl(c)) size_key=36;
	  else
	  if (IsBezierControl(c)) size_key=40;
	  else size_key=16;
	  fprintf(fTXT, "Target position track present.");
	  write_chunk_header(fA3D, CAMERA_TARGET_TRACK_ID,
		                 node->GetName(), 1+2+4+c->NumKeys()*size_key);
	  export_point3_track(c, 1, fA3D);

	  if (makeRAY) write_chunk_header(fRAY, CAMERA_TARGET_TRACK_ID,
		                 node->GetName(), 1+2+4+c->NumKeys()*size_key);
	  if (makeRAY) export_point3_track(c, 1, fRAY);
	}
  }

  // ---------------  esportiamo le tracce di FOV  -------------------
  c=gencam->GetFOVControl();
  if ((c) && (c->NumKeys()>0))
  {
	 if (IsTCBControl(c)) size_key=28;
	 else
	 if (IsBezierControl(c)) size_key=16;
	 else size_key=8;
	 fprintf(fTXT, "Camera FOV track present.");
     write_chunk_header(fA3D, CAMERA_FOV_TRACK_ID,
	                    node->GetName(), 1+2+4+c->NumKeys()*size_key);
     export_float_track(c, 1, fA3D);  // radianti
     if (makeRAY) write_chunk_header(fRAY, CAMERA_FOV_TRACK_ID,
	                    node->GetName(), 1+2+4+c->NumKeys()*size_key);
     if (makeRAY) export_float_track(c, 1, fRAY);  // radianti
  }


  // ---------------  esportiamo le tracce di roll  ------------------
  c=node->GetTMController()->GetRollController();
  if ((c) && (c->NumKeys()>0))
  {
	 if (IsTCBControl(c)) size_key=28;
	 else
	 if (IsBezierControl(c)) size_key=16;
	 else size_key=8;
	 fprintf(fTXT, "Camera roll track present.");
     write_chunk_header(fA3D, CAMERA_ROLL_TRACK_ID,
	                    node->GetName(), 1+2+4+c->NumKeys()*size_key);
     export_float_track(c, 1, fA3D); // radianti

     if (makeRAY) write_chunk_header(fRAY, CAMERA_ROLL_TRACK_ID,
	                    node->GetName(), 1+2+4+c->NumKeys()*size_key);
     if (makeRAY) export_float_track(c, 1, fRAY); // radianti
  }
  fprintf(fTXT, "\n\n--------------------------------------------------\n");
}
Пример #4
0
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);
		}
	}
}
Пример #5
0
/**
*  @brief
*    Writes the scene node modifiers
*/
void PLSceneNode::WriteModifiers(XmlElement &cSceneElement, const String &sApplicationDrive, const String &sApplicationDir)
{
	// Is there a 3ds Max node? (no 3ds Max node, no properties)
	INode *pMaxNode = GetMaxNode();
	if (pMaxNode) {
		// Has this 3ds Max node a target?
		if (pMaxNode->GetTarget()) {
			// Write down the scene node modifier
			WriteTargetRotationModifier(cSceneElement, *pMaxNode->GetTarget(), false);
		}

		// Are there any position, rotation, scale keyframes?
		bool bPositionKeyframes = false;
		bool bRotationKeyframes = false;
		bool bScaleKeyframes    = false;

		// Check 3ds Max node controllers
		Control *pTMController = pMaxNode->GetTMController();
		if (pTMController) {
			// Position controller
			Control *pController = pTMController->GetPositionController();
			if (pController) {
				// Are there any position keyframes?
				bPositionKeyframes = PLTools::HasKeyControlInterface(*pController);
				if (!bPositionKeyframes) {
					// Is there a path controller?
					IPathPosition *pPathController = GetIPathConstInterface(pController);
					if (pPathController && pPathController->GetNumTargets() > 0) {
						INode *pTarget = pPathController->GetNode(0);
						if (pTarget) {
							// Get path filename
							const String sPathFilename = PLTools::GetResourceFilename(PLTools::ResourcePath, String(pTarget->GetName()) + ".path");

							// Get the percentage along the path
							float fPercentageAlongPath = 0.0f;
							{
								IParamBlock2 *pIParamBlock2 = pPathController->GetParamBlock(path_params);
								int nRefNum = pIParamBlock2 ? pIParamBlock2->GetControllerRefNum(path_percent) : -1;
								RefTargetHandle cRefTargetHandle = (nRefNum >= 0) ? pIParamBlock2->GetReference(nRefNum) : nullptr;
								if (cRefTargetHandle)
									fPercentageAlongPath = pIParamBlock2->GetFloat(path_percent, 0);
							}

							{ // Add scene node modifier
								XmlElement *pModifierElement = new XmlElement("Modifier");
								pModifierElement->SetAttribute("Class",   "PLScene::SNMPositionPath");
								pModifierElement->SetAttribute("Filename", sPathFilename);
								pModifierElement->SetAttribute("Progress", String::Format("%f", fPercentageAlongPath));

								// [TODO] Any change to setup speed inside 3ds Max?
								static const float fSpeed = 0.03f;
								// Automatic animation playback?
								if (g_SEOptions.bAnimationPlayback)
									pModifierElement->SetAttribute("Speed", String::Format("%f", (pPathController->GetFlip() ? -fSpeed : fSpeed)));
								else
									pModifierElement->SetAttribute("Speed", "0.0");

								// Link modifier element
								cSceneElement.LinkEndChild(*pModifierElement);
							}

							// Follow?
							if (pPathController->GetFollow()) {
								// Add scene node modifier
								XmlElement *pModifierElement = new XmlElement("Modifier");
								pModifierElement->SetAttribute("Class",  "PLScene::SNMRotationMoveDirection");

								// Link modifier element
								cSceneElement.LinkEndChild(*pModifierElement);
							}
						}
					}
				}
			}

			// Rotation controller
			pController = pTMController->GetRotationController();
			if (pController) {
				// Are there any rotation keyframes?
				bRotationKeyframes = PLTools::HasKeyControlInterface(*pController);
				if (!bRotationKeyframes) {
					// Is there a look at controller?
					ILookAtConstRotation *pLookAtController = GetILookAtConstInterface(pController);
					if (pLookAtController && pLookAtController->GetNumTargets() > 0) {
						INode *pTarget = pLookAtController->GetNode(0);
						if (pTarget) {
							// Check look at controller
							bool bFlip = (pLookAtController->GetTargetAxisFlip() != 0);

							// Write down the scene node modifier
							WriteTargetRotationModifier(cSceneElement, *pTarget, bFlip);
						}
					}
				}
			}

			// Scale controller
			pController = pTMController->GetScaleController();
			if (pController) {
				// Are there any scale keyframes?
				bScaleKeyframes = PLTools::HasKeyControlInterface(*pController);
			}
		}

		// Export keyframes?
		if (bPositionKeyframes || bRotationKeyframes || bScaleKeyframes) {
			// Get timing
			Interval cInterval = GetCOREInterface()->GetAnimRange();
			int nTicksPerFrame = GetTicksPerFrame();
			int nFrameCount    = (cInterval.End() - cInterval.Start()) / nTicksPerFrame + 1;

			// Used to detect whether or not something is animated
			Point3 vFirstPos, vFirstScale;
			Quat qFirstRot;
			bool bUsePosition = false, bUseScale = false, bUseRotation = false;

			// Prepare the position chunk
			Chunk cPositionChunk;
			cPositionChunk.SetSemantic(Chunk::Position);
			cPositionChunk.Allocate(Chunk::Float, 3, nFrameCount);
			float *pfPositionData = reinterpret_cast<float*>(cPositionChunk.GetData());

			// Prepare the rotation chunk
			Chunk cRotationChunk;
			cRotationChunk.SetSemantic(Chunk::Rotation);
			cRotationChunk.Allocate(Chunk::Float, 4, nFrameCount);
			float *pfRotationData = reinterpret_cast<float*>(cRotationChunk.GetData());

			// Prepare the scale chunk
			Chunk cScaleChunk;
			cScaleChunk.SetSemantic(Chunk::Scale);
			cScaleChunk.Allocate(Chunk::Float, 3, nFrameCount);
			float *pfScaleData = reinterpret_cast<float*>(cScaleChunk.GetData());

			// Loop through all frames
			int nTime = cInterval.Start();
			for (int nFrame=0; nFrame<nFrameCount; nFrame++, nTime+=nTicksPerFrame) {
				// Get the position, rotation and scale
				Point3 vPos, vScale;
				Quat qRot;
				GetPosRotScale(vPos, qRot, vScale, nTime);

				// First frame?
				if (!nFrame) {
					vFirstPos   = vPos;
					vFirstScale = vScale;
					qFirstRot   = qRot;
				} else {
					if (!vFirstPos.Equals(vPos))
						bUsePosition = true;
					if (!vFirstScale.Equals(vScale))
						bUseScale = true;
					if (!qFirstRot.Equals(qRot))
						bUseRotation = true;
				}

				// Position
				if (bPositionKeyframes && pfPositionData) {
					// Currently ONLY the center of the container the node is in use used to make it relative
					const Point3 vParentWorldSpaceCenter = GetContainer() ? GetContainer()->GetWorldSpaceCenter() : Point3(0.0f, 0.0f, 0.0f);

					// Get the position
					const Point3 vFinalPos = (GetType() != TypeScene && GetType() != TypeCell) ? vPos-vParentWorldSpaceCenter : static_cast<const PLSceneContainer*>(this)->GetWorldSpaceCenter();

					// x
					*pfPositionData = vFinalPos.x;
					pfPositionData++;

					// y
					*pfPositionData = vFinalPos.y;
					pfPositionData++;

					// z
					*pfPositionData = vFinalPos.z;
					pfPositionData++;
				}

				// Rotation
				if (bRotationKeyframes && pfRotationData) {

					// [TODO] Check this (why do we need it?)
					qRot.Invert();

					// w
					*pfRotationData = qRot.w;
					pfRotationData++;

					// x
					*pfRotationData = qRot.x;
					pfRotationData++;

					// y
					*pfRotationData = qRot.y;
					pfRotationData++;

					// z
					*pfRotationData = qRot.z;
					pfRotationData++;
				}

				// Scale
				if (bScaleKeyframes && pfScaleData) {
					// x
					*pfScaleData = vScale.x;
					pfScaleData++;

					// y
					*pfScaleData = vScale.y;
					pfScaleData++;

					// z
					*pfScaleData = vScale.z;
					pfScaleData++;
				}
			}

			// Create keyframe animation scene node modifiers
			if (bPositionKeyframes && bUsePosition) {
				// [TODO] Better (and safer) filename
				// Save chunk
				const String sPositionKeys = PLTools::GetResourceFilename(PLTools::ResourceKeyframes, String::Format("%s_PositionKeyframes.chunk", GetName().GetASCII()).GetASCII());
				if (SaveChunk(cPositionChunk, sApplicationDrive + sApplicationDir + sPositionKeys)) {
					// Add the modifier
					XmlElement *pModifierElement = new XmlElement("Modifier");

					// Set class attribute
					pModifierElement->SetAttribute("Class", "PLScene::SNMPositionKeyframeAnimation");

					// [TODO] Currently the frame rate is by default always 24
					// Set frames per second attribute
	//				pModifierElement->SetAttribute("FramesPerSecond", GetFrameRate());


					// Automatic animation playback?
					pModifierElement->SetAttribute("Speed", g_SEOptions.bAnimationPlayback ? "1.0" : "0.0");

					// Set keys attribute
					pModifierElement->SetAttribute("Keys", sPositionKeys);

					// Link modifier elements
					cSceneElement.LinkEndChild(*pModifierElement);
				}
			}
			if (bRotationKeyframes && bUseRotation) {
				// [TODO] Better (and safer) filename
				// Save chunk
				const String sRotationKeys = PLTools::GetResourceFilename(PLTools::ResourceKeyframes, String::Format("%s_RotationKeyframes.chunk", GetName().GetASCII()).GetASCII());
				if (SaveChunk(cRotationChunk, sApplicationDrive + sApplicationDir + sRotationKeys)) {
					// Add the modifier
					XmlElement *pModifierElement = new XmlElement("Modifier");

					// Set class attribute
					pModifierElement->SetAttribute("Class", "PLScene::SNMRotationKeyframeAnimation");

					// [TODO] Currently the frame rate is by default always 24
					// Set frames per second attribute
	//				pModifierElement->SetAttribute("FramesPerSecond", GetFrameRate());

					// Automatic animation playback?
					pModifierElement->SetAttribute("Speed", g_SEOptions.bAnimationPlayback ? "1.0" : "0.0");

					// Set keys attribute
					pModifierElement->SetAttribute("Keys", sRotationKeys);

					// Link modifier elements
					cSceneElement.LinkEndChild(*pModifierElement);
				}
			}
			if (bScaleKeyframes && bUseScale) {
				// [TODO] Better (and safer) filename
				// Save chunk
				const String sScaleKeys = PLTools::GetResourceFilename(PLTools::ResourceKeyframes, String::Format("%s_ScaleKeyframes.chunk", GetName().GetASCII()).GetASCII());
				if (SaveChunk(cScaleChunk, sApplicationDrive + sApplicationDir + sScaleKeys)) {
					// Add the modifier
					XmlElement *pModifierElement = new XmlElement("Modifier");

					// Set class attribute
					pModifierElement->SetAttribute("Class", "PLScene::SNMScaleKeyframeAnimation");

					// [TODO] Currently the frame rate is by default always 24
					// Set frames per second attribute
	//				pModifierElement->SetAttribute("FramesPerSecond", GetFrameRate());

					// Automatic animation playback?
					pModifierElement->SetAttribute("Speed", g_SEOptions.bAnimationPlayback ? "1.0" : "0.0");

					// Set keys attribute
					pModifierElement->SetAttribute("Keys", sScaleKeys);

					// Link modifier elements
					cSceneElement.LinkEndChild(*pModifierElement);
				}
			}
		}

		// Use modifiers?
		if (g_SEOptions.bUserPropModifiers) {
			// Check for modifiers
			MSTR sModifier;
			int nIndex = 1;
			TSTR s3dsMaxString;
			sModifier = _T("Mod");
			while (pMaxNode->GetUserPropString(sModifier, s3dsMaxString)) {
				// Add scene node modifier
				XmlElement *pModifierElement = new XmlElement("Modifier");

				// We really NEED a 'Class' attribute!
				bool bClassFound = false;

				// Get all expressions
				static RegEx cExpressionRegEx("\\s*((\\w*\\s*=\\s*\"[^\"]*\")|(\\w*\\s*=\\s*[\\w|]*))");
				const String sString = s3dsMaxString;
				uint32 nExpressionParsePos = 0;
				while (cExpressionRegEx.Match(sString, nExpressionParsePos)) {
					// Get expression
								 nExpressionParsePos = cExpressionRegEx.GetPosition();
					const String sExpression		 = cExpressionRegEx.GetResult(0);

					// Process the found expression
					static RegEx cRegEx("\\s*(\\w*)\\s*=\\s*\"?\\s*([^\"]*)\\s*\"?");
					if (cRegEx.Match(sExpression)) {
						// Get name and value
						const String sName  = cRegEx.GetResult(0);
						const String sValue = cRegEx.GetResult(1);

						// Set attribute
						pModifierElement->SetAttribute(sName, sValue);

						// Class variable already found?
						if (!bClassFound && sName == "Class")
							bClassFound = true;
					}
				}

				// Link modifier element?
				if (bClassFound)
					cSceneElement.LinkEndChild(*pModifierElement);
				else 
					delete pModifierElement;

				// Get next modifier
				sModifier.printf(_T("Mod%d"), nIndex);
				nIndex++;
			}
		}
	}
}
Пример #6
0
// 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);
			}
		}
	}
}