老实说……看书的吃力程度……令我想起了那年被普物虐的恐怖……但是更恐怖的是,其实我知道这些本不应该很难理解的……
所以,怎么说呢,自强吧~
两个无转动的碰撞的计算
可以抽象为如下问题:
两个物体质量分别为 m1、m2,速度分别为 v1、v2,碰撞的法线为 n(以v1为参照),碰撞时损失的动量的百分比为 r,需要求碰撞后的速度。
计算方法:
- 在 n 垂直的方向上,速度不变,只计算 n 方向上的速度变化;
- 用质心系去理解和计算 n 方向上的速度变化。
技巧:
- 在存储物体质量的时候,采用质量的倒数:1/m1、1/m2,从而既涵盖infinity的情形,也方便了上边的计算。
转动的计算
部分原理
- 惯性张量
三维空间中的单个粒子,可以用一个3x3的矩阵来描述他的惯性张量:
I=⎧⎩⎨⎪⎪IxIxyIxzIyxIyIyzIzxIzyIz⎫⎭⎬⎪⎪(1)
通过恰当的指配相关参数,可以模拟普通刚体旋转
2. 气动张量
对于被风速影响的物体,如帆船和机翼等,可以用气动张量来模拟,为了达到最好的效果,可以在风速达到最大最小的时候分别设定,然后对实际风速进行插值。
3. 对浮力而言,可以将物体分块并分别计算浮力,来模拟帆船倾覆等情形。
碰撞
范围检测
- 球形包围盒
父亲包围所有孩子;孩子分属于左还是右取决于在哪边时对于球体的半径增长最小 - 多分辨率网格
碰撞检测
- 不规则的物体可以通过适当的分割,用一系列规则几何体(长方体和球体)来模拟
- 球、长方体之间的碰撞,根据点、边、面的接触,会有多种情况:
- 分别计算最深交点、法线
- 每帧中只处理一个相交,将其加入相交集中;如果物体是运动的,那么其后的帧中很可能不再失效;这里可以只存储碰撞的信息,不必存储物体的信息
碰撞处理
- 步骤如下:
- 计算碰撞处的各种局部坐标系,方便后边使用
- 计算碰撞点处每单位冲量的速度变化值,注意线性运动和角运动都要考虑
- 根据上边的值,计算碰撞处的速度变化
- 计算其相应的冲量的变化
- 将冲量变化转变为线性速度和角速度的变化
- 每单位冲量的速度变化值:
- 线性分量:质量的倒数
- 旋转分量:力方向(碰撞法线)和到碰撞点到质心距离的叉积的倒数
- 以上二者的和
- 相交处的分离
- 如果直接法线方向,线性平移两个物体,直至他们分离(需要计算之前走这么远所用的时间),那么对于侧面而来的物体,会有显得在表面“擦”过了一段距离。
- 可以加入旋转分离,虽然不能完全模拟真实情况,但是已经很好了
- 松弛法
- 每次处理一小部分内容,多次处理,使结果趋于平衡
- 防止旋转过大
- 物体小而速度快时,可能导致无论怎么旋转都不能分离;物体还有另一点即将碰撞时,旋转可能导致另一个碰撞
- 可以简单地规定最大的旋转距离,超出的部分转移到线性运动上,不过建议可以根据对象尺寸来定,小物体可能需要比较大的上限
静态接触
- 反作用力:在作用力中加上反作用力
- 微碰撞:施加一系列较小的冲量
- 移除源自前次更新操作中的、基于加速度的速度数据
- 对于低速碰撞,降低其回弹系数
- 选择性的忽略重力
- 摩擦力
- 可以使用上述微碰撞的方法
- 包含旋转和平移
稳定性和优化
- 四元数漂移
- 误差导致四元数不再是标准化的:应当适时地进行标准化
- 斜面上的相交
- 不停地相交和分离导致斜面上的物体往下移动:计算加速度引起的速度变化时,将这部分在法线方向上的分量置为0
- 每帧计算的误差:
- 计算每帧速度实际上是把每帧都当做匀速来看待了,当加速度较大时与实际不符,此时可以采用 距离-加速度 式
- 当每帧之间的加速度也变化很大时,例如弹簧,可以用Runga-Kutta积分
- 休眠
- 相交时,设置阈值,来处理误差情况
- 根据碰撞情况可以设置分组