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

📄 maxmesh.cpp

📁 liu7788414
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// MaxMesh.cpp: implementation of the CMaxMesh class.
//
//////////////////////////////////////////////////////////////////////

#include "MaxMesh.h"
#include "modStack.h"
#include "iskin.h"
#include "decomp.h"
#include "IGameModifier.h"

//#define ONE_BONE_PER_VERTEX_ONLY
//#define MAX_TWO_BONES_COMPATIBLE_ONE_BONE //

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMaxMesh::CMaxMesh()
{
	m_numMatrials = 0;
	m_numVertics = 0;
	m_numFaces = 0;
	m_numTexCoords = 0;
	m_FameCount = 0;
}

CMaxMesh::~CMaxMesh()
{
	//clear FrameVertics 
	int count = m_Vertics.size();
	for (int i=0; i<count; i++)
	{
		if (m_Vertics[i].FrameVertics != NULL)
			delete [] m_Vertics[i].FrameVertics;
	}
}

int CMaxMesh::AddMatrial(Mtl *pMtl, vector<MaxMatrial> *pMtrlList)
{
	if (pMtl == NULL) return 0;
	int oldnum = m_numMatrials;
	Mtl *pCurMtl;
	Texmap *pTexMap;
	FindTextureFilename findTextureFilename;
	MaxMatrial mat;
	
	int cSubMaterials = pMtl->NumSubMtls();
	if (cSubMaterials > 0)
	{
		//actually in our max model, we only have one main material. So the programe will not run to here
		for (int i=0; i<cSubMaterials; i++)
		{
			pCurMtl = pMtl->GetSubMtl(i);
			pTexMap = pCurMtl->GetSubTexmap(ID_DI);	
			if (pTexMap)
			{
				pTexMap->EnumAuxFiles(findTextureFilename, FILE_ENUM_ALL);
				strcpy(mat.texName, findTextureFilename.m_szTextureName);
				mat.bUseTexture = TRUE;
			}
			pMtrlList->push_back(mat);
		}
	}
	else
	{
		pTexMap = pMtl->GetSubTexmap(ID_DI);	
		if (pTexMap)
		{
			pTexMap->EnumAuxFiles(findTextureFilename, FILE_ENUM_ALL);
			strcpy(mat.texName, findTextureFilename.m_szTextureName);
			mat.bUseTexture = TRUE;
		}
		pMtrlList->push_back(mat);
	}		

	return pMtrlList->size();
}


// From the SDK
// How to calculate UV's for face mapped materials.
static Point3 basic_tva[3] = { 
	Point3(0.0,0.0,0.0),Point3(1.0,0.0,0.0),Point3(1.0,1.0,0.0)
};
static Point3 basic_tvb[3] = { 
	Point3(1.0,1.0,0.0),Point3(0.0,1.0,0.0),Point3(0.0,0.0,0.0)
};
static int nextpt[3] = {1,2,0};
static int prevpt[3] = {2,0,1};

void CMaxMesh::make_face_uv(Face *f, Point3 *tv)
{
	int na,nhid,i;
	Point3 *basetv;
	/* make the invisible edge be 2->0 */
	nhid = 2;
	if (!(f->flags&EDGE_A))  nhid=0;
	else if (!(f->flags&EDGE_B)) nhid = 1;
	else if (!(f->flags&EDGE_C)) nhid = 2;
	na = 2-nhid;
	basetv = (f->v[prevpt[nhid]]<f->v[nhid]) ? basic_tva : basic_tvb; 
	for (i=0; i<3; i++) {  
		tv[i] = basetv[na];
		na = nextpt[na];
	}
}


void CMaxMesh::AddSubMeshData(Mesh *pMesh, Mtl *pMtl, INode *pNode, IGameNode *pGameNode)
{
	MaxSubMesh submesh;
	AddMatrial(pMtl, &submesh.Mtrl);

	int vcount = 0;
	int fcount = 0;
	int texCoordcount = 0;
	int i;
	
	//temp mesh data
	MaxVertex vertex;
	MaxFace face;
	MaxTexCoord texcoord;
	Point3 data;
	
	vcount = pMesh->numVerts;
	fcount = pMesh->numFaces;
	texCoordcount = pMesh->numTVerts;
	
	pMesh->buildNormals();
	
	Matrix3 tm = pNode->GetObjTMBeforeWSM(0);
	BOOL negScale = (DotProd(CrossProd(tm.GetRow(0),tm.GetRow(1)),tm.GetRow(2))<0.0)?1:0;	
	int vx1, vx2, vx3;
		// Order of the vertices. Get 'em counter clockwise if the objects is
	// negatively scaled.
	if (negScale) {
		vx1 = 2;
		vx2 = 1;
		vx3 = 0;
	}
	else {
		vx1 = 0;
		vx2 = 1;
		vx3 = 2;
	}
	
	Matrix3 matrix = pNode->GetObjectTM(m_startTime) ;
	Point3 org(0, 0, 0);
	matrix.TransformPoints(&org,1);
	
	//get vertex data
	for (i=0; i<vcount; i++)
	{ 
		//transform vertex position and normals to get them in the world space
		data = pMesh->getVert(i);
		matrix.TransformPoints(&data, 1);
		vertex.x = data.x;
		vertex.y = data.y;
		vertex.z = data.z;
		data = pMesh->getNormal(i);
		matrix.TransformPoints(&data,1);
		data = (data-org).Normalize();
		vertex.n1 = data.x;
		vertex.n2 = data.y;
		vertex.n3 = data.z;
		submesh.Vertics.push_back(vertex);
	}
	
	//get texture coordinate
	//ok: according to the ASE source code, we maybe don't have texture coordinate from mesh
	//because of MTLREQ_FACEMAP, So we should check it first

	ULONG matreq = pMtl->Requirements(-1);
	if (matreq & MTLREQ_FACEMAP) 
	{		
		texCoordcount = fcount*3;
		for (i=0; i<pMesh->getNumFaces(); i++) 
		{
			Point3 tv[3];
			Face* f = &pMesh->faces[i];
			make_face_uv(f, tv);
			for (int k=0; k<3; k++)
			{
				texcoord.u = tv[k].x;
				texcoord.v = tv[k].y;
				submesh.TexCoord.push_back(texcoord);
			}
		}
	}
	else
	{
		for (i=0; i<texCoordcount; i++)
		{
			texcoord.u = pMesh->tVerts[i].x;
			texcoord.v = pMesh->tVerts[i].y;
			submesh.TexCoord.push_back(texcoord);
		}
	}
	
	
	//get face data
	for (i=0; i<fcount; i++)
	{
		face.v1 = pMesh->faces[i].getVert(vx1);
		face.v2 = pMesh->faces[i].getVert(vx2);
		face.v3 = pMesh->faces[i].getVert(vx3);

		//find the face normal, and keep the vertics in right order 
		Point3 normal = pMesh->getFaceNormal(i);		
		matrix.TransformPoints(&normal,1);
		face.normal = (normal-org).Normalize();

		if (matreq & MTLREQ_FACEMAP)
		{
			face.t1 = i*3+0;
			face.t2 = i*3+1;
			face.t3 = i*3+2;
		}
		else
		{
			if (texCoordcount>0)
			{
				face.t1 = pMesh->tvFace[i].t[vx1];
				face.t2 = pMesh->tvFace[i].t[vx2];
				face.t3 = pMesh->tvFace[i].t[vx3];
			}
			else
			{
				face.t1 = 0;
				face.t2 = 0;
				face.t3 = 0;
			}
		}
		
		face.matid = pMesh->faces[i].getMatID()%submesh.Mtrl.size();
		submesh.Faces.push_back(face);
	}	
	AddAnimationData(&submesh, pGameNode);

	m_meshs.push_back(submesh);
}

void CMaxMesh::ExportMaxMesh(const char *fileName)
{
	ofstream fout(fileName);
	fout.precision(4);
	fout<<fixed;
	int i=0;
	fout << "Matrial count: "<< m_numMatrials <<"\n";
	for (i=0; i<m_numMatrials; i++)
	{
		fout << m_Matrials[i].texName << "\n";
	}
	fout << "\n";
	
	fout << "vertex count: "<< m_numVertics <<"\n";
	for (i=0; i<m_numVertics; i++)
	{
		fout << m_Vertics[i].x << ", " << m_Vertics[i].y << ", " << m_Vertics[i].z << "; " 
			<< m_Vertics[i].n1 << ", " << m_Vertics[i].n2 << ", " << m_Vertics[i].n3 << ";\n";
	}
	fout << "\n";
	
	fout << "texture coordinate count: "<< m_numTexCoords <<"\n";
	for (i=0; i<m_numTexCoords; i++)
	{
		fout << m_TexCoord[i].u << ", " << m_TexCoord[i].v  << ";\n";
	}
	fout << "\n";
	
	fout << "face count: "<< m_numFaces <<"\n";
	for (i=0; i<m_numFaces; i++)
	{
		fout << m_Faces[i].matid << "; "<< m_Faces[i].v1 << ", " << m_Faces[i].v2 << ", " << m_Faces[i].v3
			 << "; " << m_Faces[i].t1 << ", " << m_Faces[i].t2 << ", " << m_Faces[i].t3<< ";\n";
	}
}

void CMaxMesh::ConvertToOurMesh(CMesh *pMesh)
{
	int i, j, m;
	
	Vertex vert;
	Texcoord texcoor;
	vector<MaxFace> tempFaceList;

	//get a origin copy
	for (i=0; i<m_numFaces; i++)
		tempFaceList.push_back(m_Faces[i]);
	
	//first convert vertex position data to int, and check if there is a same one in the new list
	MaxVertex mvtemp;
	for (i=0; i<m_numVertics; i++)
	{
		mvtemp = m_Vertics[i];
		vert.x = (int)(m_Vertics[i].x*16+(m_Vertics[i].x>0?0.5f:(-0.5f)));
		vert.y = (int)(m_Vertics[i].y*16+(m_Vertics[i].y>0?0.5f:(-0.5f)));
		vert.z = (int)(m_Vertics[i].z*16+(m_Vertics[i].z>0?0.5f:(-0.5f)));
		vert.normal_x = (int)(m_Vertics[i].n1*1024);
		vert.normal_y = (int)(m_Vertics[i].n2*1024);
		vert.normal_z = (int)(m_Vertics[i].n3*1024);
/*		for (j=0; j<pMesh->m_pvertexlist.size(); j++)
		{
			if (vert == pMesh->m_pvertexlist[j])
			{
				//search the all face list				
				for (m=0; m<m_numFaces; m++)
				{
					if (m_Faces[m].v1 == i)
					{
						tempFaceList[m].v1 = j;
					}
					if (m_Faces[m].v2 == i)
					{
						tempFaceList[m].v2 = j;
					}
					if (m_Faces[m].v3 == i)
					{
						tempFaceList[m].v3 = j;
					}
				}
				//end
				break;
			}
		}

		if (j == pMesh->m_pvertexlist.size())*/
		{
			pMesh->m_pvertexlist.push_back(vert);
/*			for (m=0; m<m_numFaces; m++)
			{
				if (m_Faces[m].v1 == i)
				{
					tempFaceList[m].v1 = j;
				}
				if (m_Faces[m].v2 == i)
				{
					tempFaceList[m].v2 = j;
				}
				if (m_Faces[m].v3 == i)
				{
					tempFaceList[m].v3 = j;
				}
			}*/
		}
	}

	int curcount;
		//first convert vertex position data to int, and check if there is a same one in the new list
	for (i=0; i<m_numTexCoords; i++)
	{
		texcoor.u = (int)(m_TexCoord[i].u *1024);
		texcoor.v = (int)(m_TexCoord[i].v *1024);

		curcount = pMesh->m_ptexcoordlist.size();
		for (j=0; j<pMesh->m_ptexcoordlist.size(); j++)
		{
			if (texcoor.u == pMesh->m_ptexcoordlist[j].u && texcoor.v == pMesh->m_ptexcoordlist[j].v)
			{
				//search the all face list				
				for (m=0; m<m_numFaces; m++)
				{
					if (m_Faces[m].t1 == i)
					{
						tempFaceList[m].t1 = j;
					}
					if (m_Faces[m].t2 == i)
					{
						tempFaceList[m].t2 = j;
					}
					if (m_Faces[m].t3 == i)
					{
						tempFaceList[m].t3 = j;
					}
					//end
				}
				break;
			}
		}
		
		if (j == curcount)
		{
			pMesh->m_ptexcoordlist.push_back(texcoor);
			for (m=0; m<m_numFaces; m++)
			{
				if (m_Faces[m].t1 == i)
				{
					tempFaceList[m].t1 = j;
				}
				if (m_Faces[m].t2 == i)
				{
					tempFaceList[m].t2 = j;
				}
				if (m_Faces[m].t3 == i)
				{
					tempFaceList[m].t3 = j;
				}
				//end
			}
		}
	}

	//vertex and texture coordinate combination complete, so put all face to submesh
	pMesh->m_submeshCount = m_numMatrials;
	Submesh submesh;
	char temp[256];
	char *sep;
	MaxMatrial mat;
	for (i=0; i<m_numMatrials; i++)
	{
		submesh.material.alphaBlendMode = 0;
		submesh.material.bAlphablend = false;
		submesh.material.cullMode = 0;
		mat = m_Matrials[i];
		strcpy(temp, m_Matrials[i].texName);
		sep = strrchr(temp, '\\');
		if (sep != NULL)
			strcpy(temp, (sep+1));
		strcpy(submesh.material.texFileName, temp);
		submesh.material.texSize = 128;
		pMesh->m_pSubMeshs.push_back(submesh);
	}
	
	GLFace glface;
	int index;
	for (i=0; i<tempFaceList.size(); i++)
	{
		index = tempFaceList[i].matid;
		glface.tex1 = tempFaceList[i].t1;
		glface.tex2 = tempFaceList[i].t2;
		glface.tex3 = tempFaceList[i].t3;
		glface.ver1 = tempFaceList[i].v1;
		glface.ver2 = tempFaceList[i].v2;
		glface.ver3 = tempFaceList[i].v3;
		glface.nx = (int)tempFaceList[i].normal.x*1024;
		glface.ny = (int)tempFaceList[i].normal.y*1024;
		glface.nz = (int)tempFaceList[i].normal.z*1024;
		pMesh->m_pSubMeshs[index].m_pfacelist.push_back(glface);
	}		
	
	//remove submesh without face
	
	vector<Submesh>::iterator mitr = pMesh->m_pSubMeshs.begin();
	while (mitr != pMesh->m_pSubMeshs.end())
	{
		if (mitr->m_pfacelist.size() == 0)
			mitr = pMesh->m_pSubMeshs.erase(mitr);
		else
			mitr++;
	}
	

	//convert bone data
	map<int, MaxBone>::iterator itr = m_Bones.begin();
	Bone bone;
	Matrix3 bmat;
	Point3 bpt;
	if (m_Bones.size()>0)

⌨️ 快捷键说明

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