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;
        }
 private void MergeNodes(List<ShapeDesc> shapes)
 {
     int count = shapes.Count;
     Dictionary<string, List<ShapeDesc>> dictionary = new Dictionary<string, List<ShapeDesc>>();
     for (int index = 0; index < shapes.Count; ++index)
     {
         ShapeDesc shape = new ShapeDesc();
         shape = shapes[index];
         string key = shape.textures[0].ToLower();
         // use vertex color flag to seperate?
         // less draw calls more important than reducing a few bytes?
         // overall it is not even reducing bytes... so no
         /*if (useOptimizer && shape.data.HasVertexColors())
         {
             key = key + "_VC";
         }*/
         // use material name from list file, Snow/Ash
         if (!this.ignoreMaterial && shape.material != "")
         {
             key = key + "_" + shape.material;
         }
         // only level 4 should have HD
         if (shape.isHighDetail && (this.quadLevel == 4 || useHDFlag))
         {
             key = key + "_HD";
         }
         // double-sided
         if (shape.isDoubleSided)
         {
             key = key + "_DS";
         }
         // clamp mode
         key = key + "_" + shape.TextureClampMode;
         if (dictionary.ContainsKey(key))
         {
             dictionary[key].Add(shape);
         }
         else
         {
             dictionary.Add(key, new List<ShapeDesc>());
             dictionary[key].Add(shape);
         }
     }
     shapes.Clear();
     foreach (KeyValuePair<string, List<ShapeDesc>> keyValuePair in dictionary)
     {
         if (keyValuePair.Value.Count == 1)
         {
             shapes.Add(keyValuePair.Value[0]);
         }
         else
         {
             SegmentDesc segmentDesc = (SegmentDesc)null;
             uint num1 = 0U;
             uint num2 = 0U;
             int num3 = -1;
             NiTriShape niTriShape = new NiTriShape();
             NiTriShapeData data = new NiTriShapeData();
             List<ShapeDesc> list = keyValuePair.Value;
             string str1 = list[0].textures[0];
             string str2 = list[0].textures[1];
             string str3 = list[0].material;
             //bool isVC = list[0].hasVertexColor;
             bool isHD = list[0].isHighDetail;
             // double-sided
             bool isDS = list[0].isDoubleSided;
             // clamp mode
             uint clampmode = list[0].TextureClampMode;
             bool allwhite = true;
             list.Sort((Comparison<ShapeDesc>)((a, b) =>
             {
                 if (a.segments[0].id > b.segments[0].id)
                     return 1;
                 return a.segments[0].id < b.segments[0].id ? -1 : 0;
             }));
             ShapeDesc shapeDesc = new ShapeDesc();
             shapeDesc.boundingBox.Set(float.MaxValue, float.MinValue, float.MaxValue, float.MinValue, float.MaxValue, float.MinValue);
             for (int index1 = 0; index1 < list.Count; ++index1)
             {
                 NiTriShapeData niTriShapeData = list[index1].data;
                 List<Vector3> vertices = niTriShapeData.GetVertices();
                 List<Triangle> triangles = new List<Triangle>(niTriShapeData.GetTriangles());
                 if ((uint)data.GetNumVertices() + (uint)vertices.Count > (uint)ushort.MaxValue || (uint)data.GetNumTriangles() + (uint)triangles.Count > (uint)ushort.MaxValue)
                 {
                     data.SetCenter(shapeDesc.boundingBox.GetCenter() / (float)this.quadLevel);
                     data.SetRadius(this.CalcRadius(data));
                     shapeDesc.segments.Add(segmentDesc);
                     shapeDesc.shape = niTriShape;
                     shapeDesc.data = data;
                     shapeDesc.textures = new string[2];
                     shapeDesc.textures[0] = str1;
                     shapeDesc.textures[1] = str2;
                     shapeDesc.material = str3;
                     shapeDesc.isHighDetail = isHD;
                     //shapeDesc.hasVertexColor = isVC;
                     // double-sided
                     shapeDesc.isDoubleSided = isDS;
                     //clamp mode
                     shapeDesc.TextureClampMode = clampmode;
                     shapes.Add(shapeDesc);
                     shapeDesc = new ShapeDesc();
                     shapeDesc.boundingBox.Set(float.MaxValue, float.MinValue, float.MaxValue, float.MinValue, float.MaxValue, float.MinValue);
                     niTriShape = new NiTriShape();
                     data = new NiTriShapeData();
                     num1 = 0U;
                     num2 = 0U;
                     num3 = -1;
                 }
                 for (int index2 = 0; index2 < (int)niTriShapeData.GetNumVertices(); ++index2)
                 {
                     Vector3 vector3 = vertices[index2] * (float)this.quadLevel;
                     shapeDesc.boundingBox.GrowByVertex(vector3);
                 }
                 data.AppendVertices(niTriShapeData.GetVertices());
                 data.AppendNormals(niTriShapeData.GetNormals());
                 data.AppendUVCoords(niTriShapeData.GetUVCoords());
                 if (this.generateTangents)
                 {
                     //str3.Length != 0
                     if (!useOptimizer || (useOptimizer && (this.quadLevel == 4 || isHD)))
                     {
                         data.AppendTangents(niTriShapeData.GetTangents());
                         data.AppendBitangents(niTriShapeData.GetBitangents());
                     }
                 }
                 // only level 4 should have vertex colors
                 if (this.generateVertexColors && (this.quadLevel == 4 || isHD))
                 {
                     List<Color4> colors = new List<Color4>();
                     if (niTriShapeData.HasVertexColors())
                     {
                         colors = niTriShapeData.GetVertexColors();
                         data.AppendVertexColors(colors);
                         for (int index2 = 0; index2 < colors.Count; index2++)
                         {
                             if (colors[index2][0] != 1f || colors[index2][2] != 1f || colors[index2][2] != 1f)
                             {
                                 allwhite = false;
                                 break;
                             }
                         }
                     }
                     else
                     {
                         for (int index2 = 0; index2 < vertices.Count; ++index2)
                         {
                             colors.Add(new Color4(1f, 1f, 1f, 1f));
                         }
                         data.AppendVertexColors(colors);
                     }
                 }
                 List<Triangle> trianglesNew = new List<Triangle>();
                 for (int index2 = 0; index2 < (int)niTriShapeData.GetNumTriangles(); ++index2)
                 {
                     trianglesNew.Add(new Triangle((ushort)(triangles[index2][0] + num1), (ushort)(triangles[index2][1] + num1), (ushort)(triangles[index2][2] + num1)));
                 }
                 data.AppendTriangles(trianglesNew);
                 num1 += (uint)niTriShapeData.GetNumVertices();
                 if (list[index1].segments[0].id != num3)
                 {
                     if (num3 != -1)
                     {
                         num2 += (uint)segmentDesc.numTriangles * 3U;
                         shapeDesc.segments.Add(segmentDesc);
                     }
                     segmentDesc = new SegmentDesc();
                     segmentDesc.id = list[index1].segments[0].id;
                     segmentDesc.startTriangle = num2;
                     segmentDesc.numTriangles = list[index1].segments[0].numTriangles;
                     num3 = list[index1].segments[0].id;
                 }
                 else
                     segmentDesc.numTriangles += list[index1].data.GetNumTriangles();
             }
             data.SetCenter(shapeDesc.boundingBox.GetCenter() / (float)this.quadLevel);
             data.SetRadius(this.CalcRadius(data));
             shapeDesc.segments.Add(segmentDesc);
             shapeDesc.shape = niTriShape;
             shapeDesc.data = data;
             shapeDesc.textures = new string[2];
             shapeDesc.textures[0] = str1;
             shapeDesc.textures[1] = str2;
             shapeDesc.material = str3;
             //shapeDesc.hasVertexColor = isVC;
             shapeDesc.isHighDetail = isHD;
             // double-sided
             shapeDesc.isDoubleSided = isDS;
             // clamp mode
             shapeDesc.TextureClampMode = clampmode;
             if (allwhite)
             {
                 shapeDesc.data.SetHasVertexColors(false);
                 shapeDesc.hasVertexColor = false;
             }
             else
             {
                 shapeDesc.data.SetHasVertexColors(true);
                 shapeDesc.hasVertexColor = true;
             }
             shapes.Add(shapeDesc);
         }
     }
 }