internal static PartitionAABB[] RunForAABB(HashSet <Vertex> solidVerts, HashSet <PolygonalFace> solidFaces, Vertex[] corverVts)
        {
            // the corner vertices are all clock wise now.
            var partitions = new List <PartitionAABB>();

            //var ddds = solid.Vertices.Max(v => v.Position[1]);
            for (var k = 0; k < corverVts.Length; k++)           //obb.CornerVertices)
            {
                var    verK = new Vertex(corverVts[k].Position); //cVer;
                var    prtn = new PartitionAABB();
                var    cornerVer = new List <Vertex>();
                double Xmin = double.PositiveInfinity, Ymin = double.PositiveInfinity, Zmin = double.PositiveInfinity;
                double Xmax = double.NegativeInfinity, Ymax = double.NegativeInfinity, Zmax = double.NegativeInfinity;
                for (var j = 0; j < corverVts.Length; j++)
                {
                    var verJ   = new Vertex(corverVts[j].Position); //cVer;
                    var midVer = new Vertex((verJ.Position.add(verK.Position)).divide(2.0));
                    cornerVer.Add(midVer);
                    if (midVer.Position[0] > Xmax)
                    {
                        Xmax = midVer.Position[0];
                    }
                    if (midVer.Position[0] < Xmin)
                    {
                        Xmin = midVer.Position[0];
                    }
                    if (midVer.Position[1] > Ymax)
                    {
                        Ymax = midVer.Position[1];
                    }
                    if (midVer.Position[1] < Ymin)
                    {
                        Ymin = midVer.Position[1];
                    }
                    if (midVer.Position[2] > Zmax)
                    {
                        Zmax = midVer.Position[2];
                    }
                    if (midVer.Position[2] < Zmin)
                    {
                        Zmin = midVer.Position[2];
                    }
                }
                prtn.X = new[] { Xmin, Xmax };
                prtn.Y = new[] { Ymin, Ymax };
                prtn.Z = new[] { Zmin, Zmax };
                prtn.CornerVertices = cornerVer.ToArray();
                prtn.SolidVertices  = new HashSet <Vertex>(solidVerts.Where(vertex => IsVertexInsidePartition(prtn, vertex)));
                prtn.SolidTriangles = PartitionTrianglesPro(prtn, solidFaces);
                // continue the octree or not?
                if (prtn.SolidTriangles.Count > 200)
                {
                    prtn.InnerPartition = RunForAABB(prtn.SolidVertices, prtn.SolidTriangles, prtn.CornerVertices);
                }
                partitions.Add(prtn);
            }
            return(partitions.ToArray());
        }
        private static bool IsVertexInsidePartition(PartitionAABB prtn, Vertex vertex)
        {
            var verPos = vertex.Position;

            if (verPos[0] > prtn.X[1] || verPos[0] < prtn.X[0] ||
                verPos[1] > prtn.Y[1] || verPos[1] < prtn.Y[0] ||
                verPos[2] > prtn.Z[1] || verPos[2] < prtn.Z[0])
            {
                return(false);
            }
            return(true);
        }
        private static HashSet <PolygonalFace> PartitionTrianglesPro(PartitionAABB partition, HashSet <PolygonalFace> solidTrgs)
        {
            var trigs = new HashSet <PolygonalFace>();

            foreach (var ver in partition.SolidVertices)
            {
                trigs.UnionWith(ver.Faces.Where(f => !trigs.Contains(f)));
            }
            // using seperating axis theorem (SAT). Among 6 faces of the box and the triangle candidate from the solid
            //    if any of them can seperate the

            // normal of the partition planes and and a vertex on the plane
            var normalsAndVertex = new Dictionary <double[], double[]>
            {
                { new[] { 1.0, 0, 0 }, new[] { partition.X[1], partition.Y[1], partition.Z[1] } },
                { new[] { -1.0, 0, 0 }, new[] { partition.X[0], partition.Y[1], partition.Z[1] } },
                { new[] { 0, 1.0, 0 }, new[] { partition.X[1], partition.Y[1], partition.Z[1] } },
                { new[] { 0, -1.0, 0 }, new[] { partition.X[1], partition.Y[0], partition.Z[1] } },
                { new[] { 0, 0, 1.0 }, new[] { partition.X[1], partition.Y[1], partition.Z[1] } },
                { new[] { 0, 0, -1.0 }, new[] { partition.X[1], partition.Y[1], partition.Z[0] } }
            };

            foreach (var pF in solidTrgs.Where(t => !trigs.Contains(t)))
            {
                var dots =
                    partition.CornerVertices.Select(
                        corVer => (corVer.Position.subtract(pF.Vertices[0].Position)).dotProduct(pF.Normal)).ToList();
                if (dots.All(d => d >= 0) || dots.All(d => d <= 0))
                {
                    continue;
                }
                var overlap = normalsAndVertex.All(dic => !pF.Vertices.All(v => dic.Key.dotProduct(v.Position.subtract(dic.Value)) >= 0));
                if (overlap)
                {
                    trigs.Add(pF);
                }
            }
            return(trigs);
        }