判断射线和AABB(Axis-Aligned Bounding Box)是否相交
已知条件
表示射线起点坐标
表示射线方向(单位向量)
表示AABB包围盒
表示包围盒在各轴向最小坐标
表示包围盒在各轴向最大坐标
一般平面方程为,因为AABB的六个面分别平行于、、平面,所以平面的方程为,,
射线与平面的交点可表示为:,为射线起点到平面的斜向距离
一、方法一: 依次判断和近面是否相交
如果射线和AABB相交,则射线必定先和三个近面中的一个相交,所以依次判断是否相交即可
步骤
- 判断起点是否在内部,如果在内部则必相交,否则
- 遍历每个轴向,求出和近面的交点
- 判断交点是否在包围盒内部
脚本
// dir为单位向量
bool IntersectRayAndAABB(const Bound& bound, const Point3& ori, const Point3& dir)
{
Point3 minBound = bound.GetMinBound(), maxBound = bound.GetMaxBound();
// 首先判断是否在内部,内部一定相交
if(ori.x > minBound.x && ori.x < maxBound.x &&
ori.y > minBound.y && ori.y < maxBound.y &&
ori.z > minBound.z && ori.z < maxBound.z)
{
return true;
}
// 分别判断射线和各轴近面的相交情况
for (int axis = 0; axis < 3; axis++) {
double t = 0.0;
if(std::abs(dir[axis]) > std::numeric_limits<double>::epsilon()){
if(dir[axis] > 0){
t = (minBound[axis] - origin[axis]) / dir[axis];
}
else{
t = (maxBound[axis] - origin[axis]) / dir[axis];
}
}
if(t > 0){ // 射线和平面相交
// 判断交点是否在面内
const Point3 pt = ori + t * dir;
if(minBound[(axis + 1) % 3] < pt[(axis + 1) % 3] && pt[(axis + 1) % 3] < maxBound[(axis + 1) % 3] &&
minBound[(axis + 2) % 3] < pt[(axis + 2) % 3] && pt[(axis + 2) % 3] < maxBound[(axis + 2) % 3])
{
return true
}
}
}
return false;
}
二、方法二:slabs
观察上图可知,光线与平面相交时的区间会交叠,即当光线进入平面处的最大值小于光线离开平面处的最小值时射线和AABB会相交。
步骤
- 遍历每个轴向,记录和
- 对比和
脚本
bool IntersectRayAndAABB(const Bound& bound, const Point3& ori, const Point3& dir)
{
double tMin = 0; // tMin设为0,可以有效过滤掉内部情况
double tMax = std::numeric_limits<double>::max();
Point3 minBound = bound.GetMinBound(), maxBound = bound.GetMaxBound();
for (int axis = 0; axis < 3; axis++) {
if (std::abs(dir[axis]) < std::numeric_limits<double>::epsilon()) { // 射线方向与某个轴向平行
if (ori[axis] > maxBound[axis] || ori[axis] < minBound[axis]){ // 起点同时在Bound于该轴的两侧,则不相交
return false;
}
continue;
}
double invD = 1 / dir[axis];
double tNear = invD * (minBound[axis] - ori[axis]); // 计算射线起点到平面的斜向距离
double tFar = invD * (maxBound[axis] - ori[axis]);
if (tNear > tFar) {
std::swap(tNear, tFar);
}
if (tNear > tMin) {
tMin = tNear;
}
if (tFar < tMax) {
tMax = tFar;
}
if (tMin > tMax) {
return false;
}
}
return true;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端