Box采用OBB定义:
enum AxisDefine{ X , Y , Z};Vector3f Center;Vector3f Axis[3];float extent[3];
Ray采用参数式Point=Origin+t∗Direction,0≤t≤∞
Vector3f Origin;Vector3f Direction;
Ray.Origin⇒O
Ray.Direction⇒Dir−→−
Box.Center⇒C
Box.Extent[i]⇒ei
Box.Axis[i]⇒Axis[i]−→−−−
采用分离轴方法来进行碰撞检测:
一:首先我们使用Box的面法线(即坐标轴)Aixs[i]−→−−−作为分离轴
在这种情况下Box在分离轴上的投影即为该轴向的边
计算光线起点在分离轴上的投影:
delta−→−−=O−C=CO−→−
ProRay=delta−→−−⋅Axis[i]−→−−−
Box在分离轴上的投影为:
−ei≤ProBox≤ei
当满足如下两种情况:
- ProRay>ei且Dir−→−⋅Axis[i]−→−−−≥0(即光线方向与分离轴的方向范围为(−90。,90。)
- ProRay<−ei且Dir−→−⋅Axis[i]−→−−−≤0
将二者结合:|ProRay|>ei and (Dir−→−⋅Axis[i]−→−−−)∗ProRay≥0
二:射线方向向量与面法线的叉乘作为分离轴
为了使得计算简单,我们可以将OBB转换为AABB
Dir−→−⇒Dir−→− ′=(Dir−→−⋅Axis[X]−→−−−−,Dir−→−⋅Axis[Y]−→−−−−,Dir−→−⋅Axis[Z]−→−−−−)
O⇒O ′=(delta−→−−⋅Axis[X]−→−−−−,delta−→−−⋅Axis[Y]−→−−−−,delta−→−−⋅Axis[Z]−→−−−−)
则Box的三个轴为:
Axis[X]−→−−−−⇒Axis[X]−→−−−− ′=(1,0,0)
Axis[Y]−→−−−−⇒Axis[Y]−→−−−− ′=(0,1,0)
Axis[Z]−→−−−−⇒Axis[Z]−→−−−− ′=(0,0,1)
则分离轴为:
v→=Dir−→− ′×Axis[i]−→−−− ′
Axis[i]−→−−− ′ | v→ | case | Axis[X]−→−−−− ′=(1,0,0) (0,Dir−→−⋅Axis[Z]−→−−−−,−Dir−→−⋅Axis[Y]−→−−−−) (1) Axis[Y]−→−−−− ′=(0,1,0) (−Dir−→−⋅Axis[Z]−→−−−−,0,Dir−→−⋅Axis[X]−→−−−−) (2) Axis[Z]−→−−−− ′=(0,0,1) (Dir−→−⋅Axis[Y]−→−−−−,−Dir−→−⋅Axis[X]−→−−−−,0) (3)Box在v→上的投影:
ProBox=e0∗|Axis[X]−→−−−− ′⋅v→|+e1∗|Axis[Y]−→−−−− ′⋅v→|+e2∗|Axis[Z]−→−−−− ′⋅v→|
v→ | ProBox | case | (0,Dir−→−⋅Axis[Z]−→−−−−,−Dir−→−⋅Axis[Y]−→−−−−) e1∗|Dir−→−⋅Axis[Z]−→−−−−+e2∗|Dir−→−⋅Axis[Y]−→−−−−| (1) (−Dir−→−⋅Axis[Z]−→−−−−,0,Dir−→−⋅Axis[X]−→−−−−) e0∗|Dir−→−⋅Axis[Z]−→−−−−|+e2∗|Dir−→−⋅Axis[X]−→−−−−| (2) (Dir−→−⋅Axis[Y]−→−−−−,−Dir−→−⋅Axis[X]−→−−−−,0) e0∗|Dir−→−⋅Axis[Y]−→−−−−|+e1∗|Dir−→−⋅Axis[X]−→−−−−| (3)Ray起点在其上的投影:
ProRay=O ′⋅v→=(delta−→−−⋅Axis[X]−→−−−−,delta−→−−⋅Axis[Y]−→−−−−,delta−→−−⋅Axis[Z]−→−−−−)⋅v→
v→与Ray.Direction垂直,因此Ray本身投影在分离轴v→为一个点
若|ProRay|>ProBox,则未碰撞
以下看看(1)情况下的v→来计算ProRay:
v→=(0,Dir−→−⋅Axis[Z]−→−−−−,−Dir−→−⋅Axis[Y]−→−−−−)
ProRay=(delta−→−−⋅Axis[X]−→−−−−,delta−→−−⋅Axis[Y]−→−−−−,delta−→−−⋅Axis[Z]−→−−−−)⋅(0,Dir−→−⋅Axis[Z]−→−−−−,−Dir−→−⋅Axis[Y]−→−−−−)
=(delta−→−−⋅Axis[Y]−→−−−−)∗(Dir−→−⋅Axis[Z]−→−−−−)−(delta−→−−⋅Axis[Z]−→−−−−)∗(Dir−→−⋅Axis[Y]−→−−−−)
=(delta−→−−.x∗Axis[Y]−→−−−−.x+delta−→−−.y∗Axis[Y]−→−−−−.y+delta−→−−.z∗Axis[Y]−→−−−−.z)∗(Dir−→−.x∗Axis[Z]−→−−−−.x+Dir−→−.y∗Axis[Z]−→−−−−.y+Dir−→−.z∗Axis[Z]−→−−−−.z)−(delta−→−−.x∗Axis[Z]−→−−−−.x+delta−→−−.y∗Axis[Z]−→−−−−.y+delta−→−−.z∗Axis[Z]−→−−−−.z)∗(Dir−→−.x∗Axis[Y]−→−−−−.x+Dir−→−.y∗Axis[Y]−→−−−−.y+Dir−→−.z∗Axis[Y]−→−−−−.z)
=(delta−→−−.z∗Dir−→−.y,delta−→−−.x∗Dir−→−.z,delta−→−−.y∗Dir−→−.x)⋅(−Axis[X]−→−−−−)+(delta−→−−.y∗Dir−→−.z,delta−→−−.z∗Dir−→−.x,delta−→−−.x∗Dir−→−.y)⋅(Axis[X]−→−−−−)
=(delta−→−−×Dir−→−)⋅Axis[X]−→−−−−
其他情况类似,因此:
v→ | ProRay | case | (0,Dir−→−⋅Axis[Z]−→−−−−,−Dir−→−⋅Axis[Y]−→−−−−) (delta−→−−×Dir−→−)⋅Axis[X]−→−−−− (1) (−Dir−→−⋅Axis[Z]−→−−−−,0,Dir−→−⋅Axis[X]−→−−−−) (delta−→−−×Dir−→−)⋅Axis[Y]−→−−−− (2) (Dir−→−⋅Axis[Y]−→−−−−,−Dir−→−⋅Axis[X]−→−−−−,0) (delta−→−−×Dir−→−)⋅Axis[Z]−→−−−− (3)