博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
3D空间中射线与三角形的交叉检測算法
阅读量:7019 次
发布时间:2019-06-28

本文共 2652 字,大约阅读时间需要 8 分钟。

引言

              射线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

            然后在进行一系列的变换。终于得到结果。

感兴趣的读者能够自行阅读,论文中具体的解释了推导过程。这里不再赘述。

Ray-Triangle交叉检測算法实现

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

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

演示样例程序截图

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

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

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

你可能感兴趣的文章
@ResponseBody处理Clob数据
查看>>
nginx安装
查看>>
Mysql5.6启动报错1067错误解决方法
查看>>
Objective-C 2.0 with Cocoa Foundation---NSObject的奥秘(1)
查看>>
CDH5 + ZOOKEEPER + HIVE安装
查看>>
如何开启MySQL的远程帐号
查看>>
通过ORACLE的UTL_HTTP工具包发送包含POST参数的请求
查看>>
Linux下安装Oracle10g详细教程
查看>>
堆与堆排序
查看>>
vs2010交叉编译生成android
查看>>
Linux软连接原理解析
查看>>
XenDesktop7实践之高可用设计③StoreFront安装和创建部署
查看>>
layer操作frame
查看>>
Android Dialog用法
查看>>
vs code不同后缀的文件按图标区分,如.vue .md
查看>>
一份来自阿里云引擎ACE的求职信,你收到了吗?
查看>>
基于Centos6.2 X64系统下的邮件系统(一)
查看>>
【掘金】学习摘录之初刻拍岸惊奇:穷小子华丽转身为大富翁(1)
查看>>
load data infile
查看>>
Apache的三种工作模式
查看>>