1. 定义
AABB(axially aligned bounding box)轴对齐矩形边界框 :
- 其边必须垂直于坐标轴,每一边都平行于一个坐标平面。
- 矩形边界框不一定都是立方体,它的长、宽、高可以彼此不同。
2. AABB 的表达方法
AABB 内的点满足下列不等式:
xmin⩽x⩽xmaxymin⩽y⩽ymaxzmin⩽z⩽zmax
其中最重要的两个点:
⎩⎨⎧pmin=[xminyminzmin]pmax=[xmaxymaxzmax]
中心点 c 为:
c=21(pmin+pmax)
尺寸向量 s :从 pmin 指向 pmax 的向量,包含了矩形边界框的长、宽、高:
s=pmax−pmin
半径向量 r :从中心点 c 指向 pmax 的向量:
r=pmax−c=21s
明确定义一个 AABB 只需要 pmin , pmax , c , s , r 这 5 个向量中的两个(除了 s 和 r 不能配对外,它们中的任意两个都可配对)。
其中 pmin , pmax 的使用频率远高于 c , s , r ,由 pmin 和 pmax 计算其余三个中的任意一个都是很容易的。
1 2 3 4 5 6
| class AABB3 { public: Vector3 min; Vector3 max; };
|
3. 计算 AABB
计算一个顶点集合的 AABB :
- 先将最小值和最大值设为“正负无穷大”或任何比实际中用到的数都大或小得多的数。
- 之后,遍历全部点,并扩展边界框直到它包含所有点为止。
先在 AABB 类中引入了两个辅助函数。
3.1 初始化 AABB
empty() 函数负责 “清空” AABB:
1 2 3 4 5 6 7 8 9 10
|
void AABB3::empty() { const float kBigNumber = 1e37f; min.x = min.y = min.z = kBigNumber; max.x = max.y = max.z = -kBigNumber; }
|
3.2 向 AABB 添加 “点”
add(const Vector3& p) 函数将单个点“加”到 AABB 中,并在必要的时候扩展 AABB 以包含每个点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
void AABB3::add(const Vector3& p) {
if (p.x < min.x) min.x = p.x; if (p.x > max.x) max.x = p.x; if (p.y < min.x) min.y = p.y; if (p.y > max.x) max.y = p.y; if (p.z < min.x) min.z = p.z; if (p.z > max.x) max.z = p.z; }
|
3.3 从点集中计算其 AABB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| AABB3 genAABB3(const int n, const Vector3 points[n]) { AABB3 box; box.empty();
for(int i = 0 ; i < n ; ++i) { box.add(points[i]); }
return box; }
|