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); }