public BVHNode Construct(BVHNode leaf) { if (leaf.Boundables.Count == 0) { return(leaf); } var bb = BoundingBox.FromBoundables(leaf.Boundables); var xLen = bb.Max.X - bb.Min.X; var yLen = bb.Max.Y - bb.Min.Y; var zLen = bb.Max.Z - bb.Min.Z; List <Boundable> sorted; if (xLen > yLen && xLen > zLen) { sorted = leaf.Boundables.OrderBy(x => x.BoundingBox.Centroid.X).ToList(); } else if (yLen > xLen && yLen > zLen) { sorted = leaf.Boundables.OrderBy(x => x.BoundingBox.Centroid.Y).ToList(); } else { sorted = leaf.Boundables.OrderBy(x => x.BoundingBox.Centroid.Z).ToList(); } var bestPlane = CalculateBestSplitPlane(sorted); //don't split further if (bestPlane.Cost > leaf.BoundingBox.Area * leaf.Boundables.Count) { return(leaf); } var left = new BVHNode(bestPlane.Left); var right = new BVHNode(bestPlane.Right); var parent = new BVHNode(Construct(left), Construct(right)); return(parent); }
private SplitPlane CalculateBestSplitPlane(List <Boundable> boundables) { var bestSplitPlane = new SplitPlane(float.MaxValue, null, null); for (int i = 1; i < boundables.Count; i++) { var left = boundables.Take(i).ToList(); var leftB = BoundingBox.FromBoundables(left); var right = boundables.Skip(i).ToList(); var rightB = BoundingBox.FromBoundables(right); var cost = leftB.Area * left.Count + rightB.Area * right.Count; if (cost < bestSplitPlane.Cost) { bestSplitPlane = new SplitPlane(cost, left, right); } } return(bestSplitPlane); }