Example #1
0
        private double SAofList(SSBVHNodeAdaptor <GO> nAda, List <GO> list)
        {
            Bounds_d box = nAda.GetObjectBounds(list[0]);

            for (int i = 1; i < list.Count - 1; i++)
            {
                box.ExpandToFit(nAda.GetObjectBounds(list[i]));
            }

            return(SA(ref box));
        }
Example #2
0
        private void ExpandVolume(Bounds_d bounds)
        {
            Bounds_d oldBox = Bounds;

            Bounds.ExpandToFit(bounds);

            if (!oldBox.Equals(Bounds) && Parent != null)
            {
                Parent.ExpandVolume(Bounds);
            }
        }
Example #3
0
        private void RemoveLeaf(SSBVHNodeAdaptor <GO> nAda, ssBVHNode <GO> removeLeaf)
        {
            if (Left == null || Right == null)
            {
                throw new Exception("bad intermediate node");
            }

            ssBVHNode <GO> keepLeaf;

            if (removeLeaf == Left)
            {
                keepLeaf = Right;
            }
            else if (removeLeaf == Right)
            {
                keepLeaf = Left;
            }
            else
            {
                throw new Exception("removeLeaf doesn't match any leaf!");
            }

            // "become" the leaf we are keeping.
            Bounds           = keepLeaf.Bounds;
            Left             = keepLeaf.Left;
            Right            = keepLeaf.Right;
            ContainedObjects = keepLeaf.ContainedObjects;
            // clear the leaf..
            // keepLeaf.left = null; keepLeaf.right = null; keepLeaf.gobjects = null; keepLeaf.parent = null;

            if (ContainedObjects == null)
            {
                Left.Parent  = this;
                Right.Parent = this;                 // reassign child parents..
                SetDepth(nAda, Depth);               // this reassigns depth for our children
            }
            else
            {
                // map the objects we adopted to us...
                ContainedObjects.ForEach(
                    o => {
                    nAda.MapObjectToBvhLeaf(o, this);
                });
            }

            // propagate our new volume..
            if (Parent != null)
            {
                Parent.ChildRefit(nAda);
            }
        }
Example #4
0
        private static void ChildRefit(SSBVHNodeAdaptor <GO> nAda, ssBVHNode <GO> curNode, bool propagate = true)
        {
            do
            {
                ssBVHNode <GO> left  = curNode.Left;
                ssBVHNode <GO> right = curNode.Right;

                // start with the left box
                Bounds_d newBox = left.Bounds.ExpandedToFit(right.Bounds);

                // now set our box to the newly created box
                curNode.Bounds = newBox;

                // and walk up the tree
                curNode = curNode.Parent;
            } while (propagate && curNode != null);
        }
Example #5
0
        private bool RefitVolume(SSBVHNodeAdaptor <GO> nAda)
        {
            if (ContainedObjects.Count == 0)
            {
                throw new NotImplementedException();
            }             // TODO: fix this... we should never get called in this case...

            Bounds_d oldbox = Bounds;

            ComputeVolume(nAda);
            if (!Bounds.Equals(oldbox))
            {
                if (Parent != null)
                {
                    Parent.ChildRefit(nAda);
                }
                return(true);
            }

            return(false);
        }
Example #6
0
        private static void AddObject(SSBVHNodeAdaptor <GO> nAda, ssBVHNode <GO> curNode, GO newOb, ref Bounds_d newObBox, double newObSAH)
        {
            // 1. first we traverse the node looking for the best leaf
            while (curNode.ContainedObjects == null)
            {
                // find the best way to add this object.. 3 options..
                // 1. send to left node  (L+N,R)
                // 2. send to right node (L,R+N)
                // 3. merge and pushdown left-and-right node (L+R,N)

                var left  = curNode.Left;
                var right = curNode.Right;

                double leftSAH               = SA(left);
                double rightSAH              = SA(right);
                double sendLeftSAH           = rightSAH + SA(left.Bounds.ExpandedToFit(newObBox));       // (L+N,R)
                double sendRightSAH          = leftSAH + SA(right.Bounds.ExpandedToFit(newObBox));       // (L,R+N)
                double mergedLeftAndRightSAH = SA(BoundsOfPair(left, right)) + newObSAH;                 // (L+R,N)

                // Doing a merge-and-pushdown can be expensive, so we only do it if it's notably better
                const double MERGE_DISCOUNT = 0.3f;

                if (mergedLeftAndRightSAH < (Math.Min(sendLeftSAH, sendRightSAH)) * MERGE_DISCOUNT)
                {
                    addObject_Pushdown(nAda, curNode, newOb);
                    return;
                }

                if (sendLeftSAH < sendRightSAH)
                {
                    curNode = left;
                }
                else
                {
                    curNode = right;
                }
            }

            // 2. then we add the object and map it to our leaf
            curNode.ContainedObjects.Add(newOb);
            nAda.MapObjectToBvhLeaf(newOb, curNode);
            curNode.RefitVolume(nAda);
            // split if necessary...
            curNode.SplitIfNecessary(nAda);
        }
Example #7
0
 internal void AddObject(SSBVHNodeAdaptor <GO> nAda, GO newOb, ref Bounds_d newObBox, double newObSAH)
 {
     AddObject(nAda, this, newOb, ref newObBox, newObSAH);
 }
Example #8
0
 public List <ssBVHNode <T> > Query(Bounds_d volume)
 {
     return(Query(box => box.Intersects(volume)));
 }