// find the best sibling
AABB leafAABB = m_nodes[leaf].aabb;
int index = m_root;
while (m_nodes[index].isLeaf() == false) {
final TreeNode node = m_nodes[index];
int child1 = node.child1;
int child2 = node.child2;
float area = node.aabb.getPerimeter();
combinedAABB.combine(node.aabb, leafAABB);
float combinedArea = combinedAABB.getPerimeter();
// Cost of creating a new parent for this node and the new leaf
float cost = 2.0f * combinedArea;
// Minimum cost of pushing the leaf further down the tree
float inheritanceCost = 2.0f * (combinedArea - area);
// Cost of descending into child1
float cost1;
if (m_nodes[child1].isLeaf()) {
combinedAABB.combine(leafAABB, m_nodes[child1].aabb);
cost1 = combinedAABB.getPerimeter() + inheritanceCost;
} else {
combinedAABB.combine(leafAABB, m_nodes[child1].aabb);
float oldArea = m_nodes[child1].aabb.getPerimeter();
float newArea = combinedAABB.getPerimeter();
cost1 = (newArea - oldArea) + inheritanceCost;
}
// Cost of descending into child2
float cost2;
if (m_nodes[child2].isLeaf()) {
combinedAABB.combine(leafAABB, m_nodes[child2].aabb);
cost2 = combinedAABB.getPerimeter() + inheritanceCost;
} else {
combinedAABB.combine(leafAABB, m_nodes[child2].aabb);
float oldArea = m_nodes[child2].aabb.getPerimeter();
float newArea = combinedAABB.getPerimeter();
cost2 = newArea - oldArea + inheritanceCost;
}
// Descend according to the minimum cost.
if (cost < cost1 && cost < cost2) {
break;
}
// Descend
if (cost1 < cost2) {
index = child1;
} else {
index = child2;
}
}
int sibling = index;
int oldParent = m_nodes[sibling].parent;
int newParentId = allocateNode();
final TreeNode newParent = m_nodes[newParentId];
newParent.parent = oldParent;
newParent.userData = null;
newParent.aabb.combine(leafAABB, m_nodes[sibling].aabb);
newParent.height = m_nodes[sibling].height + 1;