// This method will recompute the Bound without precondition. It will not cascade upwards to parent nodes, because // it is intended to be called recursively. public void BottomUpRecalculateBound() { List <BoundingBox> childBounds = new List <BoundingBox>(); foreach (SceneNode child in mChildren) { ImplicitBoundingBoxNode implicitBVChild = child as ImplicitBoundingBoxNode; if (implicitBVChild != null) { implicitBVChild.BottomUpRecalculateBound(); childBounds.Add(implicitBVChild.Bound); } else { childBounds.AddRange(child.FindExplicitBoundingVolumes()); } } BoundingBox combinedBound = childBounds.First(); foreach (BoundingBox childBox in childBounds.Skip(1)) { combinedBound = BoundingBox.CreateMerged(combinedBound, childBox); } Bound = combinedBound; }
public void InsertNode(SceneNode node, PartitionCategories category) { switch (category) { case PartitionCategories.Dynamic: mDynamicRoot.AddChild(node); break; case PartitionCategories.Static: ImplicitBoundingBoxNode boxNode = node as ImplicitBoundingBoxNode; if (boxNode == null) { boxNode = new ImplicitBoundingBoxNode(true); boxNode.AddChild(node); boxNode.RecalculateBound(); } if (mStaticTreeRoot == null) { mStaticTreeRoot = boxNode; } else { mStaticTreeRoot.InsertNodeIntoBVH(boxNode); } break; case PartitionCategories.Skybox: mSkyboxRoot.AddChild(node); break; } }
public void InsertNodeIntoBVH(ImplicitBoundingBoxNode aabb) { // See http://tog.acm.org/resources/RTNews/html/rtnews3a.html#art6 for algorithm details. BVHInsertion bestInsertion = FindBestLocalInsertion(aabb, 0.0f); BVHInsertion bestDeepInsertion = FindBestDeepInsertion(aabb, bestInsertion.LocationInheritance, bestInsertion.Cost); if (bestDeepInsertion.Cost < bestInsertion.Cost) bestInsertion = bestDeepInsertion; // Perform insertion. switch (bestInsertion.Method) { case BVHInsertion.InsertionMethod.AsSibling: ImplicitBoundingBoxNode copyOfLocation = new ImplicitBoundingBoxNode(bestInsertion.Location); bestInsertion.Location.IsLeaf = false; bestInsertion.Location.mChildren = new List<SceneNode>(); bestInsertion.Location.AddChild(copyOfLocation); bestInsertion.Location.AddChild(aabb); break; case BVHInsertion.InsertionMethod.AsChild: bestInsertion.Location.AddChild(aabb); break; } // The Bound must be recomputed after this operation. bestInsertion.Location.RecalculateBound(); }
private BVHInsertion FindBestLocalInsertion(ImplicitBoundingBoxNode aabb, float inheritedCost) { float newArea = GetAABBArea(BoundingBox.CreateMerged(Bound, aabb.Bound)); float asSiblingCost = 2.0f * newArea; float areaDiff = newArea - GetAABBArea(Bound); if (IsLeaf) { BVHInsertion leafInsertion = new BVHInsertion(this, BVHInsertion.InsertionMethod.AsSibling); leafInsertion.Cost = asSiblingCost + inheritedCost; leafInsertion.LocationInheritance = inheritedCost; return(leafInsertion); } float asChildCost = mChildren.Count * areaDiff + newArea; BVHInsertion bestInsertion; if (asSiblingCost < asChildCost) { bestInsertion = new BVHInsertion(this, BVHInsertion.InsertionMethod.AsSibling); bestInsertion.Cost = asSiblingCost + inheritedCost; } else { bestInsertion = new BVHInsertion(this, BVHInsertion.InsertionMethod.AsChild); bestInsertion.Cost = asChildCost + inheritedCost; } bestInsertion.LocationInheritance = mChildren.Count * areaDiff + inheritedCost; return(bestInsertion); }
public void InsertNodeIntoBVH(ImplicitBoundingBoxNode aabb) { // See http://tog.acm.org/resources/RTNews/html/rtnews3a.html#art6 for algorithm details. BVHInsertion bestInsertion = FindBestLocalInsertion(aabb, 0.0f); BVHInsertion bestDeepInsertion = FindBestDeepInsertion(aabb, bestInsertion.LocationInheritance, bestInsertion.Cost); if (bestDeepInsertion.Cost < bestInsertion.Cost) { bestInsertion = bestDeepInsertion; } // Perform insertion. switch (bestInsertion.Method) { case BVHInsertion.InsertionMethod.AsSibling: ImplicitBoundingBoxNode copyOfLocation = new ImplicitBoundingBoxNode(bestInsertion.Location); bestInsertion.Location.IsLeaf = false; bestInsertion.Location.mChildren = new List <SceneNode>(); bestInsertion.Location.AddChild(copyOfLocation); bestInsertion.Location.AddChild(aabb); break; case BVHInsertion.InsertionMethod.AsChild: bestInsertion.Location.AddChild(aabb); break; } // The Bound must be recomputed after this operation. bestInsertion.Location.RecalculateBound(); }
public SceneGraphRoot(SceneResources sceneResources) { mRenderContext = new RenderContext(sceneResources); mDynamicRoot = new SceneNode(); mStaticTreeRoot = null; mSkyboxRoot = new SceneNode(); mTraversalData = new TraversalContext(); }
public void SetBoundCascading(BoundingBox newBound) { if (newBound != Bound) { Bound = newBound; ImplicitBoundingBoxNode parentBox = mParent as ImplicitBoundingBoxNode; if (parentBox != null) { parentBox.RecalculateBound(); } } }
protected override void ActorInitializedHandler(object sender, EventArgs e) { ImplicitBoundingBoxNode implicitBox = SceneGraph as ImplicitBoundingBoxNode; if (implicitBox != null) { implicitBox.BottomUpRecalculateBound(); } // We shouldn't need this data anymore. Heights = null; base.ActorInitializedHandler(sender, e); }
private SceneNode PartitionSectorGrid(int xMinIndex, int xCount, int zMinIndex, int zCount) { if (xCount == 1 && zCount == 1) { return(CreateSectorNode(xMinIndex, zMinIndex)); } SceneNode child1 = null; SceneNode child2 = null; if (xCount > zCount) { child1 = PartitionSectorGrid( xMinIndex, xCount / 2, zMinIndex, zCount); child2 = PartitionSectorGrid( xMinIndex + xCount / 2, xCount - xCount / 2, zMinIndex, zCount); } else { child1 = PartitionSectorGrid( xMinIndex, xCount, zMinIndex, zCount / 2); child2 = PartitionSectorGrid( xMinIndex, xCount, zMinIndex + zCount / 2, zCount - zCount / 2); } ImplicitBoundingBoxNode implicitChild1 = child1 as ImplicitBoundingBoxNode; ImplicitBoundingBoxNode implicitChild2 = child2 as ImplicitBoundingBoxNode; // If either child is not an implicit node, then this node must be marked as a 'leaf' node so the BVH insertion will work correctly. ImplicitBoundingBoxNode parentPartition = new ImplicitBoundingBoxNode(implicitChild1 == null || implicitChild2 == null); parentPartition.AddChild(child1); parentPartition.AddChild(child2); return(parentPartition); }
private BVHInsertion FindBestDeepInsertion(ImplicitBoundingBoxNode aabb, float inheritance, float costToBeat) { if (IsLeaf) { return(BVHInsertion.WorstInsertion); } // Find best local insertion cost for each child: BVHInsertion bestChildInsertion = BVHInsertion.WorstInsertion; foreach (ImplicitBoundingBoxNode child in mChildren.OfType <ImplicitBoundingBoxNode>()) { BVHInsertion altChildInsertion = child.FindBestLocalInsertion(aabb, inheritance); if (altChildInsertion.Cost < bestChildInsertion.Cost) { bestChildInsertion = altChildInsertion; } } // Which child had the best local cost? Was it better than our local cost? If so, update the costToBeat. if (bestChildInsertion.Cost < costToBeat) { costToBeat = bestChildInsertion.Cost; } // Finally, explore the deeper insertion costs of that child... // Make sure the child's inheritance permits improvement before recursing. if (bestChildInsertion.LocationInheritance < costToBeat) { BVHInsertion bestChildDeepInsertion = bestChildInsertion.Location.FindBestDeepInsertion(aabb, bestChildInsertion.LocationInheritance, costToBeat); // Compare the deep insertion cost with our best so far... if (bestChildDeepInsertion.Cost < bestChildInsertion.Cost) { return(bestChildDeepInsertion); } } return(bestChildInsertion); }
public BVHInsertion(ImplicitBoundingBoxNode location, InsertionMethod method) { Location = location; Method = method; }
public ImplicitBoundingBoxNode(ImplicitBoundingBoxNode orig) : base(orig) { Bound = orig.Bound; IsLeaf = orig.IsLeaf; }
private BVHInsertion FindBestLocalInsertion(ImplicitBoundingBoxNode aabb, float inheritedCost) { float newArea = GetAABBArea(BoundingBox.CreateMerged(Bound, aabb.Bound)); float asSiblingCost = 2.0f * newArea; float areaDiff = newArea - GetAABBArea(Bound); if (IsLeaf) { BVHInsertion leafInsertion = new BVHInsertion(this, BVHInsertion.InsertionMethod.AsSibling); leafInsertion.Cost = asSiblingCost + inheritedCost; leafInsertion.LocationInheritance = inheritedCost; return leafInsertion; } float asChildCost = mChildren.Count * areaDiff + newArea; BVHInsertion bestInsertion; if (asSiblingCost < asChildCost) { bestInsertion = new BVHInsertion(this, BVHInsertion.InsertionMethod.AsSibling); bestInsertion.Cost = asSiblingCost + inheritedCost; } else { bestInsertion = new BVHInsertion(this, BVHInsertion.InsertionMethod.AsChild); bestInsertion.Cost = asChildCost + inheritedCost; } bestInsertion.LocationInheritance = mChildren.Count * areaDiff + inheritedCost; return bestInsertion; }
private BVHInsertion FindBestDeepInsertion(ImplicitBoundingBoxNode aabb, float inheritance, float costToBeat) { if (IsLeaf) return BVHInsertion.WorstInsertion; // Find best local insertion cost for each child: BVHInsertion bestChildInsertion = BVHInsertion.WorstInsertion; foreach (ImplicitBoundingBoxNode child in mChildren.OfType<ImplicitBoundingBoxNode>()) { BVHInsertion altChildInsertion = child.FindBestLocalInsertion(aabb, inheritance); if (altChildInsertion.Cost < bestChildInsertion.Cost) bestChildInsertion = altChildInsertion; } // Which child had the best local cost? Was it better than our local cost? If so, update the costToBeat. if (bestChildInsertion.Cost < costToBeat) costToBeat = bestChildInsertion.Cost; // Finally, explore the deeper insertion costs of that child... // Make sure the child's inheritance permits improvement before recursing. if (bestChildInsertion.LocationInheritance < costToBeat) { BVHInsertion bestChildDeepInsertion = bestChildInsertion.Location.FindBestDeepInsertion(aabb, bestChildInsertion.LocationInheritance, costToBeat); // Compare the deep insertion cost with our best so far... if (bestChildDeepInsertion.Cost < bestChildInsertion.Cost) return bestChildDeepInsertion; } return bestChildInsertion; }
private SceneNode PartitionSectorGrid(int xMinIndex, int xCount, int zMinIndex, int zCount) { if (xCount == 1 && zCount == 1) return CreateSectorNode(xMinIndex, zMinIndex); SceneNode child1 = null; SceneNode child2 = null; if (xCount > zCount) { child1 = PartitionSectorGrid( xMinIndex, xCount / 2, zMinIndex, zCount); child2 = PartitionSectorGrid( xMinIndex + xCount / 2, xCount - xCount / 2, zMinIndex, zCount); } else { child1 = PartitionSectorGrid( xMinIndex, xCount, zMinIndex, zCount / 2); child2 = PartitionSectorGrid( xMinIndex, xCount, zMinIndex + zCount / 2, zCount - zCount / 2); } ImplicitBoundingBoxNode implicitChild1 = child1 as ImplicitBoundingBoxNode; ImplicitBoundingBoxNode implicitChild2 = child2 as ImplicitBoundingBoxNode; // If either child is not an implicit node, then this node must be marked as a 'leaf' node so the BVH insertion will work correctly. ImplicitBoundingBoxNode parentPartition = new ImplicitBoundingBoxNode(implicitChild1 == null || implicitChild2 == null); parentPartition.AddChild(child1); parentPartition.AddChild(child2); return parentPartition; }