关于 Flit Physics
Flit Physics 是面向 three.js 游戏和演示项目的轻量球体物理引擎。它以扁平的 Float32Array 保存模拟状态,提供碰撞、地形、射线检测及 three.js 集成方式。
主要功能
- 01带重力和碰撞的球体模拟
- 02休眠刚体与接触求解器
- 03高度场地形碰撞
- 04空间哈希宽相位与射线检测
- 05适用于 InstancedMesh 的位置输出
适用场景
- 01为 three.js 游戏加入球体物理
- 02模拟高度场地形上的粒子
- 03将模拟位置同步到 InstancedMesh
MCP 相关
可选的 MCP 服务提供配置和重置物理世界、生成或添加粒子、推进模拟、查看状态及射线检测等工具。位置结果适用于同步到 InstancedMesh。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Flit
Flit 是一个用于 3js 的小型物理引擎。目前功能还不多!但我相信它会越来越好!
球体、碰撞、射线投射、重力和空间哈希宽相检测——有意保持精简,不做更多。
所有模拟状态都保存在扁平的 Float32Array 中(结构分离数组),因此
CPU 路径也可作为未来 WebGPU
计算后端的参考实现:使用相同的缓冲区和内核,无需重新架构。
包含内容
World— 点球粒子、半隐式欧拉积分、 冲量与位置修正接触求解器、无限地面。 保持静止的刚体会进入休眠状态(由每个刚体的静摩擦阈值驱动), 因此静止堆叠几乎不消耗资源;足够快的撞击会唤醒它们,缓慢推动则会被静摩擦抵挡。Heightfield— 以高度柱网格表示的 2.5D 地形,无需网格化: 直接采样双线性高度和中心差分法线进行碰撞检测, 并使用 2D Amanatides-Woo DDA 进行射线投射(index: -1)。- Raycast — 在宽相检测网格上进行 Amanatides-Woo 体素遍历; 从遍历路径周围的 3x3x3 区块中获取候选对象,因此不会漏掉角落擦碰。 已与暴力穷举基准实现进行差分测试。
SpatialHash— 使用 Morton(Z 序)单元格编码作为键的均匀网格宽相检测。 这是 LSH 家族中的欧几里得近亲:MinHash 按 Jaccard 相似度将文档分桶;此处则按位置分桶, 使相近的点落入同一个桶中。Morton 键是一一对应的(不会产生哈希碰撞导致的成对数量膨胀)、可逆的(无需辅助表), 并按局部性排序,适用于未来基于排序数组的 GPU 后端。- 距离与位运算工具 — 平方欧几里得/L1/Minkowski/L∞/Hellinger/
卡方/KL 距离(移植自 FLANN)、Morton(Z 序)键、
用于基数排序的浮点数位翻转、八边形近似距离。
来源和许可证请参阅
THIRD_PARTY_NOTICES.md。
供 Agent 使用
正在开发一个小型 three.js 游戏或演示?有两种方式可以开始:
- 技能:
skills/flit/SKILL.md— 将skills/flit/目录复制到 Agent 的技能路径中(例如.claude/skills/、~/.code_puppy/skills/)。 其中包含 30 秒集成指南、MCP 选项、实测性能范围和贡献者规则。 - MCP 服务(无需编写代码):运行
npm run mcp,或让客户端连接到它:
{
"mcpServers": {
"flit": {
"command": "npx",
"args": ["vite-node", "mcp/server.ts"],
"cwd": "<path-to-this-repo>"
}
}
}
工具:flit_info、flit_reset(gravity/restitution/ground/bounds/
settleSpeed/heightfield)、flit_spawn(rain/explosion/grid/fountain
预设)、flit_add_particles、flit_step、flit_state、flit_raycast
——step/state 会返回扁平的 xyz 位置,格式适合与 InstancedMesh 同步,
还会返回 settledCount,方便你观察一堆粒子逐渐静止。
用法
npm i flit-physics
import { World } from 'flit-physics';
const world = new World({ restitution: 0.4 }); // gravity and a floor at y=0 included
const ball = world.addParticle({ position: [0, 10, 0], radius: 0.5, mass: 1 });
// fixed timestep, e.g. from your rAF loop
world.step(1 / 60);
// sync to three.js: positions is a live Float32Array, 3 floats per particle
mesh.position.set(
world.positions[ball * 3],
world.positions[ball * 3 + 1],
world.positions[ball * 3 + 2],
);
地形和休眠各有一个选项:
import { Heightfield, World } from 'flit-physics';
const terrain = new Heightfield({ rows: 64, cols: 64, cellSize: 1, heights });
const world = new World({ groundY: null, heightfield: terrain });
// bodies collide with the terrain and settle on it;
// world.raycast(...) reports terrain hits as index -1
// sleep is on by default (settleSpeed 0.01 m/s); opt out per world:
const wideAwake = new World({ settleSpeed: 0 });
开发
npm install
npm test # vitest
npm run build # tsc -> dist/
npm run bench # broadphase + full-step micro-benchmarks
npm run demo # three.js demo scene (vite dev server)
基准测试
使用确定性种子;数据来自本地开发机器,于提交时记录 (完整系列,包括被否决的设计,见提交说明)。
bench/broadphase.bench.ts— 仅测试 broadphase,N=4096: xor-hash 为 3.4–3.7 ms(444 对,约 90% 碰撞膨胀)→ Morton 键 配合有序探测:3.5–3.7 ms(234 对,精确)。bench/world.bench.ts— 完整的World.step,N=1024: xor-hash 为 0.85 ms/步 → Morton 有序探测为 0.83 ms/步 → 使用顺序冲量速度求解器(4 次迭代 + LUT 摩擦)时为 0.93 ms/步。键精确,接触真实,增加 11%。bench/scaling.bench.ts— 两种情况。固定箱体(密度上升): 受拥挤物理影响,配对数约按 N² 增长。缩放箱体(保持恒定的 生成 密度):物体分散时,复杂度为平坦的 O(N),N=8000 时每 1000 个物体 约 1.2 ms。开启重力后,所有物体会在约 2–4 秒内落入密集的地面堆中 (设置WARMUP=240可复现)——自 0.3.0 起,堆积物会稳定下来: N=8000 时,每步耗时从 34.2 降至 9.2 ms(快 3.7 倍,满足 60fps 预算),因为物体会自下而上进入休眠。休眠物体不会参与积分、平面碰撞 和相互接触计算,直到受到速度超过 1 m/s 的冲击才会唤醒。 (docs/issues/001— 已解决;保留简要说明,供分析及记录剩余想法: 热启动、自适应迭代。)bench/raycast.bench.ts— N=4096 时发射 2000 条带种子的射线: 每条射线 63–68 µs(相同密度下,暴力 O(N) 基准约为 160 µs; 随着 N 增大,网格遍历的优势会进一步扩大)。bench/morton-libs.bench.ts— 与 npm 库进行编码器对比 (npm run bench:libs):本实现为 3.8 ns/次编码,fast-morton MB 为 26.1,fast-morton LUT 为 43.8,@thi.ng/morton 为 539.9。本实现胜出; 保留这些库作为开发依赖,纯粹是为了让对比测试仍可运行。bench/threaded.bench.ts— WorkerWorld 运行于真实 Worker 线程 (SAB ping-pong):主线程上的kick()耗时 0.014 ms;在 4 ms 渲染负载下,N=8192 时,流水线处理每帧耗时 8.84 ms,串行处理为 14.96 ms(113 fps 对比 67)。N=1024 时,0.8 ms 的步进耗时完全被 渲染掩盖(4.03 对比 4.80 ms)。- 根据测量结果否决(见提交记录):63 位 BigInt 键(分配开销增加 13 倍); 排序数组 + 二分查找 broadphase(在 JS 中比 Map 探测慢 1.4 倍——已记录 这一负面结果)。
路线图
Morton 有序 broadphase 单元格— 已完成、已测量并发布three.js 演示场景—npm run demo,箱体中有 220 个球 (使用?terrain查看高度场丘陵,使用?n=8000进行负载测试)Worker 线程步进—WorkerWorld:kick/waitForUpdate,使用 SAB ping-pong 实现零拷贝渲染堆积稳定后的求解器开销— 已发布逐物体休眠机制(N=8000 时,耗时从 34.2 降至 9.2 ms);问题简述 保留了剩余想法(热启动、自适应迭代)高度场地形— 已发布,无需网格生成;已预留更多碰撞体形状的接口- 若出现射线密集型工作负载,可添加射线投射粗略占用过滤器(更快跳过空白区域)——
分析见提交
3173a6f - CPU 参考实现稳定后,添加 WebGPU 计算后端
许可证
MIT — 参见 LICENSE。第三方内容及其许可证列于
THIRD_PARTY_NOTICES.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。