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); }