Beispiel #1
0
        public void LocateSelect(SelectNode locator)
        {
            if (!(root is BVHNode))
            {
                if (root != null)
                {
                    locator(root);
                }
                return;
            }
            var     stack = new Stack <BVHNode>();
            BVHNode node  = (BVHNode)root;

            while (true)
            {
                bool right = locator(node.right);
                bool left  = locator(node.left);

                if (left)
                {
                    if (right)
                    {
                        stack.Push((BVHNode)node.right);
                    }
                    node = (BVHNode)node.left;
                }
                else
                {
                    if (right)
                    {
                        node = (BVHNode)node.right;
                    }
                    else
                    {
                        if (stack.Count == 0)
                        {
                            break;
                        }
                        node = stack.Pop();
                    }
                }
            }
        }
Beispiel #2
0
        public void RemoveObject(BVHNodeBase old_object)
        {
            most_recent_node = null;

            if (old_object == root)
            {
                root = null;
                return;
            }

            BVHNodeBase keep;
            BVHNode     parent = old_object.bvh_parent;

            if (parent.left == old_object)
            {
                keep = parent.right;
            }
            else
            {
                keep = parent.left;
            }

            BVHNode grandparent = parent.bvh_parent;

            keep.bvh_parent = grandparent;
            if (grandparent == null)
            {
                root = keep;
            }
            else
            {
                if (grandparent.left == parent)
                {
                    grandparent.left = keep;
                }
                else
                {
                    grandparent.right = keep;
                }
                UpdateBounds(grandparent);
            }
        }
Beispiel #3
0
 void UpdateBounds(BVHNode node)
 {
     while (true)
     {
         Vector3 min = Vector3.Min(node.left.bbox.min, node.right.bbox.min);
         Vector3 max = Vector3.Max(node.left.bbox.max, node.right.bbox.max);
         if (min != node.bbox.min || max != node.bbox.max)
         {
             node.bbox = new BBox(min, max);
             node      = node.bvh_parent;
             if (node == null)
             {
                 break;
             }
         }
         else
         {
             break;
         }
     }
 }
Beispiel #4
0
        public void AddObject(BVHNodeBase new_object)
        {
            if (root == null)
            {
                new_object.bvh_parent = null;
                root = new_object;
                return;
            }

            // 0. start at 'most_recent_node', and go up as long as its
            // bounding box does not contain new_object's bounding box.
            BVHNodeBase walk = most_recent_node;

            if (walk == null)
            {
                walk = root;
            }
            else
            {
                while (walk != root)
                {
                    if (walk.bbox.Contains(new_object.bbox))
                    {
                        break;
                    }
                    walk = walk.bvh_parent;
                }
            }

            // 1. first we traverse the node looking for the best leaf
            float newObSAH = SA(new_object);

            while (walk is BVHNode)
            {
                var curNode = (BVHNode)walk;

                // 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)
                // we tend to avoid option 3 by the 0.3f factor below, because it means
                // that an unknown number of nodes get their depth increased.

                /* first a performance hack which also helps to randomly even out the
                 * two sides in case 'new_object' is between both the bounding box of
                 * 'left' and of 'right'
                 */
                var  right          = curNode.right;
                bool contains_right = right.bbox.Contains(new_object.bbox);
                var  left           = curNode.left;
                if (left.bbox.Contains(new_object.bbox))
                {
                    if (contains_right && _NextRandomBit())
                    {
                        walk = right;
                    }
                    else
                    {
                        walk = left;
                    }
                    continue;
                }
                else if (contains_right)
                {
                    walk = right;
                    continue;
                }

                float leftSAH               = SA(left);
                float rightSAH              = SA(right);
                float sendLeftSAH           = rightSAH + SA(left, new_object); // (L+N,R)
                float sendRightSAH          = leftSAH + SA(right, new_object); // (L,R+N)
                float mergedLeftAndRightSAH = SA(left, right) + newObSAH;      // (L+R,N)

                if (mergedLeftAndRightSAH < 0.3f * Mathf.Min(sendLeftSAH, sendRightSAH))
                {
                    break;
                }
                else
                {
                    if (sendLeftSAH < sendRightSAH)
                    {
                        walk = left;
                    }
                    else
                    {
                        walk = right;
                    }
                }
            }

            // 2. then we add the object and map it to our leaf
            BVHNode parent = walk.bvh_parent;

            most_recent_node = parent;
            var new_node = new BVHNode {
                bbox = walk.bbox, left = walk, right = new_object, bvh_parent = parent
            };

            walk.bvh_parent       = new_node;
            new_object.bvh_parent = new_node;

            if (parent == null)
            {
                Debug.Assert(walk == root);
                root = new_node;
            }
            else if (parent.left == walk)
            {
                parent.left = new_node;
            }
            else
            {
                parent.right = new_node;
            }

            UpdateBounds(new_node);
        }