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)); }
private void ExpandVolume(Bounds_d bounds) { Bounds_d oldBox = Bounds; Bounds.ExpandToFit(bounds); if (!oldBox.Equals(Bounds) && Parent != null) { Parent.ExpandVolume(Bounds); } }
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); } }
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); }
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); }
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); }
internal void AddObject(SSBVHNodeAdaptor <GO> nAda, GO newOb, ref Bounds_d newObBox, double newObSAH) { AddObject(nAda, this, newOb, ref newObBox, newObSAH); }
public List <ssBVHNode <T> > Query(Bounds_d volume) { return(Query(box => box.Intersects(volume))); }