box2d dynamic tree
dynamic tree 是一颗 full binary trees, 即非叶子节点必须有两个子节点(注:full binary trees和大学老师讲的满二叉树,完全二叉树不同)
那么如果构建树?先看源码
while (m_nodes[index].IsLeaf() == false)
{
int32 child1 = m_nodes[index].child1;
int32 child2 = m_nodes[index].child2;
float32 area = m_nodes[index].aabb.GetPerimeter();
// 面积代价
b2AABB combinedAABB;
combinedAABB.Combine(m_nodes[index].aabb, leafAABB);
float32 combinedArea = combinedAABB.GetPerimeter();
// 合并后的 周长
// Cost of creating a new parent for this node and the new leaf
float32 cost = 2.0f * combinedArea;
// Minimum cost of pushing the leaf further down the tree
float32 inheritanceCost = 2.0f * (combinedArea - area);
// Cost of descending into child1
float32 cost1;
if (m_nodes[child1].IsLeaf())
{
b2AABB aabb;
aabb.Combine(leafAABB, m_nodes[child1].aabb);
cost1 = aabb.GetPerimeter() + inheritanceCost;
}
else
{
b2AABB aabb;
aabb.Combine(leafAABB, m_nodes[child1].aabb);
float32 oldArea = m_nodes[child1].aabb.GetPerimeter();
float32 newArea = aabb.GetPerimeter();
cost1 = (newArea - oldArea) + inheritanceCost;
}
// Cost of descending into child2
float32 cost2;
if (m_nodes[child2].IsLeaf())
{
b2AABB aabb;
aabb.Combine(leafAABB, m_nodes[child2].aabb);
cost2 = aabb.GetPerimeter() + inheritanceCost;
}
else
{
b2AABB aabb;
aabb.Combine(leafAABB, m_nodes[child2].aabb);
float32 oldArea = m_nodes[child2].aabb.GetPerimeter();
float32 newArea = aabb.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;
}
}
box2d是采用surface area heuristic 划分场景的。 虽然采用的是getperimter, 获取aabb的周长,然后计算代价。 但可以从变量名上可以找到area, totalarea, newarea,oldarea. 这可能是因为采用周长的代价更低的原因。
插入思路如下:计算左右子树的代价,选择代价低的节点,如果此节点是叶子节点,将新节点插入。 如果不是,重复此步操作。
![](https://i-blog.csdnimg.cn/blog_migrate/b7357de688b7d7e46a4c44742f2c8310.png)