射线与AABB型包围盒相交算法

2023-11-08

基础知识:

AABB包围盒,也叫轴对称包围盒,意思就是它的六个面总是分别平行XYZ三个轴的

相交计算原理:

计算射线与包围盒每个面的平面的交点,计算这个点是否在包围盒面的范围,在就是相交,不在就是没有相交

图解:

用个2D图形简单讲解一下
在这里插入图片描述

首先从图中可以看到射线Ray和红色的包围盒相交了,但是怎么计算出来(毕竟在3D世界中,不可能全靠眼睛去看…)

这个包围盒有4个面,2个平行于Y轴,2个平行于X轴,有两个关键点,最小点min和最大点max(即xy值最小和最大,有正负)

下面是伪代码

//首先是看射线Ray,这条射线的原点是origin,方向是direction,
Ray ray;
if(ray.origin.x < min.x)//原点的X小于min的X,那么测试射线与垂直于X轴的面的相交点。
{
    //假设射线的X方向到达min平面的时间为t
   float t   =   (min.x - _origin.x) / _direction.x;
    //那么可以计算出射线与平面的交点为hitPoint1
    Point hitPoint1 = ray.origin + ray.direction * t;
    if(hitPoint1.y> min.y && hitPoint.y < max.y)//比较,是不是在包围盒的面内
    {
        return true;
    }
}
if(ray.origin.y < min.y)//原点的y小于min的y,那么测试射线与垂直于Y轴的面的相交点。
{
   //假设射线的Y方向到达min平面的时间为t
   float t   =   (min.y - _origin.y) / _direction.y;
   //那么可以计算出射线与平面的交点为hitPoint2
   Point hitPoint1 = ray.origin + ray.direction * t;
    if(hitPoint1.x> min.x && hitPoint.x < max.x)//比较,是不是在包围盒的面内
    {
        return true;
    }
}

三维空间里也是同样的道理。

下面是OpenGLES三维空间射线与AABB盒相交的计算源码

 /**
        *   测试射线box相交
        *   如果相交,返回值中的first == true.否则false
        *   second为射线到点的距离
        *   调用getPoint方法,则返回交点
        */
	    std::pair<bool, T> intersects(const AxisAlignedBox<T>& box) const
        {
            T           lowt    = 0.0f;
            T           t;
            bool        hit     = false;
            tvec3<T>    hitpoint;
            tvec3<T>    min      =   box.getMinimum();
            tvec3<T>    max      =   box.getMaximum();

            /**
            *   点在包围盒里面
            */
            if ( _origin > min && _origin < max )
            {
                return std::pair<bool, T>(true, 0);
            }

            // Check each face in turn, only check closest 3
            // Min x
            if (_origin.x <= min.x && _direction.x > 0)
            {
                t   =   (min.x - _origin.x) / _direction.x;
                if (t >= 0)
                {
                    // Substitute t back into ray and check bounds and dist
                    hitpoint = _origin + _direction * t;
                    if (hitpoint.y >= min.y && 
                        hitpoint.y <= max.y &&
                        hitpoint.z >= min.z && 
                        hitpoint.z <= max.z &&
                        (!hit || t < lowt))
                    {
                        hit     =   true;
                        lowt    =   t;
                    }
                }
            }
            // Max x
            if (_origin.x >= max.x && _direction.x < 0)
            {
                t   =   (max.x - _origin.x) / _direction.x;
                if (t >= 0)
                {
                    // Substitute t back into ray and check bounds and dist
                    hitpoint = _origin + _direction * t;
                    if (hitpoint.y >= min.y && 
                        hitpoint.y <= max.y &&
                        hitpoint.z >= min.z &&
                        hitpoint.z <= max.z &&
                        (!hit || t < lowt))
                    {
                        hit     =   true;
                        lowt    =   t;
                    }
                }
            }
            // Min y
            if (_origin.y <= min.y && _direction.y > 0)
            {
                t   =   (min.y - _origin.y) / _direction.y;
                if (t >= 0)
                {
                    // Substitute t back into ray and check bounds and dist
                    hitpoint = _origin + _direction * t;
                    if (hitpoint.x >= min.x && 
                        hitpoint.x <= max.x &&
                        hitpoint.z >= min.z && 
                        hitpoint.z <= max.z &&
                        (!hit || t < lowt))
                    {
                        hit     =   true;
                        lowt    =   t;
                    }
                }
            }
            // Max y
            if (_origin.y >= max.y && _direction.y < 0)
            {
                t   =   (max.y - _origin.y) / _direction.y;
                if (t >= 0)
                {
                    // Substitute t back into ray and check bounds and dist
                    hitpoint = _origin + _direction * t;
                    if (hitpoint.x >= min.x &&
                        hitpoint.x <= max.x &&
                        hitpoint.z >= min.z &&
                        hitpoint.z <= max.z &&
                        (!hit || t < lowt))
                    {
                        hit     =   true;
                        lowt    =   t;
                    }
                }
            }
            // Min z
            if (_origin.z <= min.z && _direction.z > 0)
            {
                t   =   (min.z - _origin.z) / _direction.z;
                if (t >= 0)
                {
                    // Substitute t back into ray and check bounds and dist
                    hitpoint = _origin + _direction * t;
                    if (hitpoint.x >= min.x && 
                        hitpoint.x <= max.x &&
                        hitpoint.y >= min.y &&
                        hitpoint.y <= max.y &&
                        (!hit || t < lowt))
                    {
                        hit     =   true;
                        lowt    =   t;
                    }
                }
            }
            // Max z
            if (_origin.z >= max.z && _direction.z < 0)
            {
                t   =   (max.z - _origin.z) / _direction.z;
                if (t >= 0)
                {
                    // Substitute t back into ray and check bounds and dist
                    hitpoint = _origin + _direction * t;
                    if (hitpoint.x >= min.x && 
                        hitpoint.x <= max.x &&
                        hitpoint.y >= min.y && 
                        hitpoint.y <= max.y &&
                        (!hit || t < lowt))
                    {
                        hit     =   true;
                        lowt    =   t;
                    }
                }
            }
            return std::pair<bool, T>(hit, lowt);
        }
    };
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

射线与AABB型包围盒相交算法 的相关文章

  • 纹理的内部格式

    看下面的OpenGL函数 void glTexImage2D GLenum target GLint level GLint internalFormat GLsizei width GLsizei height GLint border
  • 如何从横滚、俯仰和偏航获取相机向上矢量?

    我需要从滚动角 俯仰角和偏航角 以度为单位 获取相机的向上矢量 以获得正确的外观 我已经尝试了几个小时不同的事情 但没有运气 这里的任何帮助将不胜感激 横滚 俯仰和偏航定义 3 轴旋转 从这些角度 您可以构建一个 3x3 变换矩阵来表达该旋
  • 在 Ubuntu 中与未编译的着色器链接

    我需要加载 glsl 来绘制一些东西 我的环境是Ubuntu 13 04 因此它不存在GLuint InitShader GLuint GLuint 这是我的对象创建 预链接步骤和链接的配置 不幸的是 它仍然出现错误 该错误与未编译的着色器
  • glColor4f() - alpha 值的效果

    我正在使用 glColor4f 令人惊讶的是 更改 alpha 即第四个参数 不会导致透明度发生任何变化 代码段是 const GLfloat squareVertices 0 5 0 5 0 0 0 5 0 5 0 0 0 5 0 5 0
  • 在 OpenGL 中使用不同的着色器程序?

    我必须在 OpenGL 中针对不同的对象使用两个不同的着色器程序 我发现我必须使用glUseProgram 在不同的着色器程序之间切换 但对此没有太多信息 鉴于我有两个用于不同对象的不同着色器程序 如何为每个着色器程序生成和绑定 VAO 和
  • 使用 glGetFloatv 检索 pyglet 中的模型视图矩阵

    我正在使用 pyglet 在 python 中进行 3D 可视化 并且需要检索模型视图和投影矩阵来进行一些选择 我使用以下方式定义我的窗口 from pyglet gl import from pyglet window import wi
  • OpenGL:VAO 和 VBO 对于大型多边形渲染任务是否实用?

    如果您想渲染一次在视锥体中包含数千个多边形的大型景观 并且用户的视点不断变化 那么使用 VAO 或 VBO 是否实用 我的意思是 每次玩家的位置或摄像机旋转发生变化时 您都必须重新计算顶点数据 以便正确剔除不再可见的任何顶点或场景 以保持良
  • glm 中矩阵值的顺序不正确?

    我开始使用GLM http glm g truc net通过 OpenGL 3 和 GLSL 进行数学运算的库 我需要正交投影来绘制 2D 图形 所以我编写了这个简单的代码 glm mat4 projection 1 0 projectio
  • GL_COLOR_ATTACHMENT 有什么作用?

    我现在正在学习帧缓冲区 但我只是不明白颜色附件的作用 我了解帧缓冲区 第二个参数的意义是什么 glFramebufferTexture2D GL FRAMEBUFFER GL COLOR ATTACHMENT0 GL TEXTURE 2D
  • 为什么我的 CAOpenGLLayer 更新速度比之前的 NSOpenGLView 慢?

    我有一个在 Mac OS X 上渲染 OpenGL 内容的应用程序 最初它渲染到 NSOpenGLView 然后我将其更改为渲染到 CAOpenGLLayer 子类 当我这样做时 我看到了巨大的性能损失 帧速率减半 鼠标响应能力降低 卡顿
  • OpenGL什么时候完成函数中指针的处理?

    OpenGL有多项功能 http www opengl org wiki GLAPI glTexSubImage2D直接获取指针 他们中有一些从这些指针读取数据 http www opengl org wiki GLAPI glBuffer
  • 延迟阴影映射 GLSL

    我目前正在实施延迟渲染管道 但我仍坚持使用阴影贴图 我已经成功地将其实施到前向管道中 我所做的步骤是 获取灯光视图中的位置 转换为光视图剪辑空间 使用 0 5 0 5 获取阴影纹理坐标 检查深度 编辑 使用新结果图像更新代码 float c
  • 渲染缓冲区大于窗口大小 - OpenGL

    我正在尝试绘制大于屏幕尺寸 即 320x480 的渲染缓冲区 512x512 执行 glReadPixels 后 图像看起来是正确的 除非图像的尺寸超过了屏幕尺寸 在本例中 超过了水平 320 和垂直 480 是什么原因导致这种异常现象呢
  • OpenGL - 自动生成 glDrawArrays 的索引/步幅参数

    我正在渲染一个包含大量数据点 gt 1M 的网格结构 我的数据结构如图所示 所以我的索引缓冲区的内容看起来像这样0 100 1 101 2 102 3 103 我对索引缓冲区的巨大尺寸有点恼火 我需要它来定义我的三角形带 是否有可能告诉 O
  • 为什么 cudaGLSetGLDevice 失败,即使它是在 main 函数的第一行中调用的

    我想使用 OpenGL 和 CUDA 之间的互操作性 我知道 正如一些教程所说 第一步是选择设备 但是 当我在主函数的第一行中调用 cudaGLSetGLDevice 0 时 程序退出并显示信息 cudaSafeCall 运行时 API 错
  • 为贝塞尔曲线中的每个点绘制切线

    我设法绘制了一条贝塞尔曲线 如下所示 glColor3f 0 1 0 glBegin GL LINE STRIP for int i 3 i lt nPt i 3 glColor3f 0 0 0 for float k 0 k lt NLI
  • nVidia 和 ATI 之间的 OpenGL 渲染差异

    最近 我将 ATI 驱动程序 我使用的是 HD7970 更新为最新版本 但我的 OpenGL 项目的一些对象停止工作 更重要的是 他们适用于 nVidia 最新驱动程序 在 960m 上测试 ATI 和 nVidia 渲染管道之间有什么我应
  • OpenGL/GLSL - 纹理过滤的实现

    我想在 GLSL 着色器中自己实现纹理过滤 min 和 magfilter 因为我想使用 image load and store 而不是采样器 而且我想以特殊方式处理未定义的像素 并且我正在寻找一篇文章或者这样讨论过滤过程 我记得如何从我
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲

随机推荐

  • VS调试时显示FbxString内容

    在使用FBX SDK时 在VS里到了断点处 总是无法查看FBXString的字符串内容 在Watch里显示的也是一堆地址 以至于每次都得写下const char temp fbxString gt Buffer 今天竟然无意间发现在SDK根
  • ESP8266退出上电透传模式

    AT SAVETRANSLINK 1 192 168 6 110 1002 TCP 通过类似指令将TCP连接的信息写入到esp8266的Flash中去 并开启开机透传模式 及一开机就进入透传模式 此时的AT指令无效 要想重新使得AT指令有效
  • 由对称性知定点一定在x轴上_圆锥曲线解答题的经典答案:由椭圆的对称性知,定点在x轴上?...

    有很多圆锥曲线综合题要研究定点问题 答案里往往有这样一句话 由椭圆的对称性知 定点必在x轴上 或者说一句 显然定点在y轴上 看得童鞋们丈二和尚摸不着头脑 1 读者提问 一位来自广东 昵称为 h 的高三学生这样提问 左老师好 请教一个定点问题
  • 什么是AppImage

    A 什么是AppImage 在linux系统中使用AppImage 多年以来 我们一直使用 DEB packages 来管理 Debian Ubuntu的软件包 使用 RPM 管理 Fedora SUSE 的软件包 用户使用这些包管理工具可
  • 华为数字化转型之道认知篇第一章数字化转型,华为的战略选择

    第一章 数字化转型 华为的战略选择 农业经济以土地为生产资料 工业经济以石油和各类矿产为生产资料 数字经济则以数据为生产资料 数字化转型以ICT平台为生产工具 以数据为生产资料 以服务为产品 不仅能为企业的传统业务赋予新动能 也能为企业带来
  • jq匹配偶数行_jQuery中两种奇偶选择器的区别

    原标题 jQuery中两种奇偶选择器的区别 jQuery中的选择器在选择元素的时候经常用到 今天主要介绍jQuery中的奇偶选择器 jquery中的奇偶选择器要用到CSS3伪类选择器 nth child nth child 的用法 直接匹配
  • 为云服务器添加python web环境

    为云服务器添加python web环境 自用不喜勿喷 当前配置 阿里云win10云服务器 anaconda配置的python环境 操作步骤 1 参照教程配置python及Django 2 pyCharm如何运行Django https ww
  • vue标签属性及其用法

    一 Vue的特点 1 采用组件化模式 提高代码的复用率 且让代码更好维护 2 声明编码 让编码人员无需直接操作DOM 提高开发效率 3 使用学你DOM 优秀的Diff算法 尽量服用DOM节点 二 Vue模板语法有两大类 1 插值语法 功能
  • Springboot修改内置Tomcat版本

    背景 Tomcat的安全漏洞需要升级版本进行解决 如 9 0 63 gt 9 0 75 1 Pom文件Springboot的依赖配置项 2 Ctrl 右键点击红色框选 3 全局搜索 修改 修改数值 启动测试
  • C++实现——string的所有操作

    C 中string的操作 Constructors 构造函数 用于字符串初始化 Operators 操作符 用于字符串比较和赋值 append 在字符串的末尾添加文本 assign 为字符串赋新值 at 按给定索引值返回字符 begin 返
  • 基于python实现的CS通信和P2P通信

    实验要求 C S通信实现要求 两台计算机分别模拟服务器 客户端 通过编程实现服务器端 客户端程序Socket Client 服务器端程序监听客户端向服务器端发出的请求 并返回数据给客户端 不采用方式 自定义通信协议 传输文件要足够大 例如
  • Python GUI: PyCahrm结合Pyqt5开发图形化界面 详细步骤 踩坑!

    1 下载安装pythonPython官网下载地址 注意 1 1 Python版本选择并不是越新越好 后面会提到 我安装的版本是 V3 5 4 64位 1 2 安装的时候一定要勾选pip和add python to path 自动添加到环境变
  • 清华大佬耗时36个小时,终于整理出来了一份Python自学计划,学不会退出IT界

    在人工智能的风口 Python这门胶水语言越来越火 很多小伙伴也开始学习Python 但是没有一份合适的学习规划怎么能行 今天特意为大家整理了一份Python自学计划 希望可以帮助到处在迷茫期的你们 文末获取o 这份自学计划是我精心整理的
  • React+AntDesign开发完整的考勤系统前端页面(一)

    一 项目准备工作 1 开发环境准备 准备好Visual Studio Code前端开发工具 下载并安装Node js 2 项目准备 本次项目使用umi脚手架的方式创建 1 打开开发工具打开项目文件夹并新建终端在终端里面输入命令 npm i
  • 【概率论与数理统计】猴博士 笔记 p17-20 一、二维连续型:已知F,求f;已知f,求f

    一维连续型已知F 求f 题型 步骤 f是F的导数 对F求导即可得到f 例1 解 例2 解 一维连续型已知f 求f 题型 已知f x 求f y 步骤 注意 要满足要求 Y g X 满足单增或单减才能用公式法 看起来有点抽象 我们看一道例题 此
  • GAMES101 作业3(附三角形重心坐标,Blinn-Phong光照模型及法线贴图推导)

    目录 写在前面 第一题 三角形重心坐标 第二题 Blinn Phong光照模型 第三题 纹理贴图 第四题 凹凸贴图实现及法线贴图推导 第五题 位移贴图 写在前面 main 函数中 std function
  • FedDG: Federated Domain Generalization on Medical Image Segmentation via Episodic Learning

    FedDG Federated Domain Generalization on Medical Image Segmentation via Episodic Learning in Continuous Frequency Space
  • 数据库锁表的查询和处理

    如果遇到数据库锁表 通常需要用如下方法处理 查看表的partnum情况 oncheck pt shjz mzb baf01 grep i partnum 这个里面包含了多个分区的partnum 也包含了索引的partnum Partitio
  • Windows安装和配置VCenter

    Vcenter的环境搭建和配置 Vcenter简介 Vcenter一般指 VMware vCenter Server VMware vCenterServer 提供了一个可伸缩 可扩展的平台 为 虚拟化管理奠定了基础 VMware vCen
  • 射线与AABB型包围盒相交算法

    基础知识 AABB包围盒 也叫轴对称包围盒 意思就是它的六个面总是分别平行XYZ三个轴的 相交计算原理 计算射线与包围盒每个面的平面的交点 计算这个点是否在包围盒面的范围 在就是相交 不在就是没有相交 图解 用个2D图形简单讲解一下 首先从