Skip to content

架构总览

@tripo3d/engine 是构建于 Three.js 之上、以 ECS + 系统 + 插件 为核心的 3D 运行时。它把 Three.js 的命令式 API 切分成若干可插拔子系统,通过一个 Engine 聚合对象暴露给宿主代码(Vue 组件、业务逻辑)。

一图概览

  • createEngine(options)工厂函数,返回聚合后的 Engine 实例
    • viewThree.js 场景、相机、渲染器容器
    • worldECS 世界(Entity / Component / Script)
    • pipeline多阶段渲染管线(stage + pass)
    • pointer基于 raycaster 的指针系统
    • events类型化事件总线
    • historyCommand 式 undo/redo
    • lifecycle生命周期总线(onUpdate / onBeforeRender ...)
    • addSystem / use注册 System、安装 Plugin

五个抽象层次

1. View(视图层)

EngineView 对 Three.js 的 SceneWebGLRendererCamera 做最小封装。createEngine 会:

  • 根据 options.camera 解析相机工厂(perspective / orthographic / 自定义函数均可)
  • 根据 options.renderer 构造 WebGLRenderer
  • 根据 options.scene 或默认工厂创建 Scene

视图层本身是 被动的 —— 它只负责持有 Three.js 对象,不驱动渲染。真正的渲染由 pipeline 驱动。

2. ECS(实体层)

EngineWorld 把 Three.js 的 Object3D 包装成实体(Entity),并在此之上提供组件(Component)与脚本(Script)的附着能力。

  • Component = 纯数据/工厂,描述「这个实体拥有什么」
  • Script = 带生命周期钩子(onUpdate / onBeforeRender / onPointer ...)的逻辑块,描述「这个实体每帧做什么」
  • Query = 按 Component 组合查询实体,命中最小候选集后过滤

详见 ECS

3. System(系统层)

System 是 engine 范围的单例状态机,与特定实体无关。典型职责:

  • 封装某种 Three.js 插件(OrbitControlsTransformControlsViewportGizmo)
  • 提供跨实体的统一能力(模型加载、材质切换、性能监控)
  • 持有可被其他 System 读/改的共享状态

每个 System 通过 createSystem(name, setup) 定义,在 setup 里订阅生命周期钩子、暴露公共方法。详见 插件系统createEngine

4. Pipeline(渲染管线)

EnginePipeline 把每一帧的渲染切成若干 stage,每个 stage 内部再注册若干 pass。默认只有一个 'main' stage(等价于 renderer.render(scene, camera))。需要后处理、辉光、gizmo 图层时,在 'main' 之前/之后插入新 stage 即可。详见 渲染管线

5. Services(横向服务)

  • EventBus:类型化 on/off/emit,不带通配符。业务层自己定义事件名
  • CommandHistory:通用 redo() / undo() 命令对,支持事务批量
  • LifecycleController:生命周期总线,统一分发 onInit / onEnable / onUpdate / onBeforeRender / onAfterRender / onResize / onDispose
  • Pointer:鼠标/触控事件 → raycaster 命中测试 → 事件派发到实体链

帧循环

每帧 engine.renderFrame(time) 的内部顺序:

  • lifecycle.onUpdate(frame)脚本/系统的 onUpdate、onLateUpdate
  • pipeline.render(frame)逐个 stage 调用 pass.render,触发 onBeforeRender / onAfterRender

每个生命周期阶段内部都按 优先级数字(order) 排序后再执行——数字越小越先跑,并列则按注册顺序。

Plugin(插件)

插件是跨 System 的横切关注点。它在 engine 级别只安装一次,但可以:

  • 改写每个新创建 System 的实例(onSystemCreated)
  • 改写每个新创建 Component 的实例(onComponentCreated)
  • 改写每个新创建 Script 的实例(onScriptCreated)
  • 在 engine 销毁时清理(dispose)

最典型的例子是 createPluginVue——把所有 Component/Script/System 实例包一层 shallowReactive,让 Vue 模板能直接响应 ECS 状态变化。

生命周期快览

  • 1. createEngine(options)工厂实例化子系统,执行 options.plugins / options.systems
  • 2. engine.use(plugin)安装插件(触发 plugin.setup)
  • 3. engine.addSystem(def)注册 System,执行 setup,订阅生命周期
  • 4. engine.mount(target)挂载 canvas 到 DOM,启动 requestAnimationFrame
  • 5. 每帧: lifecycle.onUpdate → pipeline.render循环直到 unmount
  • 6. engine.unmount()断开 DOM 与 raf,但保留 state;可再次 mount
  • 7. engine.dispose()彻底释放:清空所有 system/plugin/world/pipeline/history/events

完整流程与代码示例见 createEngine

如何选择抽象

需求选哪个
描述一个实体「是什么」Component
描述一个实体每帧的行为Script
描述一个跨实体的能力(加载器、控件、gizmo)System
描述一个新渲染通道(辉光、描边、后处理)Pipeline Pass
向整个 engine 注入横切行为(响应式、埋点、错误捕获)Plugin
跨模块通信EventBus
可撤销的用户操作CommandHistory

下一步

基于 MIT 协议发布(内部使用)