碰撞检测仅针对潜在碰撞列表中的物体对展开。此时,仿真引擎遍历列表中的每个对象,检测这对物体是否真正发生碰撞。同时,按碰撞时间递增顺序排列,建立整个场景中所有碰撞的全局碰撞列表。整个过程如下。
(1)检查物体的层次表达是否在t1时刻相交。如果没有相交,则物体对被忽略。
(2)如果成功检测到相交,则通过时间回溯,将碰撞对象回到(用线性插值)碰撞刚要发生的那个时间,即碰撞物体刚要相交的时间,确定为近似碰撞时间。
(3)在碰撞时间,将从物体位置和方向获得的碰撞信息(最近特征[3]和距离)添加到全局碰撞列表(按碰撞时间递增排序)。
这个过程结束时,潜在碰撞列表被清空,全局碰撞列表可能有或没有物体对。如果没有检测到碰撞,则仿真引擎将当前仿真间隔中物体移动后的新位置和方向传给渲染引擎。否则,仿真引擎利用全局碰撞列表信息处理系统中所有的有效碰撞,包括识别每个碰撞物体的最早碰撞或同时碰撞。注意,在涉及已经碰撞的物体时,随后检测到的任何碰撞都不考虑,因为最早的碰撞将改变剩余时间间隔中碰撞物体的动力学状态。换句话说,早期碰撞求解后,物体运动的更新不应受后续时间碰撞检测的影响。
在全局碰撞列表中,从第一个对象开始,仿真引擎经过以下步骤计算每个对象的最早碰撞。特别地,一个物体对同时发生多个碰撞,则多个碰撞被加到一个碰撞组。在不同的时间(后续时间),碰撞列表中下一个有效碰撞对出现时,碰撞组才进行处理。
(1)在当前的碰撞对,检查是否有包含早期碰撞的任何物体。如果是,则忽略这个碰撞对,并移到全局碰撞列表中的下一组物体对。
(2)如果碰撞组为空,则用当前碰撞对进行初始化,移到全局碰撞列表中的下一组物体对。
(3)如果在当前碰撞组中已经有一个或多个碰撞对,则比较和碰撞组有关碰撞对与当前碰撞对的时间。(www.xing528.com)
①如果在用户调整误差范围内,时间相同,则认为这是一个同时碰撞,并把当前碰撞对加到碰撞组,移到全局碰撞列表中的下一组物体对。
②如果当前碰撞对和碰撞组的时间不同,则计算碰撞组中的同时碰撞。结束后,重设碰撞组,仅包含当前碰撞对,移到全局碰撞列表中的下一组物体对。
(4)如果碰撞组非空,当到达全局碰撞列表的末尾时,计算碰撞组中的碰撞。
最后,每一个碰撞物体的最早碰撞或同时碰撞都已求解完毕(见2.5节中碰撞求解概述)。更新每一个物体的最终位置和方向,以反映碰撞导致的物体动力学状态的变化。这个变化是通过对在碰撞时间和当前时间间隔末尾的剩余时间重新进行数值积分获得的。
因为碰撞引起的变化影响了物体的轨迹,仿真引擎需要再次检查是否存在新的碰撞。理论上,这个循环会继续进行到当前时间间隔内没有任何其他碰撞。事实上,仿真引擎需要有一种机制,这种机制负责处理碰撞迭代次数无限制增加这样的特殊情形。例如,考虑一个有很多仿真物体的系统,这些物体被许多其他邻近的运动物体包围。在每次迭代中,随着碰撞的求解,物体的新轨迹很大可能将与周围其他物体的轨迹相交,在下次迭代中引入新的碰撞。这可能在物体之间产生“反弹”效应,持续地在将来的碰撞检测中引入新的碰撞。很明显,求解这些情况下的所有碰撞需要大量的碰撞迭代。
为了解决这些不稳定的情况,我们打算创建一个用户定义的参数来限制执行的碰撞迭代次数的最大值。达到这个值后,仿真引擎覆写物体的物性参数,在所有将来的碰撞迭代中只使用非弹性碰撞(恢复系数为0)。这样的话,每次非弹性碰撞后碰撞物体间的相对运动就变为0,它们也不会发生回弹。这个简单的改变可以显著提高系统整体的性能和稳定性,因为在后续迭代中被引进的新的碰撞数量大大减少了。
总的来说,两物体间碰撞时间的求解依赖于能跟踪未相交时最近点间距离的技术,或者相交时的穿透深度。通常,物体在t0时刻开始于一个未相交位置并且已知将在t1时刻相交。在物体随着时间从t0到t1时刻移动的过程中,它们最近点间的距离减小直到到碰撞点tc变为0,其中t0≤tc≤t1。同样,随着物体逆着时间从t1到t0移动的过程中,它们的穿透深度减小直到在碰撞点变为0。无论哪一种方式,碰撞时间的求解都是一个迭代过程,递增地顺着从t0时刻或者逆着从t1时刻一步一步地移动,直到到达碰撞点,达到一个用户定义的阈值。当新的一次迭代中的最近点信息能从之前迭代中已经计算出的最近点信息中获得时,效率就提高了。计算中实际用到的算法取决于碰撞物体的形状和相对速度。更一般的非凸体形状需要计算量大的算法来计算它们的碰撞时间,而凸体则采用依赖于它们的凸特性的高效专用算法来正确执行。快速移动和稀疏物体采用连续碰撞检测进行处理,考虑从t0到t1时刻它们的轨迹,而不只是它们的在t1时刻的位置和方向。所有的这些方法将会在后续章节中详细介绍。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。