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

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

大家好,又见面了,我是全栈君。

引言

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

演示样例程序截图

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

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

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

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


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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/116258.html原文链接:https://javaforall.net

(0)
上一篇 2022年1月23日 下午10:00
下一篇 2022年1月23日 下午10:00


相关推荐

  • 终于搞懂了vue 的 render 函数(一) -_-|||

    终于搞懂了vue 的 render 函数(一) -_-|||文章目录 render 函数作用 render 函数讲解 render 函数的返回值 VNode render 函数的参数 createElemen createElemen 函数的返回值 VNode createElemen 函数的参数 三个 结合代码 vue 渲染函数文档第一遍看的晕晕乎乎的 再看看写写终于清晰了 建议配合文档阅读 本文也是根据文档加上自己的理解 注 本文代码都是在单文件组件中

    2026年3月20日
    1
  • Android中的shell循环命令

    Android中的shell循环命令新建test.txt,写入:i=0;while[$(($i))-le5];doi=$(($i+1));echo$i;done;执行这个文件adbshell<test.txt

    2022年7月24日
    9
  • CreateThread 函数[通俗易懂]

    CreateThread 函数[通俗易懂]改变了栈的大小,但是把CreateThread的第2参数改成0x100000或者更小的时候,程序还是会出现这样的问题,只有将栈的大小还原为默认值,且CreateThread的第2参数为0才能正确运行详细的请查看:http://topic.csdn.net/u/20090905/15/7bf41679-3ed9-40b5-ac71-5f11c088984c.html微软在Windows

    2022年7月11日
    28
  • 微信小程序带参数跳转页面(小程序跳转第三方网页)

    //wxml&lt;textwx:for="{{titles}}"wx:key="{{index}}"bindtap=’changeClassify’data-id="{{index}}"&gt;{{item.name}}&lt;/text&gt;//jsfunctionchangeClassify(e){//letid=e.currentTarget.da…

    2022年4月12日
    63
  • 用python画爱心的代码-Python一行代码画个爱心案例「建议收藏」

    用python画爱心的代码-Python一行代码画个爱心案例「建议收藏」昨天六一儿童节,大小朋友都过节了,真好!“人生易老天难老”,这很现实,读这句诗不期然就有一种沧桑的感觉。而要人生幸福,是需要保持一颗童心的。《三字经》开篇说“人之初,性本善”,童心就是天真,单纯而无邪。我们的身体可以老去,但可以让我们的心理年龄永远年轻,人不思老,则老将不至。拥有一颗童心,就能始终对这个世界好奇,充满想象力和创造力。拥有一颗童心,就能让我们有所“畏惧”,有所顾忌,对这个世界时刻保持…

    2025年9月25日
    11
  • 贪吃蛇程序代码python_Python贪吃蛇代码

    贪吃蛇程序代码python_Python贪吃蛇代码importsys,pygamefrompygame.localsimport*fromrandomimportrandrangeup=lambdax:(x[0]-1,x[1])down=lambdax:(x[0]+1,x[1])left=lambdax:(x[0],x[1]-1)right=lambdax:(x[0],x[1]+1)tl=lam…

    2022年8月10日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号