0%

05 - AABB 和平面的相交性检测

AABB 和平面的相交性检测

AABB : pmin\bold{p_{min}}pmax\bold{p_{max}}

平面 :pn=dis\bold{p} \cdot \bold{n} = dis ,其中 n\bold{n} 为单位向量。

1. 静态检测

计算 AABB 顶点和 n\bold{n} 的点积,通过比较点积结果与 disdis ,来检测 AABB 的顶点是否完全在平面的一边,或是在另一边。

  • 如果所有点积都大于 disdis ,那么整个 AABB 就在平面的正面所指的一侧;
  • 如果所有点积都小于 disdis ,那么整个 AABB 就在平面的反面所指的一侧。

实际上,不需要检测全部的 8 个顶点。

  • nx>0n_x > 0 ,点积最小的顶点是 x=xminx = x_{min} ,点积最大的顶点是 x=xmaxx = x_{max}
  • nx<0n_x < 0 ,点积最小的顶点是 x=xmaxx = x_{max} ,点积最大的顶点是 x=xminx = x_{min}
  • 对于 nyn_ynzn_z 同理。

计算最小点积 minD 和最大点积 maxD 的值:

  • minDdisminD \geqslant dis :AABB 在平面的正面;
  • maxDdismaxD \leqslant dis :AABB 在平面的背面;
  • minDdismaxDminD \leqslant dis \leqslant maxD :AABB 与平面相交。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//---------------------------------------------------------------------------
// AABB3::classifyPlane
//
// 静止 AABB 与平面的相交性检测
// 返回值:
// < 0 矩形边界框完全在平面的背面
// > 0 矩形边界框完全在平面的正面
// = 0 矩形边界框和平面相交

int AABB3::classifyPlane(const Vector3& n, float d) const {

// 检查法向量:计算最小和最大 D 值,即距离

float minD, maxD;

if (n.x > 0.0f) {
minD = n.x * min.x; maxD = n.x * max.x;
}
else {
minD = n.x * max.x; maxD = n.x * min.x;
}

if (n.y > 0.0f) {
minD += n.y * min.y; maxD += n.y * max.y;
}
else {
minD += n.y * max.y; maxD += n.y * min.y;
}

if (n.z > 0.0f) {
minD += n.z * min.z; maxD += n.z * max.z;
}
else {
minD += n.z * max.z; maxD += n.z * min.z;
}

// 检测是否完全在平面的前面

if (minD >= d) {
return +1;
}

// 检测是否完全在平面的背面

if (maxD <= d) {
return -1;
}

// 横跨平面

return 0;
}

2. 动态检测

// TODO