예제 #1
0
        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);
        }
예제 #2
0
        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);
        }