这几天在做3d的一个验证demo,场景硕大,碰撞体众多,现在对于碰撞的处理方式是全部都采用AABB
首先由美工在编辑器里为所有碰撞体绑定AABB,然后我写了个插件导出这些box,再写了一个外部工具来把box信息重新编码成二进制,最后在j2me里读取并重新构造这个AABB Tree
原理很简单,但美工那边的反馈是希望我能支持OBB以增加碰撞的真实性
的确,有些斜着摆放的物体,如果用AABB,则好些空地走不过去,非常不爽
但OBB的碰撞效率是非常低的,我们只能想方设法减少真实OBB碰撞的发生
现在目前的思路有两个,
1. 说服美工在摆放场景时尽量都是沿轴摆放,也不要有OBB的情况发生,这样对程序来说最方便,哈哈,不过有点偷懒的嫌疑
2. 我首先用AABB包围OBB,90%的情况下还是AABB的碰撞检测,如果发生AABB碰撞了,再看目标碰撞体是否包围有更精确的OBB,如果有,就进行更进一步的AABB-OBB检测
今天终于搞定了那个沿墙壁滑动的效果,过几天总结一下
附带一个高效的AABB_OBB的检测方法
bool testIntersectionAABB_OBB(
const
Box
&
_aabb,
const
OBB
&
_obb)
... {
float t, s;
int r;
float Bf[3][3];
float reps = (float) 1e-6;
const Vec3f &a = _aabb.extent;
const Vec3f &b = _obb.extent;
const Vec3f T = _obb.center - _aabb.center;
// float B[3][3];
// const Matrix3x3 &m = _obb.matrix;
// B[0][0] = m._11; B[0][1] = m._21; B[0][2] = m._31;
// B[1][0] = m._12; B[1][1] = m._22; B[1][2] = m._32;
// B[2][0] = m._13; B[2][1] = m._23; B[2][2] = m._33;
typedef float _mat3x3[3][3];
_mat3x3 B;
memcpy(B, _obb.matrix.m_, sizeof(_mat3x3));
// Bf = fabs(B)
Bf[0][0] = fabsf(B[0][0]); Bf[0][0] += reps;
Bf[0][1] = fabsf(B[0][1]); Bf[0][1] += reps;
Bf[0][2] = fabsf(B[0][2]); Bf[0][2] += reps;
Bf[1][0] = fabsf(B[1][0]); Bf[1][0] += reps;
Bf[1][1] = fabsf(B[1][1]); Bf[1][1] += reps;
Bf[1][2] = fabsf(B[1][2]); Bf[1][2] += reps;
Bf[2][0] = fabsf(B[2][0]); Bf[2][0] += reps;
Bf[2][1] = fabsf(B[2][1]); Bf[2][1] += reps;
Bf[2][2] = fabsf(B[2][2]); Bf[2][2] += reps;
// if any of these tests are one-sided, then the polyhedra are disjoint
r = 1;
// A1 x A2 = A0
t = fabsf(T[0]);
r &= (t <= (a[0] + b[0] * Bf[0][0] + b[1] * Bf[0][1] + b[2] * Bf[0][2]));
if (!r) return false;
// B1 x B2 = B0
s = T[0]*B[0][0] + T[1]*B[1][0] + T[2]*B[2][0];
t = fabsf(s);
r &= ( t <= (b[0] + a[0] * Bf[0][0] + a[1] * Bf[1][0] + a[2] * Bf[2][0]));
if (!r) return false;
// A2 x A0 = A1
t = fabsf(T[1]);
r &= ( t <= (a[1] + b[0] * Bf[1][0] + b[1] * Bf[1][1] + b[2] * Bf[1][2]));
if (!r) return false;
// A0 x A1 = A2
t = fabsf(T[2]);
r &= ( t <= (a[2] + b[0] * Bf[2][0] + b[1] * Bf[2][1] + b[2] * Bf[2][2]));
if (!r) return false;
// B2 x B0 = B1
s = T[0]*B[0][1] + T[1]*B[1][1] + T[2]*B[2][1];
t = fabsf(s);
r &= ( t <= (b[1] + a[0] * Bf[0][1] + a[1] * Bf[1][1] + a[2] * Bf[2][1]));
if (!r) return false;
// B0 x B1 = B2
s = T[0]*B[0][2] + T[1]*B[1][2] + T[2]*B[2][2];
t = fabsf(s);
r &= ( t <= (b[2] + a[0] * Bf[0][2] + a[1] * Bf[1][2] + a[2] * Bf[2][2]));
if (!r) return false;
// A0 x B0
s = T[2] * B[1][0] - T[1] * B[2][0];
t = fabsf(s);
r &= ( t <= (a[1] * Bf[2][0] + a[2] * Bf[1][0] + b[1] * Bf[0][2] + b[2] * Bf[0][1]));
if (!r) return false;
// A0 x B1
s = T[2] * B[1][1] - T[1] * B[2][1];
t = fabsf(s);
r &= ( t <= (a[1] * Bf[2][1] + a[2] * Bf[1][1] + b[0] * Bf[0][2] + b[2] * Bf[0][0]));
if (!r) return false;
// A0 x B2
s = T[2] * B[1][2] - T[1] * B[2][2];
t = fabsf(s);
r &= ( t <= (a[1] * Bf[2][2] + a[2] * Bf[1][2] + b[0] * Bf[0][1] + b[1] * Bf[0][0]));
if (!r) return false;
// A1 x B0
s = T[0] * B[2][0] - T[2] * B[0][0];
t = fabsf(s);
r &= ( t <= (a[0] * Bf[2][0] + a[2] * Bf[0][0] + b[1] * Bf[1][2] + b[2] * Bf[1][1]));
if (!r) return false;
// A1 x B1
s = T[0] * B[2][1] - T[2] * B[0][1];
t = fabsf(s);
r &= ( t <= (a[0] * Bf[2][1] + a[2] * Bf[0][1] + b[0] * Bf[1][2] + b[2] * Bf[1][0]));
if (!r) return false;
// A1 x B2
s = T[0] * B[2][2] - T[2] * B[0][2];
t = fabsf(s);
r &= (t <= (a[0] * Bf[2][2] + a[2] * Bf[0][2] + b[0] * Bf[1][1] + b[1] * Bf[1][0]));
if (!r) return false;
// A2 x B0
s = T[1] * B[0][0] - T[0] * B[1][0];
t = fabsf(s);
r &= (t <= (a[0] * Bf[1][0] + a[1] * Bf[0][0] + b[1] * Bf[2][2] + b[2] * Bf[2][1]));
if (!r) return false;
// A2 x B1
s = T[1] * B[0][1] - T[0] * B[1][1];
t = fabsf(s);
r &= ( t <= (a[0] * Bf[1][1] + a[1] * Bf[0][1] + b[0] * Bf[2][2] + b[2] * Bf[2][0]));
if (!r) return false;
// A2 x B2
s = T[1] * B[0][2] - T[0] * B[1][2];
t = fabsf(s);
r &= ( t <= (a[0] * Bf[1][2] + a[1] * Bf[0][2] + b[0] * Bf[2][1] + b[1] * Bf[2][0]));
if (!r) return false;
return true;
}
... {
float t, s;
int r;
float Bf[3][3];
float reps = (float) 1e-6;
const Vec3f &a = _aabb.extent;
const Vec3f &b = _obb.extent;
const Vec3f T = _obb.center - _aabb.center;
// float B[3][3];
// const Matrix3x3 &m = _obb.matrix;
// B[0][0] = m._11; B[0][1] = m._21; B[0][2] = m._31;
// B[1][0] = m._12; B[1][1] = m._22; B[1][2] = m._32;
// B[2][0] = m._13; B[2][1] = m._23; B[2][2] = m._33;
typedef float _mat3x3[3][3];
_mat3x3 B;
memcpy(B, _obb.matrix.m_, sizeof(_mat3x3));
// Bf = fabs(B)
Bf[0][0] = fabsf(B[0][0]); Bf[0][0] += reps;
Bf[0][1] = fabsf(B[0][1]); Bf[0][1] += reps;
Bf[0][2] = fabsf(B[0][2]); Bf[0][2] += reps;
Bf[1][0] = fabsf(B[1][0]); Bf[1][0] += reps;
Bf[1][1] = fabsf(B[1][1]); Bf[1][1] += reps;
Bf[1][2] = fabsf(B[1][2]); Bf[1][2] += reps;
Bf[2][0] = fabsf(B[2][0]); Bf[2][0] += reps;
Bf[2][1] = fabsf(B[2][1]); Bf[2][1] += reps;
Bf[2][2] = fabsf(B[2][2]); Bf[2][2] += reps;
// if any of these tests are one-sided, then the polyhedra are disjoint
r = 1;
// A1 x A2 = A0
t = fabsf(T[0]);
r &= (t <= (a[0] + b[0] * Bf[0][0] + b[1] * Bf[0][1] + b[2] * Bf[0][2]));
if (!r) return false;
// B1 x B2 = B0
s = T[0]*B[0][0] + T[1]*B[1][0] + T[2]*B[2][0];
t = fabsf(s);
r &= ( t <= (b[0] + a[0] * Bf[0][0] + a[1] * Bf[1][0] + a[2] * Bf[2][0]));
if (!r) return false;
// A2 x A0 = A1
t = fabsf(T[1]);
r &= ( t <= (a[1] + b[0] * Bf[1][0] + b[1] * Bf[1][1] + b[2] * Bf[1][2]));
if (!r) return false;
// A0 x A1 = A2
t = fabsf(T[2]);
r &= ( t <= (a[2] + b[0] * Bf[2][0] + b[1] * Bf[2][1] + b[2] * Bf[2][2]));
if (!r) return false;
// B2 x B0 = B1
s = T[0]*B[0][1] + T[1]*B[1][1] + T[2]*B[2][1];
t = fabsf(s);
r &= ( t <= (b[1] + a[0] * Bf[0][1] + a[1] * Bf[1][1] + a[2] * Bf[2][1]));
if (!r) return false;
// B0 x B1 = B2
s = T[0]*B[0][2] + T[1]*B[1][2] + T[2]*B[2][2];
t = fabsf(s);
r &= ( t <= (b[2] + a[0] * Bf[0][2] + a[1] * Bf[1][2] + a[2] * Bf[2][2]));
if (!r) return false;
// A0 x B0
s = T[2] * B[1][0] - T[1] * B[2][0];
t = fabsf(s);
r &= ( t <= (a[1] * Bf[2][0] + a[2] * Bf[1][0] + b[1] * Bf[0][2] + b[2] * Bf[0][1]));
if (!r) return false;
// A0 x B1
s = T[2] * B[1][1] - T[1] * B[2][1];
t = fabsf(s);
r &= ( t <= (a[1] * Bf[2][1] + a[2] * Bf[1][1] + b[0] * Bf[0][2] + b[2] * Bf[0][0]));
if (!r) return false;
// A0 x B2
s = T[2] * B[1][2] - T[1] * B[2][2];
t = fabsf(s);
r &= ( t <= (a[1] * Bf[2][2] + a[2] * Bf[1][2] + b[0] * Bf[0][1] + b[1] * Bf[0][0]));
if (!r) return false;
// A1 x B0
s = T[0] * B[2][0] - T[2] * B[0][0];
t = fabsf(s);
r &= ( t <= (a[0] * Bf[2][0] + a[2] * Bf[0][0] + b[1] * Bf[1][2] + b[2] * Bf[1][1]));
if (!r) return false;
// A1 x B1
s = T[0] * B[2][1] - T[2] * B[0][1];
t = fabsf(s);
r &= ( t <= (a[0] * Bf[2][1] + a[2] * Bf[0][1] + b[0] * Bf[1][2] + b[2] * Bf[1][0]));
if (!r) return false;
// A1 x B2
s = T[0] * B[2][2] - T[2] * B[0][2];
t = fabsf(s);
r &= (t <= (a[0] * Bf[2][2] + a[2] * Bf[0][2] + b[0] * Bf[1][1] + b[1] * Bf[1][0]));
if (!r) return false;
// A2 x B0
s = T[1] * B[0][0] - T[0] * B[1][0];
t = fabsf(s);
r &= (t <= (a[0] * Bf[1][0] + a[1] * Bf[0][0] + b[1] * Bf[2][2] + b[2] * Bf[2][1]));
if (!r) return false;
// A2 x B1
s = T[1] * B[0][1] - T[0] * B[1][1];
t = fabsf(s);
r &= ( t <= (a[0] * Bf[1][1] + a[1] * Bf[0][1] + b[0] * Bf[2][2] + b[2] * Bf[2][0]));
if (!r) return false;
// A2 x B2
s = T[1] * B[0][2] - T[0] * B[1][2];
t = fabsf(s);
r &= ( t <= (a[0] * Bf[1][2] + a[1] * Bf[0][2] + b[0] * Bf[2][1] + b[1] * Bf[2][0]));
if (!r) return false;
return true;
}