private static int Main(string[] args) { LogFile theLog = new LogFile(); if (Enumerable.Count<string>((IEnumerable<string>)args) < 1) { theLog.WriteLog("Nothing to do"); theLog.Close(); return -1; } string path = args[0]; if (!File.Exists(path)) { theLog.WriteLog("No input file " + path); theLog.Close(); return -1; } CultureInfo cultureInfo = CmdArgs.ci; StreamReader streamReader = new StreamReader(path, System.Text.Encoding.Default, true); List<StaticDesc> statics = new List<StaticDesc>(); StringList BSAFiles = new StringList(); StringList ignoreList = new StringList(); StringList HDTexture = new StringList(); StringList notHDTexture = new StringList(); StringList HDMesh = new StringList(); StringList notHDMesh = new StringList(); Game.Mode = "tes5"; // 1 = 1 cell seems best Game.sampleSize = 1f; int counter = 0; string worldspaceName = ""; string gameDir = ""; string outputDir = ""; string uvfile = ""; float southWestX = 0; float southWestY = 0; float atlasTolerance = 0.2f; bool generateVertexColors = true; bool dontFixTangents = false; bool dontGenerateTangents = false; bool mergeShapes = true; bool removeUnseenFaces = false; bool ignoreWater = false; bool useHDFlag = true; bool useOptimizer = false; bool ignoreMaterial = false; float globalScale = 1f; while (!streamReader.EndOfStream) { string[] strArray2 = streamReader.ReadLine().Split('='); if (strArray2.Length == 2) { ++counter; if (strArray2[0].ToLower() == "worldspace") { worldspaceName = strArray2[1]; } if (strArray2[0].ToLower() == "cellsw") { string[] strArray1 = strArray2[1].Split(' '); southWestX = float.Parse(strArray1[0], (IFormatProvider)cultureInfo); southWestY = float.Parse(strArray1[1], (IFormatProvider)cultureInfo); } if (strArray2[0].ToLower() == "pathdata") { gameDir = strArray2[1].ToLower(); if (!Directory.Exists(gameDir)) { theLog.WriteLog("No Data directory " + gameDir); theLog.Close(); return -1; } } if (strArray2[0].ToLower() == "pathoutput") { outputDir = strArray2[1]; if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } } if (strArray2[0].ToLower() == "textureatlasmap") { uvfile = strArray2[1]; } if (strArray2[0].ToLower() == "resource") { if (File.Exists(strArray2[1])) { BSAFiles.Add(strArray2[1].ToLower()); } } if (strArray2[0].ToLower() == "ishdmeshmask") { HDMesh.Add(strArray2[1].ToLower()); } if (strArray2[0].ToLower() == "nothdmeshmask") { notHDMesh.Add(strArray2[1].ToLower()); } if (strArray2[0].ToLower() == "ishdtexturemask") { HDTexture.Add(strArray2[1].ToLower()); } if (strArray2[0].ToLower() == "nothdtexturemask") { notHDTexture.Add(strArray2[1].ToLower()); } if (strArray2[0].ToLower() == "atlastolerance") { atlasTolerance = float.Parse(strArray2[1], (IFormatProvider)cultureInfo); } if (strArray2[0].ToLower() == "ignoretranslation") { ignoreList.Add(strArray2[1].ToLower()); } if (strArray2[0].ToLower() == "gamemode") { Game.Mode = ((strArray2[1].ToLower())); if (Game.Mode == "fo3") { Game.Mode = "fnv"; } //generateVertexColors = false; } if (strArray2[0].ToLower() == "dontgeneratevertexcolors") { generateVertexColors = !Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "dontfixtangents") { dontFixTangents = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "dontgeneratetangents") { dontGenerateTangents = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "dontmergeshapes") { mergeShapes = !Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "removeunseenfaces") { removeUnseenFaces = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "ignorewater") { ignoreWater = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "usehdflag") { useHDFlag = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "useoptimizer") { useOptimizer = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "ignorematerial") { ignoreMaterial = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower() == "globalscale") { globalScale = float.Parse(strArray2[1], (IFormatProvider)cultureInfo); } } else { break; } } Dictionary<string, string> cmdArgs = Program.CollectCmdArgs(args); if (CmdArgs.GetBool(cmdArgs, "dontGenerateVertexColors", false)) { generateVertexColors = false; } if (CmdArgs.GetBool(cmdArgs, "dontFixTangents", false)) { dontFixTangents = true; } if (CmdArgs.GetBool(cmdArgs, "dontGenerateTangents", false)) { dontGenerateTangents = true; } if (CmdArgs.GetBool(cmdArgs, "dontMergeShapes", false)) { mergeShapes = false; } if (CmdArgs.GetBool(cmdArgs, "removeUnseenFaces", false)) { removeUnseenFaces = true; } if (CmdArgs.GetBool(cmdArgs, "ignoreWater", false)) { ignoreWater = true; } if (CmdArgs.GetBool(cmdArgs, "ignoreMaterial", false)) { ignoreMaterial = true; } if (CmdArgs.GetBool(cmdArgs, "usehdlod", false)) { useHDFlag = true; } if (CmdArgs.GetBool(cmdArgs, "globalScale", false)) { globalScale = CmdArgs.GetFloat(cmdArgs, "globalScale", 1f); } int int1 = CmdArgs.GetInt(cmdArgs, "lodLevel", -1); int int2 = CmdArgs.GetInt(cmdArgs, "x", -1); int int3 = CmdArgs.GetInt(cmdArgs, "y", -1); theLog.WriteLog("Game Mode: " + Game.Mode.ToUpper()); theLog.WriteLog("Fix Tangents: " + (!dontFixTangents ? "True" : "False")); theLog.WriteLog("Generate Tangents: " + (!dontGenerateTangents ? "True" : "False")); theLog.WriteLog("Generate Vertex Colors: " + (generateVertexColors ? "True" : "False")); theLog.WriteLog("Merge Meshes: " + (mergeShapes ? "True" : "False")); theLog.WriteLog("Remove Faces under Terrain: " + (removeUnseenFaces ? "True" : "False")); theLog.WriteLog("Remove Faces under Water: " + (!ignoreWater ? "True" : "False")); theLog.WriteLog("Use HD Flag: " + (useHDFlag ? "True" : "False")); //theLog.WriteLog("Use Optimizer: " + (useOptimizer ? "True" : "False")); theLog.WriteLog("Ignore Materials: " + (ignoreMaterial ? "True" : "False")); theLog.WriteLog("Global scale: " + string.Format("{0:0.00}", globalScale)); theLog.WriteLog("Specific level: " + (int1 != -1 ? int1.ToString() : "No")); if (int2 != -1 && int3 == -1) theLog.WriteLog("Specific quad: [" + (object)int2.ToString() + ", X]"); else if (int2 == -1 && int3 != -1) theLog.WriteLog("Specific quad: [X, " + (object)int3.ToString() + "]"); else if (int2 != -1 && int3 != -1) theLog.WriteLog("Specific quad: [" + (object)int2.ToString() + ", " + (string)(object)int3.ToString() + "]"); else theLog.WriteLog("Specific quad: No"); streamReader.Close(); if (worldspaceName == "") { theLog.WriteLog("No Worldspace"); theLog.Close(); return -1; } if (outputDir == "") { theLog.WriteLog("No PathOutput"); theLog.Close(); return -1; } /*IniFile ini = new IniFile(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "My games\\skyrim\\skyrim.ini")); if (ini.IniReadValue("Archive", "sResourceArchiveList").ToLower().Contains("aaa")) { string archiveList1 = ini.IniReadValue("Archive", "sResourceArchiveList").ToLower(); string archiveList2 = ini.IniReadValue("Archive", "sResourceArchiveList2").ToLower(); if (archiveList2.Length > 0) { archiveList1 += "," + archiveList2; } BSAFiles.Clear(); BSAFiles.AddRange(archiveList1.Split(',')); for (int index = 0; index < BSAFiles.Count; ++index) { if (File.Exists(Path.Combine(gameDir, BSAFiles[index].Trim()))) { BSAFiles[index] = Path.Combine(gameDir, BSAFiles[index].Trim()); } } }*/ BSAArchive.Load(BSAFiles, theLog, (CmdArgs.GetBool(cmdArgs, "verbose", false))); streamReader = new StreamReader(path); for (int index = 0; index < counter; ++index) { streamReader.ReadLine(); } while (!streamReader.EndOfStream) { StaticDesc staticDesc = new StaticDesc(); string[] strArray2 = streamReader.ReadLine().Split('\t'); staticDesc.refID = strArray2[0]; //theLog.WriteLog(staticDesc.refID); staticDesc.staticFlags = int.Parse(strArray2[1], NumberStyles.HexNumber, (IFormatProvider)cultureInfo); staticDesc.x = float.Parse(strArray2[2], (IFormatProvider)cultureInfo); staticDesc.y = float.Parse(strArray2[3], (IFormatProvider)cultureInfo); staticDesc.z = float.Parse(strArray2[4], (IFormatProvider)cultureInfo); staticDesc.rotX = float.Parse(strArray2[5], (IFormatProvider)cultureInfo); staticDesc.rotY = float.Parse(strArray2[6], (IFormatProvider)cultureInfo); staticDesc.rotZ = float.Parse(strArray2[7], (IFormatProvider)cultureInfo); staticDesc.scale = float.Parse(strArray2[8], (IFormatProvider)cultureInfo); staticDesc.staticName = strArray2[9]; staticDesc.refFlags = int.Parse(strArray2[10], NumberStyles.HexNumber, (IFormatProvider)cultureInfo); staticDesc.materialName = strArray2[11]; staticDesc.staticFullModel = strArray2[12]; if (strArray2.Length >= 16) { staticDesc.staticModels = new string[3]; for (int index = 0; index < 3; ++index) { string str = strArray2[13 + index]; staticDesc.staticModels[index] = str.ToLower(); if (str.Length > 0 && !File.Exists(gameDir + str)) { if (!BSAArchive.FileExists(str)) { theLog.WriteLog("file not found " + gameDir + str); theLog.Close(); System.Environment.Exit(404); } } } statics.Add(staticDesc); } } streamReader.Close(); if (File.Exists(uvfile)) { theLog.WriteLog("Using UV Atlas: " + uvfile); streamReader = new StreamReader(uvfile); while (!streamReader.EndOfStream) { string[] strArray2 = streamReader.ReadLine().Split('\t'); AtlasDesc atlasDesc = new AtlasDesc(); if (strArray2.Length >= 8) { atlasDesc.SourceTexture = strArray2[0].ToLower(); int textureWidth = int.Parse(strArray2[1], (IFormatProvider)cultureInfo); int textureHeight = int.Parse(strArray2[2], (IFormatProvider)cultureInfo); int textureX = int.Parse(strArray2[3], (IFormatProvider)cultureInfo); int textureY = int.Parse(strArray2[4], (IFormatProvider)cultureInfo); int atlasWidth = int.Parse(strArray2[6], (IFormatProvider)cultureInfo); int atlasHeight = int.Parse(strArray2[7], (IFormatProvider)cultureInfo); atlasDesc.scaleU = (float) textureWidth / (float) atlasWidth; atlasDesc.scaleV = (float) textureHeight / (float)atlasHeight; atlasDesc.posU = (float)textureX / (float) atlasWidth; atlasDesc.posV = (float)textureY / (float) atlasHeight; atlasDesc.AtlasTexture = strArray2[5].ToLower(); atlasDesc.AtlasTextureN = strArray2[5].ToLower().Replace(".dds", "_n.dds"); //theLog.WriteLog(atlasDesc.SourceTexture + "\t" + atlasDesc.AtlasTexture + "\t" + atlasDesc.scaleU + "\t" + atlasDesc.scaleV + "\t" + atlasDesc.posU + "\t" + atlasDesc.posV); AtlasList.Set(atlasDesc.SourceTexture, atlasDesc); } } streamReader.Close(); } theLog.WriteLog("Output: " + outputDir); theLog.WriteLog("Generating LOD for worldspace " + worldspaceName); List<Thread> list1 = new List<Thread>(); int num = 1; int index1 = 0; while (num <= 4) { list1.Add(new Thread((ParameterizedThreadStart)(state => { List<int> list2 = (List<int>)state; new LODApp(worldspaceName, outputDir, gameDir, theLog) { verbose = (CmdArgs.GetBool(cmdArgs, "verbose", false)), fixTangents = dontFixTangents, generateTangents = !dontGenerateTangents, generateVertexColors = generateVertexColors, mergeShapes = mergeShapes, useHDFlag = useHDFlag, useOptimizer = useOptimizer, useFadeNode = CmdArgs.GetBool(cmdArgs, "useFadeNode", false), removeUnseenFaces = removeUnseenFaces, globalScale = globalScale, lodLevelToGenerate = CmdArgs.GetInt(cmdArgs, "lodLevel", -1), lodX = CmdArgs.GetInt(cmdArgs, "x", -1), lodY = CmdArgs.GetInt(cmdArgs, "y", -1), southWestX = (int) southWestX, southWestY = (int) southWestY, atlasToleranceMin = atlasTolerance * -1f, atlasToleranceMax = atlasTolerance + 1f, removeUnderwaterFaces = !ignoreWater, ignoreMaterial = ignoreMaterial, skyblivionTexPath = CmdArgs.GetBool(cmdArgs, "skyblivionTexPath", false), ignoreTransRot = ignoreList, HDTextureList = HDTexture, notHDTextureList = notHDTexture, HDMeshList = HDMesh, notHDMeshList = notHDMesh }.GenerateLOD(list2[1], list2[0], statics); }))); list1[index1].Start((object)new List<int>() { num, index1 }); num <<= 1; ++index1; } while (list1.Count > 0) { for (int index2 = 0; index2 < list1.Count; ++index2) { if (!list1[index2].IsAlive) { list1.RemoveAt(index2); --index2; } } Thread.Sleep(100); } theLog.Close(); return 0; }
public ShapeDesc(String gameDir, NiFile file, NiTriBasedGeom geom, StaticDesc stat, int quadIndex, StringList PassThruMeshList, bool skyblivionTexPath, bool useOptimizer, bool fixTangents, bool useDecalFlag, bool terrain, bool verbose, LogFile logFile) { this.name = ""; if (geom.GetNameIndex() != -1) { this.name = file.GetStringAtIndex(geom.GetNameIndex()); } else { this.name = geom.GetName(); } if (this.name == null) { this.name = ""; } this.staticName = stat.staticName; if (stat.staticModels != null && quadIndex < stat.staticModels.Count()) { this.staticModel = stat.staticModels[quadIndex].ToLower(CultureInfo.InvariantCulture); } else { this.staticModel = ""; } this.geometry = null; this.shaderType = ""; this.effectShader = null; this.lightingShader = null; this.texturingProperty = null; this.materialProperty = null; this.sourceTextureBase = null; this.sourceTextureDetail = null; this.sourceTextureGlow = null; this.sourceTextureBump = null; this.shaderHash = ""; this.shapeHash = ""; if (stat.materialName != null) { this.material = stat.materialName; } else { this.material = ""; } if (quadIndex != 0 && this.material.ToLower().Contains("largeref")) { this.material = Regex.Replace(this.material, "-largeref", "", RegexOptions.IgnoreCase); } this.textures = new string[10] { "", "", "", "", "", "", "", "", "", "" }; this.textures[0] = "textures\\default.dds"; this.textures[1] = "textures\\default_n.dds"; if (this.name == "LODGenPassThru" || this.material.ToLower(CultureInfo.InvariantCulture) == "passthru" || (PassThruMeshList != null && staticModel != "" && PassThruMeshList.Any(staticModel.Contains))) { this.isPassThru = true; this.material = "passthru"; } else { this.isPassThru = false; } if ((stat.staticFlags & 1) == 1) { this.isGroup = true; } this.isHighDetail = false; this.hasVertexColor = false; this.allWhite = false; this.isDoubleSided = false; this.isAlpha = false; this.isDecal = false; this.enableParent = 0; this.TextureClampMode = 0; this.boundingBox = new BBox(); this.x = new float(); this.y = new float(); this.segments = new List <SegmentDesc>(); this.translation = new Vector3(stat.x, stat.y, stat.z); this.scale = stat.scale; Matrix33 matrix33_1 = new Matrix33(true); Matrix33 matrix33_2 = new Matrix33(true); Matrix33 matrix33_3 = new Matrix33(true); matrix33_1.SetRotationX(Utils.ToRadians(-stat.rotX)); matrix33_2.SetRotationY(Utils.ToRadians(-stat.rotY)); matrix33_3.SetRotationZ(Utils.ToRadians(-stat.rotZ)); this.rotation = new Matrix33(true) * matrix33_1 * matrix33_2 * matrix33_3; try { if (geom.GetClassName() == "NiTriStrips") { int index = geom.GetData(); if (index == -1) { geometry = new Geometry(); } else { geometry = new Geometry(new NiTriShapeData((NiTriStripsData)file.GetBlockAtIndex(index))); } List <int> extradatalist = geom.GetExtraData(); if (extradatalist.Count == 1) { NiBinaryExtraData extradata = (NiBinaryExtraData)file.GetBlockAtIndex(extradatalist[0]); this.geometry.SetTangents(extradata.GetTangents()); this.geometry.SetBitangents(extradata.GetBitangents()); } } else { int index = geom.GetData(); if (index == -1) { geometry = new Geometry(); } else { if (file.GetBlockAtIndex(index).IsDerivedType("BSTriShape")) { BSTriShape bsts = (BSTriShape)file.GetBlockAtIndex(index); geometry = bsts.GetGeom(); } else { geometry = new Geometry((NiTriShapeData)file.GetBlockAtIndex(index)); } } } } catch { logFile.WriteLog("Skipping non supported data " + this.staticModel + " " + this.name); geometry = new Geometry(); return; } if (terrain) { return; } if (geometry.uvcoords.Count == 0) { logFile.WriteLog("Skipping no UV " + this.staticModel + " " + this.name); geometry = new Geometry(); return; } if (geometry.HasVertexColors()) { this.allWhite = true; List <Color4> vertexColors = geometry.GetVertexColors(); for (int index = 0; index < vertexColors.Count; index++) { float r = vertexColors[index][0]; float g = vertexColors[index][1]; float b = vertexColors[index][2]; float a = vertexColors[index][3]; if (r < 0.9f || b < 0.9f || g < 0.9f) { this.allWhite = false; } if (this.isPassThru && Game.Mode != "merge5") { // if neither LOD flag is set, alpha is used on/off at 0.5f, nobody wants that // HD snow shader uses alpha for something else a = 1f; } vertexColors[index] = new Color4(r, g, b, a); } if (this.allWhite) { geometry.SetVertexColors(new List <Color4>()); } else if (this.isPassThru && Game.Mode != "merge5") { geometry.SetVertexColors(vertexColors); } } this.hasVertexColor = geometry.HasVertexColors(); try { this.shapeHash = Utils.GetHash(Utils.ObjectToByteArray(geometry.vertices)); } catch { logFile.WriteLog("Can not get hash for vertices in " + this.staticModel + " block " + this.name); logFile.Close(); System.Environment.Exit(3003); } if ((file.GetVersion() > 335544325U) && (file.GetUserVersion() > 11U)) { for (int index = 0; index < 2; index++) { if (geom.GetBSProperty(index) != -1) { string type = file.GetBlockAtIndex(geom.GetBSProperty(index)).GetClassName().ToLower(CultureInfo.InvariantCulture); if (type == "nialphaproperty") { if (Game.Mode == "fo4" || Game.Mode == "merge5") { this.isAlpha = true; NiAlphaProperty alphaProperty = (NiAlphaProperty)file.GetBlockAtIndex(geom.GetBSProperty(index)); this.alphaThreshold = alphaProperty.GetThreshold(); } } else if (type == "bseffectshaderproperty") { this.shaderType = type; BSEffectShaderProperty shader = (BSEffectShaderProperty)file.GetBlockAtIndex(geom.GetBSProperty(index)); this.textures[0] = shader.GetSourceTexture().ToLower(CultureInfo.InvariantCulture); // disable non supported flags if (Game.Mode != "merge5") { shader.SetShaderFlags1(shader.GetShaderFlags1() & 3724541045); shader.SetShaderFlags2(shader.GetShaderFlags2() & 3758063615); } shader.SetSourceTexture(""); this.effectShader = shader; if (this.hasVertexColor) { shader.SetShaderFlags2(shader.GetShaderFlags2() | 32); } else { shader.SetShaderFlags2(shader.GetShaderFlags2() & 4294967263); } this.isDoubleSided = (shader.GetShaderFlags2() & 16) == 16; this.TextureClampMode = shader.GetTextureClampMode(); shader.SetTextureClampMode(3); try { this.shaderHash = Utils.GetHash(Utils.ObjectToByteArray(shader)); } catch { logFile.WriteLog("Can not get hash for shader in " + this.staticModel + " block " + this.name); logFile.Close(); System.Environment.Exit(3004); } } else if (type == "bslightingshaderproperty") { this.shaderType = type; BSLightingShaderProperty shader = (BSLightingShaderProperty)file.GetBlockAtIndex(geom.GetBSProperty(index)); // disable non supported flags if (Game.Mode != "merge5") { //enviroment shader if (shader.GetShaderType() == 1) { if ((shader.GetShaderFlags2() & 64) == 64) { //glow shader shader.SetShaderType(2); } shader.SetShaderType(0); } //3695270121 shader.SetShaderFlags1(shader.GetShaderFlags1() & 3724541045); shader.SetShaderFlags2(shader.GetShaderFlags2() & 3758063615); } this.TextureClampMode = shader.GetTextureClampMode(); shader.SetTextureClampMode(3); this.isDoubleSided = (shader.GetShaderFlags2() & 16) == 16; if ((Game.Mode == "tes5" || Game.Mode == "sse") && useDecalFlag && !this.isPassThru && ((shader.GetShaderFlags1() & 67108864) == 67108864 || (shader.GetShaderFlags1() & 134217728) == 134217728)) { this.isDecal = true; // SLSF1_Decal shader.SetShaderFlags1(shader.GetShaderFlags1() | 67108864); // SLSF1_Dynamic_Decal shader.SetShaderFlags1(shader.GetShaderFlags1() | 134217728); // SLSF2_No_Fade shader.SetShaderFlags2(shader.GetShaderFlags2() | 8); } if (this.hasVertexColor) { shader.SetShaderFlags2(shader.GetShaderFlags2() | 32); } else { shader.SetShaderFlags2(shader.GetShaderFlags2() & 4294967263); } // no specular flag -> reset specular strength, color, glossiness //if ((shader.GetShaderFlags1() & 1) == 0 || shader.GetSpecularStrength() == 0f || (shader.GetGlossiness() == 80f && shader.GetSpecularColor() == new Color3(0f, 0f, 0f) && shader.GetSpecularStrength() == 1f)) //{ shader.SetShaderFlags1(shader.GetShaderFlags1() & 4294967294); shader.SetGlossiness(80f); shader.SetSpecularColor(new Color3(0f, 0f, 0f)); shader.SetSpecularStrength(1f); //} // no soft/rim/back/effect lighting -> reset effect lighting 1 and 2 if ((shader.GetShaderFlags2() & 1308622848) == 0 || (shader.GetLightingEffect1() < 0.1f && shader.GetLightingEffect2() < 0.1f)) { shader.SetShaderFlags2(shader.GetShaderFlags2() & 2986344447); shader.SetLightingEffect1(0f); shader.SetLightingEffect2(0f); } // no own emit -> reset own emit, emissive color, muliplier if ((shader.GetShaderFlags1() & 4194304) == 0 || (shader.GetEmissiveColor()[0] < 0.1f && shader.GetEmissiveColor()[1] < 0.1f && shader.GetEmissiveColor()[2] < 0.1f) || shader.GetEmissiveMultiple() == 0f) { shader.SetShaderFlags1(shader.GetShaderFlags1() & 4290772991); shader.SetEmissiveColor(new Color3(0f, 0f, 0f)); shader.SetEmissiveMultiple(1f); } this.backlightPower = shader.GetBacklightPower(); if (shader.GetTextureSet() != -1 && this.textures[0] == "textures\\default.dds") { BSShaderTextureSet shaderTextureSet = (BSShaderTextureSet)file.GetBlockAtIndex(shader.GetTextureSet()); for (int index2 = 0; index2 < shaderTextureSet.GetNumTextures(); ++index2) { this.textures[index2] = shaderTextureSet.GetTexture(index2).ToLower(CultureInfo.InvariantCulture); } } shader.SetTextureSet(-1); //BGSM takes priority and overwrite everything in nif if (shader.GetNameIndex() != -1) { string bgsmFileName = file.GetStringAtIndex(shader.GetNameIndex()).ToLower(CultureInfo.InvariantCulture); if (bgsmFileName.Contains(".bgsm")) { int i = bgsmFileName.IndexOf("\\data\\"); if (i > 0) { i += 6; bgsmFileName = bgsmFileName.Substring(i, bgsmFileName.Length - i); } if (stat.materialSwap.ContainsKey(bgsmFileName)) { bgsmFileName = stat.materialSwap[bgsmFileName]; } BGSMFile bgsmdata = new BGSMFile(); bgsmdata.Read(gameDir, bgsmFileName, logFile); if (bgsmdata.textures[0] != "") { this.textures[0] = "textures\\" + bgsmdata.textures[0]; this.textures[1] = "textures\\" + bgsmdata.textures[1]; this.textures[7] = "textures\\" + bgsmdata.textures[2]; this.TextureClampMode = bgsmdata.textureClampMode; shader.SetTextureClampMode(this.TextureClampMode); this.isAlpha = Convert.ToBoolean(bgsmdata.alphaFlag); this.isDoubleSided = Convert.ToBoolean(bgsmdata.doubleSided); shader.SetShaderFlags2(shader.GetShaderFlags2() | 16); this.alphaThreshold = bgsmdata.alphaThreshold; this.backlightPower = bgsmdata.backlightPower; shader.SetBacklightPower(this.backlightPower); } } } try { this.shaderHash = Utils.GetHash(Utils.ObjectToByteArray(shader)); } catch { logFile.WriteLog("Can not get hash for shader in " + this.staticModel + " block " + this.name); logFile.Close(); System.Environment.Exit(3005); } this.lightingShader = shader; } else { if (this.shaderType == "") { this.shaderType = type; } } } } } else { this.shaderType = "none"; for (int index = 0; index < geom.GetNumProperties(); ++index) { NiProperty niProperty = (NiProperty)file.GetBlockAtIndex(geom.GetProperty(index)); string type = niProperty.GetClassName().ToLower(CultureInfo.InvariantCulture); if (niProperty.GetType() == typeof(BSShaderPPLightingProperty)) { BSShaderPPLightingProperty shader = (BSShaderPPLightingProperty)file.GetBlockAtIndex(geom.GetProperty(index)); BSShaderTextureSet shaderTextureSet = (BSShaderTextureSet)file.GetBlockAtIndex(shader.GetTextureSet()); for (int index2 = 0; index2 < shaderTextureSet.GetNumTextures(); ++index2) { this.textures[index2] = shaderTextureSet.GetTexture(index2).ToLower(CultureInfo.InvariantCulture); } //this.hasVertexColor = (shader.GetShaderFlags2() & 32) == 32; //this.isDoubleSided = (shader.GetShaderFlags2() & 16) == 16; //this.TextureClampMode = shader.GetTextureClampMode(); this.shaderType = type; break; } if (niProperty.GetType() == typeof(NiMaterialProperty)) { this.materialProperty = (NiMaterialProperty)niProperty; this.hasVertexColor = this.geometry.HasVertexColors(); } if (niProperty.GetType() == typeof(NiTexturingProperty)) { this.texturingProperty = (NiTexturingProperty)niProperty; string str1 = "textures\\defaultdiffuse.dds"; string str2 = "textures\\default_n.dds"; if (this.texturingProperty != null) { TexDesc baseTexture = this.texturingProperty.GetBaseTexture(); if (this.texturingProperty.HasBaseTexture() && this.texturingProperty.GetBaseTexture().source != -1) { this.sourceTextureBase = (NiSourceTexture)file.GetBlockAtIndex(this.texturingProperty.GetBaseTexture().source); str1 = this.sourceTextureBase.GetFileName().ToLower(CultureInfo.InvariantCulture); } if (this.texturingProperty.HasDarkTexture() && this.texturingProperty.GetDarkTexture().source != -1) { if (verbose) { logFile.WriteLog("dark texture " + this.staticName); } } if (this.texturingProperty.HasDetailTexture() && this.texturingProperty.GetDetailTexture().source != -1) { if (verbose) { logFile.WriteLog("detail texture " + this.staticName); } this.sourceTextureDetail = (NiSourceTexture)file.GetBlockAtIndex(this.texturingProperty.GetDetailTexture().source); str1 = this.sourceTextureDetail.GetFileName().ToLower(CultureInfo.InvariantCulture); } if (this.texturingProperty.HasGlossTexture() && this.texturingProperty.GetGlossTexture().source != -1) { if (verbose) { logFile.WriteLog("gloss texture " + this.staticName); } } if (this.texturingProperty.HasGlowTexture() && this.texturingProperty.GetGlowTexture().source != -1) { if (verbose) { logFile.WriteLog("glow texture " + this.staticName); } this.sourceTextureGlow = (NiSourceTexture)file.GetBlockAtIndex(this.texturingProperty.GetGlowTexture().source); } if (this.texturingProperty.HasBumpMapTexture() && this.texturingProperty.GetBumpMapTexture().source != -1) { if (verbose) { logFile.WriteLog("bump texture " + this.staticName); } this.sourceTextureBump = (NiSourceTexture)file.GetBlockAtIndex(this.texturingProperty.GetBumpMapTexture().source); } if (this.texturingProperty.HasDecalTexture0() && this.texturingProperty.GetDecalTexture0().source != -1) { if (verbose) { logFile.WriteLog("decal texture " + this.staticName); } } str2 = Utils.GetNormalTextureName(str1); if (skyblivionTexPath && !str1.Contains("textures\\tes4")) { str1 = str1.ToLower().Replace("textures", "textures\\tes4"); str2 = str2.ToLower().Replace("textures", "textures\\tes4"); } } this.textures[0] = str1.ToLower(CultureInfo.InvariantCulture); this.textures[1] = str2.ToLower(CultureInfo.InvariantCulture); if (this.texturingProperty.HasBaseTexture()) { this.TextureClampMode = this.texturingProperty.GetBaseTexture().clampMode; } this.shaderType = type; break; } } } for (int index = 0; index < this.textures.Length; index++) { this.textures[index] = this.textures[index].Trim(); if (this.textures[index].Contains(".dds") && !this.textures[index].Contains("textures\\")) { this.textures[index] = Path.Combine("textures\\", this.textures[index]); } } if (((Game.Mode == "convert4" || Game.Mode == "convert5") && useOptimizer && AtlasList.Contains(this.textures[0])) || this.textures[0] == "textures\\grid.dds") { string texture = this.textures[0]; geometry = geometry.ReUV(this, texture, logFile, verbose); this.textures = new string[10] { "", "", "", "", "", "", "", "", "", "" }; this.textures[0] = AtlasList.Get(texture).AtlasTexture; this.textures[1] = AtlasList.Get(texture).AtlasTextureN; if (this.textures[2] != "") { this.textures[2] = AtlasList.Get(texture).AtlasTexture; } if (Game.Mode == "fo4") { this.textures[7] = AtlasList.Get(texture).AtlasTextureS; } this.TextureClampMode = 0U; this.isHighDetail = false; } else if ((Game.Mode == "convert4" || Game.Mode == "convert5") && useOptimizer && verbose) { logFile.WriteLog(this.staticModel + " " + this.name + " " + this.textures[0] + " not in atlas file"); } if (!geometry.HasNormals()) { geometry.FaceNormals(); geometry.SmoothNormals(60f, 0.001f); } if (fixTangents && !geometry.HasTangents()) { geometry.UpdateTangents(fixTangents); } }
private List<ShapeDesc> IterateNodes(QuadDesc quad, StaticDesc stat, int level, NiFile file, NiNode parentNode, Matrix44 parentTransform, float parentScale) { List<ShapeDesc> list = new List<ShapeDesc>(); if (parentNode == null || parentNode.IsHidden()) return list; int nameIndex = parentNode.GetNameIndex(); string str = nameIndex != -1 ? file.GetStringAtIndex(nameIndex) : parentNode.GetName(); if (str != null && str.ToLower().Contains("editormarker")) return list; Matrix44 parentTransform1 = parentNode.GetTransform() * parentTransform; if (ignoreTransRot.Any(stat.staticModels[level].Contains)) { parentTransform1 = parentTransform; } float parentScale1 = parentNode.GetScale() * parentScale; uint numChildren = parentNode.GetNumChildren(); for (int index = 0; (long)index < (long)numChildren; ++index) { NiObject blockAtIndex = file.GetBlockAtIndex(parentNode.GetChildAtIndex(index)); if (blockAtIndex != null) { if (blockAtIndex.IsDerivedType("NiNode")) { list.AddRange((IEnumerable<ShapeDesc>)this.IterateNodes(quad, stat, level, file, (NiNode)blockAtIndex, parentTransform1, parentScale1)); } else if (blockAtIndex.IsDerivedType("NiTriBasedGeom")) { NiTriBasedGeom geomOld = (NiTriBasedGeom)blockAtIndex; if (index + 1 < numChildren) { NiObject blockAtIndexNext = file.GetBlockAtIndex(parentNode.GetChildAtIndex(index + 1)); if (blockAtIndexNext.IsDerivedType("NiTriBasedGeom")) { NiTriBasedGeom geomOld2 = (NiTriBasedGeom)blockAtIndexNext; if (geomOld.GetData() == geomOld2.GetData()) { //Console.WriteLine(geomOld.GetData() + " = " + geomOld2.GetData()); NiTriBasedGeom geomNew = new NiTriBasedGeom(); geomNew.SetFlags(14); geomNew.SetTranslation(geomOld.GetTranslation()); geomNew.SetRotation(geomOld.GetRotation()); geomNew.SetScale(geomOld.GetScale()); geomNew.SetNumProperties(geomOld.GetNumProperties()); for (int index2 = 0; (long)index2 < (long)geomOld.GetNumProperties(); ++index2) { geomNew.SetProperties(geomOld.GetProperty(index2)); } NiTriShapeData dataOld = (NiTriShapeData)file.GetBlockAtIndex(geomOld.GetData()); NiTriShapeData dataNew = new NiTriShapeData(); dataNew.SetNumVertices(dataOld.GetNumVertices()); dataNew.SetHasVertices(dataOld.HasVertices()); dataNew.SetVertices(new List<Vector3>(dataOld.GetVertices())); dataNew.SetNumUVSets(dataOld.GetBSNumUVSets()); dataNew.SetHasNormals(dataOld.HasNormals()); dataNew.SetNormals(new List<Vector3>(dataOld.GetNormals())); dataNew.SetTangents(new List<Vector3>(dataOld.GetTangents())); dataNew.SetBitangents(new List<Vector3>(dataOld.GetBitangents())); dataNew.SetCenter(dataOld.GetCenter()); dataNew.SetRadius(dataOld.GetRadius()); dataNew.SetHasVertexColors(dataOld.HasVertexColors()); dataNew.SetVertexColors(dataOld.GetVertexColors()); dataNew.SetUVCoords(dataOld.GetUVCoords()); dataNew.SetConsistencyFlags(dataOld.GetConsistencyFlags()); dataNew.SetNumTriangles(dataOld.GetNumTriangles()); dataNew.SetNumTrianglePoints(dataOld.GetNumTrianglePoints()); dataNew.SetHasTriangles(dataOld.HasTriangles()); dataNew.SetTriangles(new List<Triangle>(dataOld.GetTriangles())); int newdata = file.AddBlock(dataNew); geomNew.SetData(newdata); int newblock = file.AddBlock(geomNew); blockAtIndex = file.GetBlockAtIndex(newblock); //Console.WriteLine("New block " + newdata + " = " + newblock); } } } ShapeDesc shapeDesc = this.TransformShape(quad, stat, file, (NiTriBasedGeom)blockAtIndex, parentTransform1, parentScale1); if (shapeDesc != null && shapeDesc.shape != null) { list.Add(shapeDesc); } } } } /* if (useOptimizer) { List<ShapeDesc> list2 = new List<ShapeDesc>(); for (int shapeIndex = 0; shapeIndex < list.Count; shapeIndex++) { ShapeDesc shapeDesc = list[shapeIndex]; NiTriShapeData data = shapeDesc.data; List<Triangle> triangles = data.GetTriangles(); if (data.HasVertexColors() && triangles.Count != 0) { NiTriShapeData data1 = new NiTriShapeData(); NiTriShapeData data2 = new NiTriShapeData(); List<Color4> vertexcolors = data.GetVertexColors(); bool vertexcolors_white = true; bool vertexcolors_colors = true; if (vertexcolors_white && vertexcolors_colors) { Dictionary<ushort, ushort>[] dictionary = new Dictionary<ushort, ushort>[] { new Dictionary<ushort, ushort>(), new Dictionary<ushort, ushort>() }; List<Vector3> vertices = data.GetVertices(); List<UVCoord> uvcoords = data.GetUVCoords(); List<Vector3> normals = data.GetNormals(); List<Vector3> tangents = data.GetTangents(); List<Vector3> bitangents = data.GetBitangents(); List<Triangle>[] triangles1 = new List<Triangle>[] { new List<Triangle>(), new List<Triangle>() }; List<Vector3>[] vertices1 = new List<Vector3>[] { new List<Vector3>(), new List<Vector3>() }; List<UVCoord>[] uvcoords1 = new List<UVCoord>[] { new List<UVCoord>(), new List<UVCoord>() }; List<Color4>[] vertexcolors1 = new List<Color4>[] { new List<Color4>(), new List<Color4>() }; List<Vector3>[] normals1 = new List<Vector3>[] { new List<Vector3>(), new List<Vector3>() }; List<Vector3>[] tangents1 = new List<Vector3>[] { new List<Vector3>(), new List<Vector3>() }; List<Vector3>[] bitangents1 = new List<Vector3>[] { new List<Vector3>(), new List<Vector3>() }; UInt16[] index2 = new UInt16[] { 0, 0 }; for (int index = 0; index < triangles.Count; ++index) { ushort indexA = triangles[index][0]; ushort indexB = triangles[index][1]; ushort indexC = triangles[index][2]; float colorA = vertexcolors[indexA][0] + vertexcolors[indexA][1] + vertexcolors[indexA][2]; float colorB = vertexcolors[indexB][0] + vertexcolors[indexB][1] + vertexcolors[indexB][2]; float colorC = vertexcolors[indexC][0] + vertexcolors[indexC][1] + vertexcolors[indexC][2]; int shapeSplit = new int(); if (colorA > 2.6f && colorB > 2.6f && colorC > 2.6f) { shapeSplit = 0; } else { shapeSplit = 1; } if (!dictionary[shapeSplit].ContainsKey(indexA)) { dictionary[shapeSplit].Add(indexA, index2[shapeSplit]); vertices1[shapeSplit].Add(vertices[indexA]); if (uvcoords.Count != 0) { uvcoords1[shapeSplit].Add(uvcoords[indexA]); } if (shapeSplit == 1 && vertexcolors.Count != 0) { vertexcolors1[shapeSplit].Add(vertexcolors[indexA]); } if (normals.Count != 0) { normals1[shapeSplit].Add(normals[indexA]); } if (tangents.Count != 0) { tangents1[shapeSplit].Add(tangents[indexA]); } if (bitangents.Count != 0) { bitangents1[shapeSplit].Add(bitangents[indexA]); } indexA = index2[shapeSplit]; ++index2[shapeSplit]; } else { indexA = dictionary[shapeSplit][indexA]; } if (!dictionary[shapeSplit].ContainsKey(indexB)) { dictionary[shapeSplit].Add(indexB, index2[shapeSplit]); vertices1[shapeSplit].Add(vertices[indexB]); if (uvcoords.Count != 0) { uvcoords1[shapeSplit].Add(uvcoords[indexB]); } if (shapeSplit == 1 && vertexcolors.Count != 0) { vertexcolors1[shapeSplit].Add(vertexcolors[indexB]); } if (normals.Count != 0) { normals1[shapeSplit].Add(normals[indexB]); } if (tangents.Count != 0) { tangents1[shapeSplit].Add(tangents[indexB]); } if (bitangents.Count != 0) { bitangents1[shapeSplit].Add(bitangents[indexB]); } indexB = index2[shapeSplit]; ++index2[shapeSplit]; } else { indexB = dictionary[shapeSplit][indexB]; } if (!dictionary[shapeSplit].ContainsKey(indexC)) { dictionary[shapeSplit].Add(indexC, index2[shapeSplit]); vertices1[shapeSplit].Add(vertices[indexC]); if (uvcoords.Count != 0) { uvcoords1[shapeSplit].Add(uvcoords[indexC]); } if (shapeSplit == 1 && vertexcolors.Count != 0) { vertexcolors1[shapeSplit].Add(vertexcolors[indexC]); } if (normals.Count != 0) { normals1[shapeSplit].Add(normals[indexC]); } if (tangents.Count != 0) { tangents1[shapeSplit].Add(tangents[indexC]); } if (bitangents.Count != 0) { bitangents1[shapeSplit].Add(bitangents[indexC]); } indexC = index2[shapeSplit]; ++index2[shapeSplit]; } else { indexC = dictionary[shapeSplit][indexC]; } triangles1[shapeSplit].Add(new Triangle(indexA, indexB, indexC)); } if (triangles1[0].Count != 0) { ShapeDesc shapeDesc1 = new ShapeDesc(); shapeDesc1.shape = shapeDesc.shape; shapeDesc1.material = shapeDesc.material; shapeDesc1.textures = shapeDesc.textures; shapeDesc1.isHighDetail = shapeDesc.isHighDetail; shapeDesc1.hasVertexColor = false; shapeDesc1.isDoubleSided = shapeDesc.isDoubleSided; shapeDesc1.TextureClampMode = shapeDesc.TextureClampMode; shapeDesc1.boundingBox = shapeDesc.boundingBox; shapeDesc1.x = shapeDesc.x; shapeDesc1.y = shapeDesc.y; shapeDesc1.segments = shapeDesc.segments; data1.SetNumVertices((ushort)vertices1[0].Count); data1.SetHasVertices(true); data1.SetNumUVSets(4097); data1.SetHasNormals(true); data1.SetCenter(data.GetCenter()); data1.SetRadius(data.GetRadius()); data1.SetConsistencyFlags(data.GetConsistencyFlags()); data1.SetNumTriangles((ushort)triangles1[0].Count); data1.SetNumTrianglePoints((uint)triangles1[0].Count * 3); data1.SetHasTriangles(true); data1.SetHasVertexColors(false); data1.SetVertices(vertices1[0]); data1.SetNormals(normals1[0]); data1.SetTangents(tangents1[0]); data1.SetBitangents(bitangents1[0]); data1.SetUVCoords(uvcoords1[0]); //data1.SetVertexColors(vertexcolors1[0]); data1.SetTriangles(triangles1[0]); shapeDesc1.data = data1; list2.Add(shapeDesc1); } if (triangles1[1].Count != 0) { ShapeDesc shapeDesc2 = new ShapeDesc(); shapeDesc2.shape = shapeDesc.shape; shapeDesc2.material = shapeDesc.material; shapeDesc2.textures = shapeDesc.textures; shapeDesc2.isHighDetail = shapeDesc.isHighDetail; shapeDesc2.hasVertexColor = true; shapeDesc2.isDoubleSided = shapeDesc.isDoubleSided; shapeDesc2.TextureClampMode = shapeDesc.TextureClampMode; shapeDesc2.boundingBox = shapeDesc.boundingBox; shapeDesc2.x = shapeDesc.x; shapeDesc2.y = shapeDesc.y; shapeDesc2.segments = shapeDesc.segments; data2.SetNumVertices((ushort)vertices1[0].Count); data2.SetHasVertices(true); data2.SetNumUVSets(4097); data2.SetHasNormals(true); data2.SetCenter(data.GetCenter()); data2.SetRadius(data.GetRadius()); data2.SetConsistencyFlags(data.GetConsistencyFlags()); data2.SetNumTriangles((ushort)triangles1[0].Count); data2.SetNumTrianglePoints((uint)triangles1[0].Count * 3); data2.SetHasTriangles(true); data2.SetHasVertexColors(true); data2.SetVertices(vertices1[1]); data2.SetNormals(normals1[1]); data2.SetTangents(tangents1[1]); data2.SetBitangents(bitangents1[1]); data2.SetUVCoords(uvcoords1[1]); data2.SetVertexColors(vertexcolors1[1]); data2.SetTriangles(triangles1[1]); shapeDesc2.data = data2; list2.Add(shapeDesc2); } } else { list2.Add(shapeDesc); } } else { list2.Add(shapeDesc); } } return list2; }*/ return list; }
public void GenerateTest(string strfile, LogFile logFile) { NiFile file = new NiFile(); NiNode rootNode = new NiNode(); file.AddBlock((NiObject)rootNode); this.quadLevel = 4; this.quadOffset = 16384f; QuadDesc quad = new QuadDesc(); quad.x = 0; quad.y = 0; quad.statics = new List<StaticDesc>(); StaticDesc curStat = new StaticDesc(); curStat.refID = "0"; curStat.rotX = 0.0f; curStat.rotY = 0.0f; curStat.rotZ = 0.0f; curStat.scale = 1f; curStat.x = 0.0f; curStat.y = 0.0f; curStat.z = 0.0f; curStat.staticName = "Test"; curStat.staticFullModel = strfile; curStat.staticModels = new string[3]; curStat.staticModels[0] = strfile; curStat.staticModels[1] = strfile; curStat.staticModels[2] = strfile; quad.statics.Add(curStat); List<ShapeDesc> shapes = this.ParseNif(quad, curStat, 0, file, rootNode); this.MergeNodes(shapes); for (int index = 0; index < shapes.Count; ++index) { BSSegmentedTriShape segmentedTriShape = new BSSegmentedTriShape((NiGeometry)shapes[index].shape); segmentedTriShape.SetRotation(new Matrix33(true)); segmentedTriShape.SetTranslation(new Vector3(0.0f, 0.0f, 0.0f)); rootNode.AddChild(file.AddBlock((NiObject)segmentedTriShape)); segmentedTriShape.SetData(file.AddBlock((NiObject)shapes[index].data)); } file.Write(this.outputDir + "\\" + this.worldspaceName + ".test.nif", logFile); }
private bool UVAtlas(NiTriShapeData data, string texture, StaticDesc stat) { List<UVCoord> uvcoords = data.GetUVCoords(); List<UVCoord> uvcoords2 = new List<UVCoord>(); for (int index = 0; index < uvcoords.Count; ++index) { float u = uvcoords[index][0]; float v = uvcoords[index][1]; if (u < atlasToleranceMin || u > atlasToleranceMax || v < atlasToleranceMin || u > atlasToleranceMax) { if (this.verbose && !texture.Contains("glacierslablod")) { logFile.WriteLog("Out of range " + atlasToleranceMin + " <= " + u + ", " + v + " <= " + atlasToleranceMax + " for " + texture + " in " + stat.staticModels[this.quadIndex]); } return false; } u = Math.Max(u, 0); v = Math.Max(v, 0); u = Math.Min(u, 1); v = Math.Min(v, 1); u *= AtlasList.Get(texture).scaleU; v *= AtlasList.Get(texture).scaleV; u += AtlasList.Get(texture).posU; v += AtlasList.Get(texture).posV; UVCoord coords = new UVCoord(u, v); uvcoords2.Add(coords); } data.SetUVCoords(uvcoords2); return true; }
private ShapeDesc TransformShape(QuadDesc quad, StaticDesc stat, NiFile file, NiTriBasedGeom geom, Matrix44 parentTransform, float parentScale) { BBox bbox = new BBox(float.MaxValue, float.MinValue, float.MaxValue, float.MinValue, float.MaxValue, float.MinValue); ShapeDesc shape1 = new ShapeDesc(); NiTriShape shape2; NiTriShapeData data = new NiTriShapeData(); //Console.WriteLine("Reading block #" + geom.GetData()); if (geom.GetClassName() == "NiTriStrips") { shape2 = new NiTriShape(geom); data = new NiTriShapeData((NiTriStripsData)file.GetBlockAtIndex(geom.GetData())); } else if (geom.GetClassName() == "BSLODTriShape") { shape2 = new NiTriShape(geom); data = (NiTriShapeData)file.GetBlockAtIndex(geom.GetData()); } else { shape2 = new NiTriShape(geom); data = (NiTriShapeData)file.GetBlockAtIndex(geom.GetData()); } if (verbose && !data.HasVertexColors() && ((this.GetShaderFlags2(file, shape2) & 32) == 32)) { if (!stat.staticModels[this.quadIndex].Contains("glacierrubbletrim0")) { logFile.WriteLog("Vertex Colors Flag, but no vertex colors in " + stat.staticModels[this.quadIndex]); } } if (((int)data.GetBSNumUVSets() & 1) == 0) return shape1; float _x = stat.x - (float)quad.x * 4096f; float _y = stat.y - (float)quad.y * 4096f; Matrix33 matrix33_1 = new Matrix33(true); Matrix33 matrix33_2 = new Matrix33(true); Matrix33 matrix33_3 = new Matrix33(true); matrix33_1.SetRotationX(Utils.ToRadians(-stat.rotX)); matrix33_2.SetRotationY(Utils.ToRadians(-stat.rotY)); matrix33_3.SetRotationZ(Utils.ToRadians(-stat.rotZ)); Matrix44 matrix44 = new Matrix44(new Matrix33(true) * matrix33_1 * matrix33_2 * matrix33_3, new Vector3(_x, _y, stat.z), 1f); List<Vector3> vertices = new List<Vector3>(data.GetVertices()); List<Vector3> normals = new List<Vector3>(data.GetNormals()); List<Vector3> tangents = new List<Vector3>(data.GetTangents()); List<Vector3> bitangents = new List<Vector3>(data.GetBitangents()); // generate tangents independent of fix tangents setting bool newtangents = false; bool newbitangents = false; if (this.generateTangents && data.HasNormals()) { if (tangents.Count == 0) { newtangents = true; for (int index = 0; index < vertices.Count; ++index) tangents.Add(new Vector3(0.0f, 0.0f, 0.0f)); } if (bitangents.Count == 0) { newbitangents = true; for (int index = 0; index < vertices.Count; ++index) bitangents.Add(new Vector3(0.0f, 0.0f, 0.0f)); } } for (int index = 0; index < vertices.Count; ++index) { vertices[index] *= shape2.GetScale() * parentScale; vertices[index] *= shape2.GetTransform() * parentTransform; vertices[index] *= stat.scale; vertices[index] *= matrix44; if (data.HasNormals()) { normals[index] *= parentTransform.RemoveTranslation() * shape2.GetTransform().RemoveTranslation(); normals[index] *= matrix44.RemoveTranslation(); // adjust tangents as well if (tangents.Count != 0) { tangents[index] *= parentTransform.RemoveTranslation() * shape2.GetTransform().RemoveTranslation(); tangents[index] *= matrix44.RemoveTranslation(); } // adjust bitangents as well if (bitangents.Count != 0) { bitangents[index] *= parentTransform.RemoveTranslation() * shape2.GetTransform().RemoveTranslation(); bitangents[index] *= matrix44.RemoveTranslation(); } // fix tangents when they were newly generated if (newtangents || newbitangents || this.fixTangents) { Vector3 vector3_1 = Vector3.Cross(normals[index], new Vector3(0.0f, 0.0f, 1f)); Vector3 vector3_2 = Vector3.Cross(normals[index], new Vector3(0.0f, 1f, 0.0f)); if (newtangents) { tangents[index] = (double)vector3_1.Length > (double)vector3_2.Length ? vector3_1 : vector3_2; tangents[index].Normalize(); } if (newbitangents) { bitangents[index] = Vector3.Cross(normals[index], tangents[index]); bitangents[index].Normalize(); } } } bbox.GrowByVertex(vertices[index]); vertices[index] /= (float)this.quadLevel; } data.SetVertices(vertices); if (data.HasNormals()) { data.SetNormals(normals); data.SetHasTangents(false); } data.SetCenter(new Vector3((float)(((double)bbox.px1 + (double)bbox.px2) / 2.0), (float)(((double)bbox.py1 + (double)bbox.py2) / 2.0), (float)(((double)bbox.pz1 + (double)bbox.pz2) / 2.0)) / (float)this.quadLevel); data.SetRadius(this.CalcRadius(data)); data.SetConsistencyFlags((ushort)0); data.SetKeepFlags((byte)51); data.SetSkyrimMaterial(0U); shape1.shape = shape2; shape1.data = data; // relative x, y for segment shape1.x = _x; shape1.y = _y; shape1.boundingBox = bbox; //Console.WriteLine(stat.staticName + " 2 " + stat.refID + " " + file + " " + shape2.GetName() + " "); shape1.textures = this.GetMeshTextures(file, shape2); shape1.material = stat.materialName; shape1.isHighDetail = false; if (useHDFlag) { if ((stat.refFlags & 131072) == 131072) { if (HDMeshList.Any(stat.staticModels[this.quadIndex].ToLower().Contains)) { shape1.isHighDetail = true; } else if (notHDMeshList.Any(stat.staticModels[this.quadIndex].ToLower().Contains)) { shape1.isHighDetail = false; } else { shape1.isHighDetail = true; } } } // Shader Flags 2 SLSF2_Double_Sided shape1.isDoubleSided = (this.GetShaderFlags2(file, shape2) & 16) == 16; // clamp mode for atlas shape1.TextureClampMode = this.GetTextureClampMode(file, shape2); /*if ((this.GetShaderFlags1(file, shape2) & 1) == 1) { //logFile.WriteLog("Specular" + stat.staticModels[this.quadIndex]); }*/ if (AtlasList.Contains(shape1.textures[0])) { if (this.UVAtlas(data, shape1.textures[0], stat)) { string[] strArray = new string[2]; strArray[0] = AtlasList.Get(shape1.textures[0]).AtlasTexture; strArray[1] = AtlasList.Get(shape1.textures[0]).AtlasTextureN; shape1.textures = strArray; shape1.TextureClampMode = 0U; shape1.isHighDetail = false; } } else { if (useOptimizer && quadLevel != 4 && shape1.textures[0].ToLower().Contains("mountainslab01")) { string[] strArray = new string[2]; strArray[0] = "textures\\landscape\\mountains\\mountainslab02.dds"; strArray[1] = "textures\\landscape\\mountains\\mountainslab02_n.dds"; shape1.textures = strArray; } if (notHDTextureList.Any(shape1.textures[0].Contains)) { if (this.verbose) { logFile.WriteLog("No atlas for " + shape1.textures[0] + " in " + stat.staticModels[this.quadIndex]); } } else { if (!useHDFlag) { shape1.isHighDetail = true; } } } if (notHDTextureList.Any(shape1.textures[0].Contains)) { shape1.isHighDetail = false; } if (HDTextureList.Any(shape1.textures[0].Contains)) { shape1.isHighDetail = true; } if (shape1.textures[0].Contains("dyndolod\\lod")) { shape1.TextureClampMode = 0U; shape1.isHighDetail = false; } if (!this.generateVertexColors || (this.quadLevel != 4 && !shape1.isHighDetail)) { data.SetHasVertexColors(false); shape1.hasVertexColor = false; } if (this.generateTangents) { //shape1.material.Length != 0 if (!useOptimizer || (useOptimizer && (this.quadLevel == 4 || shape1.isHighDetail))) { data.SetTangents(tangents); data.SetBitangents(bitangents); } } if (this.removeUnseenFaces && quad.hasTerrainVertices) { this.RemoveUnseenFaces(quad, data, shape1); if ((int)data.GetNumTriangles() == 0) return (ShapeDesc)null; } else { quad.outValues.totalTriCount += data.GetNumTriangles(); quad.outValues.reducedTriCount += data.GetNumTriangles(); } this.GenerateSegments(quad, ref shape1); return shape1; }
private List<ShapeDesc> ParseNif(QuadDesc quad, StaticDesc curStat, int level, NiFile file, NiNode rootNode) { NiFile file1 = new NiFile(); file1.Read(this.gameDir, curStat.staticModels[level], this.logFile); return this.IterateNodes(quad, curStat, level, file1, (NiNode)file1.GetBlockAtIndex(0), new Matrix44(true), 1f); }