游戏开发中的基本物理学知识

时间:2022-04-21 03:26:36


第三章:不能再简单的世界


在真正开始编写之前,先回顾一下初中学过的经典物理的知识,OK,闭上眼睛想三分钟,嗯,动量守恒,摩擦系数,胡克定律,弹性碰撞。。。是不是突然想到了很多,但是并不系统,这里就简单的,系统的总结一下游戏中需要物理学知识(更详细的推荐《游戏开发物理学》)。


在物理世界的仿真中,一般我们至少要进行以下三种现象的仿真。

1.线性运动:包括定加速,不定加速运动,考虑摩擦力,压差,重力,阻尼,浮力等。

2.旋转:要计算角速度,力矩,转动惯量等。

3.弹性碰撞:包括完全弹性碰撞,非完全弹性碰撞,完全非弹性碰撞等。


关于二维和三维坐标系的知识就不做介绍,关于公式的推导也都省略了,只给出实用的结果公式。


注:以下公式中:*表示乘法,也是点积;×表示叉乘(外积),^表示幂。


第一节:线性运动


为了仿真物体的线性运动,需要知道计算物体的质量,速度,如果要考虑摩擦力,还需要物体的摩擦系数,要计算重力,需要引力常数等。

质心

对于组合物体,如飞船由引擎,人员,船身等各个部分组成,而不同部分的重量不同,在计算物体线性运动时,施加在物体上的力,都看做是施加在物体质心上的,所以在计算物体运动之前要先算出物体的质心。

Mc =  ∑(mc_i * m_i ) / m

Mc是物体合并后的质心,mc_i是物体中每个质点的坐标(二维或三维空间下的向量),m_i是每个质点的质量,m是物体的总质量。

牛顿第二定律

这是计算线性运动的基本定律,即根据作用在物体质心上的合力计算物体的加速度:

∑F = m*a

m是物体的质量,a是在力作用下的加速度,F是施加在质心的合力,Fa都是向量。一般把F分解为沿着空间坐标轴的分量计算沿着不同坐标轴的加速度。如果运动过程中∑F不变,则成为定加速运动,如果F再运动中变换就是变加速运动。

定加速运动

物体的及时速度 v是由上一时刻速度v'和加速度a 决定的,

v = v' + a * t

这个就不解释了,同理:

s = v * t + 1/2 * a * t^2

变加速运动

因为物体在运动中会受到阻力(这里说的不同于摩擦力),阻力一般与速度的平方成正比,由此可知阻力引起的反加速度也与速度的平方成反比:

a = -k * v^2

a既是阻力引起的加速度,k为常数而负号表示方向相反。对于此类变加速运动,及时速度为:

v = v' / (1 + v' * k * t)

v'是上一时刻的速度,t是经过的时间。而距离公式为:

s =ln(1 + v' * k * t)  /  k

其中va都是向量,ln是自然对数,在二维和三维空间中可以分别分解为坐标轴的不同分量进行计算。

各种力

说了这么多可能还有人有疑问,各种合力都是那些力啊,首先说一下重力,重力是万有引力的特殊形式,引力公式如下:

Fa = G * m1 * m2 /  r^2

G是万有引力常数,m1m2是两个物体的质量,r是物体间的距离。根据牛顿第二定律和地球的质量以及引力常数可以求得,海平面附近在地球引力作用下物体的加速度为9.8m/s^2

然后就是物体的摩擦力,物体的摩擦力比较复杂,既是两个物体在压力作用下,某个接触面阻碍相互运动的力。摩擦力公式为:

Ff = p * N

其中N为垂直于接触面的压力,p为接触面的摩擦系数。摩擦系数分为静摩系数和动摩擦系数,即物体在静止时的摩擦系数和运动时。静摩擦系数一般大于动摩擦系数,即是说物体由静止转向运动要克服一个较大的力,当物体处于运动状态则收到的摩擦力较小。摩擦系数是对于两个接触面统一来说的,而一般在游戏中通过分别设置两个物体的摩擦系数来仿真。

之前变加速运动时提到的流动阻力,比如位于两种流体间运动的物体,比如船在空气和水面间,收到水波的影响。流动阻力一般和速度的平方成反比

F = C * v^2

C为阻力系数。还有就是物体在液体中的浮力,由液体的压强差决定:

F = F_b - F_t

F_b = P * A = p * g * h * A

浮力既是物体在不同高度受到的压力差如(F_b,F_t)决定的,而压力是压强P乘以接触面积A,液体压强P是液体深度h乘以密度p再乘以重力加速度g

在仿真过程中还经常遇到弹力的例子,根据胡克定律,弹力是由于物体伸长或缩短而受到的力:

Fs = ks * ( L - r )

ks是弹力系数,L是物体伸长或缩短的长度,r是原先的长度。另外阻尼常与弹力联合使用,阻尼是抵消相对速度的力,

Fd = kd * ( v - v')

kd是阻尼常数。两个公式合并后为:

F = -( ks * ( L - r ) + kd * ( ( v - v' ) * L ) / s ) * L / s

L为弹簧阻尼单元的长度向量,而sL的长度。利用弹簧阻尼单元可以用来仿真布料,将布料网格每个交叉点看做粒子,与周围粒子靠弹簧/阻尼公式连接,这样每个粒子在重力,风等的作用下,网格就呈布料的特性。


第二节 旋转


介绍完线性运动,基本上大部分的力和定理都明白了,但是对于刚体的仿真,在力作用到刚体上时,根据作用点的不同不但会产生线性运动,还会产生转动。计算产生的转动需要的量有力矩和转动惯量。

转动惯量

转动惯量是物体绕轴旋转,其质量呈辐射分布的度量,用于计算物体的旋转。物体到某一轴的转动惯量计算公式为,其各个质点到该轴距离乘积的积分,如三维空间下,对x,y,z轴的转动惯量公式:

I_x =  ∫(y^2+z^2)dm

I_y =  ∫(x^2+z^2)dm

I_z =  ∫(y^2+x^2)dm

根据转动惯量的公式可知,物体相对于其他平行轴的转动惯量为:

I = I_o + m*d^2

其中m是物体自身的质量,d是两平行轴间的距离,I_o物体相对于自身某转动轴的转动惯量,。当md^2较大时,I_o可以忽略不计。

而对于一些规则物体,其相对于自身转动轴的转动惯量都有可直接计算的公式,如圆柱体,长方体,球体(这也是为什么大多数物理引擎的刚体都支持这些形状的原因之一)。对于这些公式就不再列举了,可以随意查到,有兴趣也可以自己积分一下。

力矩

如果力可以使物体转动,说明作用在物体上的力的力矩不为零,力矩计算如下:

M_cg = r× F

M_cg为力矩,×是叉乘(外积)F为施加在某一质点的力r为该力(向量)的作用线(直线)到质心的距离向量。根据作用力的力矩可以求出物体的转动角加速度的方程。

M_cg = I*a

其中I为转动惯量,是张量,在三维空间中是3x3的矩阵。∑M_cg为作用力矩的总和。a为角加速度。角加速度和角速度都是垂直于旋转轴的向量,二维空间中是标量。这样在计算过程中可能要不断地计算转动惯量和其逆矩阵,为了方便计算,将其化为局部坐标,公式为:

M_cg = I*(dw/dt)+w×(I*w)

w为角速度,t为时间,这样所有量都化成了局部坐标,除非物体质量或形状发生变化,不然物体的转动惯量是常数。


第三节 碰撞


冲量定律

动量就不介绍了,冲量是碰撞前后动量的变化:

Jf = m * ( v - v' )

Jm = I * ( w - w' ) 

m是物体质量,I是转动惯量,w,v是碰撞后的角速度与线速度,w',v'是碰撞前的角速度与线速度。Jf是线性冲量,Jm是角冲量。其中角冲量与线冲量的关系为:

Jm = Jf × r

即线冲量作用线与其到重心的距离向量的外积。因为外积满足分配率,由此可知角动量与线动量的关系。

动量守恒定律

动量守恒定律揭示了两个物体m1m2碰撞前后速度的关系:

m1 * v1 + m2 * v2 = m1 * v1' + m2 * v2'

其中v1,v2m1,m2碰撞前的线速度,v1',v2'm1,m2碰撞后的线速度。这里的v是线速度,如果是角速度则不成立。

能量守恒定律

能量守恒定律表示碰撞的两个物体能量不会损失:

m1 * v1^2 + m2 * v2^2 = m1 * v1'^2 + m2 * v2'^2

参数同上,根据这两个公式可以求出两个物体碰撞后的速度。

但是能量守恒定律都是对于完全弹性碰撞而言的,即刚体形状不发生变化,因为物体形状发生变化要消耗能量,能量消耗就不守恒了。为了仿真非完全弹性碰撞给出了弹性恢复公式:

e = (v1 - v2) / (v1' - v2')

e是恢复系数,根据碰撞物体不同而不同。其中当e=0是完全非弹性碰撞,即碰撞后两个物体合为一个,e=1是完全弹性碰撞即能量守恒。配合动量守恒公式,就可以求出碰撞后两物体的速度了。

最后在计算一些复杂运动物体时,物体碰撞面的线速度是由当前物体的线速度和旋转的角速度组成的,线速度v与角速度w的转换如下:

v = w × r

即线速度是角速度与接触点到质心向量的外积。这里v,w,r都是空间中的向量。


介绍完基本的物理定律,在系统中计算流程一般如下:

1.初始化时计算物体重心,转动惯量

2.在循环仿真中,先计算作用力的合力,力矩,如摩擦力,阻力,重力

3.根据动量定律,速度方程等更新物体位置

4.如果发生碰撞,根据动量守恒定律,角速度与线速度的关系,建立方程即可求得碰撞后的物体状态


这样游戏开发中遇到的基本物理学知识就差不多了。以上的不少变量都是向量,在二维和三维的系统中处理时要用到向量和矩阵运算,有关物体平移,旋转,缩放的操作之后再介绍。