学习笔记8:物体系统基础

 物理对象与形状

一般来说,游戏中的对象(Actor)分为以下四类:静态对象 Static Actor,动态对象 Dynamic Actor ---- 可能受到力/扭矩/冲量的影响,检测器 Trigger,Kinematic Actor 运动学对象---- 忽略物理法则,由游戏逻辑直接控制(可能表现的反物理)
 

形状:由于真实世界中很多物体形状极其复杂,所以游戏中会先设定较为简单的对象。常见的物理对象的形状。


 

每一种形状都有常用的实际游戏对象,比如Height Fields用来做地形等。

当我们利用这些对象去组成实际需要的物体对象时,有两个原则:

形状接近就好,不一定要完美
简单性。要尽量用简单的对象去拼接(比如尽量少用三角网格),且越少越好。
此外,一些比较重要的物理概念:

质量和密度 Mass and Density
质心(做载具时很重要)Center of Mass
摩擦和恢复(弹性) Friction & Restitution
 

Force ,Movement

Force

一般我们把力分成两种:

  • Force 可以理解为直接的重力、拉力、摩擦力等
  • Impulse 冲量,比如说爆炸导致的冲击力等(虽然其实冲量就是力x时间(恒力条件下))

运动 Movement

经典的定理(游戏中需要用数学表示):

  • 牛顿第一定律 无外力 —> 匀速直线运动

牛顿第二定律 F = ma (质量的本质是改变物体物理状态的倾向性)

力是永恒的:

当这个力是变力时:

如果简单去模拟物体随时间变化,并不是很困难。
但实际游戏中时间不是连续的,而是由一帧帧实现的,所以通常需要解决的问题是在已知当前物体位置和速度的前提下获取之后某时刻的物体位置和速度信息。

 显示欧拉法 Explicit (Forward) Euler’s Method

最简单的估计方法,假设在这个时间片里力是恒定的
每一时刻仍按照传统的牛顿力学方法去计算,其实就是用现在的速度或者力来计算未来的

但是可能导致能量可能不守恒

优点:
容易计算,效率高
 缺点:
不稳定
能量随时间增长

隐式欧拉法 Implicit (Backward) Euler’s Method

与显示近似,不过将力的值和速度的值以未来(终点)为参考

其中未来的值是假设能够通过解析解强行算出来的。
和显示方法类似,该方法的问题是能量会衰减,但由于这个衰减相对较慢,所以用户可能会认为是摩擦力、空气阻力等其他力的影响导致,从而使得这个衰减在游戏实际中相对不明显。
从另一个角度来说,我们在游戏引擎中设计中认为衰减肯定是好过增多的,前者顶多最后停下来,但后者会不可控会爆炸。
通过一系列复杂计算可以证明这种隐式方法是无条件稳定的。
但其缺点是:

计算成本高(计算未来值)
运动非线性时难以计算
能量衰减。
 

半隐式欧拉法 Semi-implicit Euler’s Method

综合前两者的特点:

计算未来速度时用当前的力,计算未来位移时用未来的速度。
前提假设:力是不变的(很危险的假设,因为实际上力跟物体位置是相关的)。
优点是:

条件性稳定
计算简单有效
随着时间的推移能够保存能量
缺点是做一些sin cos等运动时,积分出来的周期会比正确值长一点点,所以在相位上会有偏移差。

Rigid Body Dynamics 刚体动力学
 

前面所说的所有内容都是把物体看作一个质点的前提,然而事实上真实世界中大部分物体是有形状的。一般来说,我们在引入旋转时大都针对刚体(因为柔体太难了),因为刚体就是假设物体的所有粒子之间绑定相对不动。所以我们在刚体动力学中常常会比普通的线性计算(图中右侧)多一些概念,同一行概念有对应性:

角速度的求法:

转动惯量:简单的方法是通过把一个物体的各个部分看做一个质点来求。

正常的方法:

Collision Detection 碰撞检测

碰撞检测一般分为两个阶段:

  1. Broad phase 初筛 – 利用AABB等找到刚体有没有相交
  2. Narrow phase – 获取进一步信息(碰撞点、方向、深度等)

Broad Phase

一般常见的有两种方法:

  1. BVH Tree – 更新成本低,适合动态场景。
  2. Sort and Sweep – 先排序再逐个扫描,效率高,更符合大部分为静态物体小部分为动态物体的现实。更好。

在空间上看aabb的顺序是否发生变化。因为只是改变了局部的数据,所以效率很高。

Narrow phase

挑战:
- Detect overlapping precisely -准确地发现重叠
. Generate contact information 。生成联系信息
. Contact manifold 。接触歧管
. approximated with a set of contact points. Contact normal 。与一组接触点近似。接触正常
. Penetration depth 。穿透深度

Basic Shape Intersection Test

比较简单,把所有物体看作球或胶囊状去判断相交即可。

球的求法

圆柱与球

Minkowski Difference-based Methods

首先需要知道minkowski Sum(闵可夫斯基和)的概念,以两个三角形各自围成的点集为例,两个点集相加的结果是指所有A点集的点加上所有B点集的点,几何表示如下:2个集合变成另外一种集合。

当a和b有交点的时候,a-b必过原点

如果两个凸包有重叠,则它们的闵可夫斯基差必定包含原点
我们把闵可夫斯基差这些点形成的形状叫slmplex(单纯形)

由此问题转换为了如何判断两个凸包的闵可夫斯基差包含原点。
使用的方法为GJK算法。可以参考https://zhuanlan.zhihu.com/p/511164248


Separating Axis Theorem


如果两个物体分离,则肯定能找到空间中一根轴把它们分隔开,不然就是相交。
简单做法是把凸包A的每条边和凸包B的每条边当分隔线试试,比如对凸包A的边a,把所有顶点投影到这条边上去进行判断有没有重叠。如果所有边做分隔线都有重叠,那就是两个凸包相交。
在这个基础上,优化方法是取凸包A的某条边a做轴时,直接将凸包B的所有顶点投影到a的垂线上,因为这样可以保证凸包A的所有顶点都在垂线上a的一侧,所以只需要判断凸包B上所有顶点在垂线上的投影是否在另一侧就行。

延伸到3D空间,需要多加步骤:

从A检查曲面,从B检查顶点
分离轴:A的面法线,检查A的顶点和B的面
分离轴:B的面法线,检查A的边和B的边
分离轴:两个边的交叉积
 

简单讲就是如果只判断面的法线作为分隔线的可行性的话,会出现图中下面前两种情况,并误以为是两个物体相交,所以需要再加上一个检测来判断第三种情况。

碰撞解决


最简单的早期是方法是加一个与重叠反方向的penalty force,但是会导致物体突然分隔开,很假。
现在比较合适流行的方法是利用拉格朗日力学中对速度的约束的方法。简单讲大概类似于给碰撞物体加个冲量从而影响下速度,看是不是还碰撞,不断重复直到可以接受。或者迭代次数过多不管了。
 

场景请求


Raycast
通过发射一条光来判断场景中的某个点能否直接看到/射击到。
当这束光有多个撞击点时,有三种处理方式:都进行计算处理、只处理最近的、any hits(不管哪个,反正有撞击就行)any hits是最简单的


Sweep
比如判断人有没有被挡住时是把人的整个胶囊体进行扫描判断的,只要有一部分被挡住就是被挡住了。


Overlap
比如判断手雷爆炸时能炸到哪些人。通过一个新的形体来判断其他形体是否与之发生碰撞。

效率、准确性与确定性


Sleeping
物理引擎中常把场景的不同物品或部分分成所谓不同的island,而引擎设计中很重要的一部分是让没有变化或不需要参与计算的island进入sleep,所以如何让更多island进入sleep从而减少计算量是一个关键问题。


Continuous Collision Detection(CCD)
当一个快速运动的对象碰撞一个比较薄的物体时容易发生错误直接穿过去(因为前后两次计算时发现都没有碰撞,但其实不可以)
一种比较质朴的方法就是把墙等物体做的厚一点。
更规范的做法就是CCD:先计算一个安全时间(在这个时间内两个物体不会碰撞),然后开始一点点详细计算会不会碰撞,知道它们的距离小于一定阈值。


Deterministic 确定性
游戏引擎设计时需要保证确定性,即同样的代码操作下跑起来是要尽可能一样的,而不会受那么多复杂计算和浮点问题的影响导致不同(从而在Online Gaming)中出现两方不一样的问题。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值