光线与包围盒(AABB)的相交检测算法
来源:互联网 发布:如何升级淘宝新版本 编辑:程序博客网 时间:2024/04/27 14:28
这里介绍两种算法,第一种比较容易理解
下面是Cocos2dx中实现Ray-AABB相交(碰撞)检测的算法,说明看注释
bool Ray::intersects(const AABB& aabb) const{ Vec3 ptOnPlane; //射线与包围盒某面的交点 Vec3 min = aabb._min; //aabb包围盒最小点坐标 Vec3 max = aabb._max; //aabb包围盒最大点坐标 const Vec3& origin = _origin; //射线起始点 const Vec3& dir = _direction; //方向矢量 float t; //分别判断射线与各面的相交情况 //判断射线与包围盒x轴方向的面是否有交点 if (dir.x != 0.f) //射线x轴方向分量不为0 若射线方向矢量的x轴分量为0,射线不可能经过包围盒朝x轴方向的两个面 { /* 使用射线与平面相交的公式求交点 */ if (dir.x > 0)//若射线沿x轴正方向偏移 t = (min.x - origin.x) / dir.x; else //射线沿x轴负方向偏移 t = (max.x - origin.x) / dir.x; if (t > 0.f) //t>0时则射线与平面相交 { ptOnPlane = origin + t * dir; //计算交点坐标 //判断交点是否在当前面内 if (min.y < ptOnPlane.y && ptOnPlane.y < max.y && min.z < ptOnPlane.z && ptOnPlane.z < max.z) { return true; //射线与包围盒有交点 } } } //若射线沿y轴方向有分量 判断是否与包围盒y轴方向有交点 if (dir.y != 0.f) { if (dir.y > 0) t = (min.y - origin.y) / dir.y; else t = (max.y - origin.y) / dir.y; if (t > 0.f) { ptOnPlane = origin + t * dir; if (min.z < ptOnPlane.z && ptOnPlane.z < max.z && min.x < ptOnPlane.x && ptOnPlane.x < max.x) { return true; } } } //若射线沿z轴方向有分量 判断是否与包围盒y轴方向有交点 if (dir.z != 0.f) { if (dir.z > 0) t = (min.z - origin.z) / dir.z; else t = (max.z - origin.z) / dir.z; if (t > 0.f) { ptOnPlane = origin + t * dir; if (min.x < ptOnPlane.x && ptOnPlane.x < max.x && min.y < ptOnPlane.y && ptOnPlane.y < max.y) { return true; } } } return false;}
下面是另外一种Ray-AABB检测算法,称为"Slabs method"
观察上述三幅图可以得出,只要发生区间交叠,光线与平面就能相交,
那么区间交叠出现的条件便是:光线进入平面处的最大t值小于光线离开平面处的最小t值
那么问题就变成了如何求 光线进入平面处的最大t值 以及 光线离开平面处的最小t值
这个问题很简单,通过光线与平面相交的参数方程求解就可以了,
光线的参数方程为R(t) = O + t * Dir
一般平面方程为aX+bY+cZ+d=0,因为AABB的六个面分别平行于XY、XZ、YZ平面,所以平面的方程为X=d,Y=d,Z=d
光线与垂直于x轴的两个面相交时,t = (d - O.x) / Dir.x
光线与垂直于y轴的两个面相交时,t = (d - O.y) / Dir.y
光线与垂直于z轴的两个面相交时,t = (d - O.z) / Dir.z
注意到t<0时,交点位于光线的起点之后,则光线(射线)并未与盒体发生相交
bool BBox::hit(const Ray& ray) const{double ox = ray.o.x;double oy = ray.o.y;double oz = ray.o.z;double dx = ray.d.x;double dy = ray.d.y;double dz = ray.d.z;double tx_min,ty_min,tz_min;double tx_max,ty_max,tz_max;//x0,y0,z0为包围体的最小顶点//x1,y1,z1为包围体的最大顶点if(abs(dx) < 0.000001f) {//若射线方向矢量的x轴分量为0且原点不在盒体内if(ox < x1 || ox > x0)return false ;}else{if(dx>=0){tx_min = (x0-ox)/dx;tx_max = (x1-ox)/dx;}else{tx_min = (x1-ox)/dx;tx_max = (x0-ox)/dx;}}if(abs(dy) < 0.000001f) {//若射线方向矢量的x轴分量为0且原点不在盒体内if(oy < y1 || oy > y0)return false ;}else{if(dy>=0){ty_min = (y0-oy)/dy;ty_max = (y1-oy)/dy;}else{ty_min = (y1-oy)/dy;ty_max = (y0-oy)/dy;}}if(abs(dz) < 0.000001f) {//若射线方向矢量的x轴分量为0且原点不在盒体内if(oz < z1 || oz > z0)return false ;}else{if(dz>=0){tz_min = (z0-oz)/dz;tz_max = (z1-oz)/dz;}else{tz_min = (z1-oz)/dz;tz_max = (z0-oz)/dz;}}double t0,t1;//光线进入平面处(最靠近的平面)的最大t值 t0=max(tz_min,max(tx_min,ty_min));//光线离开平面处(最远离的平面)的最小t值t1=min(tz_max,min(tx_max,ty_max));return t0<t1;}
0 0
- 光线与包围盒(AABB)的相交检测算法
- 光线与包围盒(AABB)的相交检测算法
- 光线与包围盒(AABB)的相交检测算法
- 射线和轴对齐包围盒相交检测-简洁算法(ray-aabb overlap test alogrithm)
- 《实时碰撞检测算法技术》读书笔记(二):轴对齐包围盒(AABB)的计算与更新
- 3D空间中射线与轴向包围盒AABB的交叉检测算法
- 3D空间中射线与轴向包围盒AABB的交叉检测算法
- 3D空间中射线与轴向包围盒AABB的交叉检测算法
- aabb与oob包围盒 碰撞检测
- AABB包围盒算法
- 理解AABB包围盒算法
- 理解AABB包围盒算法
- [OpenGL]基于AABB包围盒的漫游时视点与场景的碰撞检测
- AABB包围盒、OBB包围盒、包围球的比较
- AABB包围盒、OBB包围盒、包围球的比较
- AABB包围盒、OBB包围盒、包围球的比较
- 光线与盒体相交检测(Ray-OBB)可用于VR中Cursor与控件的碰撞检测
- [算法][包围盒]球,AABB,OBB
- NOI 1995 石子合并
- [leetcode] 265. Paint House II 解题报告
- 第三届蓝桥杯
- 10938 - Flea circus
- leetcode319 Bulb Switcher
- 光线与包围盒(AABB)的相交检测算法
- io流复习笔记第三发流的套接结束及对象流读写
- BIOS调查笔记
- 关于CGRect
- leetcode268 Missing Number
- jQuery选择器
- eclipse 安装 svn 插件
- 央行常用操作
- ecshop 多语言版 fckeditor,支持中文英文韩文等众多语言