射线与三角面

来源:互联网 发布:js鼠标移入移出 编辑:程序博客网 时间:2024/06/11 04:37

1一种思路是先求射线与平面的交点,然后计算交点是否落在三角面内

2利用三角形方程求射线与三角面的交点Ray-Triangle交叉检测算法

射线的参数方程如下,其中O是射线的起点,D是射线的方向。

我们可以这样理解射线,一个点从起点O开始,沿着方向D移动任意长度,得到终点R,根据t值的不同,得到的R值也不同,所有这些不同的R值便构成了整条射线,比如下面的射线,起点是P0,方向是u,p0 + tu也就构成了整条射线。

 

三角形的参数方程如下,其中V0,V1和V2是三角形的三个点,u, v是V1和V2的权重,1-u-v是V0的权重,并且满足u>=0, v >= 0,u+v<=1。

确切的说,上面的方程是三角形及其内部所有点的方程,因为三角形内任意一点都可以理解为从顶点V0开始,沿着边V0V1移动一段距离,然后再沿着边V0V2移动一段距离,然后求他们的和向量。至于移动多大距离,就是由参数u和v控制的。


于是,求射线与三角形的交点也就变成了解下面这个方程-其中t,u,v是未知数,其他都是已知的

移项并整理,将t,u,v提取出来作为未知数,得到下面的线性方程组

现在开始解这个方程组,这里要用到两个知识点,一是克莱姆法则,二是向量的混合积。

令E1 = V1 - V0,E2 = V2 - V0,T = O - V0上式可以改写成

根据克莱姆法则,可得到t,u,v的解分别是

将这三个解联合起来写就是

根据混合积公式

上式可以改写成

得到最终的公式,这便是下面代码中用到的最终公式了,之所以提炼出P和Q是为了避免重复计算

代码:

DirectX SDK Pick.cpp

// Determine whether a ray intersect with a triangle // Parameters // orig: origin of the ray // dir: direction of the ray // v0, v1, v2: vertices of triangle // t(out): weight of the intersection for the ray // u(out), v(out): barycentric coordinate of intersection   bool IntersectTriangle(const Vector3& orig, const Vector3& dir,     Vector3& v0, Vector3& v1, Vector3& v2,     float* t, float* u, float* v){    // E1    Vector3 E1 = v1 - v0;    // E2    Vector3 E2 = v2 - v0;    // P    Vector3 P = dir.Cross(E2);    // determinant    float det = E1.Dot(P);    // keep det > 0, modify T accordingly    Vector3 T;    if( det >0 )    {        T = orig - v0;    }    else    {        T = v0 - orig;        det = -det;    }    // If determinant is near zero, ray lies in plane of triangle    if( det < 0.0001f )        return false;    // Calculate u and make sure u <= 1    *u = T.Dot(P);    if( *u < 0.0f || *u > det )        return false;    // Q    Vector3 Q = T.Cross(E1);     // Calculate v and make sure u + v <= 1    *v = dir.Dot(Q);    if( *v < 0.0f || *u + *v > det )        return false;    // Calculate t, scale parameters, ray intersects triangle    *t = E2.Dot(Q);    float fInvDet = 1.0f / det;    *t *= fInvDet;    *u *= fInvDet;    *v *= fInvDet;    return true;}


0 0
原创粉丝点击