Ejemplo n.º 1
0
BitmapTex* SceneExportUtil::getStdMatBitmapTex( StdMat* stdmat, int id )
{
	StdMat2* stdmat2 = 0;
	int channel = id;
	if ( stdmat->SupportsShaders() )
	{
		stdmat2 = static_cast<StdMat2*>( stdmat );
		channel = stdmat2->StdIDToChannel( id );
	}

	if ( stdmat->MapEnabled(channel) )
	{
		Texmap*	tex	= stdmat->GetSubTexmap(channel);
		if ( tex && tex->ClassID() == Class_ID(BMTEX_CLASS_ID,0) &&
			(!stdmat2 || 2 == stdmat2->GetMapState(channel)) )
		{
			BitmapTex* bmptex = static_cast<BitmapTex*>(tex);
			if ( bmptex->GetMapName() )
			{
				return bmptex;
			}
		}
	}
	return 0;
}
Ejemplo n.º 2
0
Value* reload_texture_cf (Value** arg_list, int count)
{
	// Make sure we have the correct number of arguments (1)
	check_arg_count(reload_texture, 1, count);
	char *message = "NelReloadTexture [BitmapTex]";
	//type_check (arg_list[0], TextureMap, message);

	// Get a good interface pointer
	Interface *ip = MAXScript_interface;

	theCNelExport.init (false, false, ip, true);

	// The 2 filenames
	Texmap *texmap = arg_list[0]->to_texmap ();

	// BitmapTex ?
	if (texmap->ClassID() == Class_ID (BMTEX_CLASS_ID, 0))
	{
		// Cast
		BitmapTex *bitmap = (BitmapTex*)texmap;

		// Reload
		bitmap->ReloadBitmapAndUpdate ();

		// Tell the bitmap has changed
		BroadcastNotification (NOTIFY_BITMAP_CHANGED, (void *)bitmap->GetMapName());
		
		return &true_value;
	}

	return &false_value;
}
Ejemplo n.º 3
0
//----------------------------------------------------------------------------
// Material parsing
//----------------------------------------------------------------------------
BOOL CEditableObject::ExtractTexName(Texmap *src, LPSTR dest)
{
	if( src->ClassID() != Class_ID(BMTEX_CLASS_ID,0) )
		return FALSE;
	BitmapTex *bmap = (BitmapTex*)src;
	_splitpath( bmap->GetMapName(), 0, 0, dest, 0 );
	EFS.AppendFolderToName(dest,1,TRUE);
	return TRUE;
}
Ejemplo n.º 4
0
bool SGP_MaxInterface::GetStdMtlChannelBitmapFileName( StdMat* pStdMat, int nChannel, TCHAR szFileName[] )
{
	if( !pStdMat )
	{
		assert( false );
		return false;
	}
	Texmap *tx = pStdMat->GetSubTexmap(nChannel);
	if( !tx  )
		return false;
	if(tx->ClassID() != Class_ID(BMTEX_CLASS_ID,0))
		return false;
	BitmapTex *bmt = (BitmapTex*)tx;
	_tcscpy( szFileName, bmt->GetMapName() );
	return true;
}
Ejemplo n.º 5
0
P(GmMaterial) GmUtil::createGmMaterial( Mtl* material, Mtl* bakedmaterial )
{
	require( material );

	P(GmMaterial) s = new GmMaterial;

	// get name
	static int unnamedCount = 0;
	if ( material->GetName().data() )
		s->name = material->GetName().data();
	else
		s->name = "noname #"+String::valueOf( ++unnamedCount );

	// Standard material (+Diffuse) (+ Reflection)
	if ( material->ClassID() == Class_ID(DMTL_CLASS_ID,0) )
	{
		StdMat* stdmat		= static_cast<StdMat*>(material);
	    StdMat* bakedmat	= static_cast<StdMat*>(bakedmaterial);

		// StdMat2?
		StdMat2* stdmat2 = 0;
		if ( stdmat->SupportsShaders() )
			stdmat2 = static_cast<StdMat2*>( stdmat );

		// uniform transparency
		s->opacity = stdmat->GetOpacity(0);

		// self illumination
		s->selfIllum = stdmat->GetSelfIllum(0);

		// two-sided material?
		s->twosided = ( 0 != stdmat->GetTwoSided() );

		// blending mode
		s->blend = GmMaterial::BLEND_COPY;
		if ( s->opacity < 1.f )
			s->blend = GmMaterial::BLEND_MULTIPLY;
		if ( stdmat->GetTransparencyType() == TRANSP_ADDITIVE )
			s->blend = GmMaterial::BLEND_ADD;

		// diffuse color
		s->diffuseColor = toColorf( stdmat->GetDiffuse(0) );

		// specular highlights
		float shinStr = stdmat->GetShinStr(0);
		s->specular = (shinStr > 0.f);
		if ( s->specular )
		{
			float shininess = stdmat->GetShininess(0);
			s->specularExponent = Math::pow( 2.f, shininess*10.f + 2.f );
			s->specularColor = toColorf( stdmat->GetSpecular(0) ) * shinStr;
		}
		if ( bakedmat )
		{
			shinStr = bakedmat->GetShinStr(0);
			s->specular = (shinStr > 0.f);
			if ( s->specular )
			{
				float shininess = bakedmat->GetShininess(0);
				s->specularExponent = Math::pow( 2.f, shininess*10.f + 2.f );
				s->specularColor = toColorf( bakedmat->GetSpecular(0) ) * shinStr;
			}
		}

		// diffuse texture layer
		BitmapTex* tex	= SceneExportUtil::getStdMatBitmapTex( stdmat, ID_DI );
		if ( tex )
		{
			GmMaterial::TextureLayer& layer = s->diffuseLayer;
			setLayerTex( layer, tex, s->name );
		}

		// opacity texture layer
		tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_OP );
		if ( tex )
		{
			GmMaterial::TextureLayer& layer = s->opacityLayer;
			setLayerTex( layer, tex, s->name );

			// check alpha channel validity
			Bitmap* bmp = tex->GetBitmap(0);
			if ( bmp && !bmp->HasAlpha() )
				Debug::printlnError( "Material \"{0}\" opacity map \"{1}\" must have image alpha channel.", s->name, tex->GetMapName() );
				//throw IOException( Format("Material \"{0}\" opacity map \"{1}\" must have image alpha channel.", s->name, tex->GetMapName()) );
			s->blend = GmMaterial::BLEND_MULTIPLY;

			// check that opacity map is the same as diffuse map
			if ( s->opacityLayer.filename != s->diffuseLayer.filename )
				throw IOException( Format("Material \"{0}\" diffuse bitmap needs to be the same in opacity map.(diffuse map is \"{1}\" and opacity map is \"{2}\")", s->name, s->diffuseLayer.filename, s->opacityLayer.filename) );
			if ( s->opacityLayer.coordset != s->diffuseLayer.coordset )
				throw IOException( Format("Material \"{0}\" diffuse map texture coordinate set needs to be the same in opacity map.", s->name) );
			if ( s->opacityLayer.env != s->diffuseLayer.env )
				throw IOException( Format("Material \"{0}\" diffuse map texture coordinate generator needs to be the same in opacity map.", s->name) );
		}

		// reflection texture layer
		tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_RL );
		if ( tex )
		{
			GmMaterial::TextureLayer& layer = s->reflectionLayer;
			setLayerTex( layer, tex, s->name );
		}

		// glossiness (shininess strength, SS) texture layer
		tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_SS );
		if ( tex )
		{
			GmMaterial::TextureLayer& layer = s->glossinessLayer;
			setLayerTex( layer, tex, s->name );

			// check alpha channel validity
			Bitmap* bmp = tex->GetBitmap(0);
			//if ( bmp && !bmp->HasAlpha() )
			//	throw IOException( Format("Material \"{0}\" glossiness map \"{1}\" must have image alpha channel.", s->name, tex->GetMapName()) );
			if ( bmp && !bmp->HasAlpha() )
				Debug::printlnError("Material \"{0}\" glossiness map \"{1}\" must have image alpha channel.", s->name, tex->GetMapName() );

			// check that glossiness map is the same as diffuse map
			if ( s->glossinessLayer.filename != s->diffuseLayer.filename )
				throw IOException( Format("Material \"{0}\" diffuse bitmap needs to be the same in glossiness map.(diffuse map is \"{1}\" and glossiness map is \"{2}\")", s->name, s->diffuseLayer.filename, s->glossinessLayer.filename) );
			if ( s->glossinessLayer.coordset != s->diffuseLayer.coordset )
				throw IOException( Format("Material \"{0}\" diffuse map texture coordinate set needs to be the same in glossiness map.", s->name) );
			if ( s->glossinessLayer.env != s->diffuseLayer.env )
				throw IOException( Format("Material \"{0}\" diffuse map texture coordinate generator needs to be the same in glossiness map.", s->name) );

			// check that reflection map has been set
			if ( s->reflectionLayer.filename.length() == 0 )
				throw IOException( Format("Material \"{0}\" glossiness map requires reflection map to be set.", s->name) );
		}

		// bump texture layer
		tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_BU );
		if ( tex )
		{
			GmMaterial::TextureLayer& layer = s->bumpLayer;
			setLayerTex( layer, tex, s->name );
		}

		// specular color texture layer
		tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_SP );
		if ( tex )
		{
			GmMaterial::TextureLayer& layer = s->specularColorLayer;
			setLayerTex( layer, tex, s->name );
		}

		// specular level texture layer
		tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_SH );
		if ( tex )
		{
			GmMaterial::TextureLayer& layer = s->specularLevelLayer;
			setLayerTex( layer, tex, s->name );
		}

		// lightmap texture layer ( from self-illumination map of baked material )
		tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_SI );
		BitmapTex* tex2 = 0;
		if ( bakedmat ) 
			tex2 = SceneExportUtil::getStdMatBitmapTex( bakedmat, ID_SI );
		
		if ( tex || tex2 )
		{
			GmMaterial::TextureLayer& layer = s->lightMapLayer;
	
			if ( tex && !tex2 )
				setLayerTex( layer, tex, s->name );
			else if ( tex2 )
				setLayerTex( layer, tex2, s->name );
		}
	}

	return s;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
//----------------------------------------------------------------------------
void SceneBuilder::ConvertMaterial (Mtl &mtl, MtlTree &mtlTree)
{
	// 光照属性
	PX2::Shine *shine = new0 PX2::Shine;
	Color color = mtl.GetAmbient();
	float alpha = 1.0f - mtl.GetXParency();
	shine->Ambient = PX2::Float4(color.r, color.g, color.b, 1.0f);
	color = mtl.GetDiffuse();
	shine->Diffuse = PX2::Float4(color.r, color.g, color.b, alpha);
	color = mtl.GetSpecular();
	float shininess = mtl.GetShininess()*2.0f;
	shine->Specular = PX2::Float4(color.r, color.g, color.b, shininess);

	const char *name = (const char*)mtl.GetName();
	shine->SetName(name);

	mtlTree.SetShine(shine);

	bool IsDirect9Shader = false;

	if (mtl.ClassID() == Class_ID(CMTL_CLASS_ID, 0)
		|| mtl.ClassID() == Class_ID(DMTL_CLASS_ID, 0))
	{
		StdMat2 *stdMat2 = (StdMat2*)(&mtl);
		Interval valid = FOREVER;
		stdMat2->Update(mTimeStart, valid);

		std::string strName(stdMat2->GetName());
		bool doubleSide = (stdMat2->GetTwoSided()==1);

		char strBitMapName[256];
		memset(strBitMapName, 0, 256*sizeof(char));
		std::string resourcePath;

		PX2::Shader::SamplerFilter filter = PX2::Shader::SF_LINEAR_LINEAR;
		PX2::Shader::SamplerCoordinate uvCoord = PX2::Shader::SC_REPEAT;
		PX2_UNUSED(uvCoord);

		if (stdMat2->MapEnabled(ID_DI))
		{
			BitmapTex *tex = (BitmapTex*)stdMat2->GetSubTexmap(ID_DI);

			BitmapInfo bI;
			const char *mapName = tex->GetMapName();
			TheManager->GetImageInfo(&bI, mapName);
			strcpy(strBitMapName, bI.Name());

			std::string fullName = std::string(strBitMapName);
			std::string::size_type sizeT = fullName.find_first_not_of(mSettings->SrcRootDir);
			resourcePath = std::string(strBitMapName).substr(sizeT);

			StdUVGen* uvGen = tex->GetUVGen();
			PX2_UNUSED(uvGen);
			int filType = tex->GetFilterType();
			switch (filType)
			{
				case FILTER_PYR:
					filter = PX2::Shader::SF_LINEAR_LINEAR;
					break;
				case FILTER_SAT:
					filter = PX2::Shader::SF_NEAREST;
					break;
				default:
					break;
			}
		}
		else
		{
			sprintf(strBitMapName, "%s/%s", mSettings->SrcRootDir, PX2_DEFAULT_TEXTURE);
			resourcePath = PX2_DEFAULT_TEXTURE;
		}

		PX2::Texture2D *tex2d = PX2::DynamicCast<PX2::Texture2D>(
			PX2::ResourceManager::GetSingleton().BlockLoad(strBitMapName));
		tex2d->SetResourcePath(resourcePath);

		if (tex2d)
		{
			PX2::Texture2DMaterial *tex2dMtl = new0 PX2::Texture2DMaterial(filter, 
				uvCoord, uvCoord);
			if (doubleSide)
			{
				tex2dMtl->GetCullProperty(0, 0)->Enabled = false;
			}

			PX2::MaterialInstance *instance = tex2dMtl->CreateInstance(tex2d);

			mtlTree.SetMaterialInstance(instance);
		}
		else
		{
			PX2::VertexColor4Material *vcMtl = new0 PX2::VertexColor4Material();
			PX2::MaterialInstance *instance = vcMtl->CreateInstance();
			mtlTree.SetMaterialInstance(instance);
		}
	}
	else if (mtl.ClassID() == Class_ID(MULTI_CLASS_ID, 0))
	{
	}
	else if (mtl.ClassID() == DIRECTX_9_SHADER_CLASS_ID)
	{
		IsDirect9Shader = true;

		IDxMaterial* dxMtl = (IDxMaterial*)mtl.GetInterface(IDXMATERIAL_INTERFACE);
		char *effectName = dxMtl->GetEffectFilename();
		IParamBlock2 *paramBlock = mtl.GetParamBlock(0);

		std::string outPath;
		std::string outBaseName;
		std::string outExtention;
		PX2::StringHelp::SplitFullFilename(effectName, outPath, outBaseName,
			outExtention);

		PX2::ShinePtr shineStandard = new0 PX2::Shine();
		bool alphaVertex = false;
		PX2::Texture2DPtr diffTex;
		bool normalEnable = false;
		PX2::Texture2DPtr normalTex;
		float normalScale = 0.0f;
		bool specEnable = false;
		PX2::Texture2DPtr specTex;
		float specPower = 0.0f;
		bool reflectEnable = false;
		PX2::TextureCubePtr reflectTex;
		float reflectPower = 0.0f;
		bool doubleSide = false;
		int blendMode = 2;

		ParamBlockDesc2 *paramDesc = 0;
		int numParam = 0;
		if (paramBlock)
		{
			paramDesc = paramBlock->GetDesc();
			numParam = paramBlock->NumParams();

			ParamType2 paramType;
			for (int i=0; i<numParam; i++)
			{
				std::string parmName;
				PX2::Float4 color4 = PX2::Float4(0.0f, 0.0f, 0.0f, 0.0f);
				PX2::Float3 color3 = PX2::Float3(0.0f, 0.0f, 0.0f);
				float floatValue = 0.0f;
				bool boolValue = false;
				float *floatTable = 0;
				int intValue = 0;
				std::string str;
				PX2::Texture2D *tex2d = 0;

				paramType = paramBlock->GetParameterType((ParamID)i);

				if (TYPE_STRING == paramType)
					ConvertStringAttrib(paramBlock, i, parmName, str);
				else if (TYPE_FLOAT == paramType)
					ConvertFloatAttrib(paramBlock, i, parmName, floatValue);
				else if (TYPE_INT == paramType)
					ConvertIntAttrib(paramBlock, i, parmName, intValue);
				else if (TYPE_RGBA == paramType)
					ConvertColorAttrib(paramBlock, i, parmName, color4, i);
				else if (TYPE_POINT3 == paramType)
					ConvertPoint3Attrib(paramBlock, i, parmName, color3);
				else if (TYPE_POINT4 == paramType)
					ConvertPoint4Attrib(paramBlock, i, parmName, color4);
				else if (TYPE_BOOL == paramType)
					ConvertBoolAttrib(paramBlock, i, parmName, boolValue);
				else if (TYPE_FLOAT_TAB == paramType)
					ConvertFloatTabAttrib(paramBlock, i, parmName, floatTable);
				else if (TYPE_BITMAP == paramType)
					ConvertBitMapAttrib(paramBlock, i, parmName, tex2d);
				else if (TYPE_FRGBA ==paramType)
					ConvertFRGBAAttrib(paramBlock, i, parmName, color4);

				// shine
				if (parmName == "gBlendMode")
				{
					blendMode = intValue;
				}
				else if (parmName == "gShineEmissive")
				{
					shineStandard->Emissive = color4;
				}
				else if (parmName == "gShineAmbient")
				{
					shineStandard->Ambient = color4;
				}
				else if (parmName == "gShineDiffuse")
				{
					shineStandard->Diffuse = color4;
				}
				// alpha vertex
				else if (parmName == "gAlphaVertex")
				{
					alphaVertex = boolValue;
				}
				// diffuse
				else if (parmName == "gDiffuseTexture")
				{
					diffTex = tex2d;
				}
				// normal
				else if (parmName == "gNormalEnable")
				{
					normalEnable = boolValue;
				}
				else if (parmName == "gNormalTexture")
				{
					normalTex = tex2d;
				}
				else if (parmName == "gNormalScale")
				{
					normalScale = floatValue;
				}
				// specular
				else if (parmName == "gSpecularEnable")
				{
					specEnable = boolValue;
				}
				else if (parmName == "gSpecularTexture")
				{
					specTex = tex2d;
				}
				else if (parmName == "gSpecularPower")
				{
					specPower = floatValue;
				}
				// reflect
				else if (parmName == "gReflectionEnable")
				{
					reflectEnable = boolValue;
				}
				else if (parmName == "gReflectTexture")
				{
					//reflectTex = tex2d;
				}
				else if (parmName == "gReflectPower")
				{
					reflectPower = floatValue;
				}
				// other
				else if (parmName == "gDoubleSide")
				{
					doubleSide = boolValue;
				}
			}
		}

		PX2::MaterialInstance *inst = 0;
		PX2::StandardMaterial *standardMtl = 0;
		PX2::StandardESMaterial_Default *standardESMtl_D = 0;
		PX2::StandardESMaterial_Specular *standardESMtl_S = 0;
		if (outBaseName == "Standard")
		{
			char mtlName[256];
			memset(mtlName, 0, 256*sizeof(char));
			sprintf(mtlName, "%s/%s", mSettings->DstRootDir, 
				"Data/mtls/Standard.pxfx");
			standardMtl = new0 PX2::StandardMaterial(mtlName);
		}
		else if (outBaseName == "StandardES")
		{
			if (false == specEnable)
			{
				standardESMtl_D = new0 PX2::StandardESMaterial_Default();

				if (0 == blendMode)
				{
					standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = false;
					standardESMtl_D->GetAlphaProperty(0, 0)->CompareEnabled = false;
				}
				else if (1 == blendMode)
				{
					standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = true;
				}
				else if (2 == blendMode)
				{
					standardESMtl_D->GetAlphaProperty(0, 0)->BlendEnabled = false;
					standardESMtl_D->GetAlphaProperty(0, 0)->CompareEnabled = true;
					standardESMtl_D->GetAlphaProperty(0, 0)->Compare = PX2::AlphaProperty::CM_GEQUAL;
					standardESMtl_D->GetAlphaProperty(0, 0)->Reference = 0.2f;
				}
			}
			else
			{
				char mtlName[256];
				memset(mtlName, 0, 256*sizeof(char));
				sprintf(mtlName, "%s/%s", mSettings->DstRootDir, 
					"Data/mtls/StandardES_Specular.pxfx");
				standardESMtl_S = new0 PX2::StandardESMaterial_Specular(mtlName);
			}
		}

		if (standardMtl && diffTex)
		{
			if (doubleSide)
			{
				standardMtl->GetCullProperty(0, 0)->Enabled = false;
			}

			inst = standardMtl->CreateInstance(diffTex, alphaVertex, 
				normalEnable, normalTex, normalScale, specEnable, specTex,
				specPower, 0, shineStandard);
		}
		else if (standardESMtl_D && diffTex)
		{
			if (doubleSide)
			{
				standardESMtl_D->GetCullProperty(0, 0)->Enabled = false;
			}

			inst = standardESMtl_D->CreateInstance(diffTex, 0, shineStandard);
		}
		else if (standardESMtl_S && diffTex && specTex)
		{
			if (doubleSide)
			{
				standardESMtl_S->GetCullProperty(0, 0)->Enabled = false;
			}

			inst = standardESMtl_S->CreateInstance(diffTex, specTex, specPower,
				0, shineStandard);
		}

		if (inst)
		{
			mtlTree.SetMaterialInstance(inst);
		}
		else
		{
			PX2::MaterialInstance *instance = 
				PX2::VertexColor4Material::CreateUniqueInstance();
			mtlTree.SetMaterialInstance(instance);
		}
	}
	else
	{
		PX2::VertexColor4Material *vcMtl = new0 PX2::VertexColor4Material();
		PX2::MaterialInstance *instance = vcMtl->CreateInstance();
		mtlTree.SetMaterialInstance(instance);
	}

	// 对子材质进行处理
	if (IsDirect9Shader)
		return;

	int mQuantity = mtl.NumSubMtls(); // Class_ID(MULTI_CLASS_ID, 0)
	if (mQuantity > 0)
	{
		mtlTree.SetMChildQuantity(mQuantity);
		for (int i=0; i<mQuantity; i++)
		{
			Mtl *subMtl = 0;
			subMtl = mtl.GetSubMtl(i);
			if (subMtl)
			{
				ConvertMaterial(*subMtl, mtlTree.GetMChild(i));
			}
		}
	}
}