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); } }
public void setBVH(ssBVH <SSObject> BVH) { this._BVH = BVH; }
public SSBVHRender(ssBVH <SSObject> bvh) { this.bvh = bvh; }
internal ssBVHNode(ssBVH <GO> bvh, List <GO> gobjectlist) : this(bvh, null, gobjectlist, 0) { }
internal ssBVHNode(ssBVH <GO> bvh) { ContainedObjects = new List <GO>(); Left = Right = null; Parent = null; }
/// <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; } } }
/// <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()); } } }
public void setBVH(ssBVH <IHitable> BVH) { this._BVH = BVH; }
public void setBVH(ssBVH <SSSphere> bvh) { _bvh = bvh; }
public void setBVH(ssBVH <SSSphere> BVH) { _BVH = BVH; }
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; }