首页 > 其他分享 >判断射线和AABB(Axis-Aligned Bounding Box)是否相交

判断射线和AABB(Axis-Aligned Bounding Box)是否相交

时间:2023-02-28 21:56:59浏览次数:62  
标签:Box AABB minBound 相交 ori Bounding maxBound dir axis

已知条件

\(ori(x, y, z)\)表示射线起点坐标

\(dir(x, y, z)\)表示射线方向(单位向量)

\(Bound\)表示AABB包围盒

\(Bound.MinBound\)表示包围盒在各轴向最小坐标

\(Bound.MaxBound\)表示包围盒在各轴向最大坐标

一般平面方程为\(aX+bY+cZ+d=0\),因为AABB的六个面分别平行于\(XY\)、\(XZ\)、\(YZ\)平面,所以平面的方程为\(X=d\),\(Y=d\),\(Z=d\)

射线与平面的交点可表示为:\(P = ori + t * dir\),\(t\)为射线起点到平面的斜向距离

一、方法一: 依次判断和近面是否相交

如果射线和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

观察上图可知,光线与平面相交时\(t\)的区间会交叠,即当光线进入平面处的最大\(t\)值小于光线离开平面处的最小\(t\)值时射线和AABB会相交

步骤

  • 遍历每个轴向,记录\(tMin\)和\(tMax\)
  • 对比\(tMin\)和\(tMax\)

脚本

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;
}

参考链接

https://blog.csdn.net/u012325397/article/details/50807880

标签:Box,AABB,minBound,相交,ori,Bounding,maxBound,dir,axis
From: https://www.cnblogs.com/xiaxuexiaoab/p/17149480.html

相关文章

  • .Net之Winform桌面应用程序中Combobox三级下拉菜单连动问题的解决方案
    由于上传数据库不方便,所以,就直接使用XML文件做数据库吧。这是实现后的效果截图: 三级菜单对应的XML文件(数据库):第一级:省/直辖市,对应的XML文件:Location_Province.xml第二级:......
  • OSCP考试Hackthebox靶机推荐
    Pain:Pain是一台基于Linux的靶机,难度级别为中等,涵盖了许多常见的漏洞类型和渗透测试技术。这台靶机需要进行横向渗透,涉及到一些密码破解和提权技术。Legacy:Legacy是一......
  • Winform C# .Net中给ListBox加ToolTip提示
    1、首先,在工具箱中将ToolTip控件拖入到Winform界面下方。2、接着,在指定的ListBox添加:XXX_MouseMove事件(如已添加则忽略此步)。其中:XXX为您的控件名称。3、在该事件中添加如此......
  • 工程监测多通道振弦模拟信号采集仪VTN的AABB 通讯协议
    工程监测多通道振弦模拟信号采集仪VTN的AABB通讯协议 AABB通讯协议是一种非标准自定义协议,相较于MODBUS通讯协议,结构更简单,指令生成方法更容易,便于进行快速测试。AAB......
  • 【目标检测】重读经典之 SSD: Single Shot MultiBox Detector
    原始题目SSD:SingleShotMultiBoxDetector中文名称SSD:一阶段多框检测器发表时间2015年12月8日平台ECCV2016来源北卡罗来纳大学教堂山分校......
  • Centos 7 安装Netbox
    #####installpostgresql##############sudoyuminstall-yhttps://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.r......
  • CF436E Cardboard Box 题解
    一道经典的反悔贪心题。考虑每次选择使总星数加一,那么总共有四种情况。一、对于一关没有星,选一颗星,代价为\(a_i\)。二、对于一关有一颗星,再选一颗星,代价为\(b_i-a_i\)......
  • mapbox导出图片并下载
    //下载地图图片downLoad(){letbase64=this.getMyMap().getCanvas().toDataURL('image/png')letdate=newDate();letaLink=doc......
  • Ubuntu20.04中利用VirtualBox安装Windows虚拟机
    一、virtualbox安装sudoapt-getinstallvirtualbox二、虚拟机安装Windows系统过程略过,很简单。注意点:1.在Ubuntu中利用虚拟机安装Windows系统,创建时默认不会让你选......
  • Vulnhub之Fivebox 2靶机测试过程(部分)
    Fivebox2识别目标主机IP地址(kali㉿kali)-[~/Desktop/Vulnhub/Fivebox_2]└─$sudonetdiscover-ieth1-r192.168.56.0/24Currentlyscanning:192.168.56.0/24......