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;
        }
示例#2
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);
 }