public void RebuildBottomUp()
{
var nodes = new int[m_nodeCount];
int count = 0;
// Build array of leaves. Free the rest.
for (int i = 0; i < m_nodeCapacity; ++i)
{
if (m_nodes[i].Height < 0)
{
// free node in pool
continue;
}
if (m_nodes[i].Leaf)
{
m_nodes[i].Parent = TreeNode.NULL_NODE;
nodes[count] = i;
++count;
}
else
{
FreeNode(i);
}
}
var b = new AABB();
while (count > 1)
{
float minCost = Single.MaxValue;
int iMin = -1, jMin = -1;
for (int i = 0; i < count; ++i)
{
AABB aabbi = m_nodes[nodes[i]].AABB;
for (int j = i + 1; j < count; ++j)
{
AABB aabbj = m_nodes[nodes[j]].AABB;
b.Combine(aabbi, aabbj);
float cost = b.Perimeter;
if (cost < minCost)
{
iMin = i;
jMin = j;
minCost = cost;
}
}
}
int index1 = nodes[iMin];
int index2 = nodes[jMin];
TreeNode child1 = m_nodes[index1];
TreeNode child2 = m_nodes[index2];
int parentIndex = AllocateNode();
TreeNode parent = m_nodes[parentIndex];
parent.Child1 = index1;
parent.Child2 = index2;
parent.Height = 1 + MathUtils.Max(child1.Height, child2.Height);
parent.AABB.Combine(child1.AABB, child2.AABB);
parent.Parent = TreeNode.NULL_NODE;
child1.Parent = parentIndex;
child2.Parent = parentIndex;
nodes[jMin] = nodes[count - 1];
nodes[iMin] = parentIndex;
--count;
}
m_root = nodes[0];
Validate();
}