Physique Export Interface

Character Studio Version 1.15 for 3D Studio MAX Version 2.0 
includes direct export functionality for game developers who 
which to import Physique Vertex Assignments into their Game 
Engines.  The SDK for Physique Export is provided by the 
single file: PhyExp.h

Further export functionality will be included in the 
upcoming Character Studio 2.0 Release; however for Release 
1.15 only Rigid Vertex Assignments are supported.

To access the Physique Export you must:

Compile your exporter to include PhyExp.h

Find the Physique modifier within the MAX Scene (example 
code is provided in this doc as well as commented at the 
bottom of PhyExp.h)

Call the Physique Modifier’s GetInterface Method to create a 
Physique Export Interface

From the Physique Export Interface you can create a 
ModContext Export Interface for a particular Object’s Node 
of the given Physique Export Interface.  Remember several 
Objects may share a given PhysiqueModifier (or Modifier in 
General)  The ModContext Export Interface is specific to 
this given Object

From The ModContext Export Interface you can create a Vertex 
Export Interface for each vertex of the given ModContext 
Interface Object.

The Vertex Export Interface method: GetType specifies which 
type of vertex interface you have created (Rigid, 
Deformable, Blended).  This type determines which derived 
class from the base Vertex Export Interface you have.  You 
may then coerce the base vertex interface pointer to the 
appropriate derived class for accessing Physique data from 
the Interface.  NOTE: for Version 1.15 of CS ONLY Rigid 
Vertex Interfaces are supported.

From the Rigid Vertex Interface you can call GetNode to 
return a pointer to the INode to which the given vertex is 
assigned (controlled).

From the Rigid Vertex Interface you can call GetOffsetVector 
to return a Point3 offset vector in the coordinate space of 
the associated INode (returned by GetNode).                         
NOTE: This offset vector is directly in the coordinates of 
the INode, no additional transformations have been applied 
as in the CS 1.1 .VPH file format.



1. Physique Export SDK

The header file PhyExp.h contains the following base classes 
and exported virtual methods:

class IPhysiqueExport :	
Returned by Modifier->GetInterface(I_PHYINTERFACE) 
This is the Physique Export Interface for a given Physique 
Modifier.

Methods:		
	IPhyContextExport *GetContextInterface(INode* nodePtr) 
	Returns a ModContext Export Interface for the ModContext 
	associated with the given INode.

	void ReleaseContextInterface(IPhyContextExport 
*contextExport)
	You must call ReleaseContextInterface to free the 
ModContext Interface
	from memory.


class IPhyContextExport:
Returned by IPhysiqueExport->GetContextInterface(nodePtr)
This is the ModContext Interface associated with the Object 
of the given nodePtr
for the Physique Modifier of the given Physique Export 
Interface.

Methods:

	int GetNumberVertices()
	Returns the number of vertices for the given Physique 
Object.

	void ConvertToRigid(BOOL = TRUE)
	When ConvertToRigid is set to TRUE, all vertices will be 
converted to Rigid Vertices for 	GetVertexInterface.  If 
ConvertToRigid is set to FALSE, then for version 1.15, 
	any non-Rigid vertices will return NULL for 
GetVertexInterface.

	IPhyVertexExport *GetVertexInterface(int i) 
	This will return a Vertex Export Interface for the ith 
vertex of the Mod Context Interface.
	NOTE: rigid vertices will return a RigidVertexExport, all 
other vertices will return NULL, 	unless ConvertToRigid has 
been set to TRUE, in which case all vertices return a 
	RigidVertexExport.

	void ReleaseVertexInterface(IPhyVertexExport 
*vertexExport) 
	You must call ReleaseVertexInterface to free the Vertex 
Interface from memory.


class IPhyVertexExport:
Returned by IPhyContextExport->GetVertexInterface(i)
This is the base class for all Vertex Export Interface class 
for Physique.

Methods:

	int GetVertexType()
	Returns the defined vertex type for the given derived 
Vertex Interface Class.
	NOTE: currently only type RIGID_TYPE are supported: 
IPhyRigidVertex
	
class IPhyRigidVertex : public IPhyVertexExport
Returned for Rigid Vertices by IPhyContextExport-
>GetVertexInterface(i)
This is the derived Vertex Interface class for all Rigid 
Vertex Assignments.

Methods:

	INode *GetNode()
	Returns an INode pointer for the INode (bone/link) to 
which the vertex is assigned.

	Point3 GetOffsetVector()
	Returns the coordinates of the vertex in the local 
coordinates of the associated INode 	pointer from GetNode() 
NOTE: this is NOT THE SAME as the .vph file coordinates. 
	( It is the world coordinates of the vertex transformed 
by the Inverse of the 
	INode->GetNodeTM() )

2. Finding a Physique Modifier

Below is a code example, also found commented in PhyExp.h 
for finding a Physique Modifier
if it exists for a given Inode:

Modifier* FindPhysiqueModifier (INode* nodePtr)
{
	// Get object from node. Abort if no object.
	Object* ObjectPtr = nodePtr->GetObjectRef();
	if (!ObjectPtr) return NULL;
	// Is derived object ?
	if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID)
	{
		// Yes -> Cast.
		IDerivedObject* DerivedObjectPtr = 
static_cast<IDerivedObject*>(ObjectPtr);
		// Iterate over all entries of the modifier stack.
		int ModStackIndex = 0;
		while (ModStackIndex < DerivedObjectPtr-
>NumModifiers())
		{
			// Get current modifier.
			Modifier* ModifierPtr = DerivedObjectPtr-
>GetModifier(ModStackIndex);
			// Is this Physique ?
			if (ModifierPtr->ClassID() == 
Class_ID(PHYSIQUE_CLASS_ID_A, 									      
PHYSIQUE_CLASS_ID_B))
			{
				// Yes -> Exit.
				return ModifierPtr;
			}
			// Next modifier stack entry.
			ModStackIndex++;
		}
	}
	// Not found.
	return NULL;
}






3 - 8. Using the Physique Export Interface 	
Below is a code example using the Physique Export 
Interface:	

void ExportPhysiqueData(TimeValue t, ModContext &mc, 
ObjectState *os, INode *node)
{
	Modifier *phyMod = FindPhysiqueModifier(node);
	if (!phyMod) return;	// Physique Modifier does not exist 
for given Node

	// create a Physique Export Interface for the given 
Physique Modifier
	IPhysiqueExport *phyExport = (IPhysiqueExport 
*)phyMod>GetInterface(I_PHYINTERFACE);

	if (phyExport)
	{
		// create a ModContext Export Interface for the 
specific node of the Physique Modifier
		IPhyContextExport *mcExport = (IPhyContextExport 
*)phyExport->GetContextInterface(node);

		if (mcExport)
		{
			// we convert all vertices to Rigid in this example
			mcExport->ConvertToRigid(TRUE);

			// for each vertex of Object Get the Bone (INode 
pointer) and Offset (Point3)
			for (int i = 0; i < os->obj->NumPoints();  i++)
			{
				IPhyRigidVertex *vtxExport = (IPhyRigidVertex 
*)mcExport->GetVertexInterface(i);
				if (vtxExport)
				{
					INode *Bone = vtxExport->GetNode();
					Point3 Offset = vtxExport->GetOffsetVector();
					// set the Point of the object (to test the 
export is correct)
					os->obj->SetPoint(i, bone->GetNodeTM(t) * 
offset);
					mcExport->ReleaseVertexInterface(vtxExport);
					vtxExport = NULL;
				}
			}
			phyExport->ReleaseContextInterface(mcExport);
		}
		phyMod->ReleaseInterface(I_PHYINTERFACE, phyExport);
	}
}

