如何求三角形和線的交點InterSection函數

原帖:http://blog.csdn.net/nhsoft/archive/2004/06/23/22992.aspx

 

這個算法來自微軟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;
 }

 

 

 

 

按照仿射座標系分解來理解就更好了。

三角形的兩個邊就是仿射座標系的兩個軸
把點座標分解爲仿射座標(u,v)
0<=u<=1 && 0<=v<=1 && u+v<1 表示點在三角形內部

<script language="javascript" type="text/javascript"> ad_width=468; ad_height=60; adcss=2; unionuser=19; ad_type='j'; count=5; </script> <script language="javascript" src="http://tagegg.csdn.net/showads.js" type="text/javascript"></script> <script language="JavaScript1.1" src="http://tagegg.csdn.net/a.aspx?action=displayad&unionuser=19&unionurl=http%3A%2F%2Fblog.csdn.net%2Fnhsoft%2Farchive%2F2004%2F06%2F27%2F27521.aspx&adcss=2&ad_type=j&width=468&height=60&ad_color=&ad_color_border=&count=5" type="text/javascript"></script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章