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

📄 export.cpp

📁 3dmax导出3d模型二次开发插件
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	//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 + -