物理系统拼图参考 - Soft8Soft
Description: 使用拼图来模拟物理学行为。

# 物理系统

此类拼图用来模拟对象的物理系统行为。

有关使用示例，请查看 Physics 演示（也可在资源商店中找到）。

## 内容

- 物理拼图参考
  - create physics world
  - create rigid body
  - create soft body
  - remove physics body
  - apply body param
  - get body param
  - set body state
  - on simulation tick
  - snap body
  - add constraint to
  - remove constraint from
  - anchor soft body
  - apply soft body param
  - get soft body param
  - detect collisions and collision info
- 用JavaScript进行扩展

#

## 物理拼图参考

#

### create physics world

使用指定的gravity和frames-per-second参数初始化物理引擎。默认的gravity值为9.8，对应于地球表面重力。零值表示没有重力，类似在太空。fps值越高，模拟质量越好，但要牺牲性能。

soft body复选框激活柔体模拟功能。

在底层，此拼图还启用了碰撞检测和自动图形同步。

#

### create rigid body

从一个指定的对象创建一个物理体，类型为dynamic、kinematic、static或ghost。指定碰撞形状，并为该体设置质量（仅对dynamic体有效）。也适用于对象列表，组（或者组的列表）以及 all objects 拼图。

物理体类型：

- dynamic — 由物理引擎移动，受碰撞影响，并与其他物体相撞。
- kinematic — 通过动画或用户动作移动。动态对象会被推开，但没有来自动态对象的影响。
- static — 不能移动，但会与其他对象发生碰撞。
- ghost — 类似于kinematic，但不产生任何碰撞反应。用它来检测碰撞（例如，实现接近传感器）。

支持的刚体形状：

- box — 盒子形状的边界。
- sphere — 球体形状的边界。
- mesh — 网格形状。
- capsule — 沿上下轴拉伸的胶囊形状。
- cone — 沿上下轴拉伸的圆锥体形状。
- cylinder — 沿上下轴拉伸的圆柱体形状。
- empty — 空的形状。用于创建约束附件和柔体锚点。

出于性能因素，优先考虑原始物理形状（盒子、球体、胶囊、圆锥体和圆柱体）而不是网格形状。另外，static网格的性能比dynamic、kinematic或ghost网格好得多。

#

### create soft body

从一个指定的对象中创建一个柔体，具有给定的总mass和可选的pressure参数。也适用于对象列表，组（或者组的列表）以及 all objects 拼图。

支持的柔体形状：

- volume — 封闭受压的三维体积。
- rope — 类似绳子的线状对象。
- patch — 多边形表面，如布或纺织品补丁。

在创建柔体之前，不要忘记在物理世界上激活柔体模拟。

#

### remove physics body

通过销毁与之关联的物理体，从指定的对象中移除物理特性。也适用于对象列表，组（或者组的列表）以及 all objects 拼图。

#

### apply body param

为与指定对象关联的物理体设置参数。也适用于对象列表，组（或者组的列表）以及 all objects 拼图。

参数：

angular damping
  用于减缓对象旋转的阻尼系数：`0` — 没有阻尼，`1` — 最大阻尼。输入值被钳制在[0, 1]范围内。
angular factor
  设置指定体的旋转自由度。例如，通过设置Z分量为零，您可以禁止体围绕上下（Blender, Max）或前后（Maya）轴旋转。
angular velocity
  设置旋转速度矢量。
ccd motion threshold
  用于模拟连续碰撞检测（CCD）物理学的运动阈值。指定低值，例如0.001。
ccd swept sphere radius
  用于模拟连续碰撞检测（CCD）物理的扫掠球半径。这个值应该与碰撞对象的大小相对应。例如，为了模拟尺寸为0.01米的小子弹，这个值设置为0.5会比较安全。
force
  在指定的方向上通过施加指定的力矢量来推动体。
friction
  固体相互滑动时相对运动的阻力系数。
gravity
  为指定的体单独分配重力。此值可以指定为矢量或数字。在数字的情况下，该值设置上下重力因子（沿Blender/3ds Max的Z轴或Maya的Y轴）。
impulse
  作用类似于Linear Velocity，但也考虑到了体的质量（较重的对象将获得较少的速度）。
linear damping
  将使运动对象减速的阻力系数：`0` — 没有阻尼（例如自由落体），`1` — 最大阻尼（例如对象下落时没有加速度）。输入值被钳制在[0, 1]范围内。
linear factor
  设置指定体的位置自由度。例如，通过设置Z分量为零，您可以禁止体的上下（Blender, Max）或前后（Maya）运动。
linear velocity
  设置运动速度矢量。
margin
  用于提高模拟稳定性和性能的碰撞边距。仅对mesh或cone碰撞形状指定边距。对于其他碰撞形状（box、sphere、capsule、cylinder），此值由物理引擎计算。
position
  设置体的位置（作用类似于snap body拼图）。
restitution
  弹性系数：`0` — 体像粘土一样没有弹性，`1` — 体的行为像由橡胶制成。
rotation
  设置体的旋转（以XYZ顺序的欧拉旋转，作用类似于snap body拼图）。
stiffness
  柔体（如体积和绳索）的刚度。已弃用，请改用apply soft body param。
torque
  在指定的方向上旋转体。
torque impulse
  作用类似于Angular Velocity，但也考虑到了体的质量（较重的对象将获得较少的旋转速度）。

当两个体发生碰撞时，它们的摩擦力和恢复系数参数都会被考虑在内。

#

### get body param

从与指定对象关联的物理体中获取一个参数。

参数：

angular damping
  用于减缓对象旋转的阻尼系数：`0` — 没有阻尼，`1` — 最大阻尼。
angular factor
  指定体的旋转自由度（XYZ）。
angular velocity
  旋转速度矢量。
ccd motion threshold
  用于模拟连续碰撞检测（CCD）物理学的运动阈值。
ccd swept sphere radius
  用于模拟连续碰撞检测（CCD）物理的扫掠球半径。
force
  施加到体上的力矢量。
friction
  固体相互滑动时相对运动的阻力系数。
gravity
  施加在体上的重力矢量（XYZ值）。
linear damping
  将使运动对象减速的阻力系数：`0` — 没有阻尼（例如自由落体），`1` — 最大阻尼（例如对象下落时没有加速度）。
linear factor
  指定体的位置自由度（XYZ）。
linear velocity
  运动速度矢量。
margin
  用于提高模拟稳定性和性能的碰撞边距。
position
  体的XYZ位置。
restitution
  弹性系数：`0` — 体像粘土一样没有弹性，`1` — 体的行为像由橡胶制成。
rotation
  体的XYZ欧拉旋转。
stiffness
  柔体（如体积和绳索）的刚度。已弃用，请改用get soft body param。
torque
  施加到体上的扭矩矢量。

#

### set body state

改变与指定对象关联的物理体的状态。也适用于对象列表，组（或者组的列表）以及 all objects 拼图。

参数：

- activate — 激活睡眠的体。
- sleep — 强制体进入睡眠状态。
- enable simulation — 启用体模拟（默认启用）。
- disable simulation — 禁用体模拟。
- reset — 清除所有应用于体的力和速度。
- enable contact response — 允许体之间发生碰撞（默认启用）。
- disable contact response — 禁用体的碰撞。
- make dynamic — 使体动态化。
- make kinematic — 使体运动化。
- make static — 使体静态化。
- enable deactivation — 允许体在不活动一段时间后转入睡眠状态（默认启用）。
- disable deactivation — 禁止体睡眠。

#

### on simulation tick

在物理模拟刻的之前或之后，触发在do槽中指定的拼图。

物理模拟刻与创建物理世界时指定的FPS值相对应，与渲染帧不一致。因此，我们建议您在模拟刻之前施加力/速度/冲量，在模拟刻之后检测体之间的碰撞。这样您就可以实现更稳定和更真实的模拟。

#

### snap body

通过复制目标对象的变换数据，将与指定对象关联的物理体以及对象本身移动到另一个对象的位置。同时也复制旋转。对列表、组或 all objects 拼图不起作用。

作用类似于apply body param / position拼图。

#

### add constraint to

通过给定类型的约束连接两个物理体。

约束类型：

- hinge — 通过共用轴连接两个体。
- ball — 通过球状插座连接两个体。
- slider — 限制体沿X轴方向移动。
- spring — 通过类似弹簧的关节连接两个体。
- fixed — 紧密地连接两个体。

#

### remove constraint from

移除物理约束。

#

### anchor soft body

将柔体锚定在给定矢量所代表的空间点处的给定刚体上。

#

### apply soft body param

为与指定对象关联的柔体设置参数。也适用于对象列表，组（或者组的列表）以及 all objects 拼图。

参数：

anchor hardness
  锚点硬度系数：`0` — 无锚点影响，`1` — 最大锚点影响。
angular stiffness
  角刚度：`0` — 无角刚度，`1` — 最大角刚度。
collision flags
  柔体碰撞标志：`0` — 不与其他刚体碰撞，`1` — 简化碰撞，17 — 改进的碰撞。默认值为17。
damping coefficient
  阻尼系数：`0` — 无阻尼，`1` — 最大阻尼。
drag coefficient
  阻力系数（即流体阻力）。必须为正数。
dynamic friction
  动摩擦系数。`0` — 无摩擦，`1.0` — 最大摩擦。
lift coefficient
  升力系数。必须为正数。
linear stiffness
  线性刚度：`0` — 无线性刚度，`1` — 最大线性刚度。
position iterations
  位置求解器迭代次数。值越高质量越好。必须为正整数。
pressure coefficient
  压力系数（例如用于气球）。
velocity iterations
  速度求解器迭代次数。值越高质量越好。必须为正整数。
wind velocity
  风速矢量。

#

### get soft body param

从与指定对象关联的柔体中获取一个参数。

参数：

anchor hardness
  锚点硬度系数：`0` — 无锚点影响，`1` — 最大锚点影响。
angular stiffness
  角刚度：`0` — 无角刚度，`1` — 最大角刚度。
collision flags
  柔体碰撞标志：`0` — 不与其他刚体碰撞，`1` — 简化碰撞，17 — 改进的碰撞。
damping coefficient
  阻尼系数：`0` — 无阻尼，`1` — 最大阻尼。
drag coefficient
  阻力系数（即流体阻力）。必须为正数。
dynamic friction
  动摩擦系数。`0` — 无摩擦，`1.0` — 最大摩擦。
lift coefficient
  升力系数。
linear stiffness
  线性刚度：`0` — 无线性刚度，`1` — 最大线性刚度。
position iterations
  位置求解器迭代次数。
pressure coefficient
  压力系数（例如用于气球）。
velocity iterations
  速度求解器迭代次数。
wind velocity
  风速矢量。

#

### detect collisions and collision info

检测指定的体与另一个体（或列表中的任一体或组）在此刻是否有碰撞。如果有碰撞，那么在if touching do槽中的拼图会被触发，否则将触发在if not touching do槽中的拼图。

"detect collisions"拼图在每一个渲染帧中都会触发其回调槽。

collision info拼图输出一个字典，其字段如下：

- objectA — 第一个碰撞体的名称。
- objectB — 第二个碰撞体的名称。
- distance — 碰撞点之间的距离。
- positionOnA — 第一个对象上的碰撞点的XYZ坐标。
- positionOnB — 第二个对象上的碰撞点的XYZ坐标。
- normalOnB — 第二个对象上的碰撞点的法向量的XYZ分量。

#

## 用JavaScript进行扩展

在您开始阅读以下内容之前，请先熟悉本用户手册的使用JavaScript部分。

为了构建物理拼图，我们使用了名为Ammo.js的JavaScript库。该库基本上是流行的Bullet物理引擎编译为在浏览器中使用的版本。

要熟悉Bullet，请查阅GitHub上的Bullet Physics SDK Manual以及官方的Bullet API Reference。

在Verge3D中，您可以通过使用Ammo命名空间直接执行Bullet/Ammo.js API：

`const myVector = new Ammo.btVector3(1.0, 0.0, 0.0); console.log('My physics vector is:', myVector.x(), myVector.y(), myVector.z());`

此外，您还可以通过your_app_name.js模块的`runCode()`函数的`puzzles`参数或exec script拼图中的内置`puzzles`变量，来访问我们在拼图中使用的以下数据结构：

### World

根据所初始化的物理世界，它可以是btDiscreteDynamicsWorld或btSoftRigidDynamicsWorld类的实例：

`const gravity = puzzles.physics.world.getGravity(); console.log('World gravity:', gravity.y());`

### Physics Bodies

物理体作为键值数据存储在puzzles.physics.bodies对象中：

`const body = puzzles.physics.bodies['Whirligig']; console.log('Body mass:', 1.0 / body.getInvMass());`

刚体是btRigidBody类的实例，而柔体是btSoftBody类的实例。

### Physics Constraints

Bullet/Ammo约束以键值数据的形式存储在二维的puzzles.physics.constraints对象中：

`const hingeConstraint = puzzles.physics.constraints['Suzanne']['Axis']; hingeConstraint.enableAngularMotor(true, 10, 10);`

名称分别代表约束的第一和第二体。

### Physics Sync List

Verge3D拼图使用所谓的同步列表在空间中移动由物理体代表的对象。同步列表不能被直接访问，因此您需要使用以下API方法来添加/移除您的体到/从该列表：

`// add obj / body to the sync list // the type can be 'DYNAMIC', 'KINEMATIC', 'STATIC', 'GHOST', or 'SOFT_BODY' puzzles.physics.addToSyncList(obj, body, 'DYNAMIC'); // remove obj / body from the sync list puzzles.physics.removeFromSyncList(obj, body);`

## 在使用拼图时遇到困难？

欢迎您随时在 论坛上提问！您还可以加入中文用户社区QQ群(171678760)，在线寻求帮助。