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;
}
}
}