⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ms3d.cpp

📁 小型的3D游戏引擎
💻 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 <iostream>
#include <fstream>
#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 }
}

///////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -