Skip to content

拆迁日

背景:XPBD(TS) 布料引擎已运行数周,但维护成本高、与 WASM Bullet 物理栈重复。性能差 3-5 倍。grid 样式切换后地面第一次渲染变纯色。路径归属判定散落在多个文件里,有路径遍历逃逸风险。 过程:删除 XPBD 求解器 + 碰撞器;_generateGroundTexture() 统一地面路径;isUnderRoot 工厂统一路径判定。


王逸打开 src/physics/ 目录。

十二个文件。XPBD 求解器、碰撞器、约束求解器、粒子系统——一共 3000 多行 TypeScript。

MMD 模型自带 WASM Bullet 物理引擎。布料用 XPBD(TS) 手写引擎。两套碰撞检测、两套步进逻辑、两套 UI 集成。

3000 多行代码,两套引擎。维护成本是双倍的。性能是双倍的差——同样的布料,WASM Bullet 比 XPBD 快三到五倍。

王逸想了一下。XPBD 建于 babylon-mmd 的布料 API 未完全暴露的时代。那是一个合理的过渡方案。但过渡期太长了。


一、拆除

王逸开始删除文件。

第一个:xpbd-solver.ts。1200 行。求解器的核心——位置修正、速度修正、约束投影。

每删除一个文件,跑一遍 npx vite build。TypeScript 编译器会告诉他,有没有地方还引用着这些死去的代码。

红色错误。xpbd-solverscene.ts 引用。删掉那行 import。

红色错误。xpbd-colliderscene-menu.ts 引用。删掉整个 buildPhysicsLevel() 函数。

两个小时后,编译通过了。

src/physics/ 目录只剩下两个文件:physics-bridge.tswind-physics.ts


二、网格的坑

王逸把地面样式从 solid 切到 grid

地面第一次渲染变成纯色。他刷新页面。网格还在。

GridMaterial 是 Babylon.js 的独立 shader。第一次使用时需要编译 WebGL shader。编译期间,地面用 fallback 纯色渲染。编译完成后,网格没有正确刷新——需要重启应用才能看到。

groundStyle: 'solid' 是默认值。大多数人从开始就没用过 grid 样式。所以这个 bug 在很长一段时间里只存在于代码里,没有出现在用户面前。


三、一条路

ADR-091:地面纹理统一。

删除 GridMaterial 依赖。所有 flat 样式统一用 canvas → StandardMaterial.diffuseTexture 单一路径。

_generateGroundTexture 函数:512×512 canvas 绘制——solid 是纯色填充,grid 是底色加网格线,checker 是按 pattern 绘制棋盘格。

不再需要 shader 编译。不再需要等待。


四、路径的墙

王逸搜索 normalizePath——找到四份独立实现。

src/core/fileservice.ts 里有一份。src/core/utils.ts 里有另一份。src/menus/library-core.ts 里有第三份。src/scene/scene-bundle.ts 里有第四份。

四份实现,四种边界判定逻辑。其中三份有路径遍历逃逸风险——.. 处理不一致,攻击者可能通过构造文件名读取 ../ 路径上的任意文件。

ADR-095:路径归一化与归属判定统一。

isUnderRoot 工厂——一个函数,所有文件路径归属判定走这里。normalizePath——一个函数,所有路径标准化走这里。

四份散落的代码,合并成一份。


尾声

XPBD 删除。地面纹理统一。路径归属统一。

联邦没有再走一遍老路。


教训:"能用"是技术债务的合法外衣。能用不是 bug,但能用不等于应该留着。承认过时的决策,比继续维护它更诚实。