Ejemplo n.º 1
0
        // 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;
        }
Ejemplo n.º 2
0
        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;
            }
        }
Ejemplo n.º 3
0
        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();
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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();
        }
Ejemplo n.º 6
0
 public SceneGraphRoot(SceneResources sceneResources)
 {
     mRenderContext  = new RenderContext(sceneResources);
     mDynamicRoot    = new SceneNode();
     mStaticTreeRoot = null;
     mSkyboxRoot     = new SceneNode();
     mTraversalData  = new TraversalContext();
 }
Ejemplo n.º 7
0
 public SceneGraphRoot(SceneResources sceneResources)
 {
     mRenderContext = new RenderContext(sceneResources);
     mDynamicRoot = new SceneNode();
     mStaticTreeRoot = null;
     mSkyboxRoot = new SceneNode();
     mTraversalData = new TraversalContext();
 }
Ejemplo n.º 8
0
        public void SetBoundCascading(BoundingBox newBound)
        {
            if (newBound != Bound)
            {
                Bound = newBound;
                ImplicitBoundingBoxNode parentBox = mParent as ImplicitBoundingBoxNode;

                if (parentBox != null)
                {
                    parentBox.RecalculateBound();
                }
            }
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
 public BVHInsertion(ImplicitBoundingBoxNode location, InsertionMethod method)
 {
     Location = location;
     Method   = method;
 }
Ejemplo n.º 13
0
 public ImplicitBoundingBoxNode(ImplicitBoundingBoxNode orig)
     : base(orig)
 {
     Bound = orig.Bound;
     IsLeaf = orig.IsLeaf;
 }
Ejemplo n.º 14
0
        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;
        }
Ejemplo n.º 15
0
        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;
        }
Ejemplo n.º 16
0
 public ImplicitBoundingBoxNode(ImplicitBoundingBoxNode orig)
     : base(orig)
 {
     Bound  = orig.Bound;
     IsLeaf = orig.IsLeaf;
 }
Ejemplo n.º 17
0
 public BVHInsertion(ImplicitBoundingBoxNode location, InsertionMethod method)
 {
     Location = location;
     Method = method;
 }
Ejemplo n.º 18
0
        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;
        }
Ejemplo n.º 19
0
        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;
            }
        }