/// <summary> /// This function will load all BSAs inside the provided HashSet. Do note that /// this function is required when <see cref="ScriptExecutionSettings.HandleBSAsWithInterface"/> /// is set to <c>false</c> /// </summary> /// <param name="fileList"></param> public static void LoadBSAs(HashSet <string> fileList) { BSAArchive.Load(fileList); }
private static int Main(string[] args) { if (Environment.CommandLine.Contains("\\\"")) { args = CommandLineToArgs(Environment.CommandLine.Replace("\\\"", "\"")); } Dictionary <string, string> cmdArgs = Program.CollectCmdArgs(args); string logFileName = CmdArgs.GetString(cmdArgs, "logfile", Directory.GetCurrentDirectory() + "\\LODGen_log.txt"); LogFile theLog = new LogFile(logFileName); if (Enumerable.Count <string>((IEnumerable <string>)args) < 1) { theLog.WriteLog("Nothing to do"); theLog.Close(); return(-1); } string path = CmdArgs.GetString(cmdArgs, "inputfile", 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); StreamReader streamReader2 = 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(); StringList PassThruMesh = new StringList(); Game.Mode = "tes5"; // 1 = 1 cell seems best Game.sampleSize = 1f; int counter = 0; string worldspaceName = ""; string gameDir = ""; string outputDir = ""; string texturesListFile = ""; string uvfile = ""; string flatfile = ""; string altfile = ""; float southWestX = 0; float southWestY = 0; float atlasTolerance = 0.2f; bool verbose = false; bool generateVertexColors = true; bool dontFixTangents = false; bool dontGenerateTangents = false; bool mergeShapes = true; bool removeUnseenFaces = false; float removeUnseenZShift = 0; bool ignoreWater = false; bool useHDFlag = true; bool useOptimizer = false; bool ignoreMaterial = false; bool alphaDoubleSided = false; bool useAlphaThreshold = false; bool useBacklightPower = false; bool useDecalFlag = false; bool dontGroup = true; bool removeBlocks = false; int flatLODLevelLODFlag = -1; float globalScale = 1f; while (!streamReader.EndOfStream) { string[] strArray2 = streamReader.ReadLine().Split('='); if (strArray2.Length == 2) { ++counter; if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "worldspace") { worldspaceName = strArray2[1]; } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "cellsw") { string[] strArray1 = strArray2[1].Split(' '); southWestX = float.Parse(strArray1[0], CultureInfo.InvariantCulture); southWestY = float.Parse(strArray1[1], CultureInfo.InvariantCulture); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "pathdata") { gameDir = strArray2[1].ToLower(CultureInfo.InvariantCulture); if (!Directory.Exists(gameDir)) { theLog.WriteLog("No Data directory " + gameDir); theLog.Close(); return(-1); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "pathoutput") { outputDir = strArray2[1]; if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "textureslistfile") { texturesListFile = strArray2[1]; } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "textureatlasmap") { uvfile = strArray2[1]; } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "flattextures") { flatfile = strArray2[1]; } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "alttextures") { altfile = strArray2[1]; } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "resource") { if (File.Exists(strArray2[1])) { BSAFiles.Add(strArray2[1].ToLower(CultureInfo.InvariantCulture)); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "ishdmeshmask") { if (strArray2[1] != "") { HDMesh.Add(strArray2[1].ToLower(CultureInfo.InvariantCulture)); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "nothdmeshmask") { if (strArray2[1] != "") { notHDMesh.Add(strArray2[1].ToLower(CultureInfo.InvariantCulture)); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "passthrumeshmask") { if (strArray2[1] != "") { PassThruMesh.Add(strArray2[1].ToLower(CultureInfo.InvariantCulture)); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "ishdtexturemask") { if (strArray2[1] != "") { HDTexture.Add(strArray2[1].ToLower(CultureInfo.InvariantCulture).Replace("data\\", "")); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "texturediffusehd") { if (strArray2[1] != "") { HDTexture.Add(strArray2[1].ToLower(CultureInfo.InvariantCulture).Replace("data\\", "")); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "nothdtexturemask") { if (strArray2[1] != "") { notHDTexture.Add(strArray2[1].ToLower(CultureInfo.InvariantCulture)); } } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "atlastolerance") { atlasTolerance = float.Parse(strArray2[1], CultureInfo.InvariantCulture); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "ignoretranslation") { ignoreList.Add(strArray2[1].ToLower(CultureInfo.InvariantCulture)); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "gamemode") { Game.Mode = ((strArray2[1].ToLower(CultureInfo.InvariantCulture))); if (Game.Mode == "fnv") { Game.Mode = "fo3"; } //generateVertexColors = false; } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "dontgeneratevertexcolors") { generateVertexColors = !Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "dontfixtangents") { dontFixTangents = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "dontgeneratetangents") { dontGenerateTangents = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "dontmergeshapes") { mergeShapes = !Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "removeunseenfaces") { removeUnseenFaces = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "removeunseenzshift") { removeUnseenZShift = float.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "ignorewater") { ignoreWater = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "usehdflag") { useHDFlag = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "useoptimizer") { useOptimizer = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "ignorematerial") { ignoreMaterial = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "alphadoublesided") { alphaDoubleSided = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "usealphathreshold") { useAlphaThreshold = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "usebacklightpower") { useBacklightPower = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "usedecalflag") { useDecalFlag = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "dontgroup") { dontGroup = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "flatlodlevellodflag") { flatLODLevelLODFlag = int.Parse(strArray2[1]); flatLODLevelLODFlag--; } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "globalscale") { globalScale = float.Parse(strArray2[1], CultureInfo.InvariantCulture); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "removeblocks") { removeBlocks = Boolean.Parse(strArray2[1]); } if (strArray2[0].ToLower(CultureInfo.InvariantCulture) == "verbose") { verbose = Boolean.Parse(strArray2[1]); } } else { break; } } if (CmdArgs.GetBool(cmdArgs, "gamemode", false)) { Game.Mode = CmdArgs.GetString(cmdArgs, "gamemode", Game.Mode).ToLower(); } 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); } if (CmdArgs.GetBool(cmdArgs, "verbose", false)) { verbose = true; } int int1 = CmdArgs.GetInt(cmdArgs, "lodLevel", Int32.MinValue); int int2 = CmdArgs.GetInt(cmdArgs, "x", Int32.MinValue); int int3 = CmdArgs.GetInt(cmdArgs, "y", Int32.MinValue); theLog.WriteLog("Game Mode: " + Game.Mode.ToUpper()); if (Game.Mode != "textureslist") { 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("Grouping: " + (dontGroup ? "False" : "True")); theLog.WriteLog("Remove Faces under Terrain: " + (removeUnseenFaces ? "True" : "False")); theLog.WriteLog("Remove Faces under Water: " + (!ignoreWater ? "True" : "False")); if (removeUnseenZShift != 0) { theLog.WriteLog("Remove Faces Z-Shift: " + removeUnseenZShift); } theLog.WriteLog("Use HD Flag: " + (useHDFlag ? "True" : "False")); //theLog.WriteLog("Use Optimizer: " + (useOptimizer ? "True" : "False")); theLog.WriteLog("Ignore Materials: " + (ignoreMaterial ? "True" : "False")); theLog.WriteLog("Alpha DoubleSided: " + (alphaDoubleSided ? "True" : "False")); theLog.WriteLog("Use Alpha Threshold: " + (useAlphaThreshold ? "True" : "False")); theLog.WriteLog("Use Backlight Power: " + (useBacklightPower ? "True" : "False")); theLog.WriteLog("Use Decal Flag: " + (useDecalFlag ? "True" : "False")); theLog.WriteLog("Global scale: " + string.Format("{0:0.00}", globalScale)); theLog.WriteLog("Specific level: " + (int1 != Int32.MinValue ? int1.ToString() : "No")); if (int2 != Int32.MinValue && int3 == Int32.MinValue) { theLog.WriteLog("Specific quad: [" + (object)int2.ToString() + ", X]"); } else if (int2 == Int32.MinValue && int3 != Int32.MinValue) { theLog.WriteLog("Specific quad: [X, " + (object)int3.ToString() + "]"); } else if (int2 != Int32.MinValue && int3 != Int32.MinValue) { theLog.WriteLog("Specific quad: [" + (object)int2.ToString() + ", " + (string)(object)int3.ToString() + "]"); } else { theLog.WriteLog("Specific quad: No"); } theLog.WriteLog("Output: " + outputDir); } streamReader.Close(); if (worldspaceName == "") { theLog.WriteLog("No Worldspace, set Worldspace="); theLog.Close(); return(-1); } if (outputDir == "") { theLog.WriteLog("No PathOutput, set PathOutput="); theLog.Close(); return(-1); } if (Game.Mode == "textureslist" && texturesListFile == "") { theLog.WriteLog("No output file for textures list, set TexturesListFile="); 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(CultureInfo.InvariantCulture).Contains("aaa")) * { * string archiveList1 = ini.IniReadValue("Archive", "sResourceArchiveList").ToLower(CultureInfo.InvariantCulture); * string archiveList2 = ini.IniReadValue("Archive", "sResourceArchiveList2").ToLower(CultureInfo.InvariantCulture); * 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, verbose); streamReader = new StreamReader(path); for (int index = 0; index < counter; ++index) { streamReader.ReadLine(); } while (!streamReader.EndOfStream) { StaticDesc staticDesc = new StaticDesc(); staticDesc.staticModels = new string[4]; staticDesc.staticFlags = 0; staticDesc.materialName = ""; staticDesc.staticModels[0] = ""; staticDesc.staticModels[1] = ""; staticDesc.staticModels[2] = ""; staticDesc.staticModels[3] = ""; staticDesc.enableParent = 0; staticDesc.materialSwap = new Dictionary <string, string>(); staticDesc.transrot = new Matrix44(new Matrix33(true), new Vector3(0f, 0f, 0f), 1f); staticDesc.transscale = 1f; string line = streamReader.ReadLine(); if (line.Contains('\t')) { string[] strArray2 = line.Split('\t'); counter++; if (strArray2.Count() >= 10) { staticDesc.refID = strArray2[0]; staticDesc.refFlags = int.Parse(strArray2[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture); staticDesc.x = float.Parse(strArray2[2], CultureInfo.InvariantCulture); staticDesc.y = float.Parse(strArray2[3], CultureInfo.InvariantCulture); staticDesc.z = float.Parse(strArray2[4], CultureInfo.InvariantCulture); staticDesc.rotX = float.Parse(strArray2[5], CultureInfo.InvariantCulture); staticDesc.rotY = float.Parse(strArray2[6], CultureInfo.InvariantCulture); staticDesc.rotZ = float.Parse(strArray2[7], CultureInfo.InvariantCulture); staticDesc.scale = float.Parse(strArray2[8], CultureInfo.InvariantCulture); staticDesc.staticName = strArray2[9]; staticDesc.staticModels[0] = staticDesc.staticName; } if (strArray2.Count() >= 13) { staticDesc.staticName = strArray2[9]; staticDesc.staticFlags = int.Parse(strArray2[10], NumberStyles.HexNumber, CultureInfo.InvariantCulture); staticDesc.materialName = strArray2[11]; staticDesc.staticFullModel = strArray2[12]; if (strArray2.Count() >= 16) { int noStatics = 3; staticDesc.staticModels[3] = ""; if (strArray2.Count() >= 17) { noStatics = 4; } for (int index = 0; index < noStatics; ++index) { string str = strArray2[13 + index]; staticDesc.staticModels[index] = str.ToLower(CultureInfo.InvariantCulture); 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); } } } if (strArray2.Count() >= 20) { if (strArray2[17] != "") { staticDesc.enableParent = uint.Parse(strArray2[17], NumberStyles.HexNumber, CultureInfo.InvariantCulture); } //staticDesc.enableParent = uint.Parse(strArray2[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture); string[] baseMat = strArray2[18].Split(','); string[] swapMat = strArray2[19].Split(','); if (baseMat.Count() == swapMat.Count()) { for (int index = 0; index < baseMat.Count(); index++) { if (baseMat[index] != "" && swapMat[index] != "") { staticDesc.materialSwap.Add("materials\\" + baseMat[index], "materials\\" + swapMat[index]); } } } else { theLog.WriteLog(staticDesc.refID + " ignoring material swap data because item count is not equal"); } if (strArray2.Count() == 27 && strArray2[20] != "" && strArray2[21] != "" && strArray2[22] != "" && strArray2[23] != "" && strArray2[24] != "" && strArray2[25] != "" && strArray2[26] != "") { Matrix33 matrix33_1 = new Matrix33(true); Matrix33 matrix33_2 = new Matrix33(true); Matrix33 matrix33_3 = new Matrix33(true); matrix33_1.SetRotationX(Utils.ToRadians(-float.Parse(strArray2[23], CultureInfo.InvariantCulture))); matrix33_2.SetRotationY(Utils.ToRadians(-float.Parse(strArray2[24], CultureInfo.InvariantCulture))); matrix33_3.SetRotationZ(Utils.ToRadians(-float.Parse(strArray2[25], CultureInfo.InvariantCulture))); staticDesc.transrot = new Matrix44(new Matrix33(true) * matrix33_1 * matrix33_2 * matrix33_3, new Vector3(float.Parse(strArray2[20], CultureInfo.InvariantCulture), float.Parse(strArray2[21], CultureInfo.InvariantCulture), float.Parse(strArray2[22], CultureInfo.InvariantCulture)), 1f); staticDesc.transscale = float.Parse(strArray2[26], CultureInfo.InvariantCulture); } } } } statics.Add(staticDesc); } } statics.Reverse(); streamReader.Close(); if (!File.Exists(uvfile)) { uvfile = System.AppDomain.CurrentDomain.BaseDirectory + uvfile; } if (File.Exists(uvfile) && Game.Mode != "textureslist") { theLog.WriteLog("Using UV Atlas: " + uvfile); streamReader = new StreamReader(uvfile); int lineCount = 0; while (!streamReader.EndOfStream) { lineCount++; string[] strArray2 = streamReader.ReadLine().Split('\t'); AtlasDesc atlasDesc = new AtlasDesc(); if (strArray2.Length >= 8) { try { atlasDesc.SourceTexture = strArray2[0].ToLower(CultureInfo.InvariantCulture); int textureWidth = int.Parse(strArray2[1], CultureInfo.InvariantCulture); int textureHeight = int.Parse(strArray2[2], CultureInfo.InvariantCulture); int textureX = int.Parse(strArray2[3], CultureInfo.InvariantCulture); int textureY = int.Parse(strArray2[4], CultureInfo.InvariantCulture); int atlasWidth = int.Parse(strArray2[6], CultureInfo.InvariantCulture); int atlasHeight = int.Parse(strArray2[7], CultureInfo.InvariantCulture); float scaleU = 1f; float scaleV = 1f; if (strArray2.Length >= 10) { atlasDesc.miniatlas = true; scaleU = float.Parse(strArray2[8], CultureInfo.InvariantCulture); scaleV = float.Parse(strArray2[9], CultureInfo.InvariantCulture); } else { atlasDesc.miniatlas = false; } atlasDesc.scaleU = (float)textureWidth / atlasWidth * scaleU; atlasDesc.scaleV = (float)textureHeight / atlasHeight * scaleV; atlasDesc.posU = (float)textureX / atlasWidth; atlasDesc.posV = (float)textureY / atlasHeight; atlasDesc.minU = (float)0.5 / textureWidth; atlasDesc.maxU = (float)(textureWidth - 0.5) / textureWidth; atlasDesc.minV = (float)0.5 / textureHeight; atlasDesc.maxV = (float)(textureHeight - 0.5) / textureHeight; atlasDesc.before = 0; atlasDesc.after = 0; atlasDesc.averageU = 0; atlasDesc.averageV = 0; atlasDesc.AtlasTexture = strArray2[5].ToLower(CultureInfo.InvariantCulture); atlasDesc.AtlasTextureN = Utils.GetNormalTextureName(strArray2[5].ToLower(CultureInfo.InvariantCulture)); if (Game.Mode == "fo4") { atlasDesc.AtlasTextureS = Utils.GetSpecularTextureName(strArray2[5].ToLower(CultureInfo.InvariantCulture)); } else { atlasDesc.AtlasTextureS = ""; } } catch { theLog.WriteLog("Error reading line " + lineCount + " from " + uvfile); theLog.Close(); System.Environment.Exit(1062); } //if (AtlasList.Contains(atlasDesc.SourceTexture) && AtlasList.Get(atlasDesc.SourceTexture).miniatlas) //{ // atlasDesc.SourceTexture = AtlasList.Get(atlasDesc.SourceTexture).AtlasTexture; //} if (AtlasList.Contains(atlasDesc.SourceTexture)) { theLog.WriteLog("Texture name already defined in atlas file " + atlasDesc.SourceTexture); theLog.Close(); System.Environment.Exit(1062); } AtlasList.Set(atlasDesc.SourceTexture, atlasDesc); } else { theLog.WriteLog("Line " + lineCount + " not enough data in " + uvfile); } } streamReader.Close(); } if (!File.Exists(flatfile)) { flatfile = System.AppDomain.CurrentDomain.BaseDirectory + flatfile; } if (File.Exists(flatfile)) { theLog.WriteLog("Using Flat Textures: " + flatfile); streamReader = new StreamReader(flatfile); while (!streamReader.EndOfStream) { string[] strArray2 = streamReader.ReadLine().Split('\t'); FlatDesc flatDesc = new FlatDesc(); if (strArray2.Length >= 6) { flatDesc.SourceTexture = strArray2[0].ToLower(CultureInfo.InvariantCulture); flatDesc.width = float.Parse(strArray2[1], CultureInfo.InvariantCulture); flatDesc.height = float.Parse(strArray2[2], CultureInfo.InvariantCulture); flatDesc.shiftZ = float.Parse(strArray2[3], CultureInfo.InvariantCulture); flatDesc.scale = float.Parse(strArray2[4], CultureInfo.InvariantCulture); flatDesc.effect1 = float.Parse(strArray2[5], CultureInfo.InvariantCulture); if (strArray2.Length >= 8) { flatDesc.GlowTexture = strArray2[7].ToLower(CultureInfo.InvariantCulture); } else { flatDesc.GlowTexture = "textures\\white.dds"; } flatDesc.normals = new List <Vector3>(); flatDesc.tangents = new List <Vector3>(); flatDesc.bitangents = new List <Vector3>(); if ((strArray2.Length >= 7) && (File.Exists(strArray2[6]))) { streamReader2 = new StreamReader(strArray2[6]); int index = 0; while (!streamReader2.EndOfStream) { string[] strArray3 = streamReader2.ReadLine().Split(','); if (strArray3.Length == 3) { if (index < 8) { flatDesc.normals.Add(new Vector3(float.Parse(strArray3[0], CultureInfo.InvariantCulture), float.Parse(strArray3[1], CultureInfo.InvariantCulture), float.Parse(strArray3[2], CultureInfo.InvariantCulture))); } else if (index < 16) { flatDesc.tangents.Add(new Vector3(float.Parse(strArray3[0], CultureInfo.InvariantCulture), float.Parse(strArray3[1], CultureInfo.InvariantCulture), float.Parse(strArray3[2], CultureInfo.InvariantCulture))); } else if (index < 24) { flatDesc.bitangents.Add(new Vector3(float.Parse(strArray3[0], CultureInfo.InvariantCulture), float.Parse(strArray3[1], CultureInfo.InvariantCulture), float.Parse(strArray3[2], CultureInfo.InvariantCulture))); } index++; } } } if (flatDesc.normals.Count() < 8 || flatDesc.tangents.Count() < 8 || flatDesc.bitangents.Count() < 8) { for (int index = 0; index < 8; index++) { if (flatDesc.normals.Count() < 8) { flatDesc.normals.Add(new Vector3(0.0f, 0.0f, 0.0f)); } if (flatDesc.tangents.Count() < 8) { flatDesc.tangents.Add(new Vector3(0.0f, 0.0f, 0.0f)); } if (flatDesc.bitangents.Count() < 8) { flatDesc.bitangents.Add(new Vector3(0.0f, 0.0f, 0.0f)); } } } //theLog.WriteLog(flatDesc.SourceTexture + "\t" + flatDesc.width + "\t" + flatDesc.height + "\t" + flatDesc.shiftZ + "\t" + flatDesc.scale); FlatList.Set(flatDesc.SourceTexture, flatDesc); } } streamReader.Close(); } if (!File.Exists(altfile)) { altfile = System.AppDomain.CurrentDomain.BaseDirectory + altfile; } if (File.Exists(altfile)) { theLog.WriteLog("Using Alt Textures: " + altfile); streamReader = new StreamReader(altfile); while (!streamReader.EndOfStream) { string[] strArray2 = streamReader.ReadLine().ToLower(CultureInfo.InvariantCulture).Split('\t'); if (strArray2.Length > 0) { for (int index = 1; index < strArray2.Length; index++) { string[] strArray3 = strArray2[index].Split('='); string key = strArray2[0] + "_" + strArray3[0] + "_" + strArray3[1]; AltTextureDesc altTexDesc = new AltTextureDesc(); altTexDesc.textures = strArray3[2].Split(','); if (!AltTextureList.Contains(key)) { //theLog.WriteLog(key + " = " + altTexDesc.textures[0] + ", " + altTexDesc.textures[1]); AltTextureList.Set(key, altTexDesc); } } } } streamReader.Close(); } Game.atlasToleranceMin = atlasTolerance * -1f; Game.atlasToleranceMax = atlasTolerance + 1f; if (Game.Mode == "tes5" || Game.Mode == "sse" || Game.Mode == "fo3" || Game.Mode == "fo4") { theLog.WriteLog("Generating LOD for worldspace " + worldspaceName); } else if (Game.Mode.Contains("merge")) { theLog.WriteLog("Merging meshes"); } else if (Game.Mode.Contains("convert")) { theLog.WriteLog("Converting meshes"); } else if (Game.Mode.Contains("textures")) { theLog.WriteLog("Creating textures list"); } theLog.WriteLog(""); List <Thread> list1 = new List <Thread>(); int num = 1; int index1 = 0; while (num <= 8) { list1.Add(new Thread((ParameterizedThreadStart)(state => { List <int> list2 = (List <int>)state; new LODApp(worldspaceName, outputDir, gameDir, theLog) { verbose = verbose, texturesListFile = texturesListFile, 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", Int32.MinValue), lodX = CmdArgs.GetInt(cmdArgs, "x", Int32.MinValue), lodY = CmdArgs.GetInt(cmdArgs, "y", Int32.MinValue), southWestX = (int)southWestX, southWestY = (int)southWestY, atlasToleranceMin = Game.atlasToleranceMin, atlasToleranceMax = Game.atlasToleranceMax, removeUnderwaterFaces = !ignoreWater, removeUnseenZShift = removeUnseenZShift, ignoreMaterial = ignoreMaterial, alphaDoublesided = alphaDoubleSided, useAlphaThreshold = useAlphaThreshold, useBacklightPower = useBacklightPower, useDecalFlag = useDecalFlag, dontGroup = dontGroup, skyblivionTexPath = CmdArgs.GetBool(cmdArgs, "skyblivionTexPath", false), removeBlocks = removeBlocks, flatLODLevelLODFlag = flatLODLevelLODFlag, ignoreTransRot = ignoreList, HDTextureList = HDTexture, notHDTextureList = notHDTexture, HDMeshList = HDMesh, notHDMeshList = notHDMesh, PassThruMeshList = PassThruMesh }.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(50); } //if (Game.Mode == "convert4" || Game.Mode == "convert5") { AtlasList.WriteStats(theLog); } theLog.Close(); return(0); }
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(); Game.Mode = "tes5"; Game.Testing = false; 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 ignoreMaterial = false; float globalScale = 1f; if (path.ToLower().Contains("dyndolod")) { useHDFlag = false; notHDTexture.Add("lod"); notHDTexture.Add("lowres"); } 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() == "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())); //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() == "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("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, 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 }.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); }