探索射线与三角形求交的方法

本文介绍了一种快速且节省内存的射线与三角形相交算法,该算法利用三角形重心坐标系和克莱姆法则进行优化,并提供了一个具体的实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Tomas Moller的Fast,Minimum Storage Ray/Triangle Intersection ,好像是99年的吧,这篇在讲到射线与三角形所在平面相交后,如何判断点在三角形内,运用了三角形重心坐标系的方法(详情看paper),同时运用行列式的克莱姆法则去求u,v( 重心坐标运用此两个来表示) ,不过又对其行列式进行了优化:

   |A B C| = -(A叉乘C)*B =-(C叉乘B)*A ,这样来减少计算量.

其后又看了另一个paper,讲到: 让射线与三角形所在平面相交后产生的点,在此平面一个方向上发射线,如果交点为奇数,则为在三角形里,否则在三角形外面.其它的继续探讨.....

先把Moller的程序搞过来:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#include

 

 

<iostream>

using

 

 

namespace std

;

#define

 

 

EPSILON

0.000001

#define

 

 

CROSS(dest, v1,v2

) /

 

 

dest[0] = v1[1]*v2[2]-v1[2]*v2

[1]; /

 

 

dest[1] = v1[2]*v2[0]-v1[0]*v2

[2]; /

 

 

dest[2] = v1[0]*v2[1]-v1[1]*v2

[0];

#define

 

 

DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2

[2])

#define

 

 

SUB(dest,v1,v2

) /

 

 

dest[0] = v1[0]-v2

[0]; /

 

 

dest[1] = v1[1]-v2

[1]; /

 

 

dest[2] = v1[2]-v2

[2];

int

intersect_triangle

 

 

(double orig[3], double dir

[3],

 

 

double vert0[3],double vert1[3], double vert2

[3],

 

 

double *t, double *u, double *v

)

{

 

 

double edge1[3],edge2[3],tvec[3],pvec[3],qvec

[3];

 

 

double det,inv_det

;

 

 

// find vectors for two edges sharing vert0

 

 

SUB(edge1,vert1,vert0

);

 

 

SUB(edge2,vert2,vert0

);

 

 

// begin calculating determinant - also used to calculate U parameter

 

 

CROSS(pvec,dir,edge2

);

 

 

// if determinant is near zero , the ray lies in the plane or parallel to the plane

 

 

det = DOT(edge1,pvec

);

#ifdef

 

 

TEST_CULL

// define TEST_CULL if culling is desired

if(det<EPSILON)

return 0;

// calculate distance from vert0 to ray origin

SUB(tvec,orig,vert0);

// calculate U parameter and test bounds

*u = DOT(tvec,pvec);

if(*u<0.0 || *u>det)

return 0;

// prepare to test V parameter

CROSS(qvec,tvec,edge1);

// calculate V parameter and test bounds

*v = DOT(dir,qvec);

if(*v<0.0 || *u + *v >det)

return 0;

// calculate t, scale parameters, ray intersects triangle

*t = DOT(edge2,qvec);

inv_det = 1.0/det;

*t *= inv_det;

*u *= inv_det;

*v *= inv_det;

#else

 

 

if( det > -EPSILON && det < EPSILON

)

 

 

return

0;

 

 

inv_det = 1.0 / det

;

 

 

// calculate distance from vert0 to ray origin

 

 

SUB(tvec,orig,vert0

);

 

 

// calculate U parameter and test bounds

*

 

u = DOT(tvec,pvec)*inv_det

;

 

 

if(*u < 0.0 || *u

> 1.0)

 

 

return

0;

 

 

// calculate V parameter and test bounds

*

 

v = DOT(dir,qvec)*inv_det

;

 

 

if(*v<0.0 || *u + *v

> 1.0)

 

 

return

0;

 

 

// calculate t ,ray intersects triangle

*

 

t = DOT(edge2,qvec)*inv_det

;

#endif

 

 

return

1;

}

int

 

 

main

()

{

 

 

double origin

[3] = { 0,0,0};

 

 

double dir

[3] = {1.0,1.0,1.0};

 

 

double vert1

[3] ={4,5,6};

 

 

double vert2

[3] = {5,6,8};

 

 

double vert3

[3] = {7,8,9};

 

 

double t,u,v

;

 

 

if(intersect_triangle(origin,dir,vert1,vert2,vert3,&t,&u,&v

))

 

 

cout<<" The ray has intersected the triangle"<<endl

;

 

 

else

 

 

cout<<" The ray has not intersected the triangle"<<endl

;

 

 

cin.get

();

 

 

return

1;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值