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;