Esempio n. 1
0
 internal ssBVHNode(ssBVH <GO> bvh)
 {
     gobjects        = new List <GO>();
     left            = right = null;
     parent          = null;
     this.nodeNumber = bvh.nodeCount++;
 }
        private ssBVHNode(ssBVH <GO> bvh, ssBVHNode <GO> lparent, List <GO> gobjectlist, Axis lastSplitAxis, int curdepth)
        {
            SSBVHNodeAdaptor <GO> nAda = bvh.nAda;

            this.nodeNumber = bvh.nodeCount++;

            this.parent = lparent; // save off the parent BVHGObj Node
            this.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
                gobjects = gobjectlist;
                gobjects.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
                gobjects = gobjectlist;
                computeVolume(nAda);
                splitNode(nAda);
                childRefit(nAda, propagate: false);
            }
        }
Esempio n. 3
0
 public void setBVH(ssBVH <SSObject> BVH)
 {
     this._BVH = BVH;
 }
Esempio n. 4
0
 public SSBVHRender(ssBVH <SSObject> bvh)
 {
     this.bvh = bvh;
 }
Esempio n. 5
0
 internal ssBVHNode(ssBVH <GO> bvh, List <GO> gobjectlist) : this(bvh, null, gobjectlist, 0)
 {
 }
Esempio n. 6
0
 internal ssBVHNode(ssBVH <GO> bvh)
 {
     ContainedObjects = new List <GO>();
     Left             = Right = null;
     Parent           = null;
 }
Esempio n. 7
0
        /// <summary>
        /// tryRotate looks at all candidate rotations, and executes the rotation with the best resulting SAH (if any)
        /// </summary>
        /// <param name="bvh"></param>
        internal void TryRotate(ssBVH <GO> bvh)
        {
            SSBVHNodeAdaptor <GO> nAda = bvh.nAda;

            // if we are not a grandparent, then we can't rotate, so queue our parent and bail out
            if (Left.IsLeaf && Right.IsLeaf)
            {
                if (Parent != null)
                {
                    bvh.RefitNodes.Add(Parent);
                    return;
                }
            }

            // for each rotation, check that there are grandchildren as necessary (aka not a leaf)
            // then compute total SAH cost of our branches after the rotation.

            double mySA = SA(Left) + SA(Right);

            RotOpt bestRot = eachRot.Min(
                rot => {
                switch (rot)
                {
                case Rot.NONE: return(new RotOpt(mySA, Rot.NONE));

                // child to grandchild rotations
                case Rot.L_RL:
                    if (Right.IsLeaf)
                    {
                        return(new RotOpt(double.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new RotOpt(SA(Right.Left) + SA(BoundsOfPair(Left, Right.Right)), rot));
                    }

                case Rot.L_RR:
                    if (Right.IsLeaf)
                    {
                        return(new RotOpt(double.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new RotOpt(SA(Right.Right) + SA(BoundsOfPair(Left, Right.Left)), rot));
                    }

                case Rot.R_LL:
                    if (Left.IsLeaf)
                    {
                        return(new RotOpt(double.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new RotOpt(SA(BoundsOfPair(Right, Left.Right)) + SA(Left.Left), rot));
                    }

                case Rot.R_LR:
                    if (Left.IsLeaf)
                    {
                        return(new RotOpt(double.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new RotOpt(SA(BoundsOfPair(Right, Left.Left)) + SA(Left.Right), rot));
                    }

                // grandchild to grandchild rotations
                case Rot.LL_RR:
                    if (Left.IsLeaf || Right.IsLeaf)
                    {
                        return(new RotOpt(double.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new RotOpt(SA(BoundsOfPair(Right.Right, Left.Right)) + SA(BoundsOfPair(Right.Left, Left.Left)), rot));
                    }

                case Rot.LL_RL:
                    if (Left.IsLeaf || Right.IsLeaf)
                    {
                        return(new RotOpt(double.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new RotOpt(SA(BoundsOfPair(Right.Left, Left.Right)) + SA(BoundsOfPair(Left.Left, Right.Right)), rot));
                    }

                // unknown...
                default: throw new NotImplementedException("missing implementation for BVH Rotation SAH Computation .. " + rot.ToString());
                }
            });

            // perform the best rotation...
            if (bestRot.rot != Rot.NONE)
            {
                // if the best rotation is no-rotation... we check our parents anyhow..
                if (Parent != null)
                {
                    // but only do it some random percentage of the time.
                    if ((DateTime.Now.Ticks % 100) < 2)
                    {
                        bvh.RefitNodes.Add(Parent);
                    }
                }
            }
            else
            {
                if (Parent != null)
                {
                    bvh.RefitNodes.Add(Parent);
                }

                if (((mySA - bestRot.SAH) / mySA) < 0.3f)
                {
                    return;                     // the benefit is not worth the cost
                }

                Console.WriteLine("BVH swap {0} from {1} to {2}", bestRot.rot.ToString(), mySA, bestRot.SAH);

                // in order to swap we need to:
                //  1. swap the node locations
                //  2. update the depth (if child-to-grandchild)
                //  3. update the parent pointers
                //  4. refit the boundary box
                ssBVHNode <GO> swap = null;
                switch (bestRot.rot)
                {
                case Rot.NONE: break;

                // child to grandchild rotations
                case Rot.L_RL:
                    swap        = Left;
                    Left        = Right.Left;
                    Left.Parent = this;
                    Right.Left  = swap;
                    swap.Parent = Right;
                    Right.ChildRefit(nAda, propagate: false);
                    break;

                case Rot.L_RR:
                    swap        = Left;
                    Left        = Right.Right;
                    Left.Parent = this;
                    Right.Right = swap;
                    swap.Parent = Right;
                    Right.ChildRefit(nAda, propagate: false);
                    break;

                case Rot.R_LL:
                    swap         = Right;
                    Right        = Left.Left;
                    Right.Parent = this;
                    Left.Left    = swap;
                    swap.Parent  = Left;
                    Left.ChildRefit(nAda, propagate: false);
                    break;

                case Rot.R_LR:
                    swap         = Right;
                    Right        = Left.Right;
                    Right.Parent = this;
                    Left.Right   = swap;
                    swap.Parent  = Left;
                    Left.ChildRefit(nAda, propagate: false);
                    break;

                // grandchild to grandchild rotations
                case Rot.LL_RR:
                    swap             = Left.Left;
                    Left.Left        = Right.Right;
                    Right.Right      = swap;
                    Left.Left.Parent = Left;
                    swap.Parent      = Right;
                    Left.ChildRefit(nAda, propagate: false);
                    Right.ChildRefit(nAda, propagate: false);
                    break;

                case Rot.LL_RL:
                    swap             = Left.Left;
                    Left.Left        = Right.Left;
                    Right.Left       = swap;
                    Left.Left.Parent = Left;
                    swap.Parent      = Right;
                    Left.ChildRefit(nAda, propagate: false);
                    Right.ChildRefit(nAda, propagate: false);
                    break;

                // unknown...
                default: throw new NotImplementedException("missing implementation for BVH Rotation .. " + bestRot.rot);
                }

                // fix the depths if necessary....
                switch (bestRot.rot)
                {
                case Rot.L_RL:
                case Rot.L_RR:
                case Rot.R_LL:
                case Rot.R_LR:
                    SetDepth(nAda, Depth);
                    break;
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// tryRotate looks at all candidate rotations, and executes the rotation with the best resulting SAH (if any)
        /// </summary>
        /// <param name="bvh"></param>
        internal void tryRotate(ssBVH <GO> bvh)
        {
            SSBVHNodeAdaptor <GO> nAda = bvh.nAda;

            // if we are not a grandparent, then we can't rotate, so queue our parent and bail out
            if (left.IsLeaf && right.IsLeaf)
            {
                if (parent != null)
                {
                    bvh.refitNodes.Add(parent);
                    return;
                }
            }

            // for each rotation, check that there are grandchildren as necessary (aka not a leaf)
            // then compute total SAH cost of our branches after the rotation.

            float mySAH = SAH(left) + SAH(right);

            rotOpt bestRot = eachRot.Min((rot) => {
                switch (rot)
                {
                case Rot.NONE: return(new rotOpt(mySAH, Rot.NONE));

                // child to grandchild rotations
                case Rot.L_RL:
                    if (right.IsLeaf)
                    {
                        return(new rotOpt(float.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new rotOpt(SAH(right.left) + SAH(AABBofPair(left, right.right)), rot));
                    }

                case Rot.L_RR:
                    if (right.IsLeaf)
                    {
                        return(new rotOpt(float.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new rotOpt(SAH(right.right) + SAH(AABBofPair(left, right.left)), rot));
                    }

                case Rot.R_LL:
                    if (left.IsLeaf)
                    {
                        return(new rotOpt(float.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new rotOpt(SAH(AABBofPair(right, left.right)) + SAH(left.left), rot));
                    }

                case Rot.R_LR:
                    if (left.IsLeaf)
                    {
                        return(new rotOpt(float.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new rotOpt(SAH(AABBofPair(right, left.left)) + SAH(left.right), rot));
                    }

                // grandchild to grandchild rotations
                case Rot.LL_RR:
                    if (left.IsLeaf || right.IsLeaf)
                    {
                        return(new rotOpt(float.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new rotOpt(SAH(AABBofPair(right.right, left.right)) + SAH(AABBofPair(right.left, left.left)), rot));
                    }

                case Rot.LL_RL:
                    if (left.IsLeaf || right.IsLeaf)
                    {
                        return(new rotOpt(float.MaxValue, Rot.NONE));
                    }
                    else
                    {
                        return(new rotOpt(SAH(AABBofPair(right.left, left.right)) + SAH(AABBofPair(left.left, right.right)), rot));
                    }

                // unknown...
                default: throw new NotImplementedException("missing implementation for BVH Rotation SAH Computation .. " + rot.ToString());
                }
            });

            // perform the best rotation...
            if (bestRot.rot != Rot.NONE)
            {
                // if the best rotation is no-rotation... we check our parents anyhow..
                if (parent != null)
                {
                    // but only do it some random percentage of the time.
                    if ((DateTime.Now.Ticks % 100) < 2)
                    {
                        bvh.refitNodes.Add(parent);
                    }
                }
            }
            else
            {
                if (parent != null)
                {
                    bvh.refitNodes.Add(parent);
                }

                if (((mySAH - bestRot.SAH) / mySAH) < 0.3f)
                {
                    return; // the benefit is not worth the cost
                }
                Console.WriteLine("BVH swap {0} from {1} to {2}", bestRot.rot.ToString(), mySAH, bestRot.SAH);

                // in order to swap we need to:
                //  1. swap the node locations
                //  2. update the depth (if child-to-grandchild)
                //  3. update the parent pointers
                //  4. refit the boundary box
                ssBVHNode <GO> swap = null;
                switch (bestRot.rot)
                {
                case Rot.NONE: break;

                // child to grandchild rotations
                case Rot.L_RL: swap = left;  swap.depth++; left = right.left;  left.parent = this; left.depth--;  right.left = swap;  swap.parent = right; right.childRefit(nAda); break;

                case Rot.L_RR: swap = left;  swap.depth++; left = right.right; left.parent = this; left.depth--;  right.right = swap;  swap.parent = right; right.childRefit(nAda); break;

                case Rot.R_LL: swap = right; swap.depth++; right = left.left;  right.parent = this; right.depth--; left.left = swap;  swap.parent = left;   left.childRefit(nAda); break;

                case Rot.R_LR: swap = right; swap.depth++; right = left.right; right.parent = this; right.depth--; left.right = swap;  swap.parent = left;   left.childRefit(nAda); break;

                // grandchild to grandchild rotations
                case Rot.LL_RR: swap = left.left; left.left = right.right; right.right = swap; left.left.parent = left; swap.parent = right; left.childRefit(nAda, recurse: false); right.childRefit(nAda); break;

                case Rot.LL_RL: swap = left.left; left.left = right.left;  right.left = swap; left.left.parent = left; swap.parent = right; left.childRefit(nAda, recurse: false); right.childRefit(nAda); break;

                // unknown...
                default: throw new NotImplementedException("missing implementation for BVH Rotation .. " + bestRot.rot.ToString());
                }
            }
        }
Esempio n. 9
0
 public void setBVH(ssBVH <IHitable> BVH)
 {
     this._BVH = BVH;
 }
 public void setBVH(ssBVH <SSSphere> bvh)
 {
     _bvh = bvh;
 }
Esempio n. 11
0
 public void setBVH(ssBVH <SSSphere> BVH)
 {
     _BVH = BVH;
 }
Esempio n. 12
0
 public SSBVHRender(ssBVH <SSObject> bvh)
 {
     this.bvh                 = bvh;
     this.MainColor           = Color4.Red;
     this.renderState.lighted = false;
 }
 public SSBVHRender(ssBVH <SSObject> bvh)
 {
     this.bvh       = bvh;
     this.MainColor = Color4.Red;
 }