AABB 或 Axis Aligned Bounding Box 是一个非常简单且快速的对象,用于测试两个 3D 区域的交叉/包含。
正如您所建议的,您正在计算要比较的两个区域的最小和最大 x,y,z,例如,描述截头体的区域和描述网格的区域。它是轴对齐的,因为随后的立方体具有与坐标系的每个轴平行的边缘。显然,这可能有点不准确(交叉/包含的误报,但绝不会误报),因此一旦您使用 AABB 测试过滤列表,您可能会考虑对剩余的网格执行更准确的测试。
您按如下方式测试交叉点/包含:
F = AABB 截锥体
M = AABB 网格
bool is_mesh_in_frustum(const AABB& F, const AABB& M)
{
if( F.min.x > M.max.x || M.min.x > F.max.x || F.min.y > M.max.y || M.min.y > F.max.y || F.min.z > M.max.z || M.min.z > F.max.z )
{
return false;
}
return true;
}
您还可以查找边界球体、定向边界框 (OBB) 和其他类型的边界体的算法。根据您要渲染的网格数量,您可能需要也可能不需要更准确的方法。
要首先创建 AABB,您可以简单地遍历网格的顶点并记录您遇到的最小/最大 x 和 y 和 z 值。
还要考虑,如果网格不变形,那么网格坐标空间中的边界框将是静态的,因此您可以在获得顶点数据后立即计算所有网格的 AABB。
然后,您只需要确保在执行每个渲染通道的测试之前将预先计算的 AABB 最小和最大顶点转换为平截头体坐标空间。
编辑(评论):
AABB 可能会提供误报,因为它充其量是您要界定的区域的确切形状,但通常比您要界定的区域大。
考虑一个球体,如果你使用AABB,就像把一个篮球放进一个盒子里,你在盒子的角落里有所有这些球无法到达的缝隙。
或者在截锥体向内朝向相机倾斜的截锥体的情况下,它的 AABB 将简单地沿着轴朝向相机直线继续,有效地界定了一个比相机可以看到的区域更大的区域。
这是不准确的根源,但它绝不会导致您剔除稍微位于截锥体内的对象,因此最坏的情况下,您仍将绘制一些靠近相机但仍在截锥体之外的网格。
您可以通过首先进行 AABB 测试来纠正此问题,并生成一个较小的返回 true 的网格列表,然后对该较小的列表执行更准确的测试,并为平截头体和/或网格提供更准确的边界体积。