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 + -
显示快捷键?