Open phenomLi opened 5 years ago
碰撞求解是紧接着碰撞检测后的一个步骤,顾名思义就是对发生碰撞的对象进行碰撞反应的模拟,比如反弹旋转等。碰撞求解可以说是物理引擎里最难的部分之一了,但是放心,这篇文章会先从最简单的向量部分入门,利用简单的向量知识,模拟简单的碰撞效果。
该文章只涉及少量简单数学,请放心食用。要求:
我们先从最基本的开始,考虑在理想情况下(无重力,阻力,完全弹性碰撞)有一些球在盒子里自由运动的情况: 其中箭头方向代表球的速度方向。
先不考虑球与球直接的碰撞,那么在盒子中,球只会与墙壁发生碰撞,通过碰撞不断改变球的速度方向(大小不变)。我们可以想象到,当球碰撞墙壁时,它的运动轨迹是这样的: 其中蓝色向量代表球碰撞前的速度,红色向量代表球碰撞后的速度。
所以显然的,要求解球碰撞墙壁后的速度方向就是要求红色向量。 为了求解红色的向量,我们可以对这次碰撞进行建模:
u代表碰撞前速度,v代表碰撞后速度,n代表碰撞法向,且u,v关于n对称。碰撞法向n通常情况下不容易求得,但是由于现在情景简单,所以这里我们可以一眼看出n就是垂直与墙壁平面的向量。注意n是一个单位向量。
现在u和n都是已知的,我们要做的就是用u和n去表示v。现在还是不好求出v,但我们可以把v平移到u的起点,然后延长n,延长后的n记为n'。
这时,我们很容易得到一个关键等式: 所以只要求出n'就可以了。那么怎么求呢?观察发现,由于u,v是等长的,u,v和n' 形成了一个等腰三角形,我们可以用投影解决。
首先,我们把u投影到n'上,得到1/2|n'|。 将结果乘上2便得到n'的模长,再由于n'和n是共线的,且n为单位向量,所以只要将n乘上n'的模长即可求得n':
最后,我们把n'换一下,得到v关于u,n的表达式:
解决了。很简单。
其实整个流程要注意的只有一点,就是n的方向,如果n是指向墙壁外的,那么最后的表达式就要加号换成减号。
有了上面的基础,求解球与球的碰撞就水到渠成了,只要解决两个问题就好:
球与球的碰撞法向其实也很简单,相信大家都能看出来是两个球圆心间的向量: 求得后将其单位化即可。
其次对于求解另一个球的v,只要取反向碰撞法向即可,也就是上面说到的加号变减号的情况。
本文只是碰撞求解的入门,在物理引擎中使用上面的方案其实是不现实的,因为对象还包含旋转,摩擦力和非弹性碰撞,单一的求出速度并不能解决所有问题。本文旨在让大家了解什么是碰撞求解,以及对其有个大概的认识。
碰撞求解是紧接着碰撞检测后的一个步骤,顾名思义就是对发生碰撞的对象进行碰撞反应的模拟,比如反弹旋转等。碰撞求解可以说是物理引擎里最难的部分之一了,但是放心,这篇文章会先从最简单的向量部分入门,利用简单的向量知识,模拟简单的碰撞效果。
该文章只涉及少量简单数学,请放心食用。要求:
球与墙壁的碰撞
我们先从最基本的开始,考虑在理想情况下(无重力,阻力,完全弹性碰撞)有一些球在盒子里自由运动的情况:
其中箭头方向代表球的速度方向。
先不考虑球与球直接的碰撞,那么在盒子中,球只会与墙壁发生碰撞,通过碰撞不断改变球的速度方向(大小不变)。我们可以想象到,当球碰撞墙壁时,它的运动轨迹是这样的:
其中蓝色向量代表球碰撞前的速度,红色向量代表球碰撞后的速度。
所以显然的,要求解球碰撞墙壁后的速度方向就是要求红色向量。
为了求解红色的向量,我们可以对这次碰撞进行建模:
现在u和n都是已知的,我们要做的就是用u和n去表示v。现在还是不好求出v,但我们可以把v平移到u的起点,然后延长n,延长后的n记为n'。![](https://github.com/phenomLi/myBlog/raw/master/photos/2019-8-7/微信截图_20190807111450.png)
这时,我们很容易得到一个关键等式:
所以只要求出n'就可以了。那么怎么求呢?观察发现,由于u,v是等长的,u,v和n' 形成了一个等腰三角形,我们可以用投影解决。
首先,我们把u投影到n'上,得到1/2|n'|。
将结果乘上2便得到n'的模长,再由于n'和n是共线的,且n为单位向量,所以只要将n乘上n'的模长即可求得n':
![](https://github.com/phenomLi/myBlog/raw/master/photos/2019-8-7/微信截图_20190807111521.png)
最后,我们把n'换一下,得到v关于u,n的表达式:![](https://github.com/phenomLi/myBlog/raw/master/photos/2019-8-7/微信截图_20190807111531.png)
解决了。很简单。
其实整个流程要注意的只有一点,就是n的方向,如果n是指向墙壁外的,那么最后的表达式就要加号换成减号。
球与球的碰撞
有了上面的基础,求解球与球的碰撞就水到渠成了,只要解决两个问题就好:
球与球的碰撞法向其实也很简单,相信大家都能看出来是两个球圆心间的向量:
求得后将其单位化即可。
其次对于求解另一个球的v,只要取反向碰撞法向即可,也就是上面说到的加号变减号的情况。
最后
本文只是碰撞求解的入门,在物理引擎中使用上面的方案其实是不现实的,因为对象还包含旋转,摩擦力和非弹性碰撞,单一的求出速度并不能解决所有问题。本文旨在让大家了解什么是碰撞求解,以及对其有个大概的认识。