Simulation of Physics(物理仿真)
当仿真时,许多阶段中的物理计算已被完成。如果物理为单线程,那么所有的阶段会一个接着一个进行,然而 multi-threaded(多线程)物理可以并行执行一些操作。
Rate of Physics Simulation(物理仿真率)
Unigine物理模块会在 execution sequence(执行序列)的render stage(渲染阶段),执行所有计算。关于物理需要指出一些事情:
- 使用其自身固定的FPS而得到仿真,这种方式不会依赖于渲染帧速率。(渲染的FPS也可以通过物理FPS被 覆盖重写 )。
不要将物理帧速率设置地太高;否则会造成渲染延迟。如果物理花费的时间超过了40 毫秒,将跳过进一步的计算。
- 在每个标记期间,可以执行大量的计算iterations(迭代)。这包括物理仿真的整个周期:
- 来自世界坐标脚本的flush()被这样称呼。
- 执行碰撞检测
- 接头问题得以解决
把迭代的数量设置地太高并无什么意义。Unigine会检查接下来的迭代是否会在40 毫秒的限制内得到执行,如果不能执行,那么就跳过。
Stages of Physics Simulation(物理仿真阶段)
物理仿真在对每个迭代进行更新时会经历许多阶段。这些阶段列表如下:
- Physics flush(物理清除)
- Broad phase(宽阶段) 碰撞检测
- Narrow phase(窄阶段)碰撞检测
- Simulation(仿真)
- Synchronization of physics(物理的同步)
在性能 分析器中,物理仿真的所有时间通过Physics计数器得到显示。
1. Physics Flush(物理清除)
- spatial tree(空间树)会最先得到更新。在我们获得所有最新关于全部拥有肉身的物体的安置方式的数据之后,对这些对象进行转换或者计算碰撞就很安全了。
- 如果有这种功能,C++ API Plugin(插件)flush() 就被这样调用。
- 物理板块调用世界坐标脚本的flush()。这里您可以调用所有处理物理仿真及交互的功能(不仅是这些,参看关于flush()用法及限制的具体信息)。
2. Collision Detection(碰撞检测): Broad Phase(宽阶段)
在基于脚本的改变发生后(有其形状的身体及接头根据游戏逻辑得到转换,基于物理的回叫得到设置等等),物理便可被仿真。
- 在Physical distance(物理距离)之内,会发现所有的物体都有躯体。在当前物理标记期间,这些躯体将被仿真。请确保基于Unigine的应用中的物理距离不会太短,因为此范围外的物理交互不会被计算,所以物体冻结。(然而,即使发现来自island(岛状区)的一个躯体处于物理距离范围之内,整个岛状区将被仿真)。
您可以使用addUpdateNode()功能对处于Physical distance(物理距离)外的节点进行强制更新。
- 为所有物体测试碰撞太耗费时间,尤其在大场景的情况下。这也正是发现潜在对撞物体会基于快速粗略测试的原因。如果躯体与包围盒发生正交(这些包围盒为形状大小且不会依赖于节点包围盒),或者有与这些包围盒相联的节点,这样的躯体会在一个island(岛状区)内被结合在一起。为了将其缩短,所有的躯体都以某种方式被连接在一起(空间连接或者节点连接),进入一个岛状区。 这就意味着,一个岛状区内的躯体可能在此框架内与互相作用,而不同岛状区的躯体将肯定不会发射碰撞。
基本上宽阶段增加了碰撞检测的效率减少了计算负载。在做更多精确花费大的计算之前,我们可以过滤掉几对被安置地太远以致于无法对碰的物体。非对撞body dummy(虚拟人体)会被跳过,并不会被仿真除非它通过节点与其它躯体发生相互作用。
- Unigine物理具有确定性。躯体,形状及节点被存储在岛状区内。 这样,我们得确保在预定顺序中联系的问题被解决并且世界坐标中充分重复物体的形象化。
在性能profiler(分析器)中,您可以找到:
- 通过PBroad计时器被显示的宽阶段总时间 。
- 通过PIslands计数器被显示的岛状区数量。
- 通过PBodies 计数器被显示的躯体数量。
- 通过PJoints 计数器被显示的节点总数。
3. Collision Detection(碰撞检测): Narrow Phase(窄阶段)
在窄阶段期间,会执行正确的碰撞测试。在单线程模式中(当没有或有一个独立的physics thread(物理线程)时) 仿真会以下列方式继续进行。
基于形状的碰撞会得到发现,这些碰撞用于每个岛状区内的躯体:
- 物理对象之间的碰撞:发现成对的形状之间的接触点
- 物体对象与静态表面之间的碰撞:如果表面被分配了一个 surface_base 属性 (默认),那么此表面也会被动地参与到物理相互作用并阻止物理对象把表面穿透。这种情况下,形状与曲面多边形之间的触点会得以计算。
Continuous Collision Detection(连续碰撞检测)
如果一个球面 或者一个 封装体参与到与其它形状或表面的联系,连续碰撞测试(CCD)就会被执行。Unigine采用躯体的速度和躯体形状的半径,假设它会继续其当前的轨迹,计算此躯体将会有何种接触(在当前物理标记期间)。因此,不同于简单的碰撞检测,接触未被离散地以一次一个物理标记的方式进行分析,而是整个框架被发现。
在性能分析器中,您可以找到:
- 通过PNarrow计数器被显示的窄阶段总时间。
- 通过 PContacts 计数器得到显示的触点数量。
4. Simulation(仿真)
当完成碰撞检测后,碰撞的响应时间也会得到计算,这样躯体将获得新的速度。
- 躯体已准备好马上参与碰撞:将找到的接触与前一帧的接触一同进行缓存 — 以此确保它们之间能以一种合适的方式进行交互作用。
在性能分析器中,此阶段的时间通过PUpdate计数器得到显示。
- 每个躯体的Collision response(碰撞响应)时间会得以计算。基于聚合在一起的触点数据,Unigine通过碰撞计算形状接收到的脉冲:躯体在与另一个躯体或表面发生碰撞后怎样改变自己的运动。触点以伪随机的方式得到解决实现仿真的稳定性及再现性。
- 在计算接触响应时,joints(节点)的问题也得以解决。节点给予依附在它们身上的躯体脉冲,这些脉冲也会被计算:根据当前节点状态,躯体应作出怎样的反应方式使节点不破损。(即基于大量的躯体,线性及角速度,改变它们的运动方向及方位),及相应影响节点的方式。例如节点上产生的脉冲非常大,就会破碎。
节点问题也以伪随机顺序得到解决。在一个物理迭代内,可数次处理节点问题。节点迭代数量高会增加计算的精确度,当然也会增加计算负载。在性能分析器中,碰撞相应和节点解决阶段的总时间都通过PResponse计数器得到显示。
- 接触及节点解决的结果会被累加,最终被应用到躯体上。躯体的坐标会根据它们新的线性及角速度而改变。
在性能分析器中,仿真阶段的总时间通过PIntegrate计数器得到显示。
在性能 分析器中,仿真阶段的总时间通过PSimulation计数器得到显示。
5. Synchronization of Physics(物理同步)
同步是物理仿真的最后一个阶段。在Unigine主循环中的swap()期间,物理模块调用其内部的flush()功能。躯体设置它们的计算转变成对象的方式。在下一帧中,对象将在其新的基于物理位置内被渲染。
如果visualizer(视觉型人物)选项被启用,形状,节点或者非冻结躯体的触点将被渲染。
Multi-Threaded Physics Simulation(多线程物理仿真)
当有两个或更多的物理线程时(通过 physics_threaded控制台变量进行控制),运行多线程物理仿真。
- 来自世界坐标脚本的flush() 始终在主物理线程中得以执行。
- 在此之后,Unigine在窄阶段 和仿真阶段期间使用多个CPU。
- 当完成岛状区的创建之后,可在单独的线程中对这些岛状区进行安全的操作,因为岛状区之间无联系。
- 在可用线程中找到准确的基于形状的碰撞。
- 接下来在主物理线程中同步线程岛状区用来交换关于当前接触及上一帧接触的数据。这些数据确保躯体适当的物理行为。
- 从此处起,碰撞反应时间及节点解决再一次在单独的线程中得到计算。
- 在物理与世界坐标同步之前,引擎会等到所有的线程完成它们各自的计算。一旦线程同步发生(在Unigine主循环的 swap阶段期间 ),物理会被应用到节点上。