📄 export.cpp
字号:
//Check Matrix
VxVector Z;
Z = CrossProduct(*(VxVector*)&VirtoolsMat[0][0],*(VxVector*)&VirtoolsMat[1][0]);
if (DotProduct(Z,*(VxVector *)&VirtoolsMat[2][0])<0) {
Report(REPORT_HLEVEL,"\r\nWarning Indirect Matrix detected for %s object...\r\n",entity->GetName());
Report(REPORT_HLEVEL,"\r\nAnimation may not be correct for this object...\r\n");
}
// World Position
entity->SetWorldMatrix(VirtoolsMat,TRUE);
// Show/Hide
entity->Show( node->IsHidden(0) ? CKHIDE : CKSHOW);
if (!GetGroupAsPlace()) {
CKGroup* group = CKGroups.Size() ? CKGroups.Back() : NULL;
if (group) {
group->AddObject(entity);
}
}
INode* parent = node->GetParentNode();
if (parent && !parent->IsRootNode()) {
CK3dEntity *VirtoolsParent=VirtoolsExporter->GetEntityByKey(parent);
if( !VirtoolsParent ){
VirtoolsParent=VirtoolsExporter->GetCameraByKey(parent);
}
if( !VirtoolsParent ){
VirtoolsParent=VirtoolsExporter->GetLightByKey(parent);
}
entity->SetParent(VirtoolsParent);
}
}
/****************************************************************************
Mesh output
****************************************************************************/
void Max2Nmo::ExportMesh(INode* node, CK3dEntity* ent)
{
TimeValue t = GetStaticFrame();
Mtl* nodeMtl = node->GetMtl();
Matrix3 tm = node->GetNodeTM(t);
int i;
// Since referential is not the same in Virtools indices 1 & 2 are swapped
int vx1 = 0, vx2 = 2, vx3 = 1;
// TODO : If the node does not have a material, export the wireframe color ?
// DWORD c = node->GetWireColor();
ObjectState os = node->EvalWorldState(t);
if (!os.obj || os.obj->SuperClassID()!=GEOMOBJECT_CLASS_ID) {
return; // Safety net. This shouldn't happen.
}
BOOL needDel;
TriObject* tri = GetTriObjectFromNode(node, t, needDel);
if (!tri) {
return;
}
Modifier *mod = FindSkinModifier(node);
// Check if this mesh had already been exported (instances)
// butif the node material is different we must create a new mesh :(
CKMesh* VirtoolsMesh =IsMeshInstance(os.obj,nodeMtl);
if (VirtoolsMesh && !mod) {
ent->SetCurrentMesh(VirtoolsMesh);
Report(REPORT_HLEVEL,"%sMesh Instance : %s.....",StrGroupIndent().Str(),node->GetName());
return ;
}
Mesh* mesh = &tri->GetMesh();
mesh->buildNormals();
int numVtx = mesh->getNumVerts(); // Vertex Count
int numCVx = mesh->numCVerts; // Vertex color Count
int numTVx = mesh->getNumTVerts(); // Texture coords Count
int numFaces = mesh->getNumFaces(); // Face Count
BOOL UseVertexColor = node->GetCVertMode() && numCVx ;
if (!numVtx || !numFaces) return;
Report(REPORT_HLEVEL,"%sMesh : %s.....",StrGroupIndent().Str(),node->GetName());
Report(REPORT_MLEVEL,"\r\n%s%d Max Vertices, %d Faces",StrGroupIndent().Str(),numVtx,numFaces);
VirtoolsTransitionMesh VirtoolsTempMesh(VirtoolsExporter,UseVertexColor);
//-------------- Export the vertices --------------------------
// Max Vertices are given in the ObjectTM referential and we need them in NodeTM referential
// So transform them using OffsetTM
Matrix3 OffsetTM = GetNodeOffsetTM(node);
// (transform them and invert Y & Z
for (i=0; i<numVtx; i++) {
Point3 tmp = OffsetTM.PointTransform(mesh->verts[i]);
VirtoolsTempMesh.AddPosition(VxVector(tmp.x,tmp.z,tmp.y));
}
//----------- Export the faces -------------------------------
int PreviousMatId = -1;
CKMaterial* VirtoolsMat = NULL;
Mtl* FaceMtl = NULL;
int UvIndex = 0;
TextureUVGen uvgen;
BOOL useUVGen = FALSE;
VxUV uvs[3]; // Face texture coords
for (i=0; i<numFaces; i++,UvIndex+=3) {
int MatID = mesh->faces[i].getMatID();
// No need to research the associated Virtools
// material if material index is the same
if (MatID != PreviousMatId) {
void* mtlKey = NULL;
FaceMtl = GetMaterialByIndex(nodeMtl,MatID,0, mtlKey);
VirtoolsMat = VirtoolsExporter->GetMaterialByKey(mtlKey);
useUVGen = GetTextureUvGen(FaceMtl,uvgen);
}
PreviousMatId = MatID;
VirtoolsTempMesh.AddFace(mesh->faces[i].v[vx1],
mesh->faces[i].v[vx2],
mesh->faces[i].v[vx3],VirtoolsMat);
//------- Texture coordinates
if (numTVx) {
CopyUV(&uvs[0],&mesh->tVerts[mesh->tvFace[i].t[vx1]]);
CopyUV(&uvs[1],&mesh->tVerts[mesh->tvFace[i].t[vx2]]);
CopyUV(&uvs[2],&mesh->tVerts[mesh->tvFace[i].t[vx3]]);
}
if (FaceMtl) { // Check if material use FaceMap
ULONG matreq = nodeMtl->Requirements(-1);
if (matreq & MTLREQ_FACEMAP) {
make_face_uv(&mesh->faces[i], uvs);
}
}
for (int j=0;j<3;++j) {
ApplyUvGen(uvs[j],uvgen,useUVGen);
VirtoolsTempMesh.AddUv(uvs[j]);
}
VirtoolsTempMesh.AddUVFace(UvIndex,UvIndex+1,UvIndex+2);
}
//------------ Export additionnal Texture coordinates ----------------------------
int VirtoolsChannelCount=0;
int NumMaps = mesh->getNumMaps();
for (int mp = 2; mp < NumMaps; mp++) {
if (mesh->mapSupport(mp) && VirtoolsChannelCount<MAX_UVCHANNEL_COUNT) {
int numTVx = mesh->getNumMapVerts(mp);
if (numTVx) {
// Get the material for this additional mapping channel
void* mtlKey = NULL;
Mtl* FaceMtl = GetMaterialByIndex(nodeMtl,mesh->faces[0].getMatID(),mp,mtlKey);
//--- If there's a material found for this channel ?
if (FaceMtl) {
VirtoolsChannelCount++;
CKMaterial* VirtoolsMat = VirtoolsExporter->GetMaterialByKey(mtlKey);
VirtoolsTempMesh.AddChannelMaterial(VirtoolsMat);
useUVGen = GetTextureUvGen(FaceMtl,uvgen);
int UvIndex = 0;
for (i=0; i<numFaces; i++,UvIndex+=3) {
uvs[0].u = mesh->mapVerts(mp)[mesh->mapFaces(mp)[i].t[vx1]].x;
uvs[0].v = mesh->mapVerts(mp)[mesh->mapFaces(mp)[i].t[vx1]].y;
uvs[1].u = mesh->mapVerts(mp)[mesh->mapFaces(mp)[i].t[vx2]].x;
uvs[1].v = mesh->mapVerts(mp)[mesh->mapFaces(mp)[i].t[vx2]].y;
uvs[2].u = mesh->mapVerts(mp)[mesh->mapFaces(mp)[i].t[vx3]].x;
uvs[2].v = mesh->mapVerts(mp)[mesh->mapFaces(mp)[i].t[vx3]].y;
for (int j=0;j<3;++j) {
ApplyUvGen(uvs[j],uvgen,useUVGen);
VirtoolsTempMesh.AddUv(uvs[j],VirtoolsChannelCount);
}
VirtoolsTempMesh.AddUVFace(UvIndex,UvIndex+1,UvIndex+2,VirtoolsChannelCount);
}
}
}
}
}
//-------- Export color per vertex info -------------------
#ifdef MAX4
BOOL support = mesh->mapSupport(-VDATA_ALPHA);
UVVert* alpha;
if(support)
alpha = mesh->mapVerts(-VDATA_ALPHA);
#endif
if (numCVx) {
VirtoolsTempMesh.m_VertexColors.Resize(numCVx);
for (i=0; i<numCVx; i++) {
memcpy(&VirtoolsTempMesh.m_VertexColors[i],&mesh->vertCol[i],3*sizeof(float));
VirtoolsTempMesh.m_VertexColors[i].a = 1.0f;
#ifdef MAX4
if(support)
VirtoolsTempMesh.m_VertexColors[i].a = alpha[i].x;
#endif
}
for (i=0; i<numFaces; i++) {
VirtoolsTempMesh.AddColorFace(mesh->vcFace[i].t[vx1],
mesh->vcFace[i].t[vx2],
mesh->vcFace[i].t[vx3]);
}
}
//---------- Vertex normals. --------------------------------
// In MAX a vertex can have more than one normal (but doesn't always have it).
// This is depending on the face you are accessing the vertex through.
// To get all information we need to export all three vertex normals
// for every face.
int Nindex=0;
for (i=0; i<numFaces; i++,Nindex+=3) {
Face* f = &mesh->faces[i];
Point3 vn;
vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(f->getVert(vx1)));
vn = OffsetTM.VectorTransform(vn);
VirtoolsTempMesh.m_Normals.PushBack(VxVector(vn.x,vn.z,vn.y));
vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(f->getVert(vx2)));
vn = OffsetTM.VectorTransform(vn);
VirtoolsTempMesh.m_Normals.PushBack(VxVector(vn.x,vn.z,vn.y));
vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(f->getVert(vx3)));
vn = OffsetTM.VectorTransform(vn);
VirtoolsTempMesh.m_Normals.PushBack(VxVector(vn.x,vn.z,vn.y));
VirtoolsTempMesh.AddNormalFace(Nindex,Nindex+1,Nindex+2);
}
//-------- And build Virtools Data
VirtoolsTempMesh.GenerateVirtoolsData();
XString Name = node->GetName();
Name << "_Mesh";
VirtoolsMesh = VirtoolsExporter->AddMesh(&VirtoolsTempMesh,Name.CStr(),node);
ent->SetCurrentMesh(VirtoolsMesh);
InsertNewMeshInstance(os.obj,nodeMtl,VirtoolsMesh);
Report(REPORT_LLEVEL,"\r\n%s=> %d Vertices",StrGroupIndent().Str(),VirtoolsMesh->GetVertexCount());
if (VirtoolsMesh->GetVertexCount() > 65535) {
Report(REPORT_LLEVEL,"\r\n WARNING This mesh contains more than 65535 vertices and may not render correctly");
}
if (VirtoolsMesh->GetFaceCount() > 65535) {
Report(REPORT_LLEVEL,"\r\n WARNING This mesh contains more than 65535 faces and may not render correctly");
}
//-------- Vertex Weights
float* weightOrginal = mesh->getVertexWeights();
if( VirtoolsMesh && weightOrginal ){
const int vCount = VirtoolsMesh->GetVertexCount();
VirtoolsMesh->SetVertexWeightsCount( vCount );
for( int a=0 ; a<vCount ; ++a ){
int vOriginal = VirtoolsTempMesh.m_VirtoolsVertices[a].OriginalPosIndex;
float weight = weightOrginal[vOriginal];
VirtoolsMesh->SetVertexWeight( a, weight );
}
}
//-------- Delete Temporary Tri-Mesh
if (needDel) {
delete tri;
}
}
/****************************************************************************
Patch Mesh output
****************************************************************************/
void Max2Nmo::ExportPatchMesh(INode* node, CK3dEntity* ent)
{
TimeValue t = GetStaticFrame();
Mtl* nodeMtl = node->GetMtl();
Matrix3 tm = node->GetNodeTM(t);
int channel = 0;
// TODO : If the node does not have a material, export the wireframe color ?
// DWORD c = node->GetWireColor();
ObjectState os = node->EvalWorldState(t);
if (!os.obj || os.obj->SuperClassID()!=GEOMOBJECT_CLASS_ID) {
return; // Safety net. This shouldn't happen.
}
BOOL needDel;
PatchObject* patch = GetPatchObjectFromNode(node, t, needDel);
if (!patch) return;
// Check if this mesh had already been exported (instances)
CKPatchMesh* VirtoolsPMesh = (CKPatchMesh*)IsMeshInstance(os.obj,nodeMtl);
if (VirtoolsPMesh) {
ent->SetCurrentMesh(VirtoolsPMesh);
Report(REPORT_HLEVEL,"%sPatch Mesh Instance: %s.....",StrGroupIndent().Str(),node->GetName());
return ;
}
Report(REPORT_HLEVEL,"%sPatch Mesh : %s.....",StrGroupIndent().Str(),node->GetName());
XString Name = node->GetName();
Name << "_Mesh";
PatchMesh* pmesh = &patch->patch;
if (!pmesh->numVerts || !pmesh->numVecs || !pmesh->numPatches) return;
int StepCount = pmesh->cacheSteps;
VirtoolsPMesh = VirtoolsExporter->AddPatchMesh(Name.CStr(),node);
Report(REPORT_LLEVEL,"%sPatch Mesh: %d Control Points, %d Patches, %d Vectors",StrGroupIndent().Str(),pmesh->numVerts,pmesh->numVecs,pmesh->numPatches);
VirtoolsPMesh->SetVertVecCount(pmesh->numVerts,pmesh->numVecs);
VirtoolsPMesh->SetPatchCount(pmesh->numPatches);
VirtoolsPMesh->SetEdgeCount(pmesh->numEdges);
VirtoolsPMesh->SetIterationCount(StepCount);
//-------------- Export the patch vertices and tangent vectors --------------------------
// Max Vertices are given in the ObjectTM referential and we need them in NodeTM referential
// So transform them using OffsetTM
Matrix3 OffsetTM = GetNodeOffsetTM(node);
// (transform them and invert Y & Z
for (int i=0; i<pmesh->numVerts; i++) {
Point3 tmp = OffsetTM.PointTransform(pmesh->verts[i].p);
VirtoolsPMesh->SetVert(i,&VxVector(tmp.x,tmp.z,tmp.y));
}
for (i=0; i<pmesh->numVecs; i++) {
Point3 tmp = OffsetTM.PointTransform(pmesh->vecs[i].p);
VirtoolsPMesh->SetVec(i,&VxVector(tmp.x,tmp.z,tmp.y));
}
//--------- Export edges
for (i=0;i<pmesh->numEdges;++i) {
PatchEdge* e = &pmesh->edges[i];
CKPatchEdge pe;
#if (MAX_RELEASE>=4000)
if (e->patches.Count())
pe.patch1 = e->patches[0];
else
pe.patch1 = -1;
if (e->patches.Count()>1)
pe.patch2 = e->patches[1];
else
pe.patch2 = -1;
#else
pe.patch1 = e->patch1;
pe.patch2 = e->patch2;
#endif
pe.v1 = e->v1;
pe.v2 = e->v2;
pe.vec12 = e->vec12;
pe.vec21 = e->vec21;
VirtoolsPMesh->SetEdge(i,&pe);
}
//----------- Export Patches data
int PreviousMatId = -1;
CKMaterial* VirtoolsMat = NULL;
Mtl* PatchMtl= NULL;
TextureUVGen uvgen;
BOOL useUVGen = FALSE;
for (i=0;i<pmesh->numPatches;++i) {
Patch* p = &pmesh->patches[i];
int MatID = (p->flags >> PATCH_MATID_SHIFT) & PATCH_MATID_MASK;
// No need to research the associated Virtools material if material index is the same
if (MatID != PreviousMatId) {
void* mtlKey = NULL;
PatchMtl = GetMaterialByIndex(nodeMtl,MatID,0,mtlKey);
VirtoolsMat = VirtoolsExporter->GetMaterialByKey(mtlKey);
useUVGen = GetTextureUvGen(PatchMtl,uvgen);
}
PreviousMatId = MatID;
CKPatch VirtoolsPatch;
VirtoolsPatch.v[0]=p->v[0]; VirtoolsPatch.v[1]=p->v[1];
VirtoolsPatch.v[2]=p->v[2]; VirtoolsPatch.v[3]=p->v[3];
VirtoolsPatch.vec[0]=p->vec[0]; VirtoolsPatch.vec[1]=p->vec[1];
VirtoolsPatch.vec[2]=p->vec[2]; VirtoolsPatch.vec[3]=p->vec[3];
VirtoolsPatch.vec[4]=p->vec[4]; VirtoolsPatch.vec[5]=p->vec[5];
VirtoolsPatch.vec[6]=p->vec[6]; VirtoolsPatch.vec[7]=p->vec[7];
VirtoolsPatch.interior[0]=p->interior[0]; VirtoolsPatch.interior[1]=p->interior[1];
VirtoolsPatch.interior[2]=p->interior[2]; VirtoolsPatch.interior[3]=p->interior[3];
VirtoolsPatch.edge[0]=p->edge[0]; VirtoolsPatch.edge[1]=p->edge[1];
VirtoolsPatch.edge[2]=p->edge[2]; VirtoolsPatch.edge[3]=p->edge[3];
VirtoolsPatch.auxs=NULL;
VirtoolsPatch.type = (p->type == PATCH_TRI) ? CK_PATCH_TRI : CK_PATCH_QUAD;
VirtoolsPatch.Material = CKOBJID(VirtoolsMat);
VirtoolsPatch.SmoothingGroup = p->smGroup;
VirtoolsPMesh->SetPatch(i,&VirtoolsPatch);
}
//------- Texture coordinates
int PatchChannelCount=0;
for (int mp=1;mp<pmesh->NumMapChannels();mp++) {
if (pmesh->getNumMapVerts(mp)>0) {
int MatID = (pmesh->patches[0].flags >> PATCH_MATID_SHIFT) & PATCH_MATID_MASK;
void* mtlKey = NULL;
PatchMtl = GetMaterialByIndex(nodeMtl,MatID,mp,mtlKey);
useUVGen = GetTextureUvGen(PatchMtl,uvgen);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -