快速相交检测:平面与包围盒

2024-06-16 22:08

本文主要是介绍快速相交检测:平面与包围盒,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

快速相交检测:平面与包围盒

  • 1.前言
  • 2.数学背景
  • 3.计算原理
  • 4.代码

1.前言

   在游戏等实时性要求高的三维程序中,相交检测是一项及其基础又重要的技术,大佬们相继提出各种检测技术。
  当然大多数人的实现方式可能 (确信)是将包围盒的8个点分别带入平面检测,这将要做8组点积。
  今天我来介绍其中一项比较快速的检测方法,在略去相交和内部的判断后可以直接降到四次点积,当然如果使用的是AABB则会变成一次点积,目前我是按照OBB的方式来算的。

2.数学背景

平面方程形式: A x + B y + C z + D = 0 Ax+By+Cz+D =0 Ax+By+Cz+D=0
对于坐标 P ( x 0 , y 0 , z 0 ) P(x_0,y_0,z_0) P(x0,y0,z0)
检验其是否在平面内,可以直接带入平面方程
A x 0 + B y 0 + C z 0 + D Ax_0+By_0+Cz_0+D Ax0+By0+Cz0+D

  • 若结果>0,则在平面外部。
  • 若结果=0,则在正好在平面上。
  • 若结果<0,则在平面内部。

什么?你问我平面还分内外?
这个我也无法解释,毕竟我只是一只鸽子
目前我个人来说,习惯性将平面法向量指向的那一侧称呼为外部,法向量负方向一侧称为内部

3.计算原理

   最重要的步骤是找到包围盒的n顶点和p顶点。
在这里插入图片描述

  • 如果n顶点位于平面外部,则直接返回包围盒在平面外。
  • 如果n顶点位于平面内部,p顶点位于平面外部,返回包围盒与平面相交。
  • 如果n顶点位于平面内部,p顶点位于平面内部,返回包围盒在平面内。

那么n、p顶点如何寻找呢,通过将平面法向量与包围盒的轴方向进行点积,判断点积结果的正负来寻找。

4.代码

ok,按照惯例先放出结果图

  • 0代表在外部
  • 1代表相交
  • -1代表在内部

测试用例包围盒为在点(0,0,0),长为(1,1,1),第一个轴方向为(1,0,0),第二个轴方向为(0,1,0),第二个轴方向为(0,0,1),对就是xyz轴方向
第一个是在点(2,2,2),法向量为(-1,-1,-1)的平面测试
第二个是在点(0.5,0.5,0.5),法向量为(-1,-1,-1)的平面测试
第三个是在点(-2,-2,-2),法向量为(-1,-1,-1)的平面测试
在这里插入图片描述

#include "pch.h"#include <iostream>using namespace std;class vec3
{
public:float x, y, z;
};
class box
{
public:box(vec3 dx,vec3 dy,vec3 dz,vec3 l,vec3 o):dX(dx),dY(dy),dZ(dz),len(l),origin(o){}vec3 dX, dY, dZ;vec3 len;vec3 origin;};float dot(vec3 a, vec3 b)
{return (a.x * b.x + a.y * b.y + a.z * b.z);
}class plane
{
public:plane(vec3 v,vec3 n){a = n.x;b = n.y;c = n.z;d = -(dot(v,n));}public:float check(vec3 x){return (x.x * a + x.y * b + x.z * c + d);}
public:union {struct{float a, b, c;};vec3 n;};float d;};vec3 operator+ (vec3 const& _Left, vec3 const& _Right) noexcept
{return (vec3{ _Left.x + _Right.x , _Left.y + _Right.y , _Left.z + _Right.z });
}vec3 operator* (float _Left, vec3 const& _Right) noexcept
{return (vec3{ _Left* _Right.x , _Left* _Right.y , _Left* _Right.z });
}int check(box _box,plane _plane)
{auto res1 = dot(_plane.n,_box.dX);auto res2 = dot(_plane.n, _box.dY);auto res3 = dot(_plane.n, _box.dZ);char mask_n = 0 | (res1 >= 0 ? 0 : 1) | (res2 >= 0 ? 0 : 2) | (res3 >= 0 ? 0 : 4);vec3 _n = _box.origin;if (mask_n & 1){_n = _n + (_box.len.x * _box.dX);}if (mask_n & 2){_n = _n + (_box.len.y * _box.dY);}if (mask_n & 4){_n = _n + (_box.len.z * _box.dZ);}if (_plane.check(_n) < 0.0){char mask_p = ~mask_n;vec3 _p = _box.origin;if (mask_p & 1){_p = _p + (_box.len.x * _box.dX);}if (mask_p & 2){_p = _p + (_box.len.y * _box.dY);}if (mask_p & 4){_p = _p + (_box.len.z * _box.dZ);}if (_plane.check(_p) < 0.0){// insidereturn (-1);}else{// intersectreturn (1);}}// outside;return 0;
}int main()
{plane p1({ 2,2,2 }, { -1,-1,-1 });plane p2({ 0.5,0.5,0.5 }, { -1,-1,-1 });plane p3({ -2,-2,-2 }, { -1,-1,-1 });box _box({1,0,0},{ 0,1,0},{ 0,0,1 },{1,1,1},{0,0,0});std::cout << check(_box, p1) << std::endl;std::cout << check(_box, p2) << std::endl;std::cout << check(_box, p3) << std::endl;return 0;
}

这篇关于快速相交检测:平面与包围盒的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067682

相关文章

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后

hdu 4565 推倒公式+矩阵快速幂

题意 求下式的值: Sn=⌈ (a+b√)n⌉%m S_n = \lceil\ (a + \sqrt{b}) ^ n \rceil\% m 其中: 0<a,m<215 0< a, m < 2^{15} 0<b,n<231 0 < b, n < 2^{31} (a−1)2<b<a2 (a-1)^2< b < a^2 解析 令: An=(a+b√)n A_n = (a +

v0.dev快速开发

探索v0.dev:次世代开发者之利器 今之技艺日新月异,开发者之工具亦随之进步不辍。v0.dev者,新兴之开发者利器也,迅速引起众多开发者之瞩目。本文将引汝探究v0.dev之基本功能与优势,助汝速速上手,提升开发之效率。 何谓v0.dev? v0.dev者,现代化之开发者工具也,旨在简化并加速软件开发之过程。其集多种功能于一体,助开发者高效编写、测试及部署代码。无论汝为前端开发者、后端开发者

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;