游戏引擎架构----物理部分
2017-05-23 16:05
260 查看
1. 碰撞检测系统
物理世界
形状:
相交、
接触(分离矢量,沿该矢量运动就能高效脱离碰撞妆容)、
凸(由形状内发射的光线不会穿越形状两次以上)
原型:
球体、
胶囊体、
轴对其包围盒AABB、
定向包围盒OBB、
离散定向多胞形discrete oriented polytope DOP、
任意凸体积、
多边形汤(碰撞引擎必须和每个三角形测试)、
复合形状
碰撞测试:
点和球体相交
球体和球体相交
分离轴定理:凸形状于该轴(分离轴)上的投影不重叠,能确定两个形状不相交。分离两个物体的轴/面称为分离线/面。三维空间中,分离轴仍然是个轴,分离线变成分离面。可以把形状逐一投影到各个潜在分离轴,并检查投影区间是否相交
AABB相交:分离轴定理。三个轴x,y,z。只有在三个轴都重叠,才是相交的。
检测凸碰撞:GJK算法。依赖闵可夫斯基差:把A中的所有点与B中的所有点都成对相减,得到的集合就是闵可夫斯基差。当且仅当两个形状相交,闵可夫斯基差包含原点。GJK尝试在闵科夫斯基的凸包内,尝试找出一个包含原点的四面体。若找到,则相交。
运动物体间的碰撞:
离散的静态碰撞;
sweep shape扫琼形状做静态测试(结果不准确);
连续碰撞检测continuous collision detection CCD,求出最早的冲击时间TOI
性能优化:
利用时间一致性避免每帧重新计算一些类型的信息
空间划分
粗略阶段,中间阶段,精确阶段:先AABB测试哪些物体会碰撞;再用符合形状的逼近包围体检测;最终进行青雀的碰撞检测
扫琼裁剪:sweep and prune,对各个膨胀提的AABB的最小,最大坐标再三个主轴上排序,然后通过遍历改有序表检测AABB之间是否重叠
碰撞查询:
光线投射:投射的物体并不存在于碰撞世界,不会影响其他物体。返回一个t值,P = P0 + td
形状投射:返回多个接触点。模拟玩家的脚
Phantom:查询碰撞体是否在其他指定体积里。对于其他碰撞体是透明的,也不参与动力学模拟。
碰撞过滤:决定碰撞体之间的接触是否成立
碰撞掩码及碰撞层:掩码
碰撞回调:回调函数按自己的条件决定接受或拒绝碰撞
碰撞材质:包含碰撞属性,如音效,粒子效果,摩擦系数等等
2. 刚体动力学
6个自由度DOF
线性动力学(质点)
线性速度&加速度
力&动量
运动方程求解
力作为函数:位置、速度、时间等的函数(常微分方程(ordinary differential equation ODE))。类似弹簧
解析解:找到闭合式函数,描述所有可能的时间值t的刚体位置(例如抛物线),但是游戏中几乎不可能。
常微分方程的数值解的特性:
收敛性:delta_t趋近于0的时候,近似解趋近镇世界?
阶数:误差是O(t^?)
稳定性:数值解是否会稳定下来?
数值积分:游戏引擎使用数值积分求解运动方程
显示欧拉
pos(t2) = pos(t1) + v(t1)delta_t
v(t2) = v(t1) + F(t)/m * delta_t
实际是假设在该时间步中,物体速度维持不变。由于位置的斜率就是速度,实际上也能理解为导数的逼近。当delta_t趋近于0的时候是合法的
一阶方法,误差是O(t^2),准确度达到并包括delta_t一次方的泰勒级数
韦尔莱积分
可以仅仅用到加速度就求解位置
pos(t1+delta_t) = 2pos(t1) - pos(t1-delta_t) + F(t1)/m * delta_t^2 + O(t^4)
v(t1+delta_t) = delta_pos / delta_t
速度韦尔莱积分
pos(t+delta_t)= pos(t1) + v(t1)*delta_t + 0.5a(t1)*delta_+t^2
v(t+0.5delta_t) = v(t1) + 0.5a(t1)*delta_t
求a(t1+delta_t) (假设a仅仅依赖位置,如果依赖速度,则需要先计算速度近似值)
v(t+delta_t) = v(t1) + 0.5a(t1)*delta_t + 0.5a(t2)*delta_t
旋转动力学(刚体)
二维:
定向:角度theta
角速率&加速度:
![](http://img.blog.csdn.net/20170523155748825?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20170523155815779?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
转动惯量moment of inertia:改变角速率的难易程度。用I表示
力矩torque:用N表示
N=rxF
二维中力矩必然和z轴平行
![](http://img.blog.csdn.net/20170523160019907?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
二维旋转方程求解:
![](http://img.blog.csdn.net/20170523155836108?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
显示欧拉逼近解:
![](http://img.blog.csdn.net/20170523155850869?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
三维:
惯性张量:inertia tensor,标记为I
Ixx,Iyy,Izz是刚体绕三个主轴的转动惯量。如果3个主轴对称,则对角线以外的元素(也叫惯量积)就是0
物理引擎中惯性张量简化为三元素矢量[Ixx, Iyy, Izz]
转动惯量:Izz(惯性张量沿转轴方向的主值)
方向:
可以表示为3个欧拉角[theta_x, theta_y, theta_z],但是会有万向节死锁,所以也会用四元数q表示
q=[旋转轴u*sin(0.5 theta), cos(0.5 theta)]
角速度:
矢量w:绕旋转轴u转角速度标量w=theta' * u
在无力矩情况下角速度能改变:角速度不守恒
但是角动量(angular momentum,表示为L)守恒。
L=[Lx, Ly, Lz]
![](http://img.blog.csdn.net/20170523160046666?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
由于w不守恒,所以不会像线性速度一般,视角速度为一个基本的两。角速度是第二级别的量,在确定了角动量L后才计算出w
力矩:
N = rxF = Ia = I dw/dt = d(Iw)/dt = dL/dt
三维旋转求解:
不能用二维旋转方程求解的方法求解了
需要直接对L求解
将角速度转化成四元数:w = [wx, wy, wz, 0]
方向q' = 0.5(w*q) =>四元数积
![](http://img.blog.csdn.net/20170523160133800?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
显示欧拉:
![](http://img.blog.csdn.net/20170523160207629?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
3.碰撞响应
冲量碰撞响应
根据动量守恒+动能守恒,得到公式:
![](http://img.blog.csdn.net/20170523160234817?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20170523160300730?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
如果是完全弹性碰撞,能量损失为0
无摩擦力下瞬时碰撞的牛顿恢复定律:假设接触点没有摩擦力,冲量必然垂直于表面法线
![](http://img.blog.csdn.net/20170523160323396?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
恢复系数:v2'-v1'=e(v2 - v1)
将两者求解得
![](http://img.blog.csdn.net/20170523160340568?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
根据e求得p^,带入v1 + p^/m1*n 求出v1'
惩罚性力:力会在短但有限的时间内产生所需的碰撞响应。就类似一个坚硬的阻尼弹簧。
容易实现及理解,适合低速撞击
约束
4. 摩擦力
静摩擦力
滑动摩擦力
滚动摩擦力
碰撞摩擦力
![](http://img.blog.csdn.net/20170523160357386?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUGVlcmxlc3NCbG9vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
5. 休眠
将休眠物体移除模拟之外,但是仍然参与碰撞检测
条件:
刚体受到支持
v和角动量低于阈值
总动能(0.5pv+0.5Lw)低于阈值
Havok中有模拟岛:潜在近期会互动的物体组成。模拟岛能独立于其他岛模拟,并以整个岛为单位进入休眠。
6.约束
点对点约束
弹簧约束
铰链约束
活塞约束
平面约束
轮子:无限旋转的铰链+阻尼弹簧加入某种形式的垂直悬挂系统
约束链:特殊群组,内含供求解程序使用的物体连接信息。模拟一长串的刚体信息
布娃娃:刚体用约束互相链接。是由物理系统驱动的程序式动画
富动力约束(powered constraint):外部引擎间接控制布娃娃的平移和定向。力+动画,力改变动画
7.控制运动
引力
施加力:多数引擎设计为每帧调用一次,力的影响也在该帧内
施加力矩:改变速度&角速度;力偶:一样大,方向相反,离质心距离相同的对点上施加。
施加冲量:速度瞬间改变,无穷短时间内的施力
8.游戏对象和刚体:
物理驱动的刚体
游戏驱动的刚体(动画、玩家驱动):可当作含有无穷质量,力和力矩无法改变游戏驱动刚的速度
固定刚体:不参加动力学模拟,只有碰撞的刚体
9.更新模拟
更新游戏驱动刚体
更新phantom
施以力,冲量并调整约束
步进模拟:
对运动方程数值积分,求出次帧物理状态
碰撞检测
碰撞决议
实行约束
更新物理驱动的游戏对象
执行phantom&碰撞投射查询(以回调方式异步查询or使用上一帧的结果同步查询)
渲染
更新策略:
单线程更新
多线程更新:
物理专用线程:可能导致过期的位置信息-race condition-线程同步 or 使用命令队列做线程通信
fork, join:每个模拟岛步进的过程fork成独立的线程,当所有线程完成工作后join结果,主线程继续单线程更新。
作业模型
(图片没法调整大小,扎心了)
物理世界
形状:
相交、
接触(分离矢量,沿该矢量运动就能高效脱离碰撞妆容)、
凸(由形状内发射的光线不会穿越形状两次以上)
原型:
球体、
胶囊体、
轴对其包围盒AABB、
定向包围盒OBB、
离散定向多胞形discrete oriented polytope DOP、
任意凸体积、
多边形汤(碰撞引擎必须和每个三角形测试)、
复合形状
碰撞测试:
点和球体相交
球体和球体相交
分离轴定理:凸形状于该轴(分离轴)上的投影不重叠,能确定两个形状不相交。分离两个物体的轴/面称为分离线/面。三维空间中,分离轴仍然是个轴,分离线变成分离面。可以把形状逐一投影到各个潜在分离轴,并检查投影区间是否相交
AABB相交:分离轴定理。三个轴x,y,z。只有在三个轴都重叠,才是相交的。
检测凸碰撞:GJK算法。依赖闵可夫斯基差:把A中的所有点与B中的所有点都成对相减,得到的集合就是闵可夫斯基差。当且仅当两个形状相交,闵可夫斯基差包含原点。GJK尝试在闵科夫斯基的凸包内,尝试找出一个包含原点的四面体。若找到,则相交。
运动物体间的碰撞:
离散的静态碰撞;
sweep shape扫琼形状做静态测试(结果不准确);
连续碰撞检测continuous collision detection CCD,求出最早的冲击时间TOI
性能优化:
利用时间一致性避免每帧重新计算一些类型的信息
空间划分
粗略阶段,中间阶段,精确阶段:先AABB测试哪些物体会碰撞;再用符合形状的逼近包围体检测;最终进行青雀的碰撞检测
扫琼裁剪:sweep and prune,对各个膨胀提的AABB的最小,最大坐标再三个主轴上排序,然后通过遍历改有序表检测AABB之间是否重叠
碰撞查询:
光线投射:投射的物体并不存在于碰撞世界,不会影响其他物体。返回一个t值,P = P0 + td
形状投射:返回多个接触点。模拟玩家的脚
Phantom:查询碰撞体是否在其他指定体积里。对于其他碰撞体是透明的,也不参与动力学模拟。
碰撞过滤:决定碰撞体之间的接触是否成立
碰撞掩码及碰撞层:掩码
碰撞回调:回调函数按自己的条件决定接受或拒绝碰撞
碰撞材质:包含碰撞属性,如音效,粒子效果,摩擦系数等等
2. 刚体动力学
6个自由度DOF
线性动力学(质点)
线性速度&加速度
力&动量
运动方程求解
力作为函数:位置、速度、时间等的函数(常微分方程(ordinary differential equation ODE))。类似弹簧
解析解:找到闭合式函数,描述所有可能的时间值t的刚体位置(例如抛物线),但是游戏中几乎不可能。
常微分方程的数值解的特性:
收敛性:delta_t趋近于0的时候,近似解趋近镇世界?
阶数:误差是O(t^?)
稳定性:数值解是否会稳定下来?
数值积分:游戏引擎使用数值积分求解运动方程
显示欧拉
pos(t2) = pos(t1) + v(t1)delta_t
v(t2) = v(t1) + F(t)/m * delta_t
实际是假设在该时间步中,物体速度维持不变。由于位置的斜率就是速度,实际上也能理解为导数的逼近。当delta_t趋近于0的时候是合法的
一阶方法,误差是O(t^2),准确度达到并包括delta_t一次方的泰勒级数
韦尔莱积分
可以仅仅用到加速度就求解位置
pos(t1+delta_t) = 2pos(t1) - pos(t1-delta_t) + F(t1)/m * delta_t^2 + O(t^4)
v(t1+delta_t) = delta_pos / delta_t
速度韦尔莱积分
pos(t+delta_t)= pos(t1) + v(t1)*delta_t + 0.5a(t1)*delta_+t^2
v(t+0.5delta_t) = v(t1) + 0.5a(t1)*delta_t
求a(t1+delta_t) (假设a仅仅依赖位置,如果依赖速度,则需要先计算速度近似值)
v(t+delta_t) = v(t1) + 0.5a(t1)*delta_t + 0.5a(t2)*delta_t
旋转动力学(刚体)
二维:
定向:角度theta
角速率&加速度:
转动惯量moment of inertia:改变角速率的难易程度。用I表示
力矩torque:用N表示
N=rxF
二维中力矩必然和z轴平行
二维旋转方程求解:
显示欧拉逼近解:
三维:
惯性张量:inertia tensor,标记为I
Ixx,Iyy,Izz是刚体绕三个主轴的转动惯量。如果3个主轴对称,则对角线以外的元素(也叫惯量积)就是0
物理引擎中惯性张量简化为三元素矢量[Ixx, Iyy, Izz]
转动惯量:Izz(惯性张量沿转轴方向的主值)
方向:
可以表示为3个欧拉角[theta_x, theta_y, theta_z],但是会有万向节死锁,所以也会用四元数q表示
q=[旋转轴u*sin(0.5 theta), cos(0.5 theta)]
角速度:
矢量w:绕旋转轴u转角速度标量w=theta' * u
在无力矩情况下角速度能改变:角速度不守恒
但是角动量(angular momentum,表示为L)守恒。
L=[Lx, Ly, Lz]
由于w不守恒,所以不会像线性速度一般,视角速度为一个基本的两。角速度是第二级别的量,在确定了角动量L后才计算出w
力矩:
N = rxF = Ia = I dw/dt = d(Iw)/dt = dL/dt
三维旋转求解:
不能用二维旋转方程求解的方法求解了
需要直接对L求解
将角速度转化成四元数:w = [wx, wy, wz, 0]
方向q' = 0.5(w*q) =>四元数积
显示欧拉:
3.碰撞响应
冲量碰撞响应
根据动量守恒+动能守恒,得到公式:
如果是完全弹性碰撞,能量损失为0
无摩擦力下瞬时碰撞的牛顿恢复定律:假设接触点没有摩擦力,冲量必然垂直于表面法线
恢复系数:v2'-v1'=e(v2 - v1)
将两者求解得
根据e求得p^,带入v1 + p^/m1*n 求出v1'
惩罚性力:力会在短但有限的时间内产生所需的碰撞响应。就类似一个坚硬的阻尼弹簧。
容易实现及理解,适合低速撞击
约束
4. 摩擦力
静摩擦力
滑动摩擦力
滚动摩擦力
碰撞摩擦力
5. 休眠
将休眠物体移除模拟之外,但是仍然参与碰撞检测
条件:
刚体受到支持
v和角动量低于阈值
总动能(0.5pv+0.5Lw)低于阈值
Havok中有模拟岛:潜在近期会互动的物体组成。模拟岛能独立于其他岛模拟,并以整个岛为单位进入休眠。
6.约束
点对点约束
弹簧约束
铰链约束
活塞约束
平面约束
轮子:无限旋转的铰链+阻尼弹簧加入某种形式的垂直悬挂系统
约束链:特殊群组,内含供求解程序使用的物体连接信息。模拟一长串的刚体信息
布娃娃:刚体用约束互相链接。是由物理系统驱动的程序式动画
富动力约束(powered constraint):外部引擎间接控制布娃娃的平移和定向。力+动画,力改变动画
7.控制运动
引力
施加力:多数引擎设计为每帧调用一次,力的影响也在该帧内
施加力矩:改变速度&角速度;力偶:一样大,方向相反,离质心距离相同的对点上施加。
施加冲量:速度瞬间改变,无穷短时间内的施力
8.游戏对象和刚体:
物理驱动的刚体
游戏驱动的刚体(动画、玩家驱动):可当作含有无穷质量,力和力矩无法改变游戏驱动刚的速度
固定刚体:不参加动力学模拟,只有碰撞的刚体
9.更新模拟
更新游戏驱动刚体
更新phantom
施以力,冲量并调整约束
步进模拟:
对运动方程数值积分,求出次帧物理状态
碰撞检测
碰撞决议
实行约束
更新物理驱动的游戏对象
执行phantom&碰撞投射查询(以回调方式异步查询or使用上一帧的结果同步查询)
渲染
更新策略:
单线程更新
多线程更新:
物理专用线程:可能导致过期的位置信息-race condition-线程同步 or 使用命令队列做线程通信
fork, join:每个模拟岛步进的过程fork成独立的线程,当所有线程完成工作后join结果,主线程继续单线程更新。
作业模型
(图片没法调整大小,扎心了)
相关文章推荐
- 游戏引擎剖析--第5部分: 物理,运动,效果
- 如何制作一款像超级玛丽兄弟一样基于平台的游戏-第二部分 (xcode,物理引擎,TMXTiledMap相关应用)
- 《割绳子》《蜡笔物理学》《Contre Jour》《顽皮鳄鱼爱洗澡》等游戏用Box2D引擎实现物理部分的方法(转)
- 如何使用cocos2d-x3.0和物理引擎来制作一个Breakout游戏:第二部分
- 【麦可网】Cocos2d-X跨平台游戏开发学习笔记---第二十五课:Cocos2D-X物理引擎之Box2D8-10
- 游戏引擎的三种架构方式
- 【技术讨论】从弹弹堂说起,如何用2D物理引擎编写一个游戏<一>2011-11-05 10:36
- 怎样在cocos2d里面如何使用物理引擎box2d制作弹球游戏
- AtomCat:可以做“软”物体的游戏物理引擎
- HTML5游戏开发进阶 4 :物理引擎集成
- 物理引擎与游戏引擎
- 游戏引擎架构:1
- APE物理引擎教程(最少的代码,写最有趣的游戏)
- 游戏引擎架构选摘之第五章 游戏支持系统
- android游戏物理引擎开发——碰撞检测(三)
- 纯Java开发的游戏引擎V0.4--DEMO2 -- 物理引擎
- U3D 游戏引擎之游戏架构脚本该如何来写
- 游戏引擎架构pdf
- Game.Physics.Engine.Development(游戏物理引擎开发)
- Ophone平台2D游戏引擎实现——物理引擎(一)(二)个人整理