📄 maxmesh.cpp
字号:
// 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 + -