// 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()); }
StdMat2 *NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObject) { // Texture NiMaterialPropertyRef matRef = avObject->GetPropertyByType(NiMaterialProperty::TYPE); if (matRef != NULL){ StdMat2 *m = NewDefaultStdMat(); m->SetName(matRef->GetName().c_str()); if (showTextures) { m->SetMtlFlag(MTL_DISPLAY_ENABLE_FLAGS, TRUE); } // try the civ4 shader first then default back to normal shaders if (ImportNiftoolsShader(node, avObject, m)) { return m; } NiTexturingPropertyRef texRef = avObject->GetPropertyByType(NiTexturingProperty::TYPE); NiWireframePropertyRef wireRef = avObject->GetPropertyByType(NiWireframeProperty::TYPE); NiAlphaPropertyRef alphaRef = avObject->GetPropertyByType(NiAlphaProperty::TYPE); NiStencilPropertyRef stencilRef = avObject->GetPropertyByType(NiStencilProperty::TYPE); NiShadePropertyRef shadeRef = avObject->GetPropertyByType(NiShadeProperty::TYPE); vector<NiPropertyRef> props = avObject->GetProperties(); if (IsFallout3()) { m->SetAmbient(Color(0.588f, 0.588f, 0.588f),0); m->SetDiffuse(Color(0.588f, 0.588f, 0.588f),0); m->SetSpecular(Color(0.902f, 0.902f, 0.902f),0); } else { m->SetAmbient(TOCOLOR(matRef->GetAmbientColor()),0); m->SetDiffuse(TOCOLOR(matRef->GetDiffuseColor()),0); m->SetSpecular(TOCOLOR(matRef->GetSpecularColor()),0); } Color c = TOCOLOR(matRef->GetEmissiveColor()); if (c.r != 0 || c.b != 0 || c.g != 0) { m->SetSelfIllumColorOn(TRUE); m->SetSelfIllumColor(c,0); } m->SetShinStr(0.0,0); m->SetShininess(matRef->GetGlossiness()/100.0,0); m->SetOpacity(matRef->GetTransparency(),0); bool hasShaderAttributes = (wireRef != NULL) || (stencilRef != NULL) || (shadeRef != NULL); if (m->SupportsShaders() && hasShaderAttributes) { if (Shader *s = m->GetShader()) { if (wireRef != NULL && (wireRef->GetFlags() & 1)) { BOOL value = TRUE; m->SetWire(value); } if (stencilRef != NULL) { if (stencilRef->GetFaceDrawMode() == DRAW_BOTH) { BOOL value = TRUE; m->SetTwoSided(value); } } if (shadeRef != NULL && shadeRef->GetFlags() & 1) { m->SetFaceted(TRUE); } } } if (NULL != texRef) { // Handle Base/Detail ??? if (texRef->HasTexture(DECAL_0_MAP)){ if (Texmap* tex = CreateTexture(texRef->GetTexture(DECAL_0_MAP))) m->SetSubTexmap(ID_DI, tex); if (texRef->HasTexture(BASE_MAP)){ m->LockAmbDiffTex(FALSE); if (Texmap* tex = CreateTexture(texRef->GetTexture(BASE_MAP))) m->SetSubTexmap(ID_AM, tex); } } else if (texRef->HasTexture(BASE_MAP)) { if (Texmap* tex = CreateTexture(texRef->GetTexture(BASE_MAP))) { m->SetSubTexmap(ID_DI, tex); if (showTextures) gi->ActivateTexture(tex,m); } } // Handle Bump map if (texRef->HasTexture(BUMP_MAP)) { if (Texmap* tex = CreateTexture(texRef->GetTexture(BUMP_MAP))) m->SetSubTexmap(ID_BU, CreateNormalBump(NULL, tex)); } // Shiny map if (texRef->HasTexture(GLOSS_MAP)) { if (Texmap* tex = CreateTexture(texRef->GetTexture(GLOSS_MAP))) m->SetSubTexmap(ID_SS, tex); } // Self illumination if (texRef->HasTexture(GLOW_MAP)) { if (Texmap* tex = CreateTexture(texRef->GetTexture(GLOW_MAP))) m->SetSubTexmap(ID_SI, tex); } // Custom Shader Handling int nTex = texRef->GetShaderTextureCount(); if (nTex > 0) { list<NiExtraDataRef> data = avObject->GetExtraData(); NiGeometryRef trigeom = DynamicCast<NiGeometry>(avObject); if (trigeom->HasShader()) { for (list<NiExtraDataRef>::iterator itr = data.begin(); itr != data.end(); ++itr) { if ( NiIntegerExtraDataRef idx = DynamicCast<NiIntegerExtraData>(*itr) ) { string name = idx->GetName(); if ( wildmatch("*Index", name) ) { int shader = idx->GetData(); if (shader < nTex) { if ( name == "NormalMapIndex" ) { if (Texmap* tex = CreateTexture(texRef->GetShaderTexture(shader))) m->SetSubTexmap(ID_BU, CreateNormalBump(NULL, tex)); } else if ( name == "SpecularIntensity" ) { if (Texmap* tex = CreateTexture(texRef->GetShaderTexture(shader))) m->SetSubTexmap(ID_SP, CreateNormalBump(NULL, tex)); } } } } } } } } if (NiTexturePropertyRef tex2Ref = avObject->GetPropertyByType(NiTextureProperty::TYPE)){ // Handle Base/Detail ??? if (Texmap* tex = CreateTexture(tex2Ref)) { m->SetSubTexmap(ID_DI, tex); } } if (BSShaderNoLightingPropertyRef noLightShadeRef = SelectFirstObjectOfType<BSShaderNoLightingProperty>(props)) { if ( Texmap* tex = CreateTexture( noLightShadeRef->GetFileName() ) ) { m->SetSubTexmap(ID_DI, tex); } } if (BSShaderPPLightingPropertyRef ppLightShadeRef = SelectFirstObjectOfType<BSShaderPPLightingProperty>(props)) { if ( BSShaderTextureSetRef textures = ppLightShadeRef->GetTextureSet() ) { if ( Texmap* tex = CreateTexture( textures->GetTexture(0) ) ) m->SetSubTexmap(ID_DI, tex); if ( Texmap* tex = CreateTexture( textures->GetTexture(1) ) ) m->SetSubTexmap(ID_BU, CreateNormalBump(NULL, tex)); if ( Texmap* tex = CreateTexture( textures->GetTexture(3) ) ) m->SetSubTexmap(ID_SI, tex); if ( Texmap* tex = CreateTexture( textures->GetTexture(4) ) ) m->SetSubTexmap(ID_RL, tex); if ( Texmap* tex = CreateTexture( textures->GetTexture(5) ) ) { if ( Texmap* mask = CreateTexture( textures->GetTexture(2) ) ) tex = CreateMask(NULL, tex, mask); m->SetSubTexmap(ID_SP, tex); } } } if (SkyShaderPropertyRef skyShadeRef = SelectFirstObjectOfType<SkyShaderProperty>(props)) { if ( Texmap* tex = CreateTexture( skyShadeRef->GetFileName() ) ) { m->SetSubTexmap(ID_DI, tex); } } if (TileShaderPropertyRef tileShadeRef = SelectFirstObjectOfType<TileShaderProperty>(props)) { if ( Texmap* tex = CreateTexture( tileShadeRef->GetFileName() ) ) { m->SetSubTexmap(ID_DI, tex); } } if (TallGrassShaderPropertyRef grassShadeRef = SelectFirstObjectOfType<TallGrassShaderProperty>(props)) { if ( Texmap* tex = CreateTexture( grassShadeRef->GetFileName() ) ) { m->SetSubTexmap(ID_DI, tex); } } if (Lighting30ShaderPropertyRef lighting30ShadeRef = SelectFirstObjectOfType<Lighting30ShaderProperty>(props)) { if ( BSShaderTextureSetRef textures = lighting30ShadeRef->GetTextureSet() ) { if ( Texmap* tex = CreateTexture( textures->GetTexture(0) ) ) m->SetSubTexmap(ID_DI, tex); if ( Texmap* tex = CreateTexture( textures->GetTexture(1) ) ) m->SetSubTexmap(ID_BU, CreateNormalBump(NULL, tex)); if ( Texmap* tex = CreateTexture( textures->GetTexture(3) ) ) m->SetSubTexmap(ID_SI, tex); if ( Texmap* tex = CreateTexture( textures->GetTexture(4) ) ) m->SetSubTexmap(ID_RL, tex); if ( Texmap* tex = CreateTexture( textures->GetTexture(5) ) ) { if ( Texmap* mask = CreateTexture( textures->GetTexture(2) ) ) tex = CreateMask(NULL, tex, mask); m->SetSubTexmap(ID_SP, tex); } } } return m; } return NULL; }