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); }
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); }
internal override bool TryToInsert(LeafNode node, out Node treeNode) { var newTreeNode = InternalNode.nodePool.Take(); BoundingBox.CreateMerged(ref BoundingBox, ref node.BoundingBox, out newTreeNode.BoundingBox); System.Numerics.Vector3 offset; Vector3Ex.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); }
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); }
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); } else { 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); }
internal abstract bool RemoveFast(BroadPhaseEntry entry, out LeafNode leafNode, out Node replacementNode);
internal abstract bool TryToInsert(LeafNode node, out Node treeNode);
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); System.Numerics.Vector3 offset; float originalAVolume, originalBVolume; Vector3Ex.Subtract(ref childA.BoundingBox.Max, ref childA.BoundingBox.Min, out offset); originalAVolume = offset.X * offset.Y * offset.Z; Vector3Ex.Subtract(ref childB.BoundingBox.Max, ref childB.BoundingBox.Min, out offset); originalBVolume = offset.X * offset.Y * offset.Z; float mergedAVolume, mergedBVolume; Vector3Ex.Subtract(ref mergedA.Max, ref mergedA.Min, out offset); mergedAVolume = offset.X * offset.Y * offset.Z; Vector3Ex.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); } } }