引言

射线Ray,在3D图形学中有很多重要的应用。比如,pick操作就是使用射线Ray来实现的,还有诸如子弹射线的碰撞检测等等都可以使用射线Ray来完成。所以,在本次博客中,将会简单的像大家介绍下,如何进行Ray-Triangle的交叉检测。

Ray-Triangle交叉检测算法

在Tomas Moller的MT97论文中,提出了一种新的算法。这种算法能够减少以前进行Ray-Triangle交叉检测所需要的内存消耗。在以前,进行Ray-Triangle交叉检测,主要是计算射线与三角形所构成的平面的交点,然后重新判断交点是否在三角形上,从而来判断是否发生了交叉。这种方法很直观,符合我们一直以来所学的数学知识。但是,这种检测方法进行的计算较多,而且还需要根据三角形来求它所在的平面,这样又需要进行计算,同时也需要另外开辟空间来保存计算出来的平面。

数学之美,就在于能够找到其他的方法来代替这种显而易见的方式,从而将问题简化到一定的程度。这种简化的过程,不需要在代码中实现,只需要我们事先根据条件,然后在草稿纸上计算出最后的结论,我们只需要在我们的代码中直接使用最终得到的结论即可。

在Tomas Moller的论文中,它提到了这样的一个概念:

如果一个点在三角形V0, V1, V2上,那么这个点就可以用如下的方式来表示:

T(u, v) = (1 - u - v) * V0 + u * V1 + v * V2 ;

这里u+v <= 1, u >= 0 ,  v >=0

而对于射线,我们一般使用如下的方程来表示它:

R (t)= O + t * D ; (O为射线的起始点,D为射线的方向)

所以,既然他们要有交点,我们就能够直接使用如下的方法来得出:

O + t * D = (1 - u - v) * V0 + u * V1 + v * V2

然后在进行一系列的变换,最终得到结果。感兴趣的读者可以自行阅读Tomas Moller的论文,论文中详细的解释了推导过程。这里不再赘述。

Ray-Triangle交叉检测算法实现

以下是Ray-Triangle交叉检测算法的Moller算法实现,基本上就是Tomas Moller论文中代码的拷贝,如下所示:

<span style="font-family:Microsoft YaHei;">bool Ray::intersectWithTriangle(VECTOR3 v0,VECTOR3 v1, VECTOR3 v2,
bool bCull,
float *t)
{
VECTOR3 edge1, edge2, tvec, pvec, qvec ;
float det, inv_det ;
float u,v ; //Find vectors for two edges sharing vert0
Vec3Sub(edge1, v1, v0);
Vec3Sub(edge2, v2, v0); //Begin calculating determinant - also used to calculate U parameter
Vec3Cross(pvec, dir, edge2); //If the determinant is near zero, ray lies in plane of triangle
Vec3Dot(det, edge1, pvec); //If bCull is true
if(bCull)
{
if(det < 0.00001f)
return false ; //Calculate distance from vert0 to ray origin
Vec3Sub(tvec, origin, v0); //Calculate U parameter and test bounds
Vec3Dot(u, tvec, pvec);
if(u < 0.0 || u > det)
return false ; //Prepare to test v parameter
Vec3Cross(qvec, tvec, edge1); //Calculate V parameter and test bounds
Vec3Dot(v, dir, qvec);
if(v < 0.0f || u + v > det)
return false ; //Calculate t , scale paramter, ray intersect triangle
Vec3Dot(*t, edge2, qvec);
inv_det = 1.0f / det ;
*t *= inv_det ;
u *= inv_det ;
v *= inv_det ;
}
else
{
if(det > -0.00001f && det < 0.00001)
return false ;
inv_det = 1.0f / det ; //calculate distance from v0 to ray origin
Vec3Sub(tvec, origin, v0); //Calculate u parameter and test bounds
Vec3Dot(u, tvec, pvec);
u *= inv_det ;
if(u < 0.0 || u > 1.0)
return false ; //prepare to test v parameter
Vec3Cross(qvec, tvec, edge1); //Calculate v parameter and test bounds
Vec3Dot(v, dir, qvec);
v *= inv_det ;
if(v < 0.0 || u + v > 1.0)
return false ; //calculate t, ray intersect triangle
Vec3Dot(*t, edge2, qvec);
*t *= inv_det ;
} return true ;
}// end for intersectWithTriangle</span>

示例程序截图

这个图是在没有发生交叉的时候的情况,

下图是在发生了交叉之后的截图:

http://m.blog.csdn.net/article/details?id=38332499

3D空间中射线与三角形的交叉检测算法【转】的更多相关文章

  1. 3D空间中射线与三角形的交叉检測算法

    引言 射线Ray,在3D图形学中有非常多重要的应用.比方,pick操作就是使用射线Ray来实现的,还有诸如子弹射线的碰撞检測等等都能够使用射线Ray来完毕. 所以,在本次博客中,将会简单的像大家介绍下 ...

  2. 3D空间中射线与轴向包围盒AABB的交叉检测算法【转】

    引言 在上一节中,我讲述了如何实现射线与三角形的交叉检测算法.但是,我们应该知道,在游戏开发中,一个模型有很多的三角形构成,如果要对所有的物体,所有的三角形进行这种检测,就算现在的计算机运算能力,也是 ...

  3. 3D空间中射线与轴向包围盒AABB的交叉检测算法 【转】

    http://blog.csdn.net/i_dovelemon/article/details/38342739 引言 在上一节中,我讲述了如何实现射线与三角形的交叉检测算法. 但是,我们应该知道, ...

  4. Ray-AABB交叉检测算法

      最近在解决三维问题时,需要判断线段是否与立方体交叉,这个问题可以引申为:射线是否穿过立方体AABB.   在3D游戏开发中碰撞检测普遍采用的算法是轴对齐矩形边界框(Axially Aligned ...

  5. 射线与空间内三角形的相交检测算法(Möller-Trumbore)的推导与实践

    背景介绍(学习算法之前需要先了解) 射线与空间内三角形的相交检测是游戏程序设计中一个常见的问题,最典型的应用就是拾取(Picking),本文介绍一个最常见的方法,这个方法也是DirectX中采用的方法 ...

  6. WebGL和ThreeJs学习6--射线法确定3D空间中所选物体

    一.在 threejs 中如何确定下图3D空间中鼠标点击位置的 object 对象? 二.射线法确定步骤及代码 //Three.js提供一个射线类Raycaster来拾取场景里面的物体.更方便的使用鼠 ...

  7. 射线和三角形的相交检测(ray triangle intersection test)【转】

    本文以Fast, Minimum Storage Ray Triangle Intersection为参考,在此感谢原作者,大家也可以直接阅读原版. 概述 射线和三角形的相交检测是游戏程序设计中一个常 ...

  8. 2D和3D空间中计算两点之间的距离

    自己在做游戏的忘记了Unity帮我们提供计算两点之间的距离,在百度搜索了下. 原来有一个公式自己就写了一个方法O(∩_∩)O~,到僵尸到达某一个点之后就向另一个奔跑过去 /// <summary ...

  9. OpenGL ES 3D空间中自定义显示空间

    在Android中,我们所熟知的是在ES管线中,其在图元装配时,会进行图元组装与图元分配,这样就回剪裁出来视景体中的物体.但是如果我想在3D场景中规定一个区域,凡是在这个区域中的物体就能显示出来,非这 ...

随机推荐

  1. 'org.hibernate.SQLQuery' is deprecated

    'org.hibernate.SQLQuery' is deprecated 在Hibernate5.2之后,SQLQuery已经被摒弃,改用NativeQuery代替了. 在Hibernate中使用 ...

  2. Excel Sheet Column Number(STRING-TYPE CONVERTION)

    QUESTION Related to question Excel Sheet Column Title Given a column title as appear in an Excel she ...

  3. Space Ant(极角排序)

    Space Ant http://poj.org/problem?id=1696 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions ...

  4. xp安装vmware10时一直停在installing packages on the system

    我估计的原因是: vm会在网上邻居(LAN或高速internet)下创建两个 vmware network adapter vmnet8 vmware network adapter vmnet1   ...

  5. linux,windows 可执行文件(ELF、PE)

    现在PC平台流行的可执行文件格式(Executable)主要是Windows下的PE(Portable Executable)和Linux的ELF(Executable Linkable Format ...

  6. Netty 系列目录

    Netty 系列目录 二 Netty 源码分析(4.1.20) 1.1 Netty 源码(一)Netty 组件简介 2.1 Netty 源码(一)服务端启动 2.2 Netty 源码(二)客户端启动 ...

  7. adb占用

    输入netstat -ano | findstr "5037" .然后会弹出提示告诉你哪些进程占用了该端口,记住非0地址的后面的数字 打开任务管理器,点击“进程“,“查看”-“选择 ...

  8. cubieboard安装小记

    1.1.使用ttl线 ttl线驱动程序:PL2303_Prolific_DriverInstaller_v1.7.0.exe(驱动精灵上下载) ttl终端:http://the.earth.li/~s ...

  9. 关于多系统跨浏览器 BrowserStack 的使用

    偶然在Scott Hanselman Blogs看到一篇关于 BrowserStack 博文,对于前端多浏览器测试. 现在拥有各自内核的浏览器越来越多,各自的特性也千差万别.如果作为一个前端攻城师想要 ...

  10. 用winsw让任何Windows程序都能运行为服务

    用winsw让任何Windows程序都能运行为服务 winsw介绍 有时候我们需要在Windows下开机运行某些程序,这对于有图形界面的程序来说一般不是什么事,在选项中选中开机启动,然后它们就可以自动 ...