碰撞检测阶段总结

最近调整碰撞检测,总结出以下:
(1).球和棱碰撞,碰撞法向量不是与棱相接的两个平面的法向量的和的单位向量,而是碰撞点到球心的向量。法向量要先求出,然后才能算碰撞点,法向量可以通过表示棱的向量 和 棱上一点到球心向量 的向量三重积求出。
球和点碰撞法向量好找,就是半径向量。
即:面和棱、点碰撞,碰撞法向量为那个面在碰撞点的切平面的法向量

(2)碰撞检测树可以改进成多种节点相结合的,让它们都实现一个接口ICollisionTreeNode,抽象出来method和property,分割时估算一下顶点线性相关程度,然后再选择子节点类型。

BTW:
发现最基础的问题比如几何体求交,别人都不怎么重视。也许是他们足够NB,不需要注意。一个球和三角形求交,还不是最精确的(边的求交不是直线和二次曲面求交那种,这种一个球和一条线段只能求出一个点),竟然被我弄了好几天才弄出来(+优化)。以后加上任意形状刚体那估计更不好说。
由于建碰撞树时的近似处理,当分割较BT的网格时,一个大的三角形组将会 分不成 多个小三角形组,造成递归至堆栈溢出。所以应该狠一下,精确处理。



至此,球和Tri-mesh的碰撞检测&处理就彻底OK了。接下来是Tri-mesh和Tri-mesh的……另外,最好实现OBB树。
当然,与平面有关的就比较简单,不提了。
球和Tri-mesh碰撞包括:
  球和静态物体的碰撞
  球和任意刚体的碰撞

留图


附:
球和三角形相交检测,以下过程按顺序执行,一旦相交就return,停止和这个三角形继续检测:
(1).判断球心与三角面垂直且过三边的平面的位置关系,如果被包围,那么直接判断球心到三角面所在平面距离是否<=半径
(2).根据(1)的结果,如果球心在哪条边外,那么试着和那条线段求交
(3).判断球心到三角形某顶点距离<=r

球和线段求交:
(1).计算线段包围球,检查求和这个包围球是否相交(好像可以省略判断,速度差不多)
(2).若相交,用一开始提到的向量三重积计算出法向量,用投影长算距离,算碰撞位置。
(3).判断距离是否小于半径 且 碰撞位置在线段包围球内

代码
(注:Intersect是包围球的一个方法,包围球有字段vCentre,dRange,
%为向量积运算符,&为两点距离运算符,^为两点距离平方运算符)
        /// <summary>
        
/// 判断线段是否和包围球相交
        
/// </summary>

        public bool Intersect(Vector vStart, Vector vEnd, out double dist, out Vector n, out Vector pos)
        
{
            Vector v 
= 0.5 * (vStart + vEnd);
            
double r = 0.5 * (vStart & vEnd);

            
if ((v & vCentre) <= (r + dRange))
            
{
                Vector v1 
= (vCentre - vEnd);
                Vector v2 
= (vStart - vEnd);

                n 
= (v2 % v1 % v2).UnitVector;
                dist 
= v1 * n;
                pos 
= vCentre - dist * n;

                
return (dist <= dRange) && ((pos ^ v) < r * r);
            }

            dist 
= 0;
            n 
= new Vector();
            pos 
= new Vector();
            
return false;
        }
posted @ 2007-07-13 23:54  Yuri  阅读(1373)  评论(0编辑  收藏  举报