射线与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型包围盒相交算法 的相关文章

  • 模拟绘画应用的笔触

    我正在尝试编写一个应用程序 可用于使用模拟笔触创建看起来像绘画的图片 是否有任何好的资源可以提供模拟笔触的简单方法 例如 给定用户拖动鼠标经过的鼠标位置列表 画笔宽度和画笔纹理 如何确定要在画布上绘制的内容 我尝试将画笔纹理倾斜到鼠标移动的
  • LWJGL 窗口具有透明背景?

    我想创建一个没有 黑色背景 区域的窗口 但您可以看到任何其他打开的窗口等 也就是说 渲染场景并且仅渲染场景 不留框架 不留背景区域 我读过一种方法 该方法涉及渲染到隐藏的 OpenGL 窗口并将其缓冲在内存中 创建透明分层窗口以及从内存复制
  • 3D 图形矩阵 4x4 中最后一行的 magic 4 的用途是什么?

    当我阅读有关WebGL的书时 我看到了下一个矩阵描述 有关于书中最后一行的信息 WebGL 初学者指南 初学者指南 Diego Cantor Brandon Jones 神秘的第四排 第四排没有任何特殊之处 意义 元素 m4 m8 m12
  • OpenGL 超级采样抗锯齿?

    在办公室 我们正在使用旧的 GLX Motif 软件 该软件使用 OpenGL 的 AccumulationBuffer 来实现保存图像的抗锯齿功能 我们的问题是Apple从其所有驱动程序中删除了AccumulationBuffer 从OS
  • 静态链接库时出现 glew 链接器错误

    我正在尝试在 Visual Studio 2012 中构建一个 opengl 项目 我想静态包含 glew 库 因此我从源代码构建它并将生成的 glew32sd lib 复制到我的 lib 目录 我将此 lib 路径提供给 Visual S
  • 从文件中读取 GLSL 着色器

    我正在尝试从如下所示的文件中读取顶点和片段着色器 version 330 core in vec3 ourColor out vec4 color void main color vec4 ourColor 1 0f but when i
  • OpenGL NURBS 曲面

    我正在学习 OpenGL 我想要一个中间有轻微驼峰的表面 我目前正在使用这段代码 但我不确定如何调整 ctrl 点以使其达到我想要的方式 它目前就像 我想要这样的 我不完全确定我应该使用哪些控制点 并且我对其工作原理感到困惑 include
  • (定义一个宏)方便OpenGL命令调试?

    有时插入条件打印和检查需要很长时间glGetError 使用二分搜索的形式来缩小范围 其中第一个函数调用是 OpenGL 首先报告错误 我认为如果有一种方法可以构建一个宏 我可以包装所有可能失败的 GL 调用 并有条件地调用 那就太酷了gl
  • QOpenGLFunctions 缺少重要的 OpenGL 函数

    QOpenGLFunctions 似乎缺少重要的函数 例如 glInvalidateFramebuffer 和 glMapBuffer 据我了解 QOpenGLFunctions 加载桌面 OpenGL 函数和 ES 函数的交集 如果是这样
  • 使用 Qt 在 xoverlay 之上绘制

    我希望在使用 Xoverlay 渲染的视频流之上绘制一些 UI 我正在使用 gstreamer 播放视频并使用 xoverlay 在 xvimagesink 上渲染它 我的小部件继承自 QGLWidget 我希望使用 QPainter 绘制
  • 使用 glDrawElements 时在 OpenGL 核心配置文件中选取三角形

    我正在使用 glDrawElements 绘制三角形网格 并且希望能够使用鼠标单击来拾取 选择三角形 三角形的网格可以很大 在固定功能 OpenGL 中 可以使用 GL SELECT http content gpwiki org inde
  • OpenGL 着色器不与着色器程序链接

    我正在尝试使用 GLFW GLEW 添加着色器 我收到一个错误 指出着色器已加载 但它们没有有效的对象代码 这是我用于加载着色器的代码 class SHADER public void LoadShaders const char vert
  • lwjgl 3 , glUniformMatrix4 导致 jre 崩溃

    我正在使用 lwjgl 3 并学习现代 opengl 3 我想将统一矩阵发送到顶点着色器 以便我可以应用转换 我尝试过 但程序因此错误而崩溃 A fatal error has been detected by the Java Runti
  • 使用 GLSL 着色器在同一片段着色器中定义的多个子例程类型无法正常工作

    我正在开发一个使用 GLSL 着色器的程序 我编写了 2 种不同的方法来用 2 种不同的方法计算 ADS 环境光 漫反射 镜面反射 着色 为了正确完成这项工作 我使用子例程来使用一种或另一种方法来计算 ADS 着色 这是片段着色器代码的一部
  • Eclipse 标记 OpenGL 函数无法解析

    我尝试在 Eclipse C C 中使用一些 OpenGL 函数 一些 标准 函数如 GlClear 可以被 eclipse 识别 而其他函数如 glBindBuffer 和 glEnableVertexAttribArray 则不能 它们
  • glBlitFramebuffer 渲染缓冲区和渲染全屏纹理哪个更快?

    哪个更快更高效 使用 OpenGL 纹理作为 CUDA 表面并在四边形上渲染 新样式 使用渲染缓冲区作为 CUDA 表面并使用 glBlitFramebuffer 进行渲染 None
  • glut 库中缺少 glutInitContextVersion()

    我正在练习一些 opengl 代码 但是当我想通过以下方式强制 opengl 上下文使用特定版本的 opengl 时glutInitContextVersion 它编译过程失败并给出以下消息 使用未声明的标识符 glutInitContex
  • 当 OpenGL 中同时绑定 1D 和 2D 纹理时,正确的行为是什么?

    假设你有这样的东西 glBindTexture GL TEXTURE 2D my2dTex glBindTexture GL TEXTURE 1D my1dTex glBegin 正确的 OpenGL 行为是什么 要绘制一维纹理 二维纹理还
  • 无法在 WSL2 上运行 OpenGL

    我尝试在 WSL2 上运行 OpenGL 代码 但在尝试运行可执行文件时出现以下错误 GLFW error 65543 GLX Failed to create context GLXBadFBConfig Unable to create
  • OpenGL缓冲区更新[重复]

    这个问题在这里已经有答案了 目前我正在编写一个模拟水的程序 以下是我所做的步骤 创建水面 平面 创建VAO 创建顶点缓冲区对象 在其中存储法线和顶点 将指针绑定到此 VBO 创建索引缓冲区对象 然后我使用 glDrawElements 渲染

随机推荐

  • 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图形简单讲解一下 首先从