www.pudn.com > Gimcrack-v0.0051-Source.zip > ms3d.cpp


 /* 
	GcModel.cpp 
 
		Loads and renders a Milkshape3D model.  
 
	Author:	Brett Porter 
	Email: brettporter@yahoo.com 
	Website: http://rsn.gamedev.net 
	Copyright (C)2001, Brett Porter. All Rights Reserved. 
 
	This file may be used only as long as this copyright notice remains intact. 
*/ 
 
//#include  
#include  
#include "ms3d.h" 
using namespace std; 
 
/////////////////////////////////////////////////////////////////////////////////////// 
 
GcMS3D::GcMS3D() 
{ 
	m_numMeshes = 0; 
	m_meshes = NULL; 
	m_numMaterials = 0; 
	m_materials = NULL; 
	m_numTriangles = 0; 
	m_triangles = NULL; 
	m_numVertices = 0; 
	m_vertices = NULL; 
	 
	// { NEW }  
	m_numJoints = 0; 
	m_joints = NULL; 
 
} 
 
/////////////////////////////////////////////////////////////////////////////////////// 
 
GcMS3D::~GcMS3D() 
{ 
	Destroy(); 
} 
 
/////////////////////////////////////////////////////////////////////////////////////// 
 
bool GcMS3D::Load(char *filename) 
{ 
	ifstream inputFile( filename, ios::in | ios::binary ); 
	if( inputFile.fail() ) 
	{ 
		//cerr << "Couldn't open the model file." << endl; 
		return false; 
	} 
 
	char pathTemp[PATH_MAX+1]; 
	int pathLength; 
	for ( pathLength = strlen( filename ); --pathLength; ) { 
		if ( filename[pathLength] == '/' || filename[pathLength] == '\\' ) { 
			break; 
		} 
	} 
	strncpy(pathTemp, filename, pathLength); 
	 
	int i; 
	if ( pathLength > 0 ) { 
		pathTemp[pathLength++] = '/'; 
	} 
 
	inputFile.seekg(0, ios::end); 
	long fileSize = inputFile.tellg(); 
	inputFile.seekg(0, ios::beg); 
 
	byte * pBuffer = new byte[fileSize]; 
	inputFile.read((char *)pBuffer, fileSize); 
	inputFile.close(); 
 
	const byte *pPtr = pBuffer; 
	MS3DHeader *pHeader = ( MS3DHeader* )pPtr; 
	pPtr += sizeof( MS3DHeader ); 
 
	if(strncmp( pHeader->m_ID, "MS3D000000", 10 ) != 0) 
	{ 
		//cerr << "Not an MS3D file." << endl; 
		return false; 
	} 
 
	if( pHeader->m_version < 3 ) 
	{ 
		//cerr << "I know nothing about MS3D v1.2" << endl; 
		return false; 
	} 
 
	int nVertices = *(word*)pPtr;  
	m_numVertices = nVertices; 
	m_vertices = new Vertex[nVertices]; 
	pPtr += sizeof(word); 
 
	for(i = 0; i < nVertices; i++) 
	{ 
		MS3DVertex * pVertex = (MS3DVertex*)pPtr; 
		m_vertices[i].m_boneID = pVertex->m_boneID; 
		memcpy( m_vertices[i].m_location, pVertex->m_vertex, sizeof(float)*3); 
		 
		//m_vertices[i].m_location.x = pVertex->m_vertex[0]; 
		//m_vertices[i].m_location.y = pVertex->m_vertex[1]; 
		//m_vertices[i].m_location.z = pVertex->m_vertex[2]; 
 
		pPtr += sizeof(MS3DVertex); 
	} 
 
	int nTriangles = *(word*)pPtr; 
	m_numTriangles = nTriangles; 
	m_triangles = new Triangle[nTriangles]; 
	pPtr += sizeof(word); 
 
	for ( i = 0; i < nTriangles; i++ ) 
	{ 
		MS3DTriangle *pTriangle = ( MS3DTriangle* )pPtr; 
		int vertexIndices[3] = { pTriangle->m_vertexIndices[0], pTriangle->m_vertexIndices[1], pTriangle->m_vertexIndices[2] }; 
		float t[3] = { 1.0f-pTriangle->m_t[0], 1.0f-pTriangle->m_t[1], 1.0f-pTriangle->m_t[2] }; 
		memcpy( m_triangles[i].m_vertexNormals, pTriangle->m_vertexNormals, sizeof(float)*3*3 ); 
		memcpy( m_triangles[i].m_s, pTriangle->m_s, sizeof(float)*3 ); 
		memcpy( m_triangles[i].m_t, t, sizeof(float)*3 ); 
		memcpy( m_triangles[i].m_vertexIndices, vertexIndices, sizeof(int)*3 ); 
		pPtr += sizeof( MS3DTriangle ); 
	} 
 
	int nGroups = *(word*)pPtr; 
	m_numMeshes = nGroups; 
	m_meshes = new Mesh[nGroups]; 
	pPtr += sizeof(word); 
	for ( i = 0; i < nGroups; i++ ) 
	{ 
		pPtr += sizeof(byte);	// flags 
		pPtr += 32;				// name 
 
		word nTriangles = *(word*)pPtr; 
		pPtr += sizeof(word); 
		int *pTriangleIndices = new int[nTriangles]; 
		for ( int j = 0; j < nTriangles; j++ ) 
		{ 
			pTriangleIndices[j] = *(word*)pPtr; 
			pPtr += sizeof(word); 
		} 
 
		char materialIndex = *(char*)pPtr; 
		pPtr += sizeof(char); 
	 
		m_meshes[i].m_materialIndex = materialIndex; 
		m_meshes[i].m_numTriangles = nTriangles; 
		m_meshes[i].m_triangleIndices = pTriangleIndices; 
	} 
 
	int nMaterials = *(word*)pPtr; 
	m_numMaterials = nMaterials; 
	m_materials = new Material[nMaterials]; 
	pPtr += sizeof(word); 
 
	for(i = 0; i < nMaterials; i++) 
	{ 
		MS3DMaterial *pMaterial = ( MS3DMaterial* )pPtr; 
		memcpy( m_materials[i].m_ambient, pMaterial->m_ambient, sizeof(float)*4 ); 
		memcpy( m_materials[i].m_diffuse, pMaterial->m_diffuse, sizeof(float)*4 ); 
		memcpy( m_materials[i].m_specular, pMaterial->m_specular, sizeof(float)*4 ); 
		memcpy( m_materials[i].m_emissive, pMaterial->m_emissive, sizeof(float)*4 ); 
		m_materials[i].m_shininess = pMaterial->m_shininess; 
 
		if(strncmp(pMaterial->m_texture, ".\\", 2) == 0)  
		{ 
			// MS3D 1.5.x relative path 
			strcpy(pathTemp + pathLength, pMaterial->m_texture + 2); 
			//m_materials[i].m_textureFilename = new char[strlen( pathTemp )+1]; 
			//strcpy(m_materials[i].m_textureFilename, pa 
			strcpy( m_materials[i].m_textureFilename, pathTemp ); 
			m_materials[i].texture.Create(pathTemp); 
		} 
		else  
		{ 
			// MS3D 1.4.x or earlier - absolute path 
			//m_materials[i].m_textureFilename = new char[strlen( pMaterial->m_texture )+1]; 
			strcpy( m_materials[i].m_textureFilename, pMaterial->m_texture ); 
			m_materials[i].texture.Create(pathTemp); 
		} 
 
		pPtr += sizeof(MS3DMaterial); 
	} 
 
	// Load Skeletal Animation Stuff 
 
	float animFPS = *(float*)pPtr; 
	pPtr += sizeof(float); 
 
	// skip currentTime 
	pPtr += sizeof(float); 
 
	int totalFrames = *(int*)pPtr; 
	pPtr += sizeof(int); 
 
	m_totalTime = totalFrames*1000.0/animFPS; 
 
	delete[] pBuffer; 
 
	GcVector3 extreme(0, 0, 0); 
 
	for( i = 0; i < m_numMeshes; i++ ) 
	{ 
		for( int j = 0; j < m_meshes[i].m_numTriangles; j++ ) 
		{ 
			int triangleIndex = m_meshes[i].m_triangleIndices[j]; 
			const Triangle * pTri = &m_triangles[triangleIndex]; 
				 
				 
			for ( int k = 0; k < 3; k++ ) 
			{ 
				int index = pTri->m_vertexIndices[k]; 
 
				if( m_vertices[index].m_location[0] > extreme.x ) 
					extreme.x = m_vertices[index].m_location[0]; 
 
				if( m_vertices[index].m_location[1] > extreme.y ) 
					extreme.y = m_vertices[index].m_location[1]; 
 
				if( m_vertices[index].m_location[2] > extreme.z ) 
					extreme.z = m_vertices[index].m_location[2]; 
			} 
		} 
	} 
 
	g_Debug->Log("Extreme x: %f - y: %f - z: %f\n", extreme.x, extreme.y, extreme.z ); 
	SetExtents(extreme); 
 
	return true; 
} 
 
/////////////////////////////////////////////////////////////////////////////////////// 
 
bool GcMS3D::RenderKeyFrame(int frame) 
{ 
	glPushMatrix(); 
	static int loop = 0; 
 
	loop++; 
	if(loop > 360) { 
		loop = 0; 
	} 
	 
	glMultMatrixf(m_worldMatrix); 
 
	glScalef(GetWorldScaling().x, GetWorldScaling().y, GetWorldScaling().z ); 
	 
/*	if(settings.ShowDebug()) 
	{ 
		glBegin(GL_LINES); 
			glColor3f(0.5, 0.0, 0.0); 
			glVertex3f(-2000, 0.0, 0.0); 
			glVertex3f( 2000, 0.0, 0.0); 
 
			glColor3f(0.5, 0.0, 0.0); 
			glVertex3f( 0, -2000, 0.0); 
			glVertex3f( 0, 2000, 0.0); 
 
			glColor3f(0.5, 0.0, 0.0); 
			glVertex3f( 0, 0, -2000); 
			glVertex3f( 0, 0, 2000); 
		glEnd(); 
	}*/ 
	 
 
	glColor3f(1.0, 1.0, 1.0); 
 
	// Draw by group 
	for(int i = 0; i < m_numMeshes; i++) 
	{ 
		int materialIndex = m_meshes[i].m_materialIndex; 
 
		if(materialIndex >= 0) 
		{ 
			glMaterialfv( GL_FRONT, GL_AMBIENT, m_materials[materialIndex].m_ambient ); 
			glMaterialfv( GL_FRONT, GL_DIFFUSE, m_materials[materialIndex].m_diffuse ); 
			glMaterialfv( GL_FRONT, GL_SPECULAR, m_materials[materialIndex].m_specular ); 
			glMaterialfv( GL_FRONT, GL_EMISSION, m_materials[materialIndex].m_emissive ); 
			glMaterialf( GL_FRONT, GL_SHININESS, m_materials[materialIndex].m_shininess ); 
 
			if(m_materials[materialIndex].texture.IsLoaded()) 
			{ 
				glEnable(GL_TEXTURE_2D); 
				m_materials[materialIndex].texture.Bind(); 
				 
			} 
		} 
 
		glBegin( GL_TRIANGLES ); 
		{ 
			for ( int j = 0; j < m_meshes[i].m_numTriangles; j++ ) 
			{ 
				int triangleIndex = m_meshes[i].m_triangleIndices[j]; 
				const Triangle * pTri = &m_triangles[triangleIndex]; 
 
				for ( int k = 0; k < 3; k++ ) 
				{ 
					int index = pTri->m_vertexIndices[k]; 
 
					// same as before 
					glTexCoord2f( pTri->m_s[k], pTri->m_t[k] ); 
					glNormal3fv( pTri->m_vertexNormals[k] ); 
				 
					glVertex3fv( m_vertices[index].m_location ); 
				} 
			} 
		} 
 
		glEnd(); 
	} 
 
	glPopMatrix(); 
 
	//glDisable(GL_TEXTURE_2D); 
 
	return true; 
} 
 
/////////////////////////////////////////////////////////////////////////////////////// 
 
void GcMS3D::Destroy() 
{ 
	int i; 
	 
	for ( i = 0; i < m_numMeshes; i++ ) 
		delete[] m_meshes[i].m_triangleIndices; 
	 
	//for ( i = 0; i < m_numMaterials; i++ ) 
		//delete[] m_materials[i].m_pTextureFilename; 
 
	m_numMeshes = 0; 
	if ( m_meshes != NULL ) 
	{ 
		delete[] m_meshes; 
		m_meshes = NULL; 
	} 
 
	m_numMaterials = 0; 
	if ( m_materials != NULL ) 
	{ 
		delete[] m_materials; 
		m_materials = NULL; 
	} 
 
	m_numTriangles = 0; 
	if ( m_triangles != NULL ) 
	{ 
		delete[] m_triangles; 
		m_triangles = NULL; 
	} 
 
	m_numVertices = 0; 
	if ( m_vertices != NULL ) 
	{ 
		delete[] m_vertices; 
		m_vertices = NULL; 
	} 
 
	// { NEW } 
	for ( i = 0; i < m_numJoints; i++ ) 
	{ 
		delete[] m_joints[i].m_rotationKeyframes; 
		delete[] m_joints[i].m_translationKeyframes; 
	} 
 
	m_numJoints = 0; 
	if ( m_joints != NULL ) 
	{ 
		delete[] m_joints; 
		m_joints = NULL; 
	} 
 
	// { end NEW } 
} 
 
///////////////////////////////////////////////////////////////////////////////////////