Exemplo n.º 1
0
        private static void addObject_Pushdown(SSBVHNodeAdaptor <GO> nAda, ssBVHNode <GO> curNode, GO newOb)
        {
            var left  = curNode.Left;
            var right = curNode.Right;

            // merge and pushdown left and right as a new node..
            var mergedSubnode = new ssBVHNode <GO>(nAda.BVH)
            {
                Left             = left,
                Right            = right,
                Parent           = curNode,
                ContainedObjects = null
            };

            // we need to be an interior node... so null out our object list..
            left.Parent  = mergedSubnode;
            right.Parent = mergedSubnode;
            mergedSubnode.ChildRefit(nAda, false);

            // make new subnode for obj
            var newSubnode = new ssBVHNode <GO>(nAda.BVH);

            newSubnode.Parent           = curNode;
            newSubnode.ContainedObjects = new List <GO> {
                newOb
            };
            nAda.MapObjectToBvhLeaf(newOb, newSubnode);
            newSubnode.ComputeVolume(nAda);

            // make assignments..
            curNode.Left  = mergedSubnode;
            curNode.Right = newSubnode;
            curNode.SetDepth(nAda, curNode.Depth);             // propagate new depths to our children.
            curNode.ChildRefit(nAda);
        }
Exemplo n.º 2
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);
            }
        }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
0
        private ssBVHNode(ssBVH <GO> bvh, ssBVHNode <GO> lparent, List <GO> gobjectlist, int curdepth)
        {
            SSBVHNodeAdaptor <GO> nAda = bvh.nAda;

            Parent = lparent;             // save off the parent BVHGObj Node
            Depth  = curdepth;

            if (bvh.MaxDepth < curdepth)
            {
                bvh.MaxDepth = curdepth;
            }

            // Early out check due to bad data
            // If the list is empty then we have no BVHGObj, or invalid parameters are passed in
            if (gobjectlist == null || gobjectlist.Count < 1)
            {
                throw new Exception("ssBVHNode constructed with invalid paramaters");
            }

            // Check if we’re at our LEAF node, and if so, save the objects and stop recursing.  Also store the min/max for the leaf node and update the parent appropriately
            if (gobjectlist.Count <= bvh.LEAF_OBJ_MAX)
            {
                // once we reach the leaf node, we must set prev/next to null to signify the end
                Left  = null;
                Right = null;
                // at the leaf node we store the remaining objects, so initialize a list
                ContainedObjects = gobjectlist;
                ContainedObjects.ForEach(o => nAda.MapObjectToBvhLeaf(o, this));
                ComputeVolume(nAda);
                SplitIfNecessary(nAda);
            }
            else
            {
                // --------------------------------------------------------------------------------------------
                // if we have more than (bvh.LEAF_OBJECT_COUNT) objects, then compute the volume and split
                ContainedObjects = gobjectlist;
                ComputeVolume(nAda);
                SplitNode(nAda);
                ChildRefit(nAda, false);
            }
        }