void NifImporter::SetNormals(Mesh& mesh, const vector<Niflib::Triangle>& tris, const vector<Niflib::Vector3>& n)
{
	mesh.checkNormals(TRUE);
	if (n.size() > 0)
	{
		bool needNormals = false;
		for (unsigned int i=0; i<n.size(); i++){
			Vector3 v = n[i];
			Point3 norm(v.x, v.y, v.z);
			if (norm != mesh.getNormal(i)) {
				needNormals = true;
				break;
			}
		}
		if (needNormals)
		{
#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
			mesh.SpecifyNormals();
			MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals ();
			if (NULL != specNorms)
			{
				specNorms->ClearAndFree();
				specNorms->SetNumFaces(tris.size());
				specNorms->SetNumNormals(n.size());

				Point3* norms = specNorms->GetNormalArray();
				for (unsigned int i=0; i<n.size(); i++){
					Vector3 v = n[i];
					norms[i] = Point3(v.x, v.y, v.z);
				}
				MeshNormalFace* pFaces = specNorms->GetFaceArray();
				for (unsigned int i=0; i<tris.size(); i++){
					const Triangle& tri = tris[i];
					pFaces[i].SpecifyNormalID(0, tri.v1);
					pFaces[i].SpecifyNormalID(1, tri.v2);
					pFaces[i].SpecifyNormalID(2, tri.v3);
				}
#if VERSION_3DSMAX > ((7000<<16)+(15<<8)+0) // Version 7+
				specNorms->SetAllExplicit(true);
#else
				for (int i=0; i<specNorms->GetNumNormals(); ++i) {
					specNorms->SetNormalExplicit(i, true);
				}
#endif
				specNorms->CheckNormals();
			}
#endif
		}
	}
}
Exemple #2
0
void SymmetryMod::ModifyTriObject (TimeValue t, ModContext &mc, TriObject *tobj, INode *inode) {
	Mesh &mesh = tobj->GetMesh();
	Interval iv = FOREVER;
	int axis, slice, weld, flip;
	float threshold;

	mp_pblock->GetValue (kSymAxis, t, axis, iv);
	mp_pblock->GetValue (kSymFlip, t, flip, iv);
	mp_pblock->GetValue (kSymSlice, t, slice, iv);
	mp_pblock->GetValue (kSymWeld, t, weld, iv);
	mp_pblock->GetValue (kSymThreshold, t, threshold, iv);
	if (threshold<0) threshold=0;

	// Get transform from mirror controller:
	Matrix3 tm  = CompMatrix (t, NULL, &mc, &iv);
	Matrix3 itm = Inverse (tm);

	// Get DotProd(N,x)=offset plane definition from transform
	Point3 Axis(0,0,0);
	Axis[axis] = flip ? -1.0f : 1.0f;
	Point3 origin = tm.GetTrans();
	Point3 N = Normalize(tm*Axis - origin);
	float offset = DotProd (N, origin);

	// Slice operation does not handle NormalSpecs, but it handles mapping channels.
	// move our mesh normal data to a map channel
	MeshNormalSpec *pNormals = mesh.GetSpecifiedNormals ();
	int normalMapChannel = INVALID_NORMALMAPCHANNEL;
	if (pNormals && pNormals->GetNumFaces())
	{
		pNormals->SetParent(&mesh);
		//find an empty map channel
		for (int mp = 0; mp < mesh.getNumMaps(); mp++) 
		{			
			if (!mesh.mapSupport(mp)) 
			{
				normalMapChannel = mp;

				mesh.setMapSupport(normalMapChannel,TRUE);
				MeshMap& map = mesh.Map(normalMapChannel);
				for (int i = 0; i < map.fnum; i++)
				{
					for (int j = 0; j < 3; j++)
					{
						unsigned int newID = pNormals->Face(i).GetNormalID(j);
						map.tf[i].t[j] = newID;
					}
				}
				map.setNumVerts(pNormals->GetNumNormals());
				for (int i = 0; i < map.vnum; i++)
				{
					map.tv[i] = pNormals->Normal(i);
				}				

				// make sure nothing is done with MeshNormalSpec (until data is copied back) 
				pNormals->Clear();
				break;
			}
		}
	}
	
	// Slice off everything below the plane.
	if (slice) SliceTriObject (mesh, N, offset);
	MirrorTriObject (mesh, axis, tm, itm,normalMapChannel);
	if (weld) WeldTriObject (mesh, N, offset, threshold);

	//now move the normals back
	if (pNormals && normalMapChannel != -1)
	{
		MeshMap& map = mesh.Map(normalMapChannel);
		pNormals->SetNumFaces(map.fnum);

		pNormals->SetNumNormals(map.vnum);
		pNormals->SetAllExplicit(true);
		BitArray temp;
		temp.SetSize(map.vnum);
		temp.SetAll();
		pNormals->SpecifyNormals(TRUE,&temp);

		for (int i = 0; i < map.vnum; i++)
		{
			pNormals->GetNormalArray()[i] = map.tv[i];
			pNormals->SetNormalExplicit(i,true);
		}	

		for (int i = 0; i < map.fnum; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				pNormals->SetNormalIndex(i,j,map.tf[i].t[j]);				
				MeshNormalFace& face = pNormals->Face(i);
				face.SpecifyAll(true);
			}
		}

		pNormals->SetFlag(MESH_NORMAL_MODIFIER_SUPPORT);

		for (int i = 0; i < pNormals->GetNumFaces(); i++)
		{
			for (int j = 0; j < 3; j++)
			{
				int id = pNormals->GetNormalIndex(i,j);	
			}
		}

		pNormals->CheckNormals();
		pNormals->SetParent(NULL);

		// Free the map channel
		mesh.setMapSupport(normalMapChannel,FALSE);
	}
	
	tobj->UpdateValidity (GEOM_CHAN_NUM, iv);
	tobj->UpdateValidity (TOPO_CHAN_NUM, iv);
	tobj->UpdateValidity (VERT_COLOR_CHAN_NUM, iv);
	tobj->UpdateValidity (TEXMAP_CHAN_NUM, iv);
	tobj->UpdateValidity (SELECT_CHAN_NUM, iv);
}
void WMOGroupImpl::buildMaxData()
{
	// Group Header Node
	INode* groupHeadNode = createGroupHeaderNode();
	groupHeadNode->SetGroupHead(TRUE);
	groupHeadNode->SetGroupMember(FALSE);

	// Geoset
	// 一个Render Batch构造一个Node, 并且加入到组中

	for (int i = 0; i < m_batchCount; ++i)
	{
		WMORenderBatch& renderBatch = m_batchData[i];

		m_wmoImporter->m_logStream << "Model Geoset " << i << " Vertex Info: " 
			<< renderBatch.vertexStart << " -- " << renderBatch.vertexEnd << endl;
		m_wmoImporter->m_logStream << "Model Geoset " << i << " Index Info: " 
			<< renderBatch.indexStart << " -- " << renderBatch.indexCount << endl;

		// Triangle Mesh Object
		// 基本的三角形模型对象
		TriObject* triObject = CreateNewTriObject();

		// 创建Node, 并且设为Group Header Node的子节点
		ImpNode* tmpImpNode = m_wmoImporter->m_impInterface->CreateNode();
		tmpImpNode->Reference(triObject);

		m_wmoImporter->m_impInterface->AddNodeToScene(tmpImpNode);
		INode* realINode = tmpImpNode->GetINode();
		realINode->SetGroupHead(FALSE);
		realINode->SetGroupMember(TRUE);
		groupHeadNode->AttachChild(realINode);

		m_geosetNodeList.push_back(realINode);

		TCHAR nodeName[256];
		sprintf(nodeName, "%s_part_%03d", m_groupName.c_str(), i);
		realINode->SetName(nodeName);

		// mesh
		unsigned short vertexCount = renderBatch.vertexEnd - renderBatch.vertexStart + 1;
		unsigned int trigangleCount = renderBatch.indexCount / 3;

		Mesh& mesh = triObject->GetMesh();
		mesh.setNumVerts(vertexCount);
		mesh.setNumTVerts(vertexCount, TRUE);

		mesh.setNumFaces(trigangleCount);
		mesh.setNumTVFaces(trigangleCount);

		// 顶点坐标和UV
		for (int i = 0; i < vertexCount; ++i)
		{
			mesh.verts[i] = *(Point3*)(&(m_vertexData[renderBatch.vertexStart + i]));

			// UV坐标反转
			mesh.tVerts[i].x = m_textureCoords[renderBatch.vertexStart + i].x;
			mesh.tVerts[i].y = 1.0f - m_textureCoords[renderBatch.vertexStart + i].y;
		}

		// 三角形
		for (unsigned int i = 0; i < trigangleCount; ++i)
		{
			Face& face = mesh.faces[i];
			int index1 = m_indexData[renderBatch.indexStart + i*3] - renderBatch.vertexStart;
			int index2 = m_indexData[renderBatch.indexStart + i*3+1] - renderBatch.vertexStart;
			int index3 = m_indexData[renderBatch.indexStart + i*3+2] - renderBatch.vertexStart;

			face.setVerts(index1, index2, index3);
			face.Show();
			face.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS);

			TVFace& tface = mesh.tvFace[i];
			tface.setTVerts(index1, index2, index3);
		}

		// 法线
		mesh.SpecifyNormals();
		MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals();
		if (specNorms)
		{
			specNorms->ClearAndFree();
			specNorms->SetNumFaces(trigangleCount);
			specNorms->SetNumNormals(vertexCount);

			Point3* norms = specNorms->GetNormalArray();
			for (int i = 0; i < vertexCount; ++i)
			{
				norms[i] = *(Point3*)(&m_normalData[renderBatch.vertexStart + i]);
			}

			MeshNormalFace* pFaces = specNorms->GetFaceArray();
			for (unsigned int i = 0; i < trigangleCount; ++i)
			{
				int index1 = m_indexData[renderBatch.indexStart + i*3] - renderBatch.vertexStart;
				int index2 = m_indexData[renderBatch.indexStart + i*3+1] - renderBatch.vertexStart;
				int index3 = m_indexData[renderBatch.indexStart + i*3+2] - renderBatch.vertexStart;

				pFaces[i].SpecifyNormalID(0, index1);
				pFaces[i].SpecifyNormalID(1, index2);
				pFaces[i].SpecifyNormalID(2, index3);
			}

			specNorms->SetAllExplicit(true);
			specNorms->CheckNormals();
		}

		// 删除重复的和无效的面
		mesh.RemoveDegenerateFaces();
		mesh.RemoveIllegalFaces();

		realINode->SetMtl(m_wmoImporter->m_materialList[renderBatch.texture]);
		//realINode->BackCull(FALSE);			// 取消背面裁减 不是所有的Node都要取消背面裁减
		realINode->EvalWorldState(0);
	}
}
// 1. 加载模型顶点数据
void M2Importer::importGeomObject()
{
	// Group Header Node
	INode* groupHeadNode = createGroupHeaderNode();
	groupHeadNode->SetGroupHead(TRUE);
	groupHeadNode->SetGroupMember(FALSE);

	if (m_modelHeader->nameLength > 1)
	{
		TCHAR* modelName = (TCHAR*)(m_m2FileData + m_modelHeader->nameOfs);
		groupHeadNode->SetName(modelName);
		m_logStream << "ModelName: " << modelName << endl;
	}
	else
		groupHeadNode->SetName("GeomGroup");


	// Geoset
	// 一个Geoset构造一个Node, 并且加入到组中

	unsigned short* verDataIndex = (unsigned short*)(m_m2FileData + m_modelView->ofsIndex);
	unsigned short* triData = (unsigned short*)(m_m2FileData + m_modelView->ofsTris);

	m_geosetNodeList.reserve(m_modelView->nSub);
	m_materialList.reserve(m_modelView->nSub);
	for (unsigned int i = 0; i < m_modelView->nSub; ++i)
		m_materialList.push_back(0);

	for (unsigned int i = 0; i < m_modelView->nSub; ++i)
	{
		ModelGeoset& geosetData = m_modelGeoset[i];

		// Triangle Mesh Object
		// 基本的三角形模型对象
		TriObject* triObject = CreateNewTriObject();

		// 创建Node, 并且设为Group Header Node的子节点
		ImpNode* tmpImpNode = m_impInterface->CreateNode();
		tmpImpNode->Reference(triObject);
		//tmpImpNode->SetPivot(*(Point3*)&(geosetData.v));

		m_impInterface->AddNodeToScene(tmpImpNode);
		INode* realINode = tmpImpNode->GetINode();
		realINode->SetGroupHead(FALSE);
		realINode->SetGroupMember(TRUE);
		groupHeadNode->AttachChild(realINode);

		m_geosetNodeList.push_back(realINode);

		TCHAR nodeName[256];
		sprintf(nodeName, "GeosetPart_%d", i);
		realINode->SetName(nodeName);

		// mesh
		Mesh& mesh = triObject->GetMesh();
		mesh.setNumVerts(geosetData.vcount);
		mesh.setNumTVerts(geosetData.vcount, TRUE);

		unsigned int triangeCount = geosetData.icount / 3;
		mesh.setNumFaces(triangeCount);
		mesh.setNumTVFaces(triangeCount);

		m_logStream << "Model Geoset " << i << " Vertex Count: " << geosetData.vcount << endl;
		m_logStream << "Model Geoset " << i << " Index Count: " << triangeCount << endl;

		// 顶点坐标和UV
		for (unsigned int i = 0; i < geosetData.vcount; ++i)
		{
			ModelVertex& vertexData = m_globalVertices[ verDataIndex[geosetData.vstart + i] ];

			mesh.verts[i] = *(Point3*)(&vertexData.pos);

			// UV坐标反转
			mesh.tVerts[i].x = vertexData.texcoords.x;
			mesh.tVerts[i].y = 1.0f - vertexData.texcoords.y;
		}

		// 三角形
		for (unsigned int i = 0; i < triangeCount; ++i)
		{
			Face& face = mesh.faces[i];
			face.setVerts(triData[geosetData.istart + i*3] - m_indexCount, 
						  triData[geosetData.istart + i*3+1] - m_indexCount, 
						  triData[geosetData.istart + i*3+2] - m_indexCount);
			face.Show();
			face.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS);

			TVFace& tface = mesh.tvFace[i];
			tface.setTVerts(triData[geosetData.istart + i*3] - m_indexCount, 
							triData[geosetData.istart + i*3+1] - m_indexCount, 
							triData[geosetData.istart + i*3+2] - m_indexCount);
		}

		// 法线
		mesh.SpecifyNormals();
		MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals();
		if (specNorms)
		{
			specNorms->ClearAndFree();
			specNorms->SetNumFaces(triangeCount);
			specNorms->SetNumNormals(geosetData.vcount);

			Point3* norms = specNorms->GetNormalArray();
			for (unsigned int i = 0; i < geosetData.vcount; ++i)
			{
				ModelVertex& vertexData = m_globalVertices[ verDataIndex[geosetData.vstart + i] ];
				norms[i] = *(Point3*)(&vertexData.normal);
			}

			MeshNormalFace* pFaces = specNorms->GetFaceArray();
			for (unsigned int i = 0; i < triangeCount; ++i)
			{
				pFaces[i].SpecifyNormalID(0, triData[geosetData.istart + i*3] - m_indexCount);
				pFaces[i].SpecifyNormalID(1, triData[geosetData.istart + i*3+1] - m_indexCount);
				pFaces[i].SpecifyNormalID(2, triData[geosetData.istart + i*3+2] - m_indexCount);
			}

			specNorms->SetAllExplicit(true);
			specNorms->CheckNormals();
		}

		// 删除重复的和无效的面
		mesh.RemoveDegenerateFaces();
		mesh.RemoveIllegalFaces();

		//realINode->BackCull(FALSE);			// 取消背面裁减 双面绘制与取消背面裁减一起设置
		realINode->EvalWorldState(0);

		// 索引值修正
		m_indexCount += geosetData.vcount;
	}

	// 加载材质
	unsigned short* texLookupData = (unsigned short*)(m_m2FileData + m_modelHeader->ofsTexLookup);
	ModelTextureDef* texUnitDefData = (ModelTextureDef*)(m_m2FileData + m_modelHeader->ofsTextures);
	ModelTexUnit* texUnitData = (ModelTexUnit*)(m_m2FileData + m_modelView->ofsTex);

	for (unsigned int i = 0; i < m_modelView->nTex; ++i)
	{
		ModelTexUnit& texUnit = texUnitData[i];
		unsigned short textureID = texLookupData[texUnit.textureid];
		ModelTextureDef& texDef = texUnitDefData[textureID];

		string textureName;

		if (texDef.type == 0)
			textureName = (LPCSTR)(m_m2FileData + texDef.nameOfs);
		else
			textureName = getReplacableTexture(texDef.type);

		StdMat2* material = m_materialList[texUnit.op];
		if (!material)
			material = createMaterial();

		// 根据混合属性决定加在第几层
		material->SetSubTexmap(ID_DI, createTexture(textureName.c_str()));
		material->EnableMap(ID_DI, TRUE);
		//material->SetTwoSided(TRUE);		// 双面 设置了此标志的才打开

		m_maxInterface->GetMaterialLibrary().Add(material);
		m_geosetNodeList[texUnit.op]->SetMtl(material);
	}

	m_maxInterface->RedrawViews(m_maxInterface->GetTime());
}