ms3dloader.cpp

来自「3D游戏展示程序」· C++ 代码 · 共 367 行

CPP
367
字号
//--------------------------------------------------
//  Desc: MS3D model Loader
//  Author: artsylee/2007.3.6
//--------------------------------------------------

#include "Ms3dLoader.h"
#include "GMath.h"
#include "Common.h"

const DWORD MS3DRenderVertex::MS3DFVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
const DWORD CollisionBox::COLLISIONFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;

CMS3DLoader::CMS3DLoader()
{
	m_numMeshes = 0;
	m_pMeshes = NULL;
	m_numTriangles = 0;
	m_pTriangles = NULL;
	m_numVertices = 0;
	m_pVertices = NULL;
	m_numMaterials = 0;
	m_pMaterials = NULL;
	m_ppRenderVertex = NULL;
	m_bLoad = false;
}

CMS3DLoader::~CMS3DLoader()
{
	Destroy();
}

void CMS3DLoader::Destroy(void)
{
	for(unsigned short i=0; i<m_numMeshes; i++)
	{
		delete[] m_pMeshes[i].m_pTriangleIndices;
	}
	for(unsigned short i=0; i<m_numMaterials; i++)
	{
		// 已经不再使用
		// delete[] m_pMaterials[i].m_pTextureFilename;
		if(g_pTextureManager)
		{
			g_pTextureManager->ReleaseTexture(m_pMaterials[i].m_texture);
		}
	}

	if(m_ppRenderVertex != NULL)
	{
		for(unsigned short i=0; i<m_numMeshes; i++)
		{
			if(m_ppRenderVertex[i] != NULL)
			{
				delete [] m_ppRenderVertex[i];
				m_ppRenderVertex[i] = NULL;
			}
		}
		delete [] m_ppRenderVertex;
		m_ppRenderVertex = NULL;
	}

	m_numMeshes = 0;
	if(m_pMeshes != NULL)
	{
		delete[] m_pMeshes;
		m_pMeshes = NULL;
	}

	m_numTriangles = 0;
	if(m_pTriangles != NULL)
	{
		delete [] m_pTriangles;
		m_pTriangles = NULL;
	}

	m_numVertices = 0;
	if(m_pVertices != NULL)
	{
		delete [] m_pVertices;
		m_pVertices = NULL;
	}

	m_numMaterials = 0;
	if(m_pMaterials != NULL)
	{
		delete [] m_pMaterials;
		m_pMaterials = NULL;
	}
}

bool CMS3DLoader::Load(const char *pFileName)
{
	//------------------------------------------------
	// 数学库测试
	//D3DXVECTOR3 vec(10.7,30.6,10.543);
	//D3DXVECTOR3 vec2(12.5, 42.3, 11.1);
	//float a = D3DXVec3Dot(&vec, &vec2);
	//float b = VectorDot(vec, vec2);
	//------------------------------------------------
	if(pFileName == NULL || pFileName[0] == 0)
		return false;
	FILE *file = fopen(pFileName, "rb");
	if(file == NULL)
		return false;

	//------------------------------------------------
	// 应该添加Destroy操作(OK)
	//------------------------------------------------
	Destroy();

	MS3DHeader header;
	fread(&header.m_ID, sizeof(char), 10, file);
	fread(&header.m_version, sizeof(int), 1, file);
	if(strncmp(header.m_ID, "MS3D000000", 10) != 0)
	{ 
		// 输出错误记录
		fclose(file);
		return false;
	}
	if(header.m_version<3 || header.m_version>4)
	{
		// 输出错误记录
		// Only Milkshape3D Version 1.3 and 1.4 is supported.
		fclose(file);
		return false;
	}

	// Vertices
	fread(&m_numVertices, sizeof(unsigned short), 1, file);
	m_pVertices = new Vertex[m_numVertices];
	MS3DVertex ms3dVertex;
	for(unsigned short i=0; i<m_numVertices; i++)
	{
		fread(&ms3dVertex, sizeof(MS3DVertex), 1, file);
		memcpy(m_pVertices[i].m_location, ms3dVertex.m_vertex, sizeof(float)*3);
	}
	// Triangles
	fread(&m_numTriangles, sizeof(unsigned short), 1, file);
	m_pTriangles = new Triangle[m_numTriangles];
	MS3DTriangle ms3dTriangle;
	for(unsigned short i=0; i<m_numTriangles; i++)
	{
		fread(&ms3dTriangle, sizeof(MS3DTriangle), 1, file);
		//--------------------------------------------------------
		// 每个三角形有三个法线向量, 我们只需要一个面向量.
		// 因此不使用文件中的向量数量, 自己计算.
		int v1 = ms3dTriangle.m_vertexIndices[0];
		int v2 = ms3dTriangle.m_vertexIndices[1];
		int v3 = ms3dTriangle.m_vertexIndices[2];

		D3DXVECTOR3 vec1(m_pVertices[v1].m_location[0], m_pVertices[v1].m_location[1], -m_pVertices[v1].m_location[2]);
		D3DXVECTOR3 vec2(m_pVertices[v2].m_location[0], m_pVertices[v2].m_location[1], -m_pVertices[v2].m_location[2]);
		D3DXVECTOR3 vec3(m_pVertices[v3].m_location[0], m_pVertices[v3].m_location[1], -m_pVertices[v3].m_location[2]);
		D3DXVECTOR3 vec4;
		// 顺时针方向V1, V3, V2
		vec3 -= vec1;
		vec2 -= vec1;
		
		D3DXVec3Cross(&vec4, &vec3, &vec2);
		D3DXVec3Normalize(&vec4, &vec4);
		
		m_pTriangles[i].m_normal[0] = vec4.x;
		m_pTriangles[i].m_normal[1] = vec4.y;
		m_pTriangles[i].m_normal[2] = vec4.z;
		//--------------------------------------------------------
	//	memcpy(m_pTriangles[i].m_normal, ms3dTriangle.m_vertexNormals, sizeof(float)*3*3);
		memcpy(m_pTriangles[i].m_u, ms3dTriangle.m_u, sizeof(float)*3);
		memcpy(m_pTriangles[i].m_v, ms3dTriangle.m_v, sizeof(float)*3);
		memcpy(m_pTriangles[i].m_vertexIndices, ms3dTriangle.m_vertexIndices, sizeof(unsigned short)*3);

	}
	// Meshes
	fread(&m_numMeshes, sizeof(unsigned short), 1, file);
	m_pMeshes = new Mesh[m_numMeshes];
	m_ppRenderVertex = new MS3DRenderVertex* [m_numMeshes];
	MS3DMesh ms3dMesh;
	ms3dMesh.m_TriangleIndices = new unsigned short[m_numTriangles];
	for(unsigned short i=0; i<m_numMeshes; i++)
	{
		fread(&ms3dMesh.m_flags, sizeof(unsigned char), 1, file);
		fread(ms3dMesh.m_name, sizeof(char), 32, file);
		fread(&ms3dMesh.m_numTriangles, sizeof(unsigned short), 1, file);
		fread(ms3dMesh.m_TriangleIndices, sizeof(unsigned short), ms3dMesh.m_numTriangles, file);
		fread(&ms3dMesh.m_MaterialIndex, sizeof(char), 1, file);

		m_pMeshes[i].m_pTriangleIndices = new unsigned short[ms3dMesh.m_numTriangles];
		memcpy(m_pMeshes[i].m_pTriangleIndices, ms3dMesh.m_TriangleIndices, sizeof(unsigned short)*ms3dMesh.m_numTriangles);

		m_pMeshes[i].m_textureIndex = ms3dMesh.m_MaterialIndex;
		m_pMeshes[i].m_numTriangles = ms3dMesh.m_numTriangles;
		m_ppRenderVertex[i] = new MS3DRenderVertex[m_numTriangles*3];
	}
	delete [] ms3dMesh.m_TriangleIndices;

	// Materials
	fread(&m_numMaterials, sizeof(unsigned short), 1, file);
	m_pMaterials = new Material[m_numMaterials];
	MS3DMaterial ms3dMater;
	for(unsigned short i=0; i<m_numMaterials; i++)
	{
		fread(&ms3dMater, sizeof(MS3DMaterial), 1, file);
		memcpy(m_pMaterials[i].m_ambient, ms3dMater.m_ambient, sizeof(float)*4);
		memcpy(m_pMaterials[i].m_diffuse, ms3dMater.m_diffuse, sizeof(float)*4);
		memcpy(m_pMaterials[i].m_specular, ms3dMater.m_specular, sizeof(float)*4);
		memcpy(m_pMaterials[i].m_emissive, ms3dMater.m_emissive, sizeof(float)*4);
		m_pMaterials[i].m_shininess = ms3dMater.m_shininess;
		m_pMaterials[i].m_pTextureFilename = NULL;

		char szFile[MAX_PATH];
		strcpy(szFile, pFileName);
		for(unsigned short j=strlen(szFile)-1; j>=0; j--)
		{
			if(szFile[j] == '\\')
				break;
			else
				szFile[j] = 0;
		}
		strcat(szFile, ms3dMater.m_texture);
		m_pMaterials[i].m_texture = g_pTextureManager->LoadTexture(szFile, MM_KEEPINMEMORY, 0);
	}

	fclose(file);

	CreateBoundary();

	// 填充顶点
	for(int i=0; i<m_numMeshes; i++)
	{
		for(int j=0; j<m_pMeshes[i].m_numTriangles; j++)
		{
			int triangleIndex = m_pMeshes[i].m_pTriangleIndices[j];
			// ms3d中三角形顶点按逆时针存放且定义为正面
			// 在d3d中要转换为顺时针(d3d为左手坐标系)
			for(int k=2; k>=0; k--)	// 反方向
			{
				int index = m_pTriangles[triangleIndex].m_vertexIndices[k];
				m_ppRenderVertex[i][j*3+(2-k)] = MS3DRenderVertex(
					 m_pVertices[index].m_location[0],
					 m_pVertices[index].m_location[1], 
					 // 右手坐标系转左手坐标系
					-m_pVertices[index].m_location[2],  
					
					m_pTriangles[triangleIndex].m_normal[0],
					m_pTriangles[triangleIndex].m_normal[1],
					m_pTriangles[triangleIndex].m_normal[2],
					
					m_pTriangles[triangleIndex].m_u[k],
					m_pTriangles[triangleIndex].m_v[k]);
			}
		}
	}
	m_bLoad = true;
	//------------------------------------------------
	// 成功加载后, 增加引用计数
	m_Ref = 1;
	m_Name = pFileName;
	m_Type = TYPE_MS3D;
	//------------------------------------------------

	return true;
}

void CMS3DLoader::CreateBoundary()
{
	for(unsigned short i=0; i<m_numVertices; i++)
	{
		if(m_pVertices[i].m_location[0]>m_boundary.maxx)
			m_boundary.maxx = m_pVertices[i].m_location[0];
		if(m_pVertices[i].m_location[0]<m_boundary.minx)
			m_boundary.minx = m_pVertices[i].m_location[0];
		if(m_pVertices[i].m_location[1]>m_boundary.maxy)
			m_boundary.maxy = m_pVertices[i].m_location[1];
		if(m_pVertices[i].m_location[1]<m_boundary.miny)
			m_boundary.miny = m_pVertices[i].m_location[1];
		if(-m_pVertices[i].m_location[2]>m_boundary.maxz)
			m_boundary.maxz = -m_pVertices[i].m_location[2];
		if(-m_pVertices[i].m_location[2]<m_boundary.minz)
			m_boundary.minz = -m_pVertices[i].m_location[2];
	}

	int point = 0;
	// bottom pane
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.miny, m_boundary.minz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.miny, m_boundary.minz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.miny, m_boundary.minz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.miny, m_boundary.maxz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.miny, m_boundary.maxz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.miny, m_boundary.maxz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.miny, m_boundary.maxz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.miny, m_boundary.minz);
	// top pane
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.maxy, m_boundary.minz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.maxy, m_boundary.minz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.maxy, m_boundary.minz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.maxy, m_boundary.maxz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.maxy, m_boundary.maxz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.maxy, m_boundary.maxz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.maxy, m_boundary.maxz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.maxy, m_boundary.minz);
	// other side
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.miny, m_boundary.minz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.maxy, m_boundary.minz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.miny, m_boundary.minz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.maxy, m_boundary.minz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.miny, m_boundary.maxz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.maxx, m_boundary.maxy, m_boundary.maxz);

	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.miny, m_boundary.maxz);
	m_CollisionVertex[point++] = CollisionBox(m_boundary.minx, m_boundary.maxy, m_boundary.maxz);
}

D3DXVECTOR3 CMS3DLoader::GetVertex(int number)
{
	if(number<0 || number>(m_numVertices-1))
		number=0;

	return D3DXVECTOR3(
		m_pVertices[number].m_location[0],
		m_pVertices[number].m_location[1],
		-m_pVertices[number].m_location[2]);

}

void CMS3DLoader::Render() 
{	
	if(!m_bLoad)
		return;

	g_pD3DDevice->SetFVF(MS3DRenderVertex::MS3DFVF);
	for(unsigned short i=0; i<m_numMeshes; i++)
	{
		int matIndex = m_pMeshes[i].m_textureIndex;
		// 材质
		ZeroMemory(&m_material, sizeof(D3DMATERIAL9));
		memcpy(&m_material.Diffuse, m_pMaterials[matIndex].m_diffuse, sizeof(float)*4);
		memcpy(&m_material.Ambient, m_pMaterials[matIndex].m_ambient, sizeof(float)*4);
		memcpy(&m_material.Specular, m_pMaterials[matIndex].m_specular, sizeof(float)*4);
		memcpy(&m_material.Emissive, m_pMaterials[matIndex].m_emissive, sizeof(float)*4);

		m_material.Power = 0.8f;//m_pMaterials[matIndex].m_shininess;
		g_pD3DDevice->SetMaterial(&m_material);
		SET_TEXTURE_TYPE(0, m_pMaterials[matIndex].m_texture);
		g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, m_pMeshes[i].m_numTriangles, m_ppRenderVertex[i], sizeof(MS3DRenderVertex));
	}
}

void CMS3DLoader::DrawBoundary()
{
	if(!m_bLoad)
		return;
	g_pD3DDevice->SetTexture(0, NULL);
	g_pD3DDevice->SetFVF(CollisionBox::COLLISIONFVF);
	g_pD3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 12, m_CollisionVertex, sizeof(CollisionBox));
}

// end of this file LIYUANXI(2007_3_8)


⌨️ 快捷键说明

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