コード例 #1
0
            internal override bool TryToInsert(LeafNode node, out Node treeNode)
            {
                var newTreeNode = new InternalNode();

                BoundingBox.CreateMerged(ref BoundingBox, ref node.BoundingBox, out newTreeNode.BoundingBox);
                newTreeNode.childA = this;
                newTreeNode.childB = node;
                treeNode           = newTreeNode;
                return(true);
            }
コード例 #2
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);
 }
コード例 #3
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);
 }
コード例 #4
0
        internal override bool TryToInsert(LeafNode node, out Node treeNode)
        {
            var 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);
        }
コード例 #5
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);
        }
コード例 #6
0
            internal override bool TryToInsert(LeafNode node, out Node treeNode)
            {
                ////The following can make the tree shorter, but it actually hurt query times in testing.
                //bool aIsLeaf = childA.IsLeaf;
                //bool bIsLeaf = childB.IsLeaf;
                //if (aIsLeaf && !bIsLeaf)
                //{
                //    //Just put us with the leaf.  Keeps the tree shallower.
                //    BoundingBox merged;
                //    BoundingBox.CreateMerged(ref childA.BoundingBox, ref node.BoundingBox, out merged);
                //    childA = new InternalNode() { BoundingBox = merged, childA = this.childA, childB = node };
                //    treeNode = null;
                //    return true;
                //}
                //else if (!aIsLeaf && bIsLeaf)
                //{
                //    //Just put us with the leaf.  Keeps the tree shallower.
                //    BoundingBox merged;
                //    BoundingBox.CreateMerged(ref childB.BoundingBox, ref node.BoundingBox, out merged);
                //    childB = new InternalNode() { BoundingBox = merged, childA = node, childB = this.childB };
                //    treeNode = null;
                //    return true;
                //}


                //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)
                    {
                        ChildA = new InternalNode()
                        {
                            BoundingBox = mergedA, ChildA = this.ChildA, ChildB = node
                        };
                        treeNode = null;
                        return(true);
                    }
                    else
                    {
                        ChildA.BoundingBox = mergedA;
                        treeNode           = ChildA;
                        return(false);
                    }
                }
                else
                {
                    //merging B produces a better result.
                    if (ChildB.IsLeaf)
                    {
                        //Target is a leaf! Return.
                        ChildB = new InternalNode()
                        {
                            BoundingBox = mergedB, ChildA = node, ChildB = this.ChildB
                        };
                        treeNode = null;
                        return(true);
                    }
                    else
                    {
                        ChildB.BoundingBox = mergedB;
                        treeNode           = ChildB;
                        return(false);
                    }
                }
            }
コード例 #7
0
 internal abstract bool TryToInsert(LeafNode node, out Node treeNode);
コード例 #8
0
 internal abstract bool RemoveFast(BroadPhaseEntry entry, out LeafNode leafNode, out Node replacementNode);
コード例 #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)
                {
                    var newChildA = nodePool.Take();
                    newChildA.BoundingBox   = mergedA;
                    newChildA.childA        = this.childA;
                    newChildA.childB        = node;
                    newChildA.currentVolume = mergedAVolume;
                    //newChildA.maximumVolume = newChildA.currentVolume * MaximumVolumeScale;
                    childA   = newChildA;
                    treeNode = null;
                    return(true);
                }
                else
                {
                    childA.BoundingBox = mergedA;
                    var internalNode = (InternalNode)childA;
                    internalNode.currentVolume = mergedAVolume;
                    //internalNode.maximumVolume = internalNode.currentVolume * MaximumVolumeScale;
                    treeNode = childA;
                    return(false);
                }
            }
            else
            {
                //merging B produces a better result.
                if (childB.IsLeaf)
                {
                    //Target is a leaf! Return.
                    var newChildB = nodePool.Take();
                    newChildB.BoundingBox   = mergedB;
                    newChildB.childA        = node;
                    newChildB.childB        = this.childB;
                    newChildB.currentVolume = mergedBVolume;
                    //newChildB.maximumVolume = newChildB.currentVolume * MaximumVolumeScale;
                    childB   = newChildB;
                    treeNode = null;
                    return(true);
                }
                else
                {
                    childB.BoundingBox = mergedB;
                    treeNode           = childB;
                    var internalNode = (InternalNode)childB;
                    internalNode.currentVolume = mergedBVolume;
                    //internalNode.maximumVolume = internalNode.currentVolume * MaximumVolumeScale;
                    return(false);
                }
            }
        }