示例#1
0
文件: MaxMesh.cpp 项目: imvu/cal3d
bool CMaxMesh::Create(INode *pINode, Mesh *pIMesh, bool bDelete)
{
    // check for valid mesh
    if(pIMesh == 0)
    {
        theExporter.SetLastError("Invalid handle.", __FILE__, __LINE__);
        return false;
    }

    m_pINode = pINode;
    m_pIMesh = pIMesh;
    m_bDelete = bDelete;

    // recursively create materials
    if(!CreateMaterial(m_pINode->GetMtl())) return false;

    // build all normals if necessary
    m_pIMesh->checkNormals(TRUE);

    // precalculate the object transformation matrix
    m_tm = m_pINode->GetObjectTM(SecToTicks(theExporter.GetInterface()->GetCurrentTime()));

    // try to get the physique modifier
    m_pModifier = FindPhysiqueModifier(pINode);
    if(m_pModifier == 0)
    {
        // try to get the skin modifier
        m_pModifier = FindSkinModifier(pINode);
        if(m_pModifier == 0)
        {
                  m_pModifier = FindMorpherModifier(pINode);
                  if( m_pModifier == 0 ) {
                    m_modifierType = MODIFIER_NONE;
                  }
                  m_modifierType = MODIFIER_MORPHER;
        }
        else
        {
            m_modifierType = MODIFIER_SKIN;
        }
    }
    else
    {
        m_modifierType = MODIFIER_PHYSIQUE;
    }

    return true;
}
示例#2
0
//-----------------------------------------------------------------------------
BOOL CExporter::Capture()
{
	VERIFY				(m_Style!=eExportUndef);
	Modifier*			pPhysique;
	IPhysiqueExport*	pExport;
	IPhyContextExport*	pContext;
	Object*				pObject;

	Matrix3				matMesh;
	Matrix3				matZero;

	if (!m_MeshNode){
		ERR("Select mesh and try again.");
		m_bHasError=TRUE; 
		return FALSE;
	}

	
	pObject				= m_MeshNode->GetObjectRef();
	if (!IsExportableMesh(m_MeshNode,pObject)){
		ERR("Can't receive node references.");
		m_bHasError=TRUE; 
		return FALSE;
	}

	// Get export interface
	pPhysique			= FindPhysiqueModifier(m_MeshNode);
	if (!pPhysique){
		ERR("Can't find Physique modifier.");
		m_bHasError=TRUE; 
		return FALSE;
	}
	pExport		= (IPhysiqueExport *)pPhysique->GetInterface(I_PHYINTERFACE);
	if (!pExport){
		ERR("Can't find Physique interface.");
		m_bHasError=TRUE; 
		return FALSE;
	}

	// Get mesh initial transform (used to mult by the bone matrices)
	int rval = CGINTM(m_MeshNode,pExport->GetInitNodeTM(m_MeshNode, matMesh));
	matZero.Zero();
	if (rval || matMesh.Equals(matZero, 0.0)){
		ERR("Old CS version. Can't export mesh");
		matMesh.IdentityMatrix();
	}

	// Add hierrarhy parts that has no effect on vertices, 
	// but required for hierrarhy stability

	if (eExportMotion==m_Style){
		if (m_AllBones.empty()){
			ERR("Invalid skin object. Bone not found.");
			return FALSE;
		}

		EConsole.ProgressStart((float)m_AllBones.size(),"..Capturing bones");
		for (DWORD i=0; i<m_AllBones.size(); i++){
			AddBone(m_AllBones[i], matMesh, pExport);
			EConsole.ProgressInc();
		}
		EConsole.ProgressEnd();
	}

	bool bRes = TRUE;
	if (eExportSkin==m_Style){
		// For a given Object's INode get a
		// ModContext Interface from the Physique Export Interface:
		pContext = (IPhyContextExport *)pExport->GetContextInterface(m_MeshNode);
		if (!pContext){
			ERR("Can't find Physique context interface.");
			return FALSE;
		}

		// convert to rigid with blending
		pContext->ConvertToRigid(TRUE);
		pContext->AllowBlending	(TRUE);

		// process vertices
		int	numVertices = pContext->GetNumberVertices();
		EConsole.ProgressStart(float(numVertices),"..Capturing vertices");
		for (int iVertex = 0; iVertex < numVertices; iVertex++ ){
			IPhyVertexExport *pVertexExport = (IPhyVertexExport *)pContext->GetVertexInterface(iVertex);
			R_ASSERT(pVertexExport);

			// What kind of vertices are these?
			int iVertexType = pVertexExport->GetVertexType();

			IPhyRigidVertex* pRigidVertex=(IPhyRigidVertex*)pContext->GetVertexInterface(iVertex);
			R_ASSERT					(pRigidVertex);
			switch (iVertexType){
			case RIGID_TYPE:{			
				INode* node				= pRigidVertex->GetNode(); 
				R_ASSERT				(node);
				LPCSTR nm				= node->GetName();
				// get bone and create vertex
				CVertexDef* pVertex		= AddVertex();
				int boneId				= AddBone(node,matMesh,pExport);
				if(BONE_NONE==boneId){
					ERR					("Invalid bone: ",node->GetName());
					bRes				= FALSE;
				}else pVertex->Append	(boneId,1.f);
							}break;
			case RIGID_BLENDED_TYPE:{
				IPhyBlendedRigidVertex*	pBlendedRigidVertex=(IPhyBlendedRigidVertex*)pRigidVertex;
				int cnt					= pBlendedRigidVertex->GetNumberNodes();
				CVertexDef* pVertex		= AddVertex();
				for (int i=0; i<cnt; i++){
					INode* node			= pBlendedRigidVertex->GetNode(i); 
					R_ASSERT			(node);
					LPCSTR nm			= node->GetName();
					// get bone and create vertex
					int boneId			= AddBone(node,matMesh,pExport);
					if(BONE_NONE==boneId){
						ERR				("Invalid bone: ",node->GetName());
						bRes			= FALSE;
					}else pVertex->Append(boneId,pBlendedRigidVertex->GetWeight(i));
				}
									}break;
			}

			// release vertex
			pContext->ReleaseVertexInterface( pRigidVertex );

			EConsole.ProgressInc();

			if (!bRes) break;
		}
		EConsole.ProgressEnd();

		if (!bRes) return FALSE;

		static int remap[3];
		if (U.m_SkinFlipFaces){
			remap[0] = 0;
			remap[1] = 1;
			remap[2] = 2;
		}else{
			remap[0] = 0;
			remap[1] = 2;
			remap[2] = 1;
		}

		// Process mesh
		// Get object from node. Abort if no object.
		Log("..Transforming mesh");
		BOOL		bDeleteTriObject;
		R_ASSERT	(pObject);
		TriObject *	pTriObject	= GetTriObjectFromObjRef(pObject, &bDeleteTriObject);
		if (!pTriObject){
			ERR("Can't create tri object.");
			return FALSE;
		}
		Mesh&		M = pTriObject->mesh;

		// Vertices
		{
			// check match with
			int iNumVert = M.getNumVerts();
			if (!(iNumVert==numVertices && iNumVert==m_Vertices.size()))
			{
				ERR("Non attached vertices found.");
				if (bDeleteTriObject)	delete(pTriObject);
				return FALSE;
			}

			// transform vertices
			for (int i=0; i<iNumVert; i++){
				Point3 P = M.getVert(i);
				Point3 T = matMesh.PointTransform(P);
				T *= m_fGlobalScale;
				m_Vertices[i]->SetPosition(T);
			}
		}

		Log("..Parsing materials");
		// Parse Materials
		m_MtlMain = m_MeshNode->GetMtl();
		R_ASSERT(m_MtlMain);

		DWORD cSubMaterials=m_MtlMain->NumSubMtls();
		if (cSubMaterials < 1) {
			// Count the material itself as a submaterial.
			cSubMaterials = 1;
		}

		// build normals
		M.buildRenderNormals();

		Log("..Converting vertices");
		// our Faces and Vertices
		{
			for (int i=0; i<M.getNumFaces(); i++){
				Face*	gF	= M.faces  + i;
				TVFace*	tF	= M.tvFace + i;

				int m_id = gF->getMatID();
				if (cSubMaterials == 1){
					m_id = 0;
				}else{
					// SDK recommends mod'ing the material ID by the valid # of materials, 
					// as sometimes a material number that's too high is returned.
					m_id %= cSubMaterials;
				}

				st_FACE* nF		= xr_new<st_FACE>();
				nF->m_id		= m_id;
				nF->sm_group	= gF->getSmGroup();
				for (int VVV=0; VVV<3; VVV++){
					int vert_id = gF->v[remap[VVV]];

					CVertexDef	&D	= *(m_Vertices[vert_id]);
					Point3		&UV	= M.tVerts[tF->t[remap[VVV]]];

					st_VERT		v;
					v.Set		(D);
					v.P.set		(D.P); 
					v.SetUV		(UV.x,1-UV.y);
//					v.sm_group	= U.m_SkinSuppressSmoothGroup?0:gF->getSmGroup(); // smooth group
					nF->v[VVV]	= AddVert(v);
				}
				m_ExpFaces.push_back(nF);
			}
		}
		if (bDeleteTriObject)	delete(pTriObject);
	}
	UpdateParenting();

	return bRes;
};
示例#3
0
//=================================================================
// Methods for DumpModelTEP
//
int DumpModelTEP::callback(INode *pnode)
{
	Object*	pobj;
	int	fHasMat = TRUE;

	// clear physique export parameters
	m_mcExport = NULL;
	m_phyExport = NULL;
    m_phyMod = NULL;

	ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!");

	if (::FNodeMarkedToSkip(pnode))
		return TREE_CONTINUE;
	
	int iNode = ::GetIndexOfINode(pnode);
	TSTR strNodeName(pnode->GetName());
	
	// The Footsteps node apparently MUST have a dummy mesh attached!  Ignore it explicitly.
	if (FStrEq((char*)strNodeName, "Bip01 Footsteps"))
		return TREE_CONTINUE;

	// Helper nodes don't have meshes
	pobj = pnode->GetObjectRef();
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
		return TREE_CONTINUE;

	// The model's root is a child of the real "scene root"
	INode *pnodeParent = pnode->GetParentNode();
	BOOL fNodeIsRoot = pnodeParent->IsRootNode( );

	// Get node's material: should be a multi/sub (if it has a material at all)
	Mtl *pmtlNode = pnode->GetMtl();
	if (pmtlNode == NULL)
	{
		return TREE_CONTINUE;
		fHasMat = FALSE;
	}
	else if (!(pmtlNode->ClassID() == Class_ID(MULTI_CLASS_ID, 0) && pmtlNode->IsMultiMtl()))
	{
		// sprintf(st_szDBG, "ERROR--Material on node %s isn't a Multi/Sub-Object", (char*)strNodeName);
		// ASSERT_AND_ABORT(FALSE, st_szDBG);
		fHasMat = FALSE;
	}
	
	// Get Node's object, convert to a triangle-mesh object, so I can access the Faces
	ObjectState os = pnode->EvalWorldState(m_tvToDump);
	pobj = os.obj;
	TriObject *ptriobj;
	BOOL fConvertedToTriObject = 
		pobj->CanConvertToType(triObjectClassID) &&
		(ptriobj = (TriObject*)pobj->ConvertToType(m_tvToDump, triObjectClassID)) != NULL;
	if (!fConvertedToTriObject)
		return TREE_CONTINUE;
	Mesh *pmesh = &ptriobj->mesh;

	// Shouldn't have gotten this far if it's a helper object
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
	{
		sprintf(st_szDBG, "ERROR--Helper node %s has an attached mesh, and it shouldn't.", (char*)strNodeName);
		ASSERT_AND_ABORT(FALSE, st_szDBG);
	}

	// Ensure that the vertex normals are up-to-date
	pmesh->buildNormals();

	// We want the vertex coordinates in World-space, not object-space
	Matrix3 mat3ObjectTM = pnode->GetObjectTM(m_tvToDump);


	// initialize physique export parameters
    m_phyMod = FindPhysiqueModifier(pnode);
    if (m_phyMod)
	{
		// Physique Modifier exists for given Node
	    m_phyExport = (IPhysiqueExport *)m_phyMod->GetInterface(I_PHYINTERFACE);

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

		   if (m_mcExport)
		   {
		       // convert all vertices to Rigid 
                m_mcExport->ConvertToRigid(TRUE);
		   }
		}
	}

	// Dump the triangle face info
	int cFaces = pmesh->getNumFaces();
	for (int iFace = 0; iFace < cFaces; iFace++)
	{
		Face*	pface		= &pmesh->faces[iFace];
		TVFace*	ptvface		= &pmesh->tvFace[iFace];
		DWORD	smGroupFace	= pface->getSmGroup();

		// Get face's 3 indexes into the Mesh's vertex array(s).
		DWORD iVertex0 = pface->getVert(0);
		DWORD iVertex1 = pface->getVert(1);
		DWORD iVertex2 = pface->getVert(2);
		ASSERT_AND_ABORT((int)iVertex0 < pmesh->getNumVerts(), "Bogus Vertex 0 index");
		ASSERT_AND_ABORT((int)iVertex1 < pmesh->getNumVerts(), "Bogus Vertex 1 index");
		ASSERT_AND_ABORT((int)iVertex2 < pmesh->getNumVerts(), "Bogus Vertex 2 index");
		
		// Get the 3 Vertex's for this face
		Point3 pt3Vertex0 = pmesh->getVert(iVertex0);
		Point3 pt3Vertex1 = pmesh->getVert(iVertex1);
		Point3 pt3Vertex2 = pmesh->getVert(iVertex2);

		// Get the 3 RVertex's for this face
		// NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
		RVertex *prvertex0 = pmesh->getRVertPtr(iVertex0);
		RVertex *prvertex1 = pmesh->getRVertPtr(iVertex1);
		RVertex *prvertex2 = pmesh->getRVertPtr(iVertex2);
		
		// Find appropriate normals for each RVertex
		// A vertex can be part of multiple faces, so the "smoothing group"
		// is used to locate the normal for this face's use of the vertex.
		Point3 pt3Vertex0Normal;
		Point3 pt3Vertex1Normal;
		Point3 pt3Vertex2Normal;
		if (smGroupFace) 
		{
			pt3Vertex0Normal = Pt3GetRVertexNormal(prvertex0, smGroupFace);
			pt3Vertex1Normal = Pt3GetRVertexNormal(prvertex1, smGroupFace);
			pt3Vertex2Normal = Pt3GetRVertexNormal(prvertex2, smGroupFace);
		}
		else 
		{
			pt3Vertex0Normal = pmesh->getFaceNormal( iFace );
			pt3Vertex1Normal = pmesh->getFaceNormal( iFace );
			pt3Vertex2Normal = pmesh->getFaceNormal( iFace );
		}
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus orig normal 0" );
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus orig normal 1" );
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus orig normal 2" );
	
		// Get Face's sub-material from node's material, to get the bitmap name.
		// And no, there isn't a simpler way to get the bitmap name, you have to
		// dig down through all these levels.
		TCHAR szBitmapName[256] = "null.bmp";
		if (fHasMat)
		{
			MtlID mtlidFace = pface->getMatID();
			if (mtlidFace >= pmtlNode->NumSubMtls())
			{
				sprintf(st_szDBG, "ERROR--Bogus sub-material index %d in node %s; highest valid index is %d",
					mtlidFace, (char*)strNodeName, pmtlNode->NumSubMtls()-1);
				// ASSERT_AND_ABORT(FALSE, st_szDBG);
				mtlidFace = 0;
			}
			Mtl *pmtlFace = pmtlNode->GetSubMtl(mtlidFace);
			ASSERT_AND_ABORT(pmtlFace != NULL, "NULL Sub-material returned");
 
			if ((pmtlFace->ClassID() == Class_ID(MULTI_CLASS_ID, 0) && pmtlFace->IsMultiMtl()))
			{
				// it's a sub-sub material.  Gads.
				pmtlFace = pmtlFace->GetSubMtl(mtlidFace);			
				ASSERT_AND_ABORT(pmtlFace != NULL, "NULL Sub-material returned");
			}

			if (!(pmtlFace->ClassID() == Class_ID(DMTL_CLASS_ID, 0)))
			{

				sprintf(st_szDBG,
					"ERROR--Sub-material with index %d (used in node %s) isn't a 'default/standard' material [%x].",
					mtlidFace, (char*)strNodeName, pmtlFace->ClassID());
				ASSERT_AND_ABORT(FALSE, st_szDBG);
			}
			StdMat *pstdmtlFace = (StdMat*)pmtlFace;
			Texmap *ptexmap = pstdmtlFace->GetSubTexmap(ID_DI);
			// ASSERT_AND_ABORT(ptexmap != NULL, "NULL diffuse texture")
			if (ptexmap != NULL) 
			{
				if (!(ptexmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)))
				{
					sprintf(st_szDBG,
						"ERROR--Sub-material with index %d (used in node %s) doesn't have a bitmap as its diffuse texture.",
						mtlidFace, (char*)strNodeName);
					ASSERT_AND_ABORT(FALSE, st_szDBG);
				}
				BitmapTex *pbmptex = (BitmapTex*)ptexmap;
				strcpy(szBitmapName, pbmptex->GetMapName());
				TSTR strPath, strFile;
				SplitPathFile(TSTR(szBitmapName), &strPath, &strFile);
				strcpy(szBitmapName,strFile);
			}
		}

		UVVert UVvertex0( 0, 0, 0 );
		UVVert UVvertex1( 1, 0, 0 );
		UVVert UVvertex2( 0, 1, 0 );
		
		// All faces must have textures assigned to them
		if (pface->flags & HAS_TVERTS)
		{
			// Get TVface's 3 indexes into the Mesh's TVertex array(s).
			DWORD iTVertex0 = ptvface->getTVert(0);
			DWORD iTVertex1 = ptvface->getTVert(1);
			DWORD iTVertex2 = ptvface->getTVert(2);
			ASSERT_AND_ABORT((int)iTVertex0 < pmesh->getNumTVerts(), "Bogus TVertex 0 index");
			ASSERT_AND_ABORT((int)iTVertex1 < pmesh->getNumTVerts(), "Bogus TVertex 1 index");
			ASSERT_AND_ABORT((int)iTVertex2 < pmesh->getNumTVerts(), "Bogus TVertex 2 index");

			// Get the 3 TVertex's for this TVFace
			// NOTE: I'm using getRVertPtr instead of getRVert to work around a 3DSMax bug
			UVvertex0 = pmesh->getTVert(iTVertex0);
			UVvertex1 = pmesh->getTVert(iTVertex1);
			UVvertex2 = pmesh->getTVert(iTVertex2);
		}
		else 
		{
			//sprintf(st_szDBG, "ERROR--Node %s has a textureless face.  All faces must have an applied texture.", (char*)strNodeName);
			//ASSERT_AND_ABORT(FALSE, st_szDBG);
		}
		
		/*
		const char *szExpectedExtension = ".bmp";
		if (stricmp(szBitmapName+strlen(szBitmapName)-strlen(szExpectedExtension), szExpectedExtension) != 0)
			{
			sprintf(st_szDBG, "Node %s uses %s, which is not a %s file", (char*)strNodeName, szBitmapName, szExpectedExtension);
			ASSERT_AND_ABORT(FALSE, st_szDBG);
			}
		*/

		// Determine owning bones for the vertices.
		int iNodeV0, iNodeV1, iNodeV2;
		if (m_mcExport)
		{
			// The Physique add-in allows vertices to be assigned to bones arbitrarily
			iNodeV0 = InodeOfPhyVectex( iVertex0 );
			iNodeV1 = InodeOfPhyVectex( iVertex1 );
			iNodeV2 = InodeOfPhyVectex( iVertex2 );
		}
		else
		{
			// Simple 3dsMax model: the vertices are owned by the object, and hence the node
			iNodeV0 = iNode;
			iNodeV1 = iNode;
			iNodeV2 = iNode;
		}
		
		// Rotate the face vertices out of object-space, and into world-space space
		Point3 v0 = pt3Vertex0 * mat3ObjectTM;
		Point3 v1 = pt3Vertex1 * mat3ObjectTM;
		Point3 v2 = pt3Vertex2 * mat3ObjectTM;


		Matrix3 mat3ObjectNTM = mat3ObjectTM;
		mat3ObjectNTM.NoScale( );
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus pre normal 0" );
		pt3Vertex0Normal = VectorTransform(mat3ObjectNTM, pt3Vertex0Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex0Normal ) <= 1.1, "bogus post normal 0" );
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus pre normal 1" );
		pt3Vertex1Normal = VectorTransform(mat3ObjectNTM, pt3Vertex1Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex1Normal ) <= 1.1, "bogus post normal 1" );
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus pre normal 2" );
		pt3Vertex2Normal = VectorTransform(mat3ObjectNTM, pt3Vertex2Normal);
		ASSERT_AND_ABORT( Length( pt3Vertex2Normal ) <= 1.1, "bogus post normal 2" );

		// Finally dump the bitmap name and 3 lines of face info
		fprintf(m_pfile, "%s\n", szBitmapName);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV0, v0.x, v0.y, v0.z,
				pt3Vertex0Normal.x, pt3Vertex0Normal.y, pt3Vertex0Normal.z,
				UVvertex0.x, UVvertex0.y);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV1, v1.x, v1.y, v1.z,
				pt3Vertex1Normal.x, pt3Vertex1Normal.y, pt3Vertex1Normal.z,
				UVvertex1.x, UVvertex1.y);
		fprintf(m_pfile, "%3d %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n",
				iNodeV2, v2.x, v2.y, v2.z,
				pt3Vertex2Normal.x, pt3Vertex2Normal.y, pt3Vertex2Normal.z,
				UVvertex2.x, UVvertex2.y);
	}

	cleanup( );	
	return TREE_CONTINUE;
}
//=================================================================
// Methods for CollectModelTEP
//
int CollectModelTEP::callback(INode *pnode)
{
	if (::FNodeMarkedToSkip(pnode))
		return TREE_CONTINUE;

	if ( !pnode->Selected())
		return TREE_CONTINUE;

	// clear physique export parameters
	m_mcExport = NULL;
	m_phyExport = NULL;
    m_phyMod = NULL;
    m_bonesProMod = NULL;

	ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!");

	int iNode = ::GetIndexOfINode(pnode);
	TSTR strNodeName(pnode->GetName());
	
	// The Footsteps node apparently MUST have a dummy mesh attached!  Ignore it explicitly.
	if (FStrEq((char*)strNodeName, "Bip01 Footsteps"))
		return TREE_CONTINUE;

	// Helper nodes don't have meshes
	Object *pobj = pnode->GetObjectRef();
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
		return TREE_CONTINUE;

	// Get Node's object, convert to a triangle-mesh object, so I can access the Faces
	ObjectState os = pnode->EvalWorldState(m_tvToDump);
	pobj = os.obj;

	// Shouldn't have gotten this far if it's a helper object
	if (pobj->SuperClassID() == HELPER_CLASS_ID)
	{
		sprintf(st_szDBG, "ERROR--Helper node %s has an attached mesh, and it shouldn't.", (char*)strNodeName);
		ASSERT_AND_ABORT(FALSE, st_szDBG);
	}

	// convert mesh to triobject
	if (!pobj->CanConvertToType(triObjectClassID))
		return TREE_CONTINUE;
	TriObject *ptriobj = (TriObject*)pobj->ConvertToType(m_tvToDump, triObjectClassID);

	if (ptriobj == NULL)
		return TREE_CONTINUE;

	Mesh *pmesh = &ptriobj->mesh;

	// We want the vertex coordinates in World-space, not object-space
	Matrix3 mat3ObjectTM = pnode->GetObjectTM(m_tvToDump);

	// initialize physique export parameters
    m_phyMod = FindPhysiqueModifier(pnode);
    if (m_phyMod)
	{
		// Physique Modifier exists for given Node
	    m_phyExport = (IPhysiqueExport *)m_phyMod->GetInterface(I_PHYINTERFACE);

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

		   if (m_mcExport)
		   {
		       // convert all vertices to Rigid 
                m_mcExport->ConvertToRigid(TRUE);
		   }
		}
	}

	// initialize bones pro export parameters
	m_wa  = NULL;
	m_bonesProMod = FindBonesProModifier(pnode);
	if (m_bonesProMod)
	{
		m_bonesProMod->SetProperty( BP_PROPID_GET_WEIGHTS, &m_wa );
	}


	int cVerts = pmesh->getNumVerts();

	// Dump the triangle face info
	int cFaces = pmesh->getNumFaces();

	int *iUsed = new int[cVerts];

	for (int iVert = 0; iVert < cVerts; iVert++)
	{
		iUsed[iVert] = 0;
	}

	for (int iFace = 0; iFace < cFaces; iFace++)
	{
		if (pmesh->faces[iFace].flags & HAS_TVERTS)
		{
			iUsed[pmesh->faces[iFace].getVert(0)] = 1;
			iUsed[pmesh->faces[iFace].getVert(1)] = 1;
			iUsed[pmesh->faces[iFace].getVert(2)] = 1;
		}
	}

	for (iVert = 0; iVert < cVerts; iVert++)
	{
		MaxVertWeight *pweight = m_phec->m_MaxVertex[m_phec->m_cMaxVertex] = new MaxVertWeight [m_phec->m_cMaxNode];

		Point3 pt3Vertex1 = pmesh->getVert(iVert);
		Point3 v1 = pt3Vertex1 * mat3ObjectTM;

		GetUnifiedCoord( v1, pweight, m_phec->m_MaxNode, m_phec->m_cMaxNode );

		if (CollectWeights( iVert, pweight ))
		{
			m_phec->m_cMaxVertex++;
		}
	}	

	// fflush( m_pfile );

	return TREE_CONTINUE;
}