線段與三角形求交

最近需要用到這個求交計算,開始看了《計算機圖形學幾何工具算法詳解》,裏面的講解很詳細,但是給出的代碼有點問題,而且用到的類/結構體的定義並沒有給出,所以只能自己猜測,後來發現有的時候求出的結果有誤,所以又在網上搜了一下,自己再整理如下,大家可以直接拷貝粘貼過去使用。

該算法主要思想是先求出線段與三角形所在平面的交點,然後判斷該交點是否位於三角形內部。

利用三角形(頂點爲V0, V1, V2)內任意一點Q可以用重心座標表示爲 Q = w*V0 + u*V1 + v*V2; 其中w+u+v=1,三元組(w, u, v)稱爲Q的重心座標。設線段方程爲 L: p + t*d; p爲一個端點,d 爲兩個端點的差,即方向。

由 p + t*d = (1-u-v)*V0 + u*V1 + v*V2; 可以求出t, u, v的值。當 0=<u, v<=1 並且 0=<u+v<=1時,交點位於三角形內。

 

struct tri3d
{
     float v0[3];
     float v1[3];
     float v2[3];
};

 

float vector_dot(float v0[3], float3 v1[3])
{
     return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
}

 

void vector_minus(float a[3], float b[3], float res[3])
{
     res[0] = a[0]-b[0];
     res[1] = a[1]-b[1];
     res[2] = a[2]-b[2];
}

 

void vector_cross(float a[3], float b[3], float res[3])
{
     res[0] = a[1]*b[2]-a[2]*b[1];
     res[1] = a[2]*b[0]-a[0]*b[2];
     res[2] = a[0]*b[1]-a[1]*b[0];
}

 

bool LineTriangleIntersect(float start[3], float end[3], tri3d tri, float intersection[3])
{
     const float epsilon = 0.000001f;
     float e1[3], e2[3], p[3], s[3], q[3];
     float t, u, v, tmp;
     float direction[3]; 
     vector_minus(end, start, direction);
     vector_minus(tri.v1, tri.v0, e1);
     vector_minus(tri.v2, tri.v0, e2);
     vector_cross(direction, e2, p);
     tmp = vector_dot(p, e1);
     if (tmp > -epsilon && tmp < epsilon)
          return false;
     tmp = 1.0f / tmp;
     vector_minus(start, tri.v0, s);
     u = tmp * vector_dot(s, p);
     if (u < 0.0 || u > 1.0)
          return false;
     vector_cross(s, e1, q);
     v = tmp * vector_dot(direction, q);
     if (v < 0.0 || v > 1.0)
          return false;
     if (u + v > 1.0)
          return false;
     t = tmp * vector_dot(e2, q);
     if (t < 0.0 || t > 1.0)
          return false;
     intersection[0] = start[0] + t * direction[0];
     intersection[1] = start[1] + t * direction[1];
     intersection[2] = start[2] + t * direction[2];
     return true;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章