求三角形和线的交点.InterSection函数的方法

求三角形和线的交点.InterSection函数的方法

这个算法来自微软DirectX SDK.兰幽草推荐的.
基本算法都想明白了。就是那个t 为什么没有负号.我还没有想明白.不知道为什么
不过结果基本已经正确了。应该比较好用的。

bool InterSection(XRay& ray,XTriangle& tri,XPoint& point,float& t, float& u, float& v )
{
// Find vectors for two edges sharing vert0
/***

三角形为 v1,v2,v3
两条边为 e1 = v2-v1 e2 = v3 - v1
射线为 ray = p0 + d * t
三角形内部的一点 p = v1 + u * e1 + v * e2 ( u+v<1)

所以:
v1 + u * e1 + v * e2 = p0 + d * t ===>
u * e1 + v * e2 - t * d = p0 - v1 ===>
- t * d + v * e2 + u * e1 = p0 - v1 ===>

| d.x d.y d.z |
[-t,v,u] | e2.x e2.y e2.z | = p0 - p1 ===>
| e1.x e1.y e1.z |


[-t,v,u] * M = p0 - p1 ;


[-t,v,u] = (p0 - p1) * Inv(M);


t = (p0 - p1) * e1 X e2 / Det(M) = (p0 - p1) X e1 * e2 / Det(M)

v = (p0 - p1) * e1 X d / Det(M) = (p0 - p1) X e1 * d / Det(M)

u = (p0 - p1) * d X e2 / Det(M)

**/
XVector3D e1 = tri.m_points[1] - tri.m_points[0];
XVector3D e2 = tri.m_points[2] - tri.m_points[0];


//求出矩阵 M 的 det(M)。并记录 d x e2;
XVector3D vCP_dir_e2;
ray.m_Dir.cp(e2,vCP_dir_e2);

//得到矩阵的行列式的值
float det = e1.dp(vCP_dir_e2);

//保存 (p0 - p1)
XVector3D v_p0_p1;

//为了判断方便。det = abs(det)
if( det > 0 )
{
v_p0_p1 = ray.m_Point - tri.m_points[0];
}
else
{
v_p0_p1 = tri.m_points[0] - ray.m_Point ;
det = -det;
}

if( det < 0.0000001f )
return false;

// u = (p0 - p1) * d X e2 / Det(M) Det(M)以后再除
u = v_p0_p1.dp(vCP_dir_e2);
if( u < 0.0f || u > det )
return false;


// 保存 (p0 - p1) X e1
XVector3D vCP_p0p1_e1;
v_p0_p1.cp(e1,vCP_p0p1_e1);

// v = (p0 - p1) * e1 X d / Det(M) = (p0 - p1) X e1 * d / Det(M)
// Det(M)以后再除

v = ray.m_Dir.dp(vCP_p0p1_e1);
if( v < 0.0f || u + v > det )
return false;

// Calculate t, scale parameters, ray intersects triangle
t = e2.dp(vCP_p0p1_e1);
float fInvDet = 1.0f / det;
t *= fInvDet;
u *= fInvDet;
v *= fInvDet;

point = ray.m_Point + ray.m_Dir*t;

return true;
}