碰撞检测算法
碰撞检测算法有很多,直接检测代价很大,一般使用多种算法进行优化。
首先会对物体生成包围盒,例如AABB包围盒,该盒的面平行于XYZ轴,对包围盒是否碰撞进行检测,如果包围盒碰撞,那么就需要进一步检测。我们还会对物体生成凸多面体进行包围。当然碰撞检测一般针对的是动态物体和动态物体或者动态物体和静态物体。
粗略阶段:
1.利用空间划分,例如使用八叉树,划分后不在同一节点的两物体可以认为不会碰撞。
2.N个物体两两检测的话代价为O(N²) 可以使用Sweep and Prune算法,该算法的思想是在X,Y,Z三个轴上对AABB包围盒进行Overlap检测,包围盒只有在三个轴上的投影重叠才算相交。做覆盖检测前首先要对各个包围盒按轴的坐标进行排序,代价为O(nlogn),但是可以利用帧间一致性(这个思想是如果上一帧排序了,下一帧只要对运动的物体进行插入排序即可,即插入排序)这样代价为O(N)
中间阶段:
将物体用复合包围盒进行包围,例如椅子可以用两个不同大小的长方体包围,遍历这些结构,找到可能碰撞的子包围盒。
精确阶段:
这一阶段需要对凸多面体进行检测,可以使用两个算法。
1.分离轴定理(separating axis theorem) 。对凸多变体每个面作为可能的分离轴的面,作过原点的垂直于分离平面的线,求每个面在该线上投影,看是否重叠,如果所有情况下都重叠,则相交。
2.GJK算法。该算法依赖于闵可夫斯基差,即对AB两物体每对点作减法,看做差后的点是否能形成一个过原点的四面体。GJK是一个迭代算法,即先随意找一个四面体,看哪个方向靠近原点,搜寻原点附近的点加入到当前点集中,不断迭代直到找到一个过原点的单纯体,或者失败。