碰撞检测中函数(线与面,线与多边形,点到线的最近点) _ 转 - [
转载地址:http://sakishum.blogbus.com/logs/53944554.html 1、线和平面碰撞。传入参数:线(起点,终点),平面(三个顶点) 调用:IntersectedPlane(vTriangle,vLine); bool IntersectedPlane(CVector3 vTriangle[],CVector3 vLine[]) // originDistance 为 Ax+By+Cz+D=0中的D (A,B,C为法向量) float originDistance = PlaneDistance(vNormal,vTriangle[0]);
//求出线段两端点到平面的距离,若距离相乘为负,相交,否则不相交 distance1 = ((vNormal.x * vLine[0].x) +// Ax + (vNormal.z * vLine[0].z)) + originDistance;// Cz + D distance2 = ((vNormal.x * vLine[1].x) +// Ax + if(distance1 * distance2 >= 0) return false; } 2.线段和多边形相交,参数:多边形顶点数组,线段,多边形顶点个数 IntersectedPolygon(vTriangle,vLine,3); bool IntersectedPolygon(CVector3 vPoly[],CVector3 vLine[],int verticeCount) //如果不和多边形所在平面相交,则不相交 if(!IntersectedPlane(vPoly,vNormal,originDistance)) //求出线和平面的交点 CVector3 vIntersection = IntersectionPoint(vNormal,originDistance); //如果交点在多边形内,就相交 if(InsidePolygon(vIntersection,vPoly,verticeCount)) return false; 辅助函数1:IntersectionPoint()返回线和平面的交点 思路:求出点与点和平面交点的距离1,用起始点+线段方向*距离1,求出交点 CVector3 IntersectionPoint(CVector3 vNormal,double distance) { 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 + Denominator = Dot(vNormal,vLineDir);//法线和线段夹角的cos值 if( Denominator == 0.0)//如何平面法向量和线段垂直,线段在平面上,返回线段上任意一点 return vLine[0]; dist = Numerator / Denominator;//线段起点到和平面交点的距离 vPoint.x = (float)(vLine[0].x + (vLineDir.x * dist)); return vPoint; 辅助函数2:InsidePolygon()判断点是否在多边形内 思路:当点在多边形内时,点和多边形任意两个角形成的角度之和等于360 bool InsidePolygon(CVector3 vIntersection,CVector3 Poly[],long verticeCount) double Angle = 0.0; CVector3 vA,vB; for (int i = 0; i < verticeCount; i++) { vB = Vector(Poly[(i + 1) % verticeCount],vIntersection); if(Angle >= (MATCH_FACTOR * (2.0 * PI)) ) return TRUE; } 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);//线段方向 if (t <= 0)//如果投影长度<0,为起点为最近点 CVector3 vClosestPoint = vA + vVector3; return vClosestPoint;
收藏到:
Del.icio.us
http://www.blogbus.com/public/tb.php/4811502/53944554/7803cbb58abefd43d9c7275fd48 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |