基于物理冲量模拟的刚体碰撞(图形学Games103)
雪风carel
2022年02月06日 19:19
收录于文集
共7篇

最近闲来无事,就看了下games103的课,感觉很有意思,做了下作业,写一下心得。视频效果如下B站链接。物理碰撞​

整个模拟过程需要对刚体的坐标,角度,线速度,角速度,力,力矩,转动惯量张量,冲量进行维护和管理,所以我在fixedUpdate里进行更新和维护(而shape matching是非物理)

我们可以把刚体的运动总是分解成它的质心的以速度v的平移运动和绕着质心的角速度为w的旋转运动。所以以下都是以更新v和w为目前的物理模拟。

1.力和力矩

     力的三要素为:作用力的方向,作用力的大小,作用点。用个结构体去包一下。

本次模拟考虑重力和空气阻力。重力就不多说了。这里空气阻力这里做了简化处理,不考虑气动外型,故作用点在质心,大小为线速度*线速度阻尼系数,方向为线速度的反方向。

力矩部分:只考虑空气阻力矩,比较简单。空气阻力矩大小为角速度*角速度阻尼系数,方向与角速度相反。

碰撞产生的力和力矩:碰撞产生力之后使用平移轴定理分解成作用于质心的力和力矩。理论上也要归纳在上面,但是它是瞬时产生的,我们直接用冲量和冲量矩进行单独处理即可。

2.转动惯量张量

转动惯量张量J是一个矩阵,其对角线组成的向量为转动惯量,其他元素为惯性积。大学力学有讲这里我就不班门弄斧了。

3.线加速度和角度加速度

上面已经计算出来了力和力矩,直接计算即可。

4.速度,角速度,坐标,角度

根据线加速度->速度,根据角度加速度->角速度,根据速度->坐标,根据角速度->角度。

5.碰撞检测

目前对碰撞检测做得比较简单,使用了最简单的sdf进行检测。每帧检测每个粒子的sdf是否小于0(在内部),为了节省计算我把坐标转换到局部空间下进行计算,不然每个粒子都要转换到世界空间比较费。如果sdf小于0,则应该进行碰撞响应把模型弹出去,由于我们想尽量减少碰撞响应,故那些粒子的sdf小于0,但是速度方向和sdf的梯度方向相同的则不进行碰撞响应(说明粒子在远离)。

6.碰撞响应

在进行碰撞响应时,墙面会给我们的物体的碰撞点一个冲量,如果能得到这个冲量,利用平移轴定理分解成作用于质心的冲量和冲量矩,就能计算出新速度和新的角速度。但是直接求冲量是很难的,但是我们可以求碰撞前和碰撞后的碰撞点的速度变化,来得到一个冲量。然后再用平移轴定理,即可计算速度和角速度。 首先我们需要计算碰撞点的碰撞前后速度变化。

当触发碰撞响应时,我们把进入碰撞响应的粒子作为一个碰撞点,求其平均坐标和平均速度(局部空间)。

然后把速度分解成垂直于SDF梯度方向和平行于梯度方向的2个分量。平行于SDF梯度方向的速度会发生反向,而垂直于SDF梯度方向就会因为摩擦而减速甚至为0。

速度的分解

其中摩擦损失系数的计算,王老师给出了基于库伦定律公式,如下图。

基于库伦定律的摩擦力公式(反正我没推导过)

然后知道了老的速度和新的速度,就可以计算出作用于该碰撞点的冲量了。这里我们需要把它转换到世界空间下进行计算,其代码如下。

得到作用于该作用点的冲量后,使用平移轴定理把作用点平移到质心位置,进行分解成冲量矩和冲量。然后分别更新物体本身的速度和角速度。

其中我们发现,如果碰撞前本身的线速度很大,物体就会卡进墙里,我们把它朝sdf方向顶出去(不过这个就不物理了)。

最终,我们就得到了完整的物理模拟了。我的代码不一定完全正确,有错误欢迎指出。

参考:Games103的课程链接。http://games-cn.org/games103/