射线和立方体相交的判断

本文主要介绍如何判定一条线和一个立方体相交
1、Slabs的使用(2D的介绍)
2、将Slabs推广到3D
其中只介绍数学相关,代码实现可自行实现
检测物体碰撞的时候,我们通常在物体表面添加包围盒,其中常用的包围盒有如下三种,其中Slabs主要适用于AABB包围盒
OBB比包围球和AABB更加逼近物体,能显著减少包围体的个数。因此,人们通常进行两个回合的碰撞/相交检测,用包围球做第一回合的快速测试,用OBB进行第二回合的测试。第一回合的测试可以剔除大多数不可见或不必裁剪的物体,这样不必进行第二回合测试的几率就会大得多。

在这里插入图片描述

1、Slabs的使用(2D的介绍)

如果一条射线与有长方形构成的AABB区域相交,则该射线在x-slab和y-slab之间的线段有相交,如下图所示:
在这里插入图片描述
定义四个点,分别叫做 xnear,xfar,ynear,yfar,分别对应射线与长方形两条横线的两个交点,射线与长方形两条竖线的两个交点,如图所示

我们假设射线为 L ( t ) = t d ⃗ + P L(t) =t\vec{d}+P L(t)=td +P,其中P为射线起点, d ⃗ \vec{d} d 为射线的方向,那么此时,上述四个点可以表示为

t x n e a r d ⃗ + P , t x f a r d ⃗ + P , t y n e a r d ⃗ + P , t y f a r d ⃗ + P t_{xnear}\vec{d}+P,t_{xfar}\vec{d}+P,t_{ynear}\vec{d}+P,t_{yfar}\vec{d}+P txneard +Ptxfard +Ptyneard +Ptyfard +P

如果 m a x ( t x n e a r , t y n e a r ) ≤ m i n ( t x f a r , t y f a r ) max(t_{xnear},t_{ynear})≤min(t_{xfar},t_{yfar}) max(txnear,tynear)min(txfar,tyfar),则射线与长方形相交

2、将Slabs推广到3D

3D的Slabs同2D,3D空间中判断射线是否与长方体构成的AABB包围盒相交的方法是,判断该射线在

x-slab,y-slab,z-slab之间的部分是否有公共区域。

我们假设射线为 L ( t ) = t D ⃗ + P L(t) =t\vec{D}+P L(t)=tD +P,其中P为射线起点, d ⃗ \vec{d} d 为射线的方向,我们假设平面方程为

X n ⃗ = d X\vec{n}=d Xn =d,这是点法式,X为平面上的点, n ⃗ \vec{n} n 为平面法向量,d为原点到平面的有向距离。

我们将射线带入平面可得到

( t D ⃗ + P ) n ⃗ = d , 即 t = d − P n ⃗ n ⃗ D ⃗ (t\vec{D}+P)\vec{n}=d,即 t=\frac{d-P\vec{n}}{\vec{n}\vec{D}} (tD +P)n =dt=n D dPn ,设P(px,py,pz),

D(Dx,Dy,Dz),在使用slabs的时候有两个分量为0,因此我们可以求得如下几个t值

x-slab: t x = ( d − p x ) / D x t_x=(d-p_x)/D_x tx=(dpx)/Dx

y-slab: t y = ( d − p y ) / D y t_y=(d-p_y)/D_y ty=(dpy)/Dy

z-slab: t z = ( d − p z ) / D z t_z=(d-p_z)/D_z tz=(dpz)/Dz

接下去我们同样求解出 xnear,xfar,ynear,yfar,znear,zfar

此时,如果 m a x ( t x n e a r , t y n e a r , t z n e a r ) ≤ m i n ( t x f a r , t y f a r , t z f a r ) max(t_{xnear},t_{ynear},t_{znear})≤min(t_{xfar},t_{yfar},t_{zfar}) max(txnear,tynear,tznear)min(txfar,tyfar,tzfar),则射线与长方体相交

vec2 intersectBox(const Ray& ray, const Box& cube)
{
 vec3 inv_dir = 1.0f / ray.direction;
 vec3 tMin = (cube.min - ray.origin) * inv_dir;
 vec3 tMax = (cube.max - ray.origin) * inv_dir;
 vec3 t1 = min(tMin, tMax);
 vec3 t2 = max(tMin, tMax);
 float tNear = max(max(t1.x, t1.y), t1.z);
 float tFar = min(min(t2.x, t2.y), t2.z);

 return vec2(tNear, tFar);
}

如果返回值tNear > tFar则不相交,否则射线与AABB包围盒相交。

参考文章

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值