现在的位置: 首页 > 综合 > 正文

碰撞检测中函数(线与面,线与多边形,点到线的最近点) _ 转 – [叁]

2014年01月28日 ⁄ 综合 ⁄ 共 3611字 ⁄ 字号 评论关闭

转载地址:http://sakishum.blogbus.com/logs/53944554.html

1、线和平面碰撞。传入参数:线(起点,终点),平面(三个顶点) 

调用:IntersectedPlane(vTriangle, vLine);

bool IntersectedPlane(CVector3 vTriangle[], CVector3 vLine[])

{

 float distance1=0, distance2=0;         

 CVector3 vNormal = Normal(vTriangle); //三角形法向量 

// originDistance 为 Ax+By+Cz+D=0中的D (A,B,C为法向量)

float originDistance = PlaneDistance(vNormal, vTriangle[0]);

 

//求出线段两端点到平面的距离,若距离相乘为负,相交,否则不相交

 distance1 = ((vNormal.x * vLine[0].x)  +     // Ax +

              (vNormal.y * vLine[0].y)  +     // Bx +

  (vNormal.z * vLine[0].z)) + originDistance; // Cz + D

 distance2 = ((vNormal.x * vLine[1].x)  +     // Ax +

              (vNormal.y * vLine[1].y)  +     // Bx +

  (vNormal.z * vLine[1].z)) + originDistance; // Cz + D

  if(distance1 * distance2 >= 0)   

      return false;       

   return true;       

}

2.线段和多边形相交,参数:多边形顶点数组,线段,多边形顶点个数

 IntersectedPolygon(vTriangle, vLine, 3);

bool IntersectedPolygon(CVector3 vPoly[], CVector3 vLine[], int verticeCount)

{

  CVector3 vNormal = {0};

  float originDistance = 0;

  //如果不和多边形所在平面相交,则不相交

  if(!IntersectedPlane(vPoly, vLine,   vNormal,   originDistance))

      return false;

 //求出线和平面的交点

 CVector3 vIntersection = IntersectionPoint(vNormal, vLine, originDistance);

//如果交点在多边形内,就相交

 if(InsidePolygon(vIntersection, vPoly, verticeCount))

   return true; 

   return false;   

 }

辅助函数1:IntersectionPoint()返回线和平面的交点

思路:求出点与点和平面交点的距离1,用起始点+线段方向*距离1,求出交点

CVector3 IntersectionPoint(CVector3 vNormal, CVector3 vLine[], double distance)

{

 CVector3 vPoint = {0}, vLineDir = {0};  

 double Numerator = 0.0, Denominator = 0.0, dist = 0.0;

 vLineDir = Vector(vLine[1], vLine[0]);  //得到线向量

 vLineDir = Normalize(vLineDir);         //标准化

 

//注意1:为什么要加负号,假设线段方向从平面正面指向背面。求线段到线段和平面间交点的距离(为正)

//1.点在平面正面,x1:Ax+By+Cz+D>0,线段方向和法向量的夹角x2:cos<0,dist=-x1/x2>0

//2.点在平面背面,x1:Ax+By+Cz+D<0,线段方向和法向量的夹角x2:cos<0,dist=-x1/x2<0

//在最终计算交点交点时, vPoint.x = vLine[0].x + vLineDir.x * dist;

//不管点在哪一面,交点始终指向平面

//注意2:线段:起点
vLine[0],方向vLineDir,定义射线 vLine[0]+t*vLineDir

//Ax+By+Cz为原点到平面的距离,在之前定义了Ax+By+Cz+distance=0

//所以原点到已知平面的距离为 -distance

//若线段和射线相交( vLine[0]+t*vLineDir)*vNormal=-distance

//t=(-distance-vLine[0]*vNormal)/(vNormal*vLineDir)

Numerator = - (vNormal.x * vLine[0].x +  vNormal.y * vLine[0].y +

              vNormal.z * vLine[0].z + distance);  //线段起点到平面的距离

Denominator = Dot(vNormal, vLineDir); //法线和线段夹角的cos值

  if( Denominator == 0.0)      //如何平面法向量和线段垂直,线段在平面上,返回线段上任意一点

     return vLine[0];  

dist = Numerator / Denominator;  //线段起点到和平面交点的距离

 vPoint.x = (float)(vLine[0].x + (vLineDir.x * dist));

 vPoint.y = (float)(vLine[0].y + (vLineDir.y * dist));

 vPoint.z = (float)(vLine[0].z + (vLineDir.z * dist));

 return vPoint;       

}

辅助函数2:InsidePolygon()判断点是否在多边形内

思路:当点在多边形内时,点和多边形任意两个角形成的角度之和等于360

bool InsidePolygon(CVector3 vIntersection, CVector3 Poly[], long verticeCount)
{

 const double MATCH_FACTOR = 0.9999;  

 double Angle = 0.0;    

 CVector3 vA, vB; 

for (int i = 0; i < verticeCount; i++)  

 { 

  vA = Vector(Poly[i], vIntersection); 

  vB = Vector(Poly[(i + 1) % verticeCount], vIntersection);

            

  Angle += AngleBetweenVectors(vA, vB); //返回(vA*vB)/(|vA|*|vB|)的arcos

 }

 if(Angle >= (MATCH_FACTOR * (2.0 * PI)) ) 

  return TRUE;        

 return FALSE;        

}

3.求一个球的球心到一条线段上的最近点,参数:线段点1,线段点2,小球球心

 ClosestPointOnLine(g_vLine[0], g_vLine[1], g_vPosition);

思路:球心vPoint,线段起点vA,终点vB,求出线段起点到小球球心向量在线段上的投影长度,

线段起点+投影长度*线段方向即为所求

CVector3 ClosestPointOnLine(CVector3 vA, CVector3 vB, CVector3 vPoint)

{

   CVector3 vVector1 = vPoint - vA;   //线段起点到小球球心向量

   CVector3 vVector2 = Normalize(vB - vA); //线段方向

   float d = Distance(vA, vB);          //d为线段长度

   float t = Dot(vVector2, vVector1);   //t为投影长度

   if (t <= 0)  //如果投影长度<0,为起点为最近点

      return vA;

   if (t >= d)  //如果投影长度>线段长度,终点为最近点

       return vB;

   CVector3 vVector3 = vVector2 * t;

   CVector3 vClosestPoint = vA + vVector3;

 

  return vClosestPoint;

}

收藏到:Del.icio.us


http://www.blogbus.com/public/tb.php/4811502/53944554/7803cbb58abefd43d9c7275fd48

抱歉!评论已关闭.