www.pudn.com > Direct3D-3ds_loader-render.rar > 3ds.cpp


// 3ds.cpp: implementation of the C3ds class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "3ds.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
C3ds::C3ds() 
{ 
	error=1; 
	textures=NULL; 
} 
 
// filter : 0 - nearest | 1 - linear | 2 - bilinear, linear_mipmap_nearest | 3 - trilinear, linear_mipmap_linear 
C3ds::C3ds(char *file_name, LPDIRECT3DDEVICE9 pDevice, int filter, int faceNormal, int shadowObject) 
{ 
	z3ds_Chunk ch; 
	char strMessage[255]={0}; 
	textures = NULL; 
	isShadowObject = shadowObject; 
	isFaceNormal = faceNormal; 
 
	file = fopen( file_name, "rb"); 
	 
	if(!file) 
	{ 
		sprintf(strMessage, "Unable to find the file: %s!", file_name); 
		MessageBox(NULL, strMessage, "Error", MB_OK); 
		error = 1; 
		return; 
	} 
 
	ReadChunk( &ch); 
	// Make sure this is a 3DS file 
	if (ch.ID != MAIN3DS) 
	{ 
		sprintf(strMessage, "Unable to load PRIMARY chuck from file: %s!", file_name); 
		MessageBox(NULL, strMessage, "Error", MB_OK); 
		error = 1; 
		return; 
	} 
	ReadNextChunk( &ch); 
	fclose( file); 
 
	if(isShadowObject) 
	{ 
		for(int i=0; i0)textures = new texture[materials.size()]; 
	// Go through all the materials 
	for(int i = 0; i < materials.size(); i++) 
	{ 
		// Check to see if there is a file name to load in this material 
		if(strlen(materials[i].strFile) > 0) 
		{ 
			// Use the name of the texture file to load the bitmap, with a texture ID (i). 
			char text[300]; 
			 
			char* pdest = strrchr( file_name, '/' );		// find '/' 
			if( pdest==NULL)strncpy(text, materials[i].strFile, 300); 
			else 
			{ 
				strncpy( text, file_name, pdest-file_name+1); 
				text[pdest-file_name+1]=NULL; 
				strcat(text, materials[i].strFile); 
			} 
			if( !textures[i].load( text, pDevice, 1, filter))error = 1; 
		} 
		// Set the texture ID for this material 
		materials[i].texureId = i; 
	} 
	RotateX90();	//转换左右手坐标系 
//	Rescale(.2,.2,.2);	//缩放模型 
	if (!CreateDXObjects(pDevice)) 
	{ 
		MessageBox(NULL,"Failed to create Direct3D objects form 3ds file", file_name, MB_OK|MB_ICONERROR); 
	} 
} 
 
C3ds::~C3ds() 
{ 
} 
 
void C3ds::ReadChunk(z3ds_Chunk *pChunk) 
{ 
	// This reads the chunk ID which is 2 bytes. 
	// The chunk ID is like OBJECT or MATERIAL.  It tells what data is 
	// able to be read in within the chunks section.   
	pChunk->bytesRead = fread(&pChunk->ID, 1, 2, file); 
 
	// Then, we read the length of the chunk which is 4 bytes. 
	// This is how we know how much to read in, or read past. 
	pChunk->bytesRead += fread(&pChunk->length, 1, 4, file); 
} 
 
void C3ds::ReadNextChunk(z3ds_Chunk *old) 
{ 
	z3ds_Chunk ch; 
		 
	while( old->bytesRead < old->length ) 
	{ 
		ReadChunk( &ch); 
 
		switch( ch.ID) 
		{ 
		case VERSION:							// This holds the version of the file 
			{ 
				unsigned short version = 0;					// This will hold the file version 
				ch.bytesRead += fread(&version, 1, ch.length - ch.bytesRead, file); 
				// If the file version is over 3, give a warning that there could be a problem 
				if (version > 0x03) 
					MessageBox(NULL, "This 3DS file is over version 3 so it may load incorrectly", "Warning", MB_OK); 
			} 
			break; 
		case EDIT3DS:				// 0x3D3D 
			ReadEdit( &ch); 
			break; 
		case KEYF3DS:				// 0xB000 
		//	Read_KeyF( &ch); 
			fseek( file, ch.length-ch.bytesRead, SEEK_CUR); 
			ch.bytesRead = ch.length; 
			break; 
		default: 
			fseek( file, ch.length-ch.bytesRead, SEEK_CUR); 
			ch.bytesRead = ch.length; 
		} 
		old->bytesRead += ch.bytesRead; 
	} 
} 
 
void C3ds::ReadEdit(z3ds_Chunk *old) 
{ 
	z3ds_Chunk ch; 
		 
	while( old->bytesRead < old->length ) 
	{ 
		ReadChunk( &ch); 
 
		switch( ch.ID) 
		{ 
		case EDIT_MATERIAL:				// 0xAFFF 
			ReadEditMaterial( &ch); 
			break; 
		case EDIT_OBJECT:				// 0x4000 
			ReadEditObject( &ch); 
			break; 
		default: 
			fseek( file, ch.length-ch.bytesRead, SEEK_CUR); 
			ch.bytesRead = ch.length; 
		} 
		old->bytesRead += ch.bytesRead; 
	} 
} 
 
void C3ds::ReadEditMaterial(z3ds_Chunk *old) 
{ 
	unsigned char buf[100]; 
	unsigned char color[3]; 
	z3ds_Chunk ch, temp;; 
	z3ds_MaterialInfo mat; 
	memset( &mat, 0, sizeof(z3ds_MaterialInfo)); 
		 
	while( old->bytesRead < old->length ) 
	{ 
		ReadChunk( &ch); 
 
		switch( ch.ID) 
		{ 
		case 0xA000:				// This holds the material name 
			ch.bytesRead += fread( mat.strName, 1, ch.length-ch.bytesRead, file); 
			break; 
		case 0xA010:				// This holds the ambient color of the object/material 
			{ 
				ReadChunk( &temp); 
				fread( color, 1, temp.length-temp.bytesRead, file); 
				mat.ambient.set( (float)color[0]/255.f, (float)color[1]/255.f, (float)color[2]/255.f ); 
				ch.bytesRead += temp.length; 
			} 
			break; 
		case 0xA020:				// This holds the diffuse color of the object/material 
			{ 
				ReadChunk( &temp); 
				fread( color, 1, temp.length-temp.bytesRead, file); 
				mat.diffuse.set( (float)color[0]/255.f, (float)color[1]/255.f, (float)color[2]/255.f ); 
				ch.bytesRead += temp.length; 
			} 
			break; 
		case 0xA030:				// This holds the specular color of the object/material 
			{ 
				ReadChunk( &temp); 
				fread( color, 1, temp.length-temp.bytesRead, file); 
				mat.specular.set( (float)color[0]/255.f, (float)color[1]/255.f, (float)color[2]/255.f ); 
				ch.bytesRead += temp.length; 
			} 
			break; 
		case 0xA040:				// This holds the specular shininess of the object/material 
			{ 
				ReadChunk( &temp); 
				fread( color, 1, temp.length-temp.bytesRead, file); 
				mat.shininess = (float)color[0]; 
				ch.bytesRead += temp.length; 
			} 
			break; 
		case 0xA041:				// This holds the specular level of the object/material 
			{ 
				ReadChunk( &temp); 
				fread( color, 1, temp.length-temp.bytesRead, file); 
				mat.specular = mat.specular*0.01f*(256.f*color[1]+color[0]); 
				ch.bytesRead += temp.length; 
			} 
			break; 
		case 0xA084:				// This holds the specular level of the object/material 
			{ 
				ReadChunk( &temp); 
				fread( color, 1, temp.length-temp.bytesRead, file); 
				mat.emission = mat.diffuse*0.01f*color[0]; 
				ch.bytesRead += temp.length; 
			} 
			break; 
		case 0xA200:				// This is a header for a new material 
			ReadEditMaterialTexture( &ch, mat); 
			break; 
		case 0xA300:				// This holds the file name of the texture 
			ch.bytesRead += fread( mat.strFile, 1, ch.length-ch.bytesRead, file); 
			break; 
		default: 
			fread( buf, 1, ch.length-ch.bytesRead, file); 
		//	fseek( file, ch.length-ch.bytesRead, SEEK_CUR); 
			ch.bytesRead = ch.length; 
		} 
		old->bytesRead += ch.bytesRead; 
	} 
	materials.push_back(mat); 
} 
 
void C3ds::ReadEditMaterialTexture(z3ds_Chunk *old, z3ds_MaterialInfo &mat) 
{ 
	z3ds_Chunk ch; 
	char buf[100]; 
	 
	while( old->bytesRead < old->length ) 
	{ 
		ReadChunk( &ch); 
 
		switch( ch.ID) 
		{ 
		case 0xA300:				// This holds the file name of the texture 
			ch.bytesRead += fread( mat.strFile, 1, ch.length-ch.bytesRead, file); 
			break; 
		default: 
			fread( buf, 1, ch.length-ch.bytesRead, file); 
		//	fseek( file, ch.length-ch.bytesRead, SEEK_CUR); 
			ch.bytesRead = ch.length; 
		} 
		old->bytesRead += ch.bytesRead; 
	} 
} 
 
void C3ds::ReadEditObject(z3ds_Chunk *old) 
{ 
	z3ds_Chunk ch; 
	z3ds_Object obj;// = {0}; 
	memset( &obj, 0, sizeof(z3ds_Object)); 
	old->bytesRead += GetString(obj.strName); 
 
	while( old->bytesRead < old->length ) 
	{ 
		ReadChunk( &ch); 
 
		switch( ch.ID) 
		{ 
		case OBJ_TRIMESH:				// 0x4100 
			ReadEditObjectTriMesh( &ch, obj); 
			break; 
	//	case OBJ_LIGHT     0x4600 
	//	case OBJ_CAMERA    0x4700 
 
	//	case OBJ_UNKNWN01  0x4010 
	//	case OBJ_UNKNWN02  0x4012 //---- Could be shadow 
		default: 
			fseek( file, ch.length-ch.bytesRead, SEEK_CUR); 
			ch.bytesRead = ch.length; 
		} 
		old->bytesRead += ch.bytesRead; 
	} 
	objects.push_back( obj); 
} 
 
void C3ds::ReadEditObjectTriMesh(z3ds_Chunk *old, z3ds_Object &obj) 
{ 
	z3ds_Chunk ch; 
 
	while( old->bytesRead < old->length ) 
	{ 
		ReadChunk( &ch); 
 
		switch( ch.ID) 
		{ 
		case TRI_VERTEXL:			// 0x4110 
			ReadEditObjectTriMeshVertex( &ch, obj); 
			break; 
//		case TRI_FACEL2:			// 0x4111  
		case TRI_FACEL1:			// 0x4120 
			ReadEditObjectTriMeshFace( &ch, obj); 
			break; 
		case 0x4130:				// Face Material Chunk  
			ReadEditObjectTriMeshMaterial( &ch, obj); 
			break; 
		case 0x4140:				// Mapping coordinates 
			ReadEditObjectTriMeshUV( &ch, obj); 
			break; 
		case TRI_SMOOTH:			// 0x4150 
		case TRI_LOCAL:				// 0x4160 
		case TRI_VISIBLE:			// 0x4165 
		default: 
			fseek( file, ch.length-ch.bytesRead, SEEK_CUR); 
			ch.bytesRead = ch.length; 
		} 
		old->bytesRead += ch.bytesRead; 
	} 
} 
 
void C3ds::ReadEditObjectTriMeshVertex(z3ds_Chunk *old, z3ds_Object &obj) 
{ 
	old->bytesRead += fread( &obj.numOfVerts, 1, 2, file); 
	obj.pVerts = new vec[obj.numOfVerts]; 
	if(obj.pVerts==NULL){ error=1; return;} 
	old->bytesRead += fread( obj.pVerts, 1, sizeof(vec)*obj.numOfVerts, file); 
} 
 
void C3ds::ReadEditObjectTriMeshFace(z3ds_Chunk *old, z3ds_Object &obj) 
{ 
	old->bytesRead += fread( &obj.numOfFaces, 1, 2, file); 
	obj.pFaces = new z3ds_Face[obj.numOfFaces]; 
	if(obj.pFaces==NULL){ error=1; return;} 
 
	unsigned short *temp; 
	temp = new unsigned short[8*obj.numOfFaces]; 
	if(temp==NULL){ error=1; return;} 
	old->bytesRead += fread( temp, 1, 2*4*obj.numOfFaces, file); 
	for(unsigned short i=0; ibytesRead += GetString( strMaterial ); 
 
	for(int i=0; i 0) obj.bHasTexture = true; 
			break; 
		} 
		else 
			obj.materialID = -1;	// Set the ID to -1 to show there is no material for this object 
	} 
	fseek( file, old->length-old->bytesRead, SEEK_CUR); 
	old->bytesRead = old->length; 
} 
 
void C3ds::ReadEditObjectTriMeshUV(z3ds_Chunk *old, z3ds_Object &obj) 
{ 
	old->bytesRead += fread( &obj.numTexVertex, 1, 2, file); 
	obj.pTexVerts = new vec2[ obj.numTexVertex]; 
	old->bytesRead += fread( obj.pTexVerts, 1, old->length-old->bytesRead, file); 
} 
 
void C3ds::ComputeNormals() 
{ 
	for(int i=0; iobjects.size(); i++) 
	{ 
		vec* faceN; 
		z3ds_Object *obj; 
		obj = &objects[i]; 
 
		faceN = new vec[obj->numOfFaces]; 
		if(faceN==NULL)return; 
		obj->pNormals = new vec[obj->numOfVerts]; 
		if(obj->pNormals==NULL)return; 
 
		for(int j=0; jnumOfFaces; j++) 
		{ 
			vec a,b; 
			a = obj->pVerts[obj->pFaces[j].vertIndex[1]] - obj->pVerts[obj->pFaces[j].vertIndex[0]]; 
			b = obj->pVerts[obj->pFaces[j].vertIndex[2]] - obj->pVerts[obj->pFaces[j].vertIndex[0]]; 
			faceN[j] = CROSS( a, b); 
			if(isShadowObject) 
			{ 
				obj->pFacesShadow[j].normal=faceN[j]; 
				obj->pFacesShadow[j].normal.Normalize(); 
				obj->pFacesShadow[j].delta = -DOT3( obj->pFacesShadow[j].normal, obj->pVerts[obj->pFaces[j].vertIndex[0]]); 
			} 
		//	if(isFaceNormal) 
			//	faceN[j].Normalize(); 
		} 
		if(isFaceNormal) 
		{ 
			obj->pNormals = faceN; 
			faceN = NULL; 
			continue; 
		} 
 
		int count; 
		for(j=0; jnumOfVerts; j++)			// Go through all of the vertices 
		{ 
			count=0; 
			obj->pNormals[j].clear();				 
			for(int k=0; knumOfFaces; k++)	// Go through all of the triangles 
			{										// Check if the vertex is shared by another face 
				if( obj->pFaces[k].vertIndex[0]==j ||  
					obj->pFaces[k].vertIndex[1]==j || 
					obj->pFaces[k].vertIndex[2]==j ) 
				{ 
					obj->pNormals[j] += faceN[k]; 
					count++; 
				} 
			} 
			obj->pNormals[j] *= 1.f/(float)count; 
			obj->pNormals[j].Normalize(); 
		} 
		if(faceN!=NULL)delete [] faceN; 
	} 
} 
 
void C3ds::SetConnectivity() 
{ 
	for( int iobj=0; iobjnumOfFaces)-1; ifaceA++) 
		{ 
			for(int edgeA=0; edgeA<3; edgeA++) 
			{ 
				if(obj->pFacesShadow[ifaceA].neighbourIndices[edgeA]>-1)continue; 
 
				for(int ifaceB=ifaceA+1; ifaceBnumOfFaces; ifaceB++) 
				{ 
					for(int edgeB=0; edgeB<3; edgeB++) 
					{ 
						unsigned short a1,a2,b1,b2; 
 
						a1 = obj->pFaces[ifaceA].vertIndex[edgeA]; 
						a2 = obj->pFaces[ifaceA].vertIndex[(edgeA+1)%3]; 
						b1 = obj->pFaces[ifaceB].vertIndex[edgeB]; 
						b2 = obj->pFaces[ifaceB].vertIndex[(edgeB+1)%3]; 
 
						if( (a1==b1 && a2==b2) || (a1==b2 && a2==b1) ) 
						{ 
							obj->pFacesShadow[ifaceA].neighbourIndices[edgeA]=ifaceB; 
							obj->pFacesShadow[ifaceB].neighbourIndices[edgeB]=ifaceA; 
						} 
					} 
				} 
			} 
		} 
	} 
} 
 
int C3ds::GetString(char *pBuffer) 
{ 
	int index = 0; 
 
	fread(pBuffer, 1, 1, file); 
	// Loop until we get NULL 
	while (*(pBuffer + index++) != 0)  
		fread(pBuffer + index, 1, 1, file);		// Read in a character at a time until we hit NULL. 
	return strlen(pBuffer) + 1;	// Return the string length, which is how many bytes we read in (including the NULL) 
} 
 
 
////////////////////////////////////////////////////////////////////////// 
//左手、右手坐标系转换函数 
//void C3ds::RotateX90() 
////////////////////////////////////////////////////////////////////////// 
void C3ds::RotateX90()		 
{ 
	for(int i=0; ipVerts!=NULL) 
		{ 
			for(int j=0; jnumOfVerts; j++) 
			{ 
				float z = -obj->pVerts[j].y; 
				obj->pVerts[j].y = obj->pVerts[j].z; 
				obj->pVerts[j].z = z; 
			} 
		} 
		if(obj->pNormals!=NULL) 
		{ 
			for(int j=0; jnumOfVerts; j++) 
			{ 
				float z = -obj->pNormals[j].y; 
				obj->pNormals[j].y = obj->pNormals[j].z; 
				obj->pNormals[j].z = z; 
			} 
		} 
 
		if(obj->pFacesShadow!=NULL) 
		{ 
			for(int j=0; jnumOfFaces; j++) 
			{ 
				float z = -obj->pFacesShadow[j].normal.y; 
				obj->pFacesShadow[j].normal.y = obj->pFacesShadow[j].normal.z; 
				obj->pFacesShadow[j].normal.z = z; 
			} 
		} 
	} 
} 
 
void C3ds::Rescale(float scaleX,float scaleY,float scaleZ) 
{ 
	for(int i=0; ipVerts!=NULL) 
		{ 
			for(int j=0; jnumOfVerts; j++) 
			{ 
				obj->pVerts[j].x*=scaleX; 
				obj->pVerts[j].y*=scaleY; 
				obj->pVerts[j].z*=scaleZ; 
			} 
		} 
	} 
} 
 
int C3ds::CreateDXObjects(LPDIRECT3DDEVICE9 pDevice) 
{ 
	z3ds_DXobj dxobj; 
	// Since we know how many objects our model has, go through each of them. 
	for(int i = 0; i < objects.size(); i++) 
	{ 
		z3ds_Object *obj = &objects[i]; 
 
		// zistime ci mame nacitane texturove koordinacie 
		if(obj->bHasTexture && obj->pTexVerts!=NULL)dxobj.have_texture_coord_0 = 1; 
		else dxobj.have_texture_coord_0 = 0; 
 
		dxobj.materialID = obj->materialID; 
		dxobj.count = obj->numOfFaces; 
		dxobj.pvb = NULL; 
		 
		if( FAILED(pDevice->CreateVertexBuffer( dxobj.count*3*sizeof(z3ds_CUSTOMVERTEX),D3DUSAGE_WRITEONLY,  
								D3DFVF_CUSTOMVERTEX_3ds,D3DPOOL_DEFAULT, &dxobj.pvb, NULL) ) )return 0; 
 
		void* p; 
		if( FAILED( (dxobj.pvb)->Lock( 0, dxobj.count*3*sizeof(z3ds_CUSTOMVERTEX), &p, 0 ) ) )return 0; 
		 
		int i_vec=0; 
		// Go through all of the faces (polygons) of the object and draw them 
		for(int j = 0; j < obj->numOfFaces; j++) 
		{ 
			// Go through each corner of the triangle and draw it. 
			for(int whichVertex = 0; whichVertex < 3; whichVertex++) 
			{ 
				// Get the index for each point of the face 
				int index = obj->pFaces[j].vertIndex[whichVertex]; 
 
				// normal 
				((z3ds_CUSTOMVERTEX*)p)[i_vec].n = obj->pNormals[ index ]; 
				// texture coordinates 
				if(dxobj.have_texture_coord_0)((z3ds_CUSTOMVERTEX*)p)[i_vec].t0 = obj->pTexVerts[ index ]; 
				((z3ds_CUSTOMVERTEX*)p)[i_vec].t0.y = 1.f -((z3ds_CUSTOMVERTEX*)p)[i_vec].t0.y; 
				// vertex 
				((z3ds_CUSTOMVERTEX*)p)[i_vec++].v = obj->pVerts[ index ]; 
			} 
		} 
		dxobj.pvb->Unlock(); 
 
		dxobjs.push_back(dxobj); 
		dxobj.pvb = NULL; 
	} 
	DeleteObjects(); 
	return 1; 
} 
 
void C3ds::DeleteObjects() 
{ 
	for(int i=0; iobjects.size(); i++) 
	{ 
		if(objects[i].pFaces!=NULL) delete [] objects[i].pFaces; 
		if(objects[i].pFacesShadow!=NULL) delete [] objects[i].pFacesShadow; 
		if(objects[i].pNormals!=NULL) delete [] objects[i].pNormals; 
		if(objects[i].pTexVerts!=NULL) delete [] objects[i].pTexVerts; 
		if(objects[i].pVerts!=NULL) delete [] objects[i].pVerts; 
	} 
	objects.clear(); 
} 
 
 
// texturing:  
// 0-vypnuty	// nenastavuje sa akt. textura, glDisable(GL_TEXTURE_2D);, nezadavaju sa Tex Coord 
// 1-zapnuty	// nastavuje sa akt. textura, glEnable(GL_TEXTURE_2D);, zadavaju sa Tex Coord 
// 2-environmental mapping	// nenastavuje sa akt. textura, nezadavaju sa Tex Coord 
// 3-bez zmeny	// nenastavuje sa akt. textura, zadavaju sa Tex Coord 
// material 
// 0-ziadne zmeny ohladne nastavenia farieb 
// 1-farby su nastavene podla materialu, ak je zapnute osvetlenie nastavuje sa material 
 
void C3ds::Render(LPDIRECT3DDEVICE9 pd, int texturing, int material, DWORD hVertexShader) 
{ 
	for(int i=0; i=0 && dxobjs[i].materialIDdiffuse.x; 
				mtrl.Diffuse.g = mtrl.Ambient.g = mat->diffuse.y; 
				mtrl.Diffuse.b = mtrl.Ambient.b = mat->diffuse.z; 
				mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; 
				pd->SetMaterial( &mtrl ); 
			} 
 
			if(dxobjs[i].have_texture_coord_0 && texturing) 
			{ 
				textures[mat->texureId].SetTexture(pd); 
				pd->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE ); 
				pd->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); 
				pd->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_CURRENT ); 
				pd->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE ); 
			} 
			else 
				pd->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE ); 
		} 
		pd->SetStreamSource( 0, dxobjs[i].pvb, 0, sizeof(z3ds_CUSTOMVERTEX) ); 
		 
//		pd->SetVertexShader( hVertexShader ); 
 
		for(int j=0; jDrawPrimitive( D3DPT_TRIANGLELIST, 3*j, 21000 ); 
		pd->DrawPrimitive( D3DPT_TRIANGLELIST, 3*j, dxobjs[i].count-j ); 
 
		pd->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE ); 
	} 
 
// 	if(material) 
// 	{ 
// 		D3DMATERIAL9 mtrl; 
// 		ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) ); 
// 		mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; 
// 		mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; 
// 		mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f; 
// 		mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; 
// 		pd->SetMaterial( &mtrl ); 
// 	} 
 
}