コード例 #1
0
        internal override bool Remove(BroadPhaseEntry entry, out LeafNode leafNode, out Node replacementNode)
        {
            replacementNode = null;
            if (element == entry)
            {
                leafNode = this;
                return(true);
            }

            leafNode = null;
            return(false);
        }
コード例 #2
0
        internal override bool RemoveFast(BroadPhaseEntry entry, out LeafNode leafNode, out Node replacementNode)
        {
            //The fastremove leaf node procedure is identical to the brute force approach.
            //We don't need to perform any bounding box test here; if they're equal, they're equal!
            replacementNode = null;
            if (element == entry)
            {
                leafNode = this;
                return(true);
            }

            leafNode = null;
            return(false);
        }
コード例 #3
0
        internal override bool TryToInsert(LeafNode node, out Node treeNode)
        {
            InternalNode newTreeNode = InternalNode.nodePool.Take();

            BoundingBox.CreateMerged(ref BoundingBox, ref node.BoundingBox, out newTreeNode.BoundingBox);
            Vector3 offset;

            Vector3.Subtract(ref newTreeNode.BoundingBox.Max, ref newTreeNode.BoundingBox.Min, out offset);
            newTreeNode.currentVolume = offset.X * offset.Y * offset.Z;
            //newTreeNode.maximumVolume = newTreeNode.currentVolume * InternalNode.MaximumVolumeScale;
            newTreeNode.childA = this;
            newTreeNode.childB = node;
            treeNode           = newTreeNode;
            return(true);
        }
コード例 #4
0
        internal override bool RemoveFast(BroadPhaseEntry entry, out LeafNode leafNode, out Node replacementNode)
        {
            //Only bother checking deeper in the path if the entry and child have overlapping bounding boxes.
            bool intersects;

            childA.BoundingBox.Intersects(ref entry.boundingBox, out intersects);
            if (intersects && childA.RemoveFast(entry, out leafNode, out replacementNode))
            {
                if (childA.IsLeaf)
                {
                    replacementNode = childB;
                }
                else
                {
                    //It was not a leaf node, but a child found the leaf.
                    //Change the child to the replacement node.
                    childA          = replacementNode;
                    replacementNode = this; //We don't need to be replaced!
                }

                return(true);
            }

            childB.BoundingBox.Intersects(ref entry.boundingBox, out intersects);
            if (intersects && childB.RemoveFast(entry, out leafNode, out replacementNode))
            {
                if (childB.IsLeaf)
                {
                    replacementNode = childA;
                }
                else
                {
                    //It was not a leaf node, but a child found the leaf.
                    //Change the child to the replacement node.
                    childB          = replacementNode;
                    replacementNode = this; //We don't need to be replaced!
                }

                return(true);
            }

            replacementNode = this;
            leafNode        = null;
            return(false);
        }
コード例 #5
0
        /// <summary>
        /// Adds an entry to the hierarchy.
        /// </summary>
        /// <param name="entry">Entry to add.</param>
        public override void Add(BroadPhaseEntry entry)
        {
            base.Add(entry);
            //Entities do not set up their own bounding box before getting stuck in here.  If they're all zeroed out, the tree will be horrible.
            Vector3 offset;

            Vector3.Subtract(ref entry.boundingBox.Max, ref entry.boundingBox.Min, out offset);
            if (offset.X * offset.Y * offset.Z == 0)
            {
                entry.UpdateBoundingBox();
            }

            //Could buffer additions to get a better construction in the tree.
            LeafNode node = leafNodes.Take();

            node.Initialize(entry);
            if (root == null)
            {
                //Empty tree.  This is the first and only node.
                root = node;
            }
            else
            {
                if (root.IsLeaf) //Root is alone.
                {
                    root.TryToInsert(node, out root);
                }
                else
                {
                    BoundingBox.CreateMerged(ref node.BoundingBox, ref root.BoundingBox, out root.BoundingBox);
                    InternalNode internalNode = (InternalNode)root;
                    Vector3.Subtract(ref root.BoundingBox.Max, ref root.BoundingBox.Min, out offset);
                    internalNode.currentVolume = offset.X * offset.Y * offset.Z;
                    //internalNode.maximumVolume = internalNode.currentVolume * InternalNode.MaximumVolumeScale;
                    //The caller is responsible for the merge.
                    Node treeNode = root;
                    while (!treeNode.TryToInsert(node, out treeNode))
                    {
                        ; //TryToInsert returns the next node, if any, and updates node bounding box.
                    }
                }
            }
        }
コード例 #6
0
        internal override bool Remove(BroadPhaseEntry entry, out LeafNode leafNode, out Node replacementNode)
        {
            if (childA.Remove(entry, out leafNode, out replacementNode))
            {
                if (childA.IsLeaf)
                {
                    replacementNode = childB;
                }
                else
                {
                    //It was not a leaf node, but a child found the leaf.
                    //Change the child to the replacement node.
                    childA          = replacementNode;
                    replacementNode = this; //We don't need to be replaced!
                }

                return(true);
            }

            if (childB.Remove(entry, out leafNode, out replacementNode))
            {
                if (childB.IsLeaf)
                {
                    replacementNode = childA;
                }
                else
                {
                    //It was not a leaf node, but a child found the leaf.
                    //Change the child to the replacement node.
                    childB          = replacementNode;
                    replacementNode = this; //We don't need to be replaced!
                }

                return(true);
            }

            replacementNode = this;
            return(false);
        }
コード例 #7
0
 internal abstract bool RemoveFast(BroadPhaseEntry entry, out LeafNode leafNode, out Node replacementNode);
コード例 #8
0
 internal abstract bool TryToInsert(LeafNode node, out Node treeNode);
コード例 #9
0
        internal override bool TryToInsert(LeafNode node, out Node treeNode)
        {
            //Since we are an internal node, we know we have two children.
            //Regardless of what kind of nodes they are, figure out which would be a better choice to merge the new node with.

            //Use the path which produces the smallest 'volume.'
            BoundingBox mergedA, mergedB;

            BoundingBox.CreateMerged(ref childA.BoundingBox, ref node.BoundingBox, out mergedA);
            BoundingBox.CreateMerged(ref childB.BoundingBox, ref node.BoundingBox, out mergedB);

            Vector3 offset;
            float   originalAVolume, originalBVolume;

            Vector3.Subtract(ref childA.BoundingBox.Max, ref childA.BoundingBox.Min, out offset);
            originalAVolume = offset.X * offset.Y * offset.Z;
            Vector3.Subtract(ref childB.BoundingBox.Max, ref childB.BoundingBox.Min, out offset);
            originalBVolume = offset.X * offset.Y * offset.Z;

            float mergedAVolume, mergedBVolume;

            Vector3.Subtract(ref mergedA.Max, ref mergedA.Min, out offset);
            mergedAVolume = offset.X * offset.Y * offset.Z;
            Vector3.Subtract(ref mergedB.Max, ref mergedB.Min, out offset);
            mergedBVolume = offset.X * offset.Y * offset.Z;

            //Could use factor increase or absolute difference
            if (mergedAVolume - originalAVolume < mergedBVolume - originalBVolume)
            {
                //merging A produces a better result.
                if (childA.IsLeaf)
                {
                    InternalNode newChildA = nodePool.Take();
                    newChildA.BoundingBox   = mergedA;
                    newChildA.childA        = childA;
                    newChildA.childB        = node;
                    newChildA.currentVolume = mergedAVolume;
                    //newChildA.maximumVolume = newChildA.currentVolume * MaximumVolumeScale;
                    childA   = newChildA;
                    treeNode = null;
                    return(true);
                }

                childA.BoundingBox = mergedA;
                InternalNode internalNode = (InternalNode)childA;
                internalNode.currentVolume = mergedAVolume;
                //internalNode.maximumVolume = internalNode.currentVolume * MaximumVolumeScale;
                treeNode = childA;
                return(false);
            }

            //merging B produces a better result.
            if (childB.IsLeaf)
            {
                //Target is a leaf! Return.
                InternalNode newChildB = nodePool.Take();
                newChildB.BoundingBox   = mergedB;
                newChildB.childA        = node;
                newChildB.childB        = childB;
                newChildB.currentVolume = mergedBVolume;
                //newChildB.maximumVolume = newChildB.currentVolume * MaximumVolumeScale;
                childB   = newChildB;
                treeNode = null;
                return(true);
            }

            {
                childB.BoundingBox = mergedB;
                treeNode           = childB;
                InternalNode internalNode = (InternalNode)childB;
                internalNode.currentVolume = mergedBVolume;
                //internalNode.maximumVolume = internalNode.currentVolume * MaximumVolumeScale;
                return(false);
            }
        }