diff --git a/docs/api/README.md b/docs/api/README.md new file mode 100644 index 0000000..1cbc078 --- /dev/null +++ b/docs/api/README.md @@ -0,0 +1,21 @@ +--- +title: Picea API 索引 +--- + +# Picea 项目 API 总览 + +本文档集合了本仓库内所有公开 API、函数以及对外组件的详细说明。请根据需求跳转到对应文档阅读。 + +## 文档导航 + +- [picea 物理引擎 API](./picea.md) +- [picea-macro-tools 宏库 API](./picea_macro_tools.md) +- [picea-web WebAssembly 绑定 API](./picea_web.md) + +## 阅读建议 + +- 如需了解场景管理、约束或图形学相关功能,请先从 `picea` 文档开始。 +- 需要为结构体生成 Builder、Fields 等宏能力时,请查看 `picea-macro-tools` 文档。 +- 若要在浏览器中运行 Picea,请阅读 `picea-web` 的 WebAssembly 接口说明。 + +文档结构遵循模块划分,避免重复内容。如遇到跨模块的概念,请优先查看 `picea` 主文档中的背景介绍。 diff --git a/docs/api/picea.md b/docs/api/picea.md new file mode 100644 index 0000000..c4aa0ac --- /dev/null +++ b/docs/api/picea.md @@ -0,0 +1,296 @@ +--- +title: picea API 文档 +--- + +# picea 物理引擎 API 文档 + +`picea` 是一个 2D 刚体物理引擎,提供场景管理、碰撞检测、约束求解、形状建模与数值工具。本章节列出所有对外公开的结构体、函数与 trait,并给出使用示例。 + +## 1. 快速开始 + +下面的示例展示了如何创建一个场景、添加矩形和圆形元素,并在主循环中推进物理模拟: + +```rust +use picea::prelude::*; + +fn main() { + let mut scene = Scene::new(); + + // 创建一个静态地面 + let ground = ElementBuilder::new( + Rect::new(0.0, 300.0, 800.0, 40.0), + MetaBuilder::new().mass(1000.0).is_fixed(true), + (), + ); + scene.push_element(ground); + + // 创建一个可运动的方块 + let box_meta = MetaBuilder::new() + .mass(5.0) + .factor_restitution(0.1) + .velocity((2.0, 0.0)); + let block = ElementBuilder::new( + Square::new((200.0, 120.0), 40.0), + box_meta, + (), + ); + let block_id = scene.push_element(block); + + // 每帧调用 tick 推进世界时间 + for _frame in 0..600 { + scene.tick(1.0 / 60.0); + + if let Some(element) = scene.get_element(block_id) { + println!("高度: {}", element.center_point().y()); + } + } +} +``` + +## 2. 模块导航 + +| 模块 | 说明 | +| --- | --- | +| `prelude` | 常用类型重导出,便于快速引入引擎核心能力 | +| `scene` | 场景生命周期管理、约束调度、回调注册等 | +| `element` | 物体结构定义、构建器、克隆与惯量计算 | +| `shape` | 几何体实现及通用变换、最近点计算工具 | +| `math` | 数学基础类型(向量、点、矩阵、常量等) | +| `meta` | 元数据与物理属性(质量、速度、变换、力) | +| `constraints` | 点约束、关节约束及软约束参数求解 | +| `collision` | 碰撞检测流程、GJK/EPA 支持点与接触对 | +| `tools` | 调试与辅助工具(拖拽、快照、碰撞视图) | +| `algo` | 引擎内部排序算法实现(对外仅接口说明) | + +## 3. Prelude + +`picea::prelude` 重导出以下类型,推荐在项目入口 `use picea::prelude::*;`: + +- `Scene` +- 元素相关:`ElementBuilder`, `ShapeTraitUnion`, `ComputeMomentOfInertia`, `SelfClone`, `ID` +- 数学类型:`Point`, `Vector`, `Segment`, `Edge`, `FloatNum` +- 元数据:`Mass`, `Meta`, `MetaBuilder` +- 形状 trait:`CenterPoint`, `EdgeIterable`, `GeometryTransformer`, `NearestPoint` +- 约束配置:`JoinConstraintConfig`, `JoinConstraintConfigBuilder` +- 碰撞接口:`Projector` + +## 4. 场景 (`scene` 模块) + +### 4.1 `Scene` + +`Scene` 是引擎的顶级调度器,泛型 `Data` 用于存储用户自定义的全局状态(可选,需实现 `Clone + Default`)。关键公开方法如下: + +| 方法 | 说明 | +| --- | --- | +| `Scene::new()` | 创建一个默认场景,容量按需增长 | +| `Scene::width_capacity(capacity)` | 预分配元素存储容量,降低重新分配成本 | +| `scene.push_element(ElementBuilder)` | 将元素放入场景并返回元素 ID | +| `scene.has_element(id)` / `remove_element(id)` | 检查或移除元素 | +| `scene.element_size()` | 返回当前元素数量 | +| `scene.tick(delta_time)` | 推进模拟,内部完成速度积分、碰撞检测、约束求解与位置修正 | +| `scene.total_duration()` | 累计经过的模拟时间 | +| `scene.register_element_position_update_callback(f)` | 注册元素位置变化回调,返回回调 ID | +| `scene.unregister_element_position_update_callback(id)` | 取消回调 | +| `scene.elements_iter()` / `elements_iter_mut()` | 迭代所有元素(不可变/可变) | +| `scene.get_element(id)` / `get_element_mut(id)` | 按 ID 查询元素 | +| `scene.frame_count()` | 返回累计帧数 | +| `scene.context_mut()` | 获取 `Context` 进行全局配置(约束参数、重力、睡眠等) | +| `scene.clear()` | 清空所有元素与约束,并重置帧计数 | +| `scene.is_element_collide(a_id, b_id, query_from_manifold)` | 查询两个元素是否碰撞,可选择是否直接使用当前接触流形 | +| `scene.set_gravity(reducer)` | 自定义重力向量(传入闭包修改默认重力) | +| `scene.create_point_constraint(...)` | 创建元素与固定点的软/硬约束,返回约束 ID | +| `scene.point_constraints()` | 遍历当前点约束 | +| `scene.get_point_constraint(id)` / `get_point_constraint_mut(id)` | 查询指定点约束 | +| `scene.remove_point_constraint(id)` | 删除点约束并解绑元素锚点 | +| `scene.create_join_constraint(...)` | 创建元素之间的关节约束 | +| `scene.join_constraints()` / `get_join_constraint(_mut)` | 查询关节约束 | +| `scene.remove_join_constraint(id)` | 移除关节并解绑元素锚点 | +| `scene.set_sleep_mode(enabled)` | 开启/关闭睡眠模式,自动沉睡低能量物体 | +| `scene.silent()` | 将所有元素的线速度与角速度置零 | +| `scene.get_position_fix_map()` | 调试当前接触求解的位移修正量 | + +> 提示:`Context` 中的 `constraint_parameters` 可调节碰撞穿透修正、默认摩擦系数、最大限制力等数值,适合在初始化阶段设定。 + +### 4.2 `Context` + +`Scene::context_mut()` 返回 `Context`,主要字段: + +- `constraint_parameters` (`ConstraintParameters`):控制解算器参数,如 `factor_position_bias`、`max_allow_permeate`、`split_position_fix` 等。 +- `enable_sleep_mode`:是否启用睡眠判定。 +- `max_enter_sleep_kinetic`、`max_enter_sleep_frame`:睡眠阈值。 +- `enable_gravity`、`default_gravity`:全局重力开关与向量。 + +## 5. 元素与构建 (`element` 模块) + +### 5.1 `Element` + +`Element` 代表场景中的刚体元素,`T` 为附加数据类型。关键方法: + +- `Element::new(shape, meta, data)`:直接用形状、元数据、附加数据构造一个元素。 +- `element.center_point()`:返回当前中心点。 +- `element.integrate_position(delta_time)`:根据当前速度积分位置,返回 `(平移, 旋转)`。 +- `element.meta()` / `meta_mut()`:访问元数据。 +- `element.shape()`:借助 `Fields` 派生的 getter 获取动态形状引用。 +- `element.transform(transform)`、`element.apply_transform()`:内部使用,处理增量变换。 +- `element.create_bind_point(id, point)` / `get_bind_point(id)` / `remove_bind_point(id)`:管理约束绑定点。 + +### 5.2 `ElementBuilder` + +用于构建元素的便捷接口: + +- `ElementBuilder::new(shape, meta, data)`:shape 必须实现 `Into>`,meta 可直接传入 `Meta` 或 `MetaBuilder`。 +- 链式 API:`builder.shape(new_shape)`、`builder.meta(meta)`、`builder.addition_data(data)`。 +- `ElementBuilder` 自动在 `Scene::push_element` 时计算形状的转动惯量并注入到 `Meta`。 + +### 5.3 Trait 汇总 + +- `ComputeMomentOfInertia`:计算给定质量下的转动惯量,所有形状需实现。 +- `SelfClone`:将形状克隆为 trait 对象,用于元素复制。 +- `ShapeTraitUnion`:统一抽象(`GeometryTransformer + CenterPoint + NearestPoint + EdgeIterable + ComputeMomentOfInertia + Projector + Collider + SelfClone`)。 +- `ConstraintObject`(定义于 `constraints`):约束系统使用元素的公共接口。 + +### 5.4 `ElementStore` + +`ElementStore` 是公开结构体,主要通过 `Scene` 间接使用。其提供: + +- `ElementStore::with_capacity(capacity)` +- `store.iter()` / `iter_mut()` +- `store.push(element)`、`remove_element(id)`、`clear()` +- `store.get_element_by_id(id)`、`get_mut_element_by_id(id)` +- `store.detective_collision(handler)`:执行碰撞检测并回调结果(通常由 `Scene` 调用)。 + +## 6. 元数据 (`meta` 模块) + +### 6.1 `Meta` + +`Meta` 存储元素的物理属性: + +- 质量 (`mass`)、转动惯量 (`moment_of_inertia`)、线速度 (`velocity`)、角速度 (`angle_velocity`) +- 摩擦系数 (`factor_friction`)、弹性系数 (`factor_restitution`) +- 状态标记:`is_fixed`、`is_transparent`、`is_ignore_gravity`、`is_sleeping` +- 累积变换:`delta_transform`、`total_transform` +- 接触统计:`contact_count`、`inactive_frame_count` + +常用方法: + +| 方法 | 说明 | +| --- | --- | +| `meta.mass()` / `meta.set_mass(value)` | 读取或设定质量,并自动更新倒数 | +| `meta.inv_mass()`、`meta.inv_moment_of_inertia()` | 返回倒数,求解器使用 | +| `meta.motion()` | 返回线动量向量 | +| `meta.apply_impulse(impulse, r)` | 对质心施加冲量,并根据力臂更新角速度 | +| `meta.compute_kinetic_energy()` | 计算动能 | +| `meta.compute_rough_energy()` | 返回调试用能量指标数组 | +| `meta.silent()` | 清除速度、角速度 | + +### 6.2 `MetaBuilder` + +`MetaBuilder::new()` 创建默认元数据,可链式调用: + +- `mass(value)`、`velocity((x, y))`、`angle_velocity(value)` +- `factor_friction(value)`、`factor_restitution(value)` +- `is_fixed(bool)`、`is_transparent(bool)`、`is_ignore_gravity(bool)` + +### 6.3 力系统 (`meta::force`) + +- `Force::new(id, vector)`:创建具名力,可设置临时标记 `set_temporary`。 +- `Force::get_vector()` / `set_vector(reducer)`:读取或更新力向量。 +- `ForceGroup`:管理一组力,提供 `add_force`、`get_force(_mut)`、`remove`、`sum_force`、`iter` 等接口。 + +## 7. 数学工具 (`math` 模块) + +- `FloatNum`:浮点类型别名(`f32`)。 +- 常量函数:`pi()`、`tau()`。 +- `axis::AxisDirection`:`X`、`Y` 枚举,支持取反 `!axis`。 +- `point::Point`:点坐标,支持 `Point::new(x, y)`、坐标访问、向量转换。 +- `vector::Vector` / `Vector3`:包含加减乘除、点积、叉积、归一化、旋转、角度计算等常见操作。 +- `segment::Segment`:线段封装,可获取起终点、向量投影等。 +- `edge::Edge`:多种边缘类型枚举(线段、圆弧、圆),用于形状迭代。 +- `matrix`:提供基础矩阵运算(详见源码)。 +- `num::is_same_sign(a, b)`:判断符号是否相同(内部使用,同样为 `pub(crate)`,不对外暴露)。 + +## 8. 形状 (`shape` 模块) + +所有形状实现 `ShapeTraitUnion` 所需 trait,可直接用于 `ElementBuilder::new`。关键结构体及构造函数: + +- `Rect::new(top_left_x, top_left_y, width, height)` +- `Square::new(center_point, edge_length)` +- `Triangle::new([Point; 3])` +- `Circle::new(center_point, radius)` +- `Line::new(start_point, end_point)` +- `ConvexPolygon::new(vertices: Vec)` +- `ConcavePolygon::new(vertices: Vec)` +- `RegularPolygon::new(center_point, edge_count, radius)` +- `ConstRegularPolygon::::new(center_point, radius)`(编译期定边正多边形) +- `ConstPolygon::::new(vertices: [Point; N])` + +通用工具(`shape::utils`): + +- `compute_polygon_approximate_center_point`、`compute_convex_center_point`、`compute_area_of_convex` +- `check_is_polygon_clockwise`、`check_is_concave` +- 变换函数:`translate_polygon`、`rotate_polygon`、`resize_by_vector` +- 碰撞辅助:`projection_polygon_on_vector`、`check_is_segment_cross`、`compute_cross_point_between_two_segment` +- 几何拆分:`split_convex_polygon_to_triangles`、`split_clockwise_concave_polygon_to_two_convex_polygon` + +## 9. 碰撞 (`collision` 模块) + +- Trait + - `Projector`:投影到向量/坐标轴,所有碰撞形状需实现。 + - `SubCollider`:具备 `Projector + CenterPoint + NearestPoint` 的子碰撞体。 + - `Collider`:整体碰撞体,可提供 `sub_colliders()` 以支持组合碰撞体。 + - `CollisionalCollection`:可排序的碰撞体集合接口,`ElementStore` 实现了此 trait。 +- 流程函数 + - `detect_collision(collection, handler, skip)`:包裹粗检测、子碰撞体精确检测,并将最终接触点列表交给 `handler`。 + - `rough_collision_detection(collection, handler)`:Sweep & Prune 粗检测。 + - `prepare_accurate_collision_detection(collider_a, collider_b, handler)`:枚举子碰撞体组合。 + - `accurate_collision_detection_for_sub_collider(a, b)`:GJK + EPA 计算接触点对。 +- 数据结构 + - `ContactPointPair`:包含接触点(A/B)、法线、穿透深度、平均点。 + - `MinkowskiDifferencePoint`、`MinkowskiEdge`:EPA 过程中使用的中间结构。 + +## 10. 约束 (`constraints` 模块) + +- `JoinConstraintConfig` + - 字段:`distance`、`damping_ratio`、`frequency`、`hard` + - 通过 `JoinConstraintConfigBuilder` 链式设置(由 `picea_macro_tools::Builder` 生成)。 + +- `compute_inv_mass_effective(normal, (obj_a, obj_b), r_a, r_b)`:常规约束质量组合计算。 +- `compute_soft_constraints_params(mass, damping_ratio, frequency, delta_time)`:返回 `(force_soft_factor, position_fix_factor)`。 + +- `PointConstraint` + - `PointConstraint::new(id, obj_id, fixed_point, move_point, config)` + - `stretch_length()`:返回当前伸长向量。 + - 场景在预求解时会调用内部 `reset_params` 与 `solve`(无需手动)。 + +- `JoinConstraint`(详见 `constraints/join.rs`) + - 提供双元素约束,支持软硬配置。 + - 提供 `move_point_pair()`、`config()` 等访问器。 + +- `contact::ContactConstraint` 与 `contact_manifold::ContactConstraintManifold` + - 管理碰撞接触对及其累计冲量。 + +## 11. 调试与工具 (`tools` 模块) + +- `tools::snapshot::create_element_construct_code_snapshot(element)`:根据元素当前状态生成可复现的 Rust 构造代码字符串。 +- `tools::drag::Draggable` + - `on_mouse_down(scene)` / `on_mouse_move(scene, x, y)` / `on_mouse_up()`:实现简单的鼠标拖拽交互。 + - `mouse_point()`:返回当前鼠标位置。 +- `tools::collision_view::CollisionStatusViewer` + - `on_update(scene)`:刷新内部接触状态缓存。 + - `get_collision_infos()`:获取 `ContactInfos` 列表,调试用。 + +## 12. 算法 (`algo` 模块) + +`algo::sort` 模块主要供内部使用,但对外可见的 trait 有助于自定义集合: + +- `SortableCollection`(`pub(crate)`,默认不对外开放):若需扩展,可参考 `ElementStore` 实现快速排序与插入排序组合策略。 + +## 13. 实用技巧 + +- **使用 `Scene::tick` 的 delta time**:内部限制在 `[1/60, 1/25]` 区间,避免跳帧导致数值不稳定。 +- **约束绑定点**:创建约束时会自动在元素内部注册绑定点,删除约束时记得调用 `remove_point_constraint`/`remove_join_constraint`,以移除绑定引用。 +- **睡眠模式**:当启用睡眠后,元素动能低于阈值并持续若干帧会自动停用,需外力唤醒时可调用 `scene.silent()` 或直接修改元素元数据。 + +## 14. 进一步阅读 + +示例目录 `crates/picea/examples/` 覆盖了积木堆叠、布料、桥梁、坑洞等场景。可参考 `stack.rs`、`bridge.rs` 等文件,了解多约束组合的实践方式。 diff --git a/docs/api/picea_macro_tools.md b/docs/api/picea_macro_tools.md new file mode 100644 index 0000000..ebc9984 --- /dev/null +++ b/docs/api/picea_macro_tools.md @@ -0,0 +1,163 @@ +--- +title: picea-macro-tools API 文档 +--- + +# picea-macro-tools 宏库 + +`picea-macro-tools` 为 `picea` 项目及其扩展提供一组派生宏与属性宏,帮助快速生成 Builder、字段访问器、Deref 实现以及 WebAssembly 配置映射。本节逐一介绍公开宏、支持的属性参数以及常见用法示例。 + +## 1. 派生宏总览 + +| 宏 | 目标 | 说明 | +| --- | --- | --- | +| `#[derive(Shape)]` | 结构体 | 自动实现碰撞相关 trait,使形状可直接参与物理引擎计算 | +| `#[derive(Deref)]` | 结构体 | 基于 `#[deref]` 标记的字段生成 `Deref`/`DerefMut` | +| `#[derive(Builder)]` | 结构体 | 生成 `*Builder` 构建器、默认值及链式设置方法 | +| `#[derive(Fields)]` | 结构体 | 依据字段属性生成读取、写入、可变引用等访问器 | +| `#[wasm_config(...)]` | 结构体 | 生成 WebAssembly 绑定结构及 `serde_wasm_bindgen` 映射 | + +以下章节分别说明每个宏的行为与可选参数。 + +## 2. `#[derive(Shape)]` + +`Shape` 派生宏会为目标结构体实现以下 trait: + +- `crate::collision::Collider` +- `crate::element::SelfClone` + +该宏假设目标结构体自身已经实现(或通过 `Fields`/`Deref` 间接提供)`GeometryTransformer`、`CenterPoint`、`EdgeIterable`、`NearestPoint`、`Projector`、`ComputeMomentOfInertia` 等 trait。 + +### 属性 + +- `#[inner]`:可与 `Fields` 配合,标记嵌套字段以导出内部访问器。 + +### 示例 + +```10:18:crates/picea/src/shape/rect.rs +#[derive(Clone, Debug, Shape, Deref, Fields)] +pub struct Rect { + #[r] + width: f32, + #[r] + height: f32, + #[deref] + inner: ConstPolygon<4>, +} +``` + +通过 `Shape` 与 `Deref` 联合使用,`Rect` 自动具备碰撞体能力,并将大部分实现委托给内部的 `ConstPolygon`。 + +## 3. `#[derive(Deref)]` + +该宏依赖字段级属性 `#[deref]` 指定唯一的目标字段,生成 `core::ops::Deref` 与 `DerefMut` 实现。 + +### 使用要点 + +- 仅支持结构体。 +- 必须恰好有一个字段带 `#[deref]`。 +- 可结合 `Fields` 为外层结构体提供访问器,同时继承内层类型的方法。 + +## 4. `#[derive(Builder)]` + +`Builder` 派生宏会为结构体生成同名加后缀 `Builder` 的构建器类型,提供默认实现、`new()` 构造方法、链式字段设置以及 `From` 转换。 + +### 属性 + +- `#[default = ]`:指定字段的默认值表达式。若缺失则调用 `Default::default()`。 +- `#[builder(skip)]`:跳过为该字段生成链式 setter。 +- `#[shared(skip)]`:与 `Fields` 配置一致,阻止在生成器和访问器中重复暴露字段。 + +### 生成结果 + +- `FooBuilder` 结构体包含与原结构体相同的字段。 +- `impl Default for FooBuilder` 与 `impl Default for Foo` 会根据 `#[default]` 自动填充。 +- `impl From for Foo`:方便在构建器与目标类型之间转换。 + +## 5. `#[derive(Fields)]` + +`Fields` 宏根据字段属性生成访问器/修改器。默认情况下: + +- 为原结构体添加只读方法(返回引用或原始值)。 +- 可选生成可变引用方法、设置器或使用闭包的 reducer。 + +### 字段级属性 + +- `#[r]`:生成只读访问器。支持参数: + - `vis(pub(crate))`:覆盖生成方法的可见性。 + - `copy`:强制返回值而非引用。 +- `#[w]`:生成写访问能力。支持参数: + - `vis(...)`:设置方法可见性。 + - `reducer`:生成 `set_(FnOnce(T) -> T)`,用于基于旧值计算新值。 + - `set`:生成 `set_(Into)`,链式返回 `&mut Self`。 +- `#[shared(skip)]`:完全跳过该字段。 + +### 结构体级属性 + +- 可在结构体上使用 `#[r(...)]` 或 `#[w(...)]` 设置默认访问策略,供未显式标注的字段继承。 + +### 示例 + +```85:95:crates/picea/src/element/mod.rs +#[derive(Fields)] +#[r] +pub struct Element { + id: ID, + #[w] + meta: Meta, + #[w] + shape: Box, + bind_points: BTreeMap, + data: Data, +} +``` + +上例展示了: + +- 结构体级 `#[r]` 使未显式标注的字段默认生成 `fn field(&self) -> &T`。 +- `#[w]` 为 `meta`、`shape` 生成 `set_meta`, `meta_mut` 等方法,便于运行时调整。 + +## 6. `#[wasm_config]` 属性宏 + +`wasm_config` 属性宏用于定义可导出到 WebAssembly 的配置结构。核心特性: + +- 自动派生 `picea_macro_tools::Fields`(便于读写字段)。 +- 自动派生 `Serialize`/`Deserialize`,支持通过 `serde_wasm_bindgen` 与 JS 交互。 +- 生成 `Web` 与 `OptionalWeb` 类型别名(对应完整配置与部分配置)。 +- 若提供 `bind = TypeName` 参数,会生成与 `picea::prelude::TypeName` 互转的实现,方便在 Rust 与 JS 之间共享构建器。 + +### 字段默认值 + +- 与 `Builder` 类似,支持在字段上使用 `#[default = ]` 定义 JS 端缺省值。 + +### 示例 + +```83:95:crates/picea-web/src/common.rs +#[wasm_config(bind = Meta)] +pub(crate) struct Meta { + #[default = 1.0] + pub mass: FloatNum, + #[default = true] + pub is_fixed: bool, + pub is_transparent: bool, + pub velocity: Tuple2, + #[default = 0.2] + pub factor_friction: FloatNum, + #[default = 1.] + pub factor_restitution: FloatNum, +} +``` + +生成的辅助类型与实现包括: + +- `WebMeta` / `OptionalWebMeta`:用于 JS 层类型提示与运行时校验。 +- `impl From<&picea::prelude::Meta> for Meta` 与 `impl From<&Meta> for picea::prelude::MetaBuilder`(当配置包含 `bind` 时)。 +- `impl Default for Meta`:按 `#[default]` 设置初始值。 + +## 7. 最佳实践 + +- **组合使用**:常见组合是 `#[derive(Fields, Builder)]`,先生成访问器,再通过构建器提供友好的初始化 API。 +- **可见性控制**:通过 `vis(pub(crate))` 等参数精细化 getter/setter 暴露范围,避免内部字段泄漏。 +- **与 `picea` 配合**:在自定义形状或约束对象上,推荐同时使用 `Shape` 和 `Fields`,并在场景初始化阶段利用 `Builder` 快速创建 `Meta` 或约束配置。 +- **WebAssembly 场景**:结合 `wasm_config` 与 `serde_wasm_bindgen`,可以在 TypeScript 中获得强类型提示,同时保持 Rust 端构建逻辑一致。 + +如需进一步了解代码生成的具体实现,可直接查阅 `crates/macro-tools/src/` 目录下对应的宏实现源文件。 diff --git a/docs/api/picea_web.md b/docs/api/picea_web.md new file mode 100644 index 0000000..804b997 --- /dev/null +++ b/docs/api/picea_web.md @@ -0,0 +1,159 @@ +--- +title: picea-web API 文档 +--- + +# picea-web WebAssembly 接口 + +`picea-web` 将 `picea` 物理引擎封装为 WebAssembly 模块,提供面向 TypeScript/JavaScript 的高层 API。本节列出所有公开导出、数据结构及使用示例,便于在浏览器或 Node.js 环境中构建 2D 物理应用。 + +## 1. 基本概念 + +- **值类型包装**: + - `Tuple2`:`{ x: number, y: number }`,用于点与向量。 + - `WebVector`、`WebPoint`:对应 TypeScript 类型 `Vector`、`Point`。 + - `WebMeta` / `OptionalWebMeta`:元素物理属性;对应 `Meta` 与 `MetaPartial`。 + - `WebJoinConstraintConfig` / `OptionalWebJoinConstraintConfig`:关节配置。 +- **Scene 句柄**:`WebScene` 持有内部 `Scene` 指针,并通过 `wasm_bindgen` 自动处理可变访问(内部使用 `UnsafeCell`)。 +- **约束句柄**:`PointConstraint` 与 `JoinConstraint` 对象提供引用操作与销毁函数。 + +## 2. 初始化流程 + +```typescript +import init, { setPanicConsoleHook, create_scene } from "picea-web"; + +async function bootstrap() { + await init(); + setPanicConsoleHook(); + + const scene = create_scene(); + scene.setGravity({ x: 0, y: 9.8 }); + + const ground = scene.createRect(0, 580, 800, 40, { + mass: 1000, + isFixed: true, + factorFriction: 0.8, + }); + + const ball = scene.createCircle(400, 100, 20, { + mass: 5, + factorRestitution: 0.6, + }); + + function step() { + scene.tick(1 / 60); + requestAnimationFrame(step); + } + + step(); +} + +bootstrap(); +``` + +## 3. 全局导出 + +| 函数 | 说明 | +| --- | --- | +| `set_panic_console_hook()` | 将 Rust panic 重定位到浏览器控制台,便于调试 | +| `create_scene()` | 创建新的 `WebScene` 实例 | +| `is_point_valid_add_into_polygon(point, vertices)` | 验证新增顶点是否破坏多边形合法性 | + +## 4. `WebScene` 接口 + +### 4.1 世界配置 + +| 方法 | 说明 | +| --- | --- | +| `setGravity(WebVector)` | 修改默认重力向量 | +| `enableSleepMode()` / `disableSleepMode()` | 控制睡眠优化 | +| `clear()` | 重置场景,包括元素、约束与帧计数 | +| `frameCount()` | 返回累计模拟帧数 | + +### 4.2 时间推进与事件 + +| 方法 | 说明 | +| --- | --- | +| `tick(delta_t: number)` | 推进世界时间(内部会限制 Delta 范围) | +| `registerElementPositionUpdateCallback(callback)` | 注册位置更新回调,返回回调 ID | +| `unregisterElementPositionUpdateCallback(id)` | 移除回调 | +| `forEachElement(callback)` | 遍历所有元素的几何信息(多边形或圆),回调接收 `Shape` 对象 | + +### 4.3 元素创建与管理 + +| 方法 | 说明 | +| --- | --- | +| `createRect(x, y, width, height, meta?)` | 新增矩形,顶点坐标以左上角为基准 | +| `createCircle(cx, cy, radius, meta?)` | 新增圆形 | +| `createRegularPolygon(x, y, edgeCount, radius, meta?)` | 新增正多边形 | +| `createPolygon(vertices, meta?)` | 新增自定义凹/凸多边形 | +| `createLine(start: WebPoint, end: WebPoint, meta?)` | 新增线段 | +| `cloneElement(elementId, metaOverride?)` | 克隆现有元素形状,并可覆盖元数据 | +| `hasElement(id)` | 是否存在指定元素 | +| `removeElement(id)` | 删除元素 | +| `elements_iter()` (通过 `forEachElement`) | 遍历元素 | + +### 4.4 元素查询 + +| 方法 | 说明 | +| --- | --- | +| `getElementMetaData(id)` | 获取元素 `Meta`,返回 `WebMeta`(可直接解构) | +| `updateElementMeta(id, metaPartial)` | 通过部分配置更新元数据(透明、固定、质量、速度等) | +| `getElementVertices(id)` | 返回元素所有顶点(线段返回起点列表,圆形暂未实现) | +| `getElementCenterPoint(id)` | 返回元素中心点 | +| `getElementRawRustCode(id)` | 生成当前元素的 Rust 构造代码快照 | +| `isPointInsideElement(x, y, id)` | 判断点是否位于元素内部 | +| `getElementKinetic(id)` | 返回能量估计(`[v², ω², Δx², Δθ]`) | +| `getSleepingStatus(id)` | 返回元素是否处于睡眠状态 | +| `element_ids()` | 获取所有元素 ID | +| `getPositionFixMap()` | 返回碰撞位移修正调试数据 | +| `isElementCollide(aId, bId, query_from_manifold?)` | 查询碰撞状态,可选择是否使用当前接触流形缓存 | + +### 4.5 约束管理 + +| 方法 | 说明 | +| --- | --- | +| `createPointConstraint(elementId, elementPoint, fixedPoint, config?)` | 生成点-锚约束,返回 `PointConstraint` 对象 | +| `pointConstraints()` | 获取当前所有点约束句柄列表 | +| `createJoinConstraint(elementAId, pointA, elementBId, pointB, config?)` | 生成元素间关节,返回 `JoinConstraint` 对象 | +| `joinConstraints()` | 获取当前所有关节句柄 | + +## 5. 约束句柄 + +### 5.1 `PointConstraint` + +- `config()`:返回 `WebJoinConstraintConfig`,反映当前配置。 +- `updateMovePoint(point)`:移动固定锚点。 +- `getPointPair()`:返回元素锚点与固定点(两个 `WebPoint`)。 +- `updateConfig(OptionalWebJoinConstraintConfig)`:部分更新配置。 +- `dispose()`:销毁约束并自动从场景中移除。 + +### 5.2 `JoinConstraint` + +- `config()`:返回现有配置。 +- `getPointPair()`:返回绑定在元素 A/B 上的移动点。 +- `updateConfig(OptionalWebJoinConstraintConfig)`:更新配置参数。 +- `dispose()`:销毁约束并解除锚点。 + +> 两种约束均在内部记录 `is_dispose` 状态,重复调用 `dispose()` 为安全操作(无副作用)。 + +## 6. TypeScript 类型声明 + +`crates/picea-web/src/type.d.ts` 随编译结果一并导出,核心类型如下: + +- `type Vector = { x: number; y: number }` +- `type Point = { x: number; y: number }` +- `type Meta` / `type MetaPartial` +- `type JoinConstraintConfig` / `type JoinConstraintConfigPartial` +- `type Shape = { id: number; centerPoint: Point; shapeType: "circle" | "polygon"; ... }` +- `interface WebScene` 补充 `forEachElement`、`registerElementPositionUpdateCallback` 等回调接口。 + +在 TypeScript 项目中,可直接通过 `/// ` 或打包工具(如 Vite、Webpack)自动拾取这些类型定义,享受静态检查。 + +## 7. 调试与实践建议 + +- **panic 钩子**:生产环境可根据需要选择是否调用 `setPanicConsoleHook`,以避免在发行模式下暴露调试信息。 +- **性能**:`tick` 内部使用固定迭代次数(约束解算 10 次,位置修复 20 次),如需更稳定可在 JS 层控制帧率。 +- **内存管理**:所有返回的约束句柄都持有对 `WebScene` 的引用,务必在不需要后调用 `dispose()` 释放;场景 `clear()` 会自动使旧句柄失效。 +- **几何调试**:结合 `forEachElement` 的多边形/圆数据与 `getPositionFixMap()`,可以构建可视化层调试碰撞与修正。 + +以上接口覆盖了 `picea-web` 当前所有对外可用方法。若需扩展浏览器端渲染或交互功能,可在此基础上结合 Canvas/WebGL 或其它渲染库构建上层框架。