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

📄 mesh.cpp

📁 liu7788414
💻 CPP
字号:
#include "Mesh.h"
#include "..\System\simplememory.h"
#include "..\System\resfile.h"
#include "Texture.h"
#include "..\System\bufReader.h"


CMesh::CMesh()
{
		Release();
}

CMesh::~CMesh()
{
}


void CMesh::Release()
{	
	m_iCurFrame = -1;
	m_vertexnum = 0;
	m_texcoordnum = 0;
	m_pvertexlist = NULL;
	m_ptexcoordlist = NULL;
	m_pSubMeshs = NULL;		
	m_pBones = NULL;
	m_boneNum = 0;
	m_frameCount = 0;
	m_pVertexRenderBuf = NULL;
	m_submeshCount = 0;		
	m_oneBoneVertex = NULL;
	m_twoBoneVertex = NULL;
	m_oneBVCount = 0;
	m_twoBVCount = 0;
}

extern CResFile *pResFile;
extern CSimpleMemory *SMemory;
extern CGraphics3D *pG3D;
extern int OpenModelFrameCount;
extern char ResFileName[MAX_PATH];

bool CMesh::LoadMesh(CGraphics3D *pG3d, const char* filename)
{	
	if (m_submeshCount > 0)
		return TRUE;
	void *pFile;

	DBGPRINTF("BEGIN LOAD MESH: %s", filename);
	//CEngine *pEngine = pG3d->GetEngine();
	CResFile *pRes = pResFile;
	int rest_size = pRes->LoadFileToStack(filename,&pFile);
	
	DBGPRINTF("LoadFileToStack: SUCCESS");
	CBufReader pData;
	
	if( pFile )
	{
		pData.CBufReader_init( pFile, rest_size);
	}
	else
		return false;
	
	//FILE FLAG's values
	//0x80;// if have the texture
	//0x20;// we have the normal	
	//0x10;// we have the animation	
	//0x01;// we USE the VERTEX animation
	//0x02;// we have the Maximam TWO BONES for one vertex to do animation.

	m_fileflag = pData.ReadChar();

	m_vertexnum = pData.ReadUShort();// the num of the point
	DBGPRINTF("vertex number: %d", m_vertexnum);

	m_texcoordnum = pData.ReadUShort();//
	DBGPRINTF("texture coord number: %d", m_texcoordnum);

	m_submeshCount = pData.ReadUShort();//
	DBGPRINTF("SubMeshCount coord number: %d", m_submeshCount);

	
	DBGPRINTF("READ INFO: SUCCESS");

	m_pvertexlist = (Vertex *)SMemory->HeapMalloc(m_vertexnum * sizeof(Vertex));
	int i, j;
	
	DBGPRINTF("SIZE OF VERTEX: %d", sizeof(Vertex));
	
	if( (m_fileflag&0x20) == 0)
		pData.ReadBlock(m_pvertexlist, m_vertexnum*6);
	else
	{
		int temp[6];
	for(i=0;i<m_vertexnum;i++)
	{
		pData.ReadBlock((void*)&m_pvertexlist[i], 6);

		{
				pData.ReadBlock(temp, 6);
			//to save memory, we remove the normal from vertex struct, we could add it back as need
				//m_pvertexlist[i].normal_x = pData.ReadShort();
				//m_pvertexlist[i].normal_y = pData.ReadShort();
				//m_pvertexlist[i].normal_z = pData.ReadShort();
			}
		}
	}
	
	DBGPRINTF("READ VERTEX: SUCCESS");
	
	m_ptexcoordlist = (Texcoord *)SMemory->HeapMalloc(m_texcoordnum * sizeof(Texcoord));

	pData.ReadBlock((void*)m_ptexcoordlist, m_texcoordnum * sizeof(Texcoord));
	for (i=0; i<m_texcoordnum; i++)
	{		
		m_ptexcoordlist[i].u >>= 2;
		m_ptexcoordlist[i].v >>= 2;
	}

	DBGPRINTF("READ TEX COORD: SUCCESS");
	
	char textureFileName[30], temp[MAX_PATH];
	
	m_pSubMeshs = (Submesh *)SMemory->HeapMalloc(m_submeshCount * sizeof(Submesh));
	for (i=0; i<m_submeshCount; i++)
	{		
		pData.ReadString(textureFileName);
		STRCPY(temp, ResFileName);
		STRCAT(temp, textureFileName);		
		m_pSubMeshs[i].m_material.texid = pG3d->LoadTexture(temp);
		m_pSubMeshs[i].m_facenum = pData.ReadUShort();		
		m_pSubMeshs[i].m_pfaceIndics = (Face *)SMemory->HeapMalloc(m_pSubMeshs[i].m_facenum * sizeof(Face));
		
		for (j=0;j<m_pSubMeshs[i].m_facenum;j++)	{
			pData.ReadBlock((void*)(&m_pSubMeshs[i].m_pfaceIndics[j]), 2*6);
		}				
	}

	//read animation data
	if ((m_fileflag&0x10) != 0)
	{
		m_frameCount = pData.ReadShort();
		if (m_frameCount>0)
		{
			m_boneNum = pData.ReadShort();
			m_pBones = (Bone *)SMemory->HeapMalloc(m_boneNum * sizeof(Bone));
			if ((m_fileflag&0x02) != 0) //two bones
			{
				m_oneBVCount = pData.ReadShort();	
				m_twoBVCount = pData.ReadShort();
				m_oneBoneVertex = (OneBoneVertex *)SMemory->HeapMalloc(m_oneBVCount * sizeof(OneBoneVertex));
				m_twoBoneVertex = (TwoBoneVertex *)SMemory->HeapMalloc(m_twoBVCount * sizeof(TwoBoneVertex));
				
				for (j=0; j<m_oneBVCount; j++)
				{
					m_oneBoneVertex[j].vertexIndex = pData.ReadShort();	
					m_oneBoneVertex[j].boneIndex = pData.ReadChar();				
				}
				for (j=0; j<m_twoBVCount; j++)
				{
					m_twoBoneVertex[j].vertexIndex = pData.ReadShort();	
					m_twoBoneVertex[j].boneIndex1 = pData.ReadChar();						
					m_twoBoneVertex[j].boneWeight1 = pData.ReadUChar(); 
					m_twoBoneVertex[j].boneIndex2 = pData.ReadChar();						
					m_twoBoneVertex[j].boneWeight2 = pData.ReadUChar();
				}					
			}
			for (j=0; j<m_boneNum; j++)
			{
				if ((m_fileflag&0x02) == 0) //ONE bone
				{
					m_pBones[j].vertexCount = pData.ReadShort();
					m_pBones[j].vertexIndics = (short *)SMemory->HeapMalloc(m_pBones[j].vertexCount * sizeof(short));
					pData.ReadBlock(m_pBones[j].vertexIndics, m_pBones[j].vertexCount*2); //short
				}

				//bone's transformations
				m_pBones[j].transforms = (CMatrix44 *)SMemory->HeapMalloc(m_frameCount*sizeof(CMatrix44));
				pData.ReadBlock(m_pBones[j].transforms, m_frameCount*24); //short
				for (i=0; i<m_frameCount; i++)
				{
					for (int k=0; k<9; k++)
						m_pBones[j].transforms[i].m[k] *= 16; //(1<<4)
				}
			}
			OpenModelFrameCount = m_frameCount;
		}
	}

	//read bonding box data
	int count;
	for (i=0; i<m_submeshCount; i++)
	{
		count = m_frameCount;
		if ((m_fileflag&0x10) == 0)
		{
			count = 1;
		}
		m_pSubMeshs[i].m_bbox = (BBox *)SMemory->HeapMalloc(count*sizeof(BBox));
		pData.ReadBlock(m_pSubMeshs[i].m_bbox, count*12);	
	}
	
	DBGPRINTF("read all: SUCCESS");
	pFile = NULL;

	SMemory->StackFree(0);

	if (m_frameCount>0)
	{
		m_pVertexRenderBuf = (Vertex *)SMemory->HeapMalloc(m_vertexnum * sizeof(Vertex));
		MEMCPY(m_pVertexRenderBuf, m_pvertexlist, sizeof(Vertex)*m_vertexnum);
	}
	else
	{		
		GenerateFaceNormal();
	}
/*
	if (m_frameCount>0)	{
		//	allocate 2000 vertex container for animation vertics
		m_pVertexRenderBuf = (Vertex *)SMemory->HeapMalloc(m_vertexnum * sizeof(Vertex));
//		MEMCPY(m_pVertexRenderBuf, m_pvertexlist, sizeof(Vertex)*m_vertexnum);
		for (k=0; k<m_submeshCount; k++)
			m_pSubMeshs[k].m_bbox = (BBox *)SMemory->HeapMalloc(m_frameCount * sizeof(BBox));
		for (i=0; i<m_frameCount; i++)	{
			SetCurrentFrame(i);
			for (k=0; k<m_submeshCount; k++)	{
				m_pSubMeshs[k].m_bbox[i].vtmin = m_pVertexRenderBuf[m_pSubMeshs[k].m_pfaceIndics[0].ver1];
				m_pSubMeshs[k].m_bbox[i].vtmax = m_pVertexRenderBuf[m_pSubMeshs[k].m_pfaceIndics[0].ver1];
				for (j=0;j<m_pSubMeshs[k].m_facenum;j++)	{
					m_pSubMeshs[k].m_bbox[i].vtmin.VMin(m_pVertexRenderBuf[m_pSubMeshs[k].m_pfaceIndics[j].ver1]);
					m_pSubMeshs[k].m_bbox[i].vtmin.VMin(m_pVertexRenderBuf[m_pSubMeshs[k].m_pfaceIndics[j].ver2]);
					m_pSubMeshs[k].m_bbox[i].vtmin.VMin(m_pVertexRenderBuf[m_pSubMeshs[k].m_pfaceIndics[j].ver3]);
					m_pSubMeshs[k].m_bbox[i].vtmax.VMax(m_pVertexRenderBuf[m_pSubMeshs[k].m_pfaceIndics[j].ver1]);
					m_pSubMeshs[k].m_bbox[i].vtmax.VMax(m_pVertexRenderBuf[m_pSubMeshs[k].m_pfaceIndics[j].ver2]);
					m_pSubMeshs[k].m_bbox[i].vtmax.VMax(m_pVertexRenderBuf[m_pSubMeshs[k].m_pfaceIndics[j].ver3]);
				}
			}
		}
	}	else	{
		for (k=0; k<m_submeshCount; k++)	{
			m_pSubMeshs[k].m_bbox = (BBox *)SMemory->HeapMalloc(sizeof(BBox));
			m_pSubMeshs[k].m_bbox->vtmin = m_pvertexlist[m_pSubMeshs[k].m_pfaceIndics[0].ver1];
			m_pSubMeshs[k].m_bbox->vtmax = m_pvertexlist[m_pSubMeshs[k].m_pfaceIndics[0].ver1];
			for (j=0;j<m_pSubMeshs[k].m_facenum;j++)	{
				m_pSubMeshs[k].m_bbox->vtmin.VMin(m_pvertexlist[m_pSubMeshs[k].m_pfaceIndics[j].ver1]);
				m_pSubMeshs[k].m_bbox->vtmin.VMin(m_pvertexlist[m_pSubMeshs[k].m_pfaceIndics[j].ver2]);
				m_pSubMeshs[k].m_bbox->vtmin.VMin(m_pvertexlist[m_pSubMeshs[k].m_pfaceIndics[j].ver3]);
				m_pSubMeshs[k].m_bbox->vtmax.VMax(m_pvertexlist[m_pSubMeshs[k].m_pfaceIndics[j].ver1]);
				m_pSubMeshs[k].m_bbox->vtmax.VMax(m_pvertexlist[m_pSubMeshs[k].m_pfaceIndics[j].ver2]);
				m_pSubMeshs[k].m_bbox->vtmax.VMax(m_pvertexlist[m_pSubMeshs[k].m_pfaceIndics[j].ver3]);
			}
		}
		GenerateFaceNormal();
	}
*/
	DBGPRINTF("end read mesh");
	return true;
}

void CMesh::DrawMesh(CGraphics3D *pG3d)
{
	
	pG3d->SetPreciseMat(m_fileflag&FLAG_UNITDIV16);
	m_pG3d = pG3d;
	for (int i=0; i<m_submeshCount; i++)	
	{
		if( m_pSubMeshs[i].m_material.texid != -1 )
		{
			m_pG3d->SetTexture(m_pSubMeshs[i].m_material.texid);
			DrawSubMesh(i);
		}
	}
}

void CMesh::DrawTexturedMesh(CGraphics3D *pG3d, int texid)
{
	m_pG3d = pG3d;
	for (int i=0; i<m_submeshCount; i++)	
	{
		m_pG3d->SetTexture(texid);
		DrawSubMesh(i);
	}
}

void CMesh::DrawSubMesh(int submeshIndex)
{
//	DBGPRINTF("%d", m_pSubMeshs[submeshIndex].m_facenum);
	if (m_iCurFrame <= 0)	
	{
		if (!m_pG3d->BBCheck(m_pSubMeshs[submeshIndex].m_bbox->vtmin, m_pSubMeshs[submeshIndex].m_bbox->vtmax))
			return;
	}	
	else
	{
		if (!m_pG3d->BBCheck(m_pSubMeshs[submeshIndex].m_bbox[m_iCurFrame].vtmin, m_pSubMeshs[submeshIndex].m_bbox[m_iCurFrame].vtmax))
			return;
	}

	if (m_frameCount > 0)
		m_pG3d->RenderIndexdPrimitives(m_pVertexRenderBuf, m_ptexcoordlist, m_pSubMeshs[submeshIndex].m_pfaceIndics, m_pSubMeshs[submeshIndex].m_facenum);
	else
		m_pG3d->RenderIndexdPrimitives(m_pvertexlist, m_ptexcoordlist, m_pSubMeshs[submeshIndex].m_pfaceIndics, m_pSubMeshs[submeshIndex].m_facenum);
}

void CMesh::SetCurrentFrame(int frameid)
{
	if (m_frameCount == 0)
		return;
//	DBGPRINTF("SetFrame");
	int id = frameid%m_frameCount;
	if (m_iCurFrame == id)
		return;

	m_iCurFrame = id;
	
	
	int i, j;
	Vertex temp1, temp2;
	unsigned int weight1, weight2;
	if ((m_fileflag&0x02) != 0) //two bones
	{
		for (i=0; i<m_oneBVCount; i++)
		{
			m_pVertexRenderBuf[m_oneBoneVertex[i].vertexIndex] = 
				m_pBones[m_oneBoneVertex[i].boneIndex].transforms[id].Transform(m_pvertexlist[m_oneBoneVertex[i].vertexIndex]);
		}
		for (i=0; i<m_twoBVCount; i++)
		{
			temp1 = m_pBones[m_twoBoneVertex[i].boneIndex1].transforms[id].Transform(m_pvertexlist[m_twoBoneVertex[i].vertexIndex]);
			temp2 = m_pBones[m_twoBoneVertex[i].boneIndex2].transforms[id].Transform(m_pvertexlist[m_twoBoneVertex[i].vertexIndex]);
			weight1 = m_twoBoneVertex[i].boneWeight1;
			weight2 = m_twoBoneVertex[i].boneWeight2;
			m_pVertexRenderBuf[m_twoBoneVertex[i].vertexIndex].x = (weight1*temp1.x + weight2*temp2.x)>>7;
			m_pVertexRenderBuf[m_twoBoneVertex[i].vertexIndex].y = (weight1*temp1.y + weight2*temp2.y)>>7;
			m_pVertexRenderBuf[m_twoBoneVertex[i].vertexIndex].z = (weight1*temp1.z + weight2*temp2.z)>>7;
		}
	}
	else // one bone
	{
		for (i=0; i<m_boneNum; i++)
		{
			for (j=0; j<m_pBones[i].vertexCount; j++)
			{
				m_pVertexRenderBuf[m_pBones[i].vertexIndics[j]] = m_pBones[i].transforms[id].Transform(m_pvertexlist[m_pBones[i].vertexIndics[j]]);
			}
		}
	}
	GenerateFaceNormal();
//	DBGPRINTF("End SetFrame");
}

void CMesh::GenerateFaceNormal()
{
	int i, j;
	Face *pFace;
	Vertex v1, v2, v3;
	Vector4s vec;
	for (i=0; i<m_submeshCount; i++)
	{
		for (j=0; j<m_pSubMeshs[i].m_facenum; j++)
		{
			pFace = &m_pSubMeshs[i].m_pfaceIndics[j];
			if (m_frameCount > 0) 
			{//animation model, generate from render buf
				v1 = m_pVertexRenderBuf[pFace->ver[0]];
				v2 = m_pVertexRenderBuf[pFace->ver[1]];
				v3 = m_pVertexRenderBuf[pFace->ver[2]];
			}
			else
			{				
				v1 = m_pvertexlist[pFace->ver[0]];
				v2 = m_pvertexlist[pFace->ver[1]];
				v3 = m_pvertexlist[pFace->ver[2]];
			}

			//cross (v2-v1)*(v3-v1) 
			v2 -= v1;
			v3 -= v1;
			vec.x = v2.y * v3.z - v2.z * v3.y;			
			vec.y = v2.z * v3.x - v2.x * v3.z;			
			vec.z = v2.x * v3.y - v2.y * v3.x;	
			vec.Normalize();
			pFace->normalx = vec.x;			
			pFace->normaly = vec.y;			
			pFace->normalz = vec.z;			
		}
	}
}

⌨️ 快捷键说明

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