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 RemoveUnseenFaces(QuadDesc quad, NiTriShapeData data, ShapeDesc shape)
        {
            List<Triangle> triangles = data.GetTriangles();
            List<Vector3> vertices = data.GetVertices();
            int count = triangles.Count;
            quad.outValues.totalTriCount += count;
            int loops = 0;
            if (this.removeUnderwaterFaces)
            {
                loops = 1;
            }
            for (int loop = 0; loop <= loops; loop++)
            {
                for (int index = 0; index < triangles.Count; ++index)
                {
                    QuadDesc quadCurrent = new QuadDesc();
                    List<Triangle> trianglesCompare = new List<Triangle>();
                    List<Vector3> verticesCompare = new List<Vector3>();
                    bool[] vertexBelow = new bool[3];
                    for (int index1 = 0; index1 < 3; index1++)
                    {
                        Vector3 vertex = vertices[triangles[index][index1]];
                        float x = vertex[0];
                        float y = vertex[1];
                        int vertexQuadx = quad.x + cellquad(x * quadLevel, southWestX);
                        int vertexQuady = quad.y + cellquad(y * quadLevel, southWestY);
                        if (quad.x != vertexQuadx || quad.y != vertexQuady)
                        {
                            for (int index3 = 0; index3 < this.quadList.Count; ++index3)
                            {
                                if (vertexQuadx == this.quadList[index3].x && vertexQuady == this.quadList[index3].y)
                                {
                                    quadCurrent = this.quadList[index3];
                                    x -= (vertexQuadx - quad.x) / quadLevel * 4096;
                                    y -= (vertexQuady - quad.y) / quadLevel * 4096;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            quadCurrent = quad;
                        }
                        if (!quadCurrent.hasTerrainVertices)
                        {
                            continue;
                        }
                        Vector3 vertex1 = new Vector3(x, y, vertex[2]);
                        List<Triangle> trianglesTerrain = new List<Triangle>();
                        List<Vector3> verticesTerrain = new List<Vector3>();
                        if (this.removeUnderwaterFaces && loop == 0)
                        {
                            if (quadCurrent.waterQuadTree != null)
                            {
                                trianglesTerrain = quadCurrent.waterQuadTree.entirequad.triangles;
                                verticesTerrain = quadCurrent.waterQuadTree.vertices;
                            }
                        }
                        else
                        {
                            trianglesTerrain = quadCurrent.terrainQuadTree.GetSegment(vertex1, quadLevel);
                            verticesTerrain = quadCurrent.terrainQuadTree.vertices;
                        }
                        if (trianglesTerrain == null)
                        {
                            vertexBelow[index1] = true;
                        }
                        else
                        {
                            if (trianglesTerrain.Count != 0)
                            {
                                float num1 = float.MaxValue;
                                num1 = GetTriangleHeight(verticesTerrain, trianglesTerrain, vertex1);
                                if (vertex1[2] < num1)
                                {
                                    vertexBelow[index1] = true;
                                }
                            }
                        }
                    }
                    if (vertexBelow[0] && vertexBelow[1] && vertexBelow[2])
                    {
                        triangles.RemoveAt(index);
                        --index;
                    }
                }
            }

            // remove elements from other lists too
            if (triangles.Count != 0 && triangles.Count != count)
            {
                Dictionary<ushort, ushort> dictionary = new Dictionary<ushort, ushort>();
                List<Vector3> vertices2 = new List<Vector3>();
                List<UVCoord> uvcoords = data.GetUVCoords();
                List<UVCoord> uvcoords2 = new List<UVCoord>();
                List<Color4> vertexcolors = data.GetVertexColors();
                List<Color4> vertexcolors2 = new List<Color4>();
                List<Vector3> normals = data.GetNormals();
                List<Vector3> normals2 = new List<Vector3>();
                List<Vector3> tangents = data.GetTangents();
                List<Vector3> tangents2 = new List<Vector3>();
                List<Vector3> bitangents = data.GetBitangents();
                List<Vector3> bitangents2 = new List<Vector3>();
                ushort index2 = 0;
                bool vertexcolors_allwhite = true;
                for (int index = 0; index < triangles.Count; ++index)
                {
                    for (int index3 = 0; index3 < 3; ++index3)
                    {
                        ushort v1 = triangles[index][index3];
                        if (!dictionary.ContainsKey(v1))
                        {
                            dictionary.Add(v1, index2);
                            ++index2;
                            if (vertices.Count != 0)
                            {
                                vertices2.Add(vertices[v1]);
                            }
                            if (uvcoords.Count != 0)
                            {
                                uvcoords2.Add(uvcoords[v1]);
                            }
                            if (vertexcolors.Count != 0)
                            {
                                float r = vertexcolors[v1][0];
                                float g = vertexcolors[v1][1];
                                float b = vertexcolors[v1][2];
                                if (r != 1f || b != 1f || g != 1f)
                                {
                                    vertexcolors_allwhite = false;
                                }
                                vertexcolors2.Add(vertexcolors[v1]);
                            }
                            if (normals.Count != 0)
                            {
                                normals2.Add(normals[v1]);
                            }
                            if (tangents.Count != 0)
                            {
                                tangents2.Add(tangents[v1]);
                            }
                            if (bitangents.Count != 0)
                            {
                                bitangents2.Add(bitangents[v1]);
                            }
                        }
                    }
                }
                // update indexes of triangles
                for (int index = 0; index < triangles.Count; ++index)
                {
                    for (int index3 = 0; index3 < 3; ++index3)
                    {
                        ushort key = triangles[index][index3];
                        if (!dictionary.ContainsKey(key))
                        {
                            this.logFile.WriteLog("no index for " + key);
                        }
                        ushort v1 = dictionary[key];
                        Triangle triangle;
                        (triangle = triangles[index])[index3] = (v1);
                    }
                }
                if (vertices2.Count != 0)
                {
                    data.SetVertices(vertices2);
                }
                if (uvcoords2.Count != 0)
                {
                    data.SetUVCoords(uvcoords2);
                }
                if (vertexcolors2.Count != 0)
                {
                    if (vertexcolors_allwhite)
                    {
                        data.SetHasVertexColors(false);
                        shape.hasVertexColor = false;
                    }
                    else
                    {
                        data.SetHasVertexColors(true);
                        shape.hasVertexColor = true;
                        data.SetVertexColors(vertexcolors2);
                    }
                }
                if (normals2.Count != 0)
                {
                    data.SetNormals(normals2);
                }
                if (tangents2.Count != 0)
                {
                    data.SetTangents(tangents2);
                }
                if (bitangents2.Count != 0)
                {
                    data.SetBitangents(bitangents2);
                }
            }
            quad.outValues.reducedTriCount += triangles.Count;
            data.SetTriangles(triangles);
        }