http://blog.csdn.net/i_dovelemon/article/details/38332499

引言

射线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论文中代码的拷贝,如下所示:

[cpp] view plaincopy
  1. <span style="font-family:Microsoft YaHei;">bool Ray::intersectWithTriangle(VECTOR3 v0,VECTOR3 v1, VECTOR3 v2,
  2. bool bCull,
  3. float *t)
  4. {
  5. VECTOR3 edge1, edge2, tvec, pvec, qvec ;
  6. float det, inv_det ;
  7. float u,v ;
  8. //Find vectors for two edges sharing vert0
  9. Vec3Sub(edge1, v1, v0);
  10. Vec3Sub(edge2, v2, v0);
  11. //Begin calculating determinant - also used to calculate U parameter
  12. Vec3Cross(pvec, dir, edge2);
  13. //If the determinant is near zero, ray lies in plane of triangle
  14. Vec3Dot(det, edge1, pvec);
  15. //If bCull is true
  16. if(bCull)
  17. {
  18. if(det < 0.00001f)
  19. return false ;
  20. //Calculate distance from vert0 to ray origin
  21. Vec3Sub(tvec, origin, v0);
  22. //Calculate U parameter and test bounds
  23. Vec3Dot(u, tvec, pvec);
  24. if(u < 0.0 || u > det)
  25. return false ;
  26. //Prepare to test v parameter
  27. Vec3Cross(qvec, tvec, edge1);
  28. //Calculate V parameter and test bounds
  29. Vec3Dot(v, dir, qvec);
  30. if(v < 0.0f || u + v > det)
  31. return false ;
  32. //Calculate t , scale paramter, ray intersect triangle
  33. Vec3Dot(*t, edge2, qvec);
  34. inv_det = 1.0f / det ;
  35. *t *= inv_det ;
  36. u *= inv_det ;
  37. v *= inv_det ;
  38. }
  39. else
  40. {
  41. if(det > -0.00001f && det < 0.00001)
  42. return false ;
  43. inv_det = 1.0f / det ;
  44. //calculate distance from v0 to ray origin
  45. Vec3Sub(tvec, origin, v0);
  46. //Calculate u parameter  and test bounds
  47. Vec3Dot(u, tvec, pvec);
  48. u *= inv_det ;
  49. if(u < 0.0 || u > 1.0)
  50. return false ;
  51. //prepare to test v parameter
  52. Vec3Cross(qvec, tvec, edge1);
  53. //Calculate v parameter and test bounds
  54. Vec3Dot(v, dir, qvec);
  55. v *= inv_det ;
  56. if(v < 0.0 || u + v > 1.0)
  57. return false ;
  58. //calculate t, ray intersect triangle
  59. Vec3Dot(*t, edge2, qvec);
  60. *t *= inv_det ;
  61. }
  62. return true ;
  63. }// end for intersectWithTriangle</span>

示例程序截图

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

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

今天的笔记就此结束。以后会陆续出现这种文章,请大家关注吧!!!

3D空间中射线与三角形的交叉检测算法相关推荐

  1. 3D空间中射线与三角形的交叉检测算法【转】

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

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

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

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

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

  4. 在3D空间中绘制四边形

    在3D空间中绘制四边形 四边形 GL_QUADS OpenGL的GL_QUADS图元用于绘制四边形,它根据每四个顶点绘制一个四边形. 注意,在使用四边形时,必需记住一个重要规则:一个四边形的四个角必须 ...

  5. 使3D空间中物体朝向和其速度方向一致的旋转矩阵计算方案

    在3D空间中的物体以某一速度运动,有时候需要这个物体的朝向和速度的方向一致, 为了实现这个目标我们一般借助旋转矩阵 M 来将物体旋转到对应的朝向. 例如速度方向矢量 spdV: Vector3D(1, ...

  6. 使用脑电图慢皮层电位重建3D空间中的手,肘和肩的实际和想象的轨迹

    导读 从神经活动中解码想象运动的运动学的能力对于开发可以帮助行动不便的人的假肢设备至关重要.当前采用脑电图(EEG)等无创记录方法解码实际和想象的手运动轨迹来控制神经运动假体,通常通过应用多维线性回归 ...

  7. 3D 空间中拟合曲线

    算法来源:C++/PCL:最小二乘拟合平面直线,平面多项式曲线,空间多项式曲线 以下是我改写的算法,未经验证正确性!!! // 3D 空间中拟合曲线 void fittingPolynomial3D( ...

  8. 3D空间中的点坐标转化为屏幕二维点坐标(一)

    每个人在进入计算机图形学的世界中,都有一个同样的困惑,三维世界中的三维坐标是如何被转换成屏幕上的二维坐标的,我如何在屏幕上找到一个点(二维点)对应三维世界中的点(三维点)呢? 要理解其中的过程,对学习 ...

  9. 一般向量空间的基变换_向量几何--3-D空间中的基变换与坐标变换【转】 - 回到未来 - C++博客...

    <6>3-D空间中的基变换与坐标变换-Twinsen编写 -本人水平有限,疏忽错误在所难免,还请各位数学高手.编程高手不吝赐教 -我的Email-address:popyy@netease ...

最新文章

  1. 所有人问「贴吧之父」俞军
  2. SSH项目中遇到拦截器无法注入服务的问题
  3. python功能函数_Python-功能函数的使用
  4. 如何用法向量求点到平面距离_支持向量机(SVM)
  5. leetcode python 1
  6. mysqld -install命令时出现install/remove of the service denied错误的原因和解决办法
  7. HTTP相关知识 --转载
  8. 顺序执行命令需要哪个符号链接_18年MBA联考如何安排答题时间及顺序
  9. 鸿蒙的下一个时期叫什么,华为鸿蒙,一个本属于2025年的产品
  10. java基础---Java---面试题---银行业务调度系统(线程同步锁、枚举、线程池)
  11. c语言实验报告大气,dsp实验报告心得体会
  12. 国际会议关于Poster的一个网站
  13. 实战解决小程序图片加载问题
  14. 苹果雪豹操作系统正式版_苹果放出iOS 13andiPadOS beta 2:加入SMB网络共享、APFS硬盘支持...
  15. oracle查询平均每月数据,oracle 按每天,每周,每月,每季度,每年查询统计数据
  16. 天冷就要大口吃肉肉~python采集周边烤肉店数据【附代码】
  17. 拆长虹iho3000_(CA版)四川长虹iho-3000t晶晨s905l-b刷全网通系统教程可救砖头
  18. 华为双前置摄像头_华为第一款“刘海屏”手机发布,前置摄像头逆天
  19. 机器翻译:征服巴别塔
  20. 用python构建多只股票日收益率直方图_用Python分析多股票的投资组合

热门文章

  1. 怎么看服务器连接记录_企业微信怎么查看打卡记录?自己和他人的都可以看
  2. yum命令 启用仓库_yum仓库详细解读
  3. java 控制鼠标点击_java中控制鼠标点击的方法
  4. 深度linux安装make,linux下安装python3完整教程(依赖环境gcc,make,cmake,configure等详细解释)...
  5. 简单 黑苹果dsdt教程_黑苹果笔记本:关于DSDT亮度表的分析与修改
  6. python如何读取tfrecord_tensorflow读取tfrecords格式文件
  7. Python中raise用法
  8. 自动化测试用例设计的原则
  9. html 把文字显示控制,控制字体加粗显示的html标签是哪个
  10. java自定义表单_JSP实现用于自动生成表单标签html代码的自定义表单标签