Skip to content

Commit 1ae76e9

Browse files
ID-Emmettlslzl3000
authored andcommitted
docs(zh): update physics docs (#178)
1 parent 605db12 commit 1ae76e9

File tree

14 files changed

+937
-222
lines changed

14 files changed

+937
-222
lines changed

docs/.vitepress/config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,10 @@ function sidebarGuide(): SidebarItem {
348348
collapsible: true,
349349
items: [
350350
{ text: '物理总览', link: '/guide/physics/Readme.md' },
351-
{ text: '内置组件', link: '/guide/physics/rigidbody.md' },
351+
{ text: '碰撞体', link: '/guide/physics/collisionShape.md' },
352+
{ text: '刚体', link: '/guide/physics/rigidbody.md' },
353+
{ text: '软体', link: '/guide/physics/softbody.md' },
354+
{ text: '约束', link: '/guide/physics/constraint.md' },
352355
]
353356
},
354357
{

docs/.vitepress/theme/custom.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@
8181
display: table;
8282
table-layout: auto;
8383
}
84+
.details > table {
85+
display: block;
86+
}
8487
thead,
8588
tbody {
8689
width: 100%;

docs/guide/physics/Readme.md

Lines changed: 74 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,30 @@ import { Physics } from "@orillusion/physics"
3232
</script>
3333
```
3434

35-
## 物理环境的运行
36-
35+
## 基本用法
3736
目前 [Physics](/physics/classes/Physics) 支持的参数及方法如下表所示:
3837

3938
| API | 描述 |
4039
| --- | --- |
4140
| init(): void | 初始化物理引擎 |
41+
| initDebugDrawer(): void | 初始化物理调试器 |
4242
| update(): void | 更新物理系统,需要在 loop 主体中调用 |
4343
| gravity: Vector3 | 重力参数 |
4444
| isStop: boolean | 控制物理世界是否暂停运行 |
45-
| world: Ammo.btDiscreteDynamicsWorld | ammo.js 原生物理世界 |
45+
| debugDrawer: PhysicsDebugDrawer | 可视化调试工具 |
46+
| physicsDragger: PhysicsDragger | 拖拽交互工具 |
47+
| world: Ammo.btDiscreteDynamicsWorld | Ammo.js 原生物理世界 |
48+
49+
`init()` 初始化配置参数:
50+
51+
| 参数 | 类型 | 描述 |
52+
| --- | --- | --- |
53+
| useSoftBody | `boolean` | 是否启用软体模拟 |
54+
| useDrag | `boolean` | 是否启用拖拽交互功能 |
55+
| physicBound | `Vector3` | 物理世界边界 |
56+
| destroyObjectBeyondBounds | `boolean` | 超出边界时销毁3D对象 |
4657

58+
### 启动物理系统
4759
我们可以初始化 `init()` 来开启物理系统,并通过在渲染主循环中调用 `update()` 实现物理世界的运行:
4860
```ts
4961
import { Engine3D } from '@orillusion/core'
@@ -54,21 +66,61 @@ await Engine3D.init({
5466
renderLoop: () => Physics.update()
5567
});
5668
```
69+
::: tip
5770
通过以上方法开启并运行物理系统后,引擎会在每一帧渲染时,根据设定的参数计算并更新物体模型对物理世界的实际响应。
71+
:::
5872

59-
在一些项目中通常会有暂停物理世界模拟的需求,因此我们提供了一个参数可以暂停&恢复物理世界的运行:
73+
### 暂停与恢复
6074
```ts
6175
Physics.isStop = !Physics.isStop;
6276
```
6377

64-
## 重力环境模拟
65-
引擎默认的重力参数为 `Vector3(0, -9.8, 0)`,模拟的是地球的重力。如果需要自定义重力参数的话,只需更改 `Physics.gravity` 属性即可。
6678

67-
例如,如果需要模拟太空中的无重力环境,可以更改 `gravity` 参数为:
79+
### 重力环境模拟
80+
默认重力为 `Vector3(0, -9.8, 0)`(地球重力)。自定义重力只需修改 `Physics.gravity`
81+
```ts
82+
Physics.gravity = new Vector3(0, 0, 0); // 无重力环境
83+
```
84+
85+
## 辅助功能
86+
- **物理可视化**:为了可视化物理对象,我们可以在引擎启动后初始化物理可视化调试器,需要为其传入 `Graphic3D` 对象:
6887
```ts
69-
Physics.gravity = new Vector3(0,0,0);
88+
const graphic3D = new Graphic3D();
89+
scene.addChild(graphic3D);
90+
Physics.initDebugDrawer(graphic3D, { enable: true });
7091
```
7192

93+
::: details 使用 dat 控制调试器
94+
```ts
95+
import dat from "dat.gui";
96+
97+
let gui = new dat.GUI();
98+
let f = gui.addFolder("PhysicsDebugDrawer");
99+
f.add(Physics.debugDrawer, 'enable').listen(); // 开启或关闭调试功能
100+
f.add(Physics.debugDrawer, 'debugMode', Physics.debugDrawer.debugModeList); // 调试模式
101+
f.add(Physics.debugDrawer, 'updateFreq', 1, 360, 1); // 线条渲染的频率(每帧)
102+
f.add(Physics.debugDrawer, 'maxLineCount', 100, 33000, 100); // 设置渲染的最大线条数量
103+
```
104+
:::
105+
106+
- **物理对象交互**:如果需要使用鼠标与刚体进行拖拽控制,可以在 `init()` 中将此功能开启:
107+
108+
```ts
109+
await Physics.init({ useDrag: true });
110+
```
111+
::: tip
112+
可以通过 `Physics.physicsDragger` 进行相关设置,详见 [PhysicsDragger](/physics/classes/PhysicsDragger)
113+
:::
114+
115+
## 物理工具
116+
物理系统提供了一些工具,帮助开发者更灵活地进行定制开发。
117+
- [CollisionShapeUtil](/physics/classes/CollisionShapeUtil):提供多种方法来创建不同类型的碰撞形状。
118+
- [ContactProcessedUtil](/physics/classes/ContactProcessedUtil):用于注册和管理物理对象之间碰撞事件的工具类。
119+
- [RigidBodyMapping](/physics/classes/RigidBodyMapping):管理 `Ammo` 刚体与三维模型对象映射关系的工具类,需手动指定映射。
120+
- [RigidBodyUtil](/physics/classes/RigidBodyUtil):提供多种与 `Ammo` 刚体相关的实用方法,简化刚体的创建和各项操作。
121+
- [TempPhyMath](/physics/classes/TempPhyMath):临时物理数学工具类,提供 `Ammo` 数学对象(如向量和四元数)的实例,并支持与引擎数据类型相互转换。
122+
123+
72124
## 原生扩展
73125
当前引擎只封装了几个常用的组件,如果需要实现复杂的物理模拟,用户可以直接引用 `Ammo` 来使用原生的物理世界对象,通过 `Ammo.js` 自身提供的原生 `API` 实现更多自定化需求:
74126
```ts
@@ -89,45 +141,43 @@ let transform = new Ammo.btTransform();
89141
更多用法详见 [Ammo API](/physics/modules/Ammo)
90142

91143
## 简单示例
92-
这里我们通过模拟一个正方体掉落在地上的过程,看一下物理系统具体可以提供哪下效果
144+
这里我们通过模拟一个正方体掉落在地上的过程,看一下物理系统具体可以提供哪些效果
93145

94146
<Demo src="/demos/physics/demo1.ts"></Demo>
95147

96148
<<< @/public/demos/physics/demo1.ts
97149

98150
依照前面章节所介绍的流程,我们首先将场景、相机、环境贴图、光照等基础组件初始化并设定好参数。
99-
接下来,我们创建一个立方体,并为其添加刚体与碰撞体组件,使之拥有质量并能正确响应重力与碰撞。
100-
```ts
151+
接下来,我们创建一个立方体,并为其添加刚体组件并指定碰撞形状,使之拥有质量并能正确响应重力与碰撞。
152+
153+
```ts {7-9}
101154
const obj = new Object3D();
102155
let mr = obj.addComponent(MeshRenderer);
103156
mr.geometry = new BoxGeometry(5, 5, 5);
104157
mr.material = new LitMaterial();
105-
// 响应重力
158+
159+
// 响应重力并设置碰撞形状
106160
let rigidbody = obj.addComponent(Rigidbody);
107161
rigidbody.mass = 10;
108-
// 设置碰撞盒子
109-
let collider = obj.addComponent(ColliderComponent);
110-
collider.shape = new BoxColliderShape();
111-
collider.shape.size = new Vector3(5, 5, 5);
162+
rigidbody.shape = Rigidbody.collisionShape.createShapeFromObject(obj);
112163

113164
scene3D.addChild(obj);
114165
```
115166

116-
之后,我们在正方体下方创建一个平面,作为地面,同样为其添加刚体与碰撞体组件。由于地面是静止的,所以我们设置其质量为 `0`
117-
```ts
167+
之后,我们在正方体下方创建一个平面,作为地面,同样为其添加刚体组件并指定碰撞形状。由于地面是静止的,所以我们设置其质量为 `0`
168+
169+
```ts {7-9}
118170
const obj = new Object3D();
119171
let mr = obj.addComponent(MeshRenderer);
120172
mr.geometry = new PlaneGeometry(size.x, size.y);
121173
mr.material = new LitMaterial();
122-
// 静态钢体,不响应重力
174+
175+
// 静态刚体,不响应重力
123176
let rigidbody = obj.addComponent(Rigidbody);
124177
rigidbody.mass = 0;
125-
// 设置碰撞盒子
126-
let collider = obj.addComponent(ColliderComponent);
127-
collider.shape = new BoxColliderShape();
128-
collider.shape.size = new Vector3(size.x, 0.1, size.y);
178+
rigidbody.shape = Rigidbody.collisionShape.createShapeFromObject(obj);
129179

130180
scene.addChild(obj);
131181
```
132182

133-
物理系统启动后,引擎立即根据物体质量响应其重力感应,当立方体和地面的碰撞体形状产生交集时,我们可以看到真实的物体落地碰撞效果更多[物理示例](/example/physics/Dominoes)
183+
物理系统启动后,引擎立即根据物体质量响应其重力感应,当立方体和地面的碰撞体形状产生交集时,我们可以看到真实的物体落地碰撞效果更多[物理示例](/example/physics/Dominoes)

docs/guide/physics/collider.md

Lines changed: 0 additions & 82 deletions
This file was deleted.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# 碰撞体
2+
碰撞体形状 `Collision Shape` 定义了刚体响应碰撞的实际物理形状,物理系统可以通过 `Shape` 判定两个物体是否相交,从而产生碰撞效果。
3+
4+
:::tip
5+
`@orillusion/physics@0.3` 开始,我们推荐直接使用 `Ammo` 原生 `Shape` 管理碰撞体
6+
:::
7+
8+
## 碰撞体工具
9+
为了简化碰撞体的创建过程,[CollisionShapeUtil](/physics/classes/CollisionShapeUtil) 工具类提供了便捷的物理形状构建方法,涵盖了多种常见的碰撞体形状。该工具类将复杂的物理形状生成过程封装为一系列易于调用的方法,使开发者能够快速高效地为模型对象生成适配的碰撞体。
10+
11+
### 内置形状
12+
13+
目前 [CollisionShapeUtil](/physics/classes/CollisionShapeUtil) 提供的物理形状创建方法如下表所示:
14+
15+
| 函数名称 | 返回类型 | 描述 |
16+
| --- | --- | --- |
17+
| createStaticPlaneShape | `Ammo.btStaticPlaneShape` | 创建一个静态平面碰撞形状,适用于无限大且静止的平面,如地面或墙壁 |
18+
| createBoxShape | `Ammo.btBoxShape` | 盒型碰撞形状 |
19+
| createSphereShape | `Ammo.btSphereShape` | 球型碰撞形状 |
20+
| createCapsuleShape | `Ammo.btCapsuleShape` | 胶囊型碰撞形状 |
21+
| createCylinderShape | `Ammo.btCylinderShape` | 圆柱型碰撞形状 |
22+
| createConeShape | `Ammo.btConeShape` | 圆锥形碰撞形状 |
23+
| createCompoundShape | `Ammo.btCompoundShape` | 复合形状,将多个子形状组合成一个复杂的碰撞体 |
24+
| createHeightfieldTerrainShape | `Ammo.btHeightfieldTerrainShape` | 高度场形状,适用于地形的碰撞检测 |
25+
| createConvexHullShape | `Ammo.btConvexHullShape` | 凸包形状,适用于动态物体的快速碰撞检测 |
26+
| createConvexTriangleMeshShape | `Ammo.btConvexTriangleMeshShape` | 凸包网格形状,适用于需要复杂几何表示的动态物体 |
27+
| createBvhTriangleMeshShape | `Ammo.btBvhTriangleMeshShape` | 边界体积层次 `BVH` 网格形状,适用于需要复杂几何表示的静态物体 |
28+
| createGImpactMeshShape | `Ammo.btGImpactMeshShape` | `GImpact` 网格形状,适用于复杂的三角网格碰撞检测,特别是动态物体 |
29+
| createShapeFromObject | `Ammo.btCollisionShape` | 创建一个匹配 `Object3D` 几何体类型的碰撞形状 |
30+
31+
### 复杂结构支持
32+
`CollisionShapeUtil` 提供了两个支持处理嵌套对象的 `API`。这些 `API` 可以自动生成适合的碰撞形状或提取几何数据,适用于由引擎创建的复杂结构,无需手动为每个子对象单独配置。
33+
34+
| 函数名称 | 返回类型 | 描述 |
35+
| --- | --- | --- |
36+
| createCompoundShapeFromObject | `Ammo.btCompoundShape` | 根据传入的 `Object3D` 及其子对象的几何体类型,自动创建一个复合碰撞体 |
37+
| getAllMeshVerticesAndIndices | `{ vertices:Float32Array; indices: Uint16Array; }` | 返回 `Object3D` 及其子对象的所有顶点和索引数据,经过世界变换矩阵转换后,可用于创建高精度的网格碰撞体 |
38+
39+
## 基本使用
40+
41+
创建碰撞体的过程已被简化,在大多数情况下,只需传入 `Object3D`,即可生成碰撞体。以下是使用 `CollisionShapeUtil` 创建基础碰撞形状的示例代码:
42+
43+
```ts
44+
import { Object3D, MeshRenderer, CylinderGeometry, LitMaterial } from '@orillusion/core';
45+
import { CollisionShapeUtil } from '@orillusion/physics';
46+
47+
// 创建一个圆锥体
48+
const coneObject = new Object3D();
49+
let mr = coneObject.addComponent(MeshRenderer);
50+
mr.geometry = new CylinderGeometry(0.01, 1, 5);
51+
mr.material = new LitMaterial();
52+
53+
// 对于简单类型的几何体,如盒型、球型、圆锥、圆柱可以使用通用的方法创建碰撞体
54+
let coneShape1 = CollisionShapeUtil.createShapeFromObject(coneObject);
55+
// 或者通过计算局部包围盒创建圆锥形状
56+
let coneShape2 = CollisionShapeUtil.createConeShape(coneObject);
57+
// 或者指定形状尺寸
58+
let coneShape3 = CollisionShapeUtil.createConeShape(null, 1, 5);
59+
```
60+
61+
同时,针对复杂类型的碰撞形状,构建流程也得到了简化。为了满足自定义需求,开发者可以传入 `vertices``indices` 以生成自定义的碰撞形状:
62+
63+
```ts
64+
const object = await Engine3D.res.loadGltf('model.glb');
65+
66+
// 创建一个BVH网格形状,使用模型自身的顶点和索引
67+
let bvhMeshShape = CollisionShapeUtil.createBvhTriangleMeshShape(object);
68+
69+
// 或手动传入的顶点和索引
70+
const vertices = [...]
71+
const indices = [...]
72+
const vertices = new Float32Array(vertices);
73+
const indices = new Uint16Array(data.indices);
74+
let bvhMeshShape = CollisionShapeUtil.createBvhTriangleMeshShape(object, vertices, indices);
75+
```
76+
77+
此外,基于 `TerrainGeometry``PlaneGeometry`,可以创建适用于模拟地形的高度场碰撞形状:
78+
79+
```ts
80+
import { TerrainGeometry } from '@orillusion/geometry';
81+
82+
// Load textures and create terrain geometry
83+
let heightTexture = await Engine3D.res.loadTexture('height.png');
84+
let terrainGeometry = new TerrainGeometry(100, 100, 60, 60);
85+
terrainGeometry.setHeight(heightTexture as BitmapTexture2D, 50);
86+
87+
const terrain = new Object3D();
88+
let mr = terrain.addComponent(MeshRenderer);
89+
mr.geometry = terrainGeometry;
90+
mr.material = new LitMaterial();
91+
92+
// 创建地形碰撞体
93+
let terrainShape = CollisionShapeUtil.createHeightfieldTerrainShape(terrain);
94+
```
95+
96+
通过上述操作,我们可以创建多种碰撞体以适应不同的物理需求。然而,为了实现全面的物理模拟,单独的碰撞体是不够的。要获得真实的物理效果,还需要与 [刚体](/guide/physics/Rigidbody.html) 结合使用,从而实现完整的物理交互和模拟。
97+
98+
99+
## 示例
100+
101+
不同的碰撞体形状适用于各类物理场景。以下示例展示了如何使用 `CollisionShapeUtil` 为多种几何形状生成对应的碰撞体,并结合 [刚体](/guide/physics/Rigidbody.html) 在物理系统中应用这些形状。
102+
103+
<Demo src="/demos/physics/shapes.ts"></Demo>
104+
105+
<<< @/public/demos/physics/shapes.ts
106+
107+
更多[物理示例](/example/physics/Dominoes)

0 commit comments

Comments
 (0)