我正在制作一个基于 BSP 级别的引擎。我有一个实心叶 BSP 树,我已经可以测试点是否位于实心叶或空叶中,但是我不明白如何对边界框执行相同操作。
我尝试将边界框的最小和最大尺寸添加到速度中:
public bool CanMove(Vector3 _velocity) {
Vector3 velocity = new Vector3(_velocity.X > 0 ? _velocity.X + max.X : _velocity.X + min.X, _velocity.Y > 0 ? _velocity.Y + max.Y : _velocity.Y + min.Y, _velocity.Z > 0 ? _velocity.Z + max.Z : _velocity.Z + min.Z);
return IsPointInNode(center + velocity, map.coreNode);
}
bool IsPointInNode(Vector3 position, MapNode node) {
if (node.isLeaf) {
return node.isSolid;
}
return Vector3.Dot(node.plane.normal, position) + node.plane.distance < 0 ? IsPointInNode(position, node.frontChild) : IsPointInNode(position, node.backChild);
}
}
它有效,但是一次只能应用最小或最大边界框大小,因此会发生剪切。 我知道 quake 的碰撞外壳 BSP,但这对我来说似乎不太好,因为我预计会有很多不同的对撞机大小,并且为每个对撞机存储单独的树似乎没有吸引力。
是否有更好的方法来使用 BSP 检查边界框碰撞,或者我应该将原始画笔存储在地图内并使用它们进行碰撞检测?
我已经弄清楚了。您可以在遍历 BSP 树本身时将碰撞箱大小添加到平面距离,而不是使用具有扩展墙(平面)的单独树:
return Vector3.Dot(node.plane.normal, position) + (node.plane.distance + hullSize) < 0 ? IsPointInNode(position, node.frontChild) : IsPointInNode(position, node.backChild);
如果你的碰撞盒在不同的维度上有不同的尺寸,你只需将平面法线乘以碰撞盒大小即可:
float hullSize = Math.Abs(node.plane.normal.X * size.X) +
Math.Abs(node.plane.normal.Y * size.Y) +
Math.Abs(node.plane.normal.Z * size.Z);