用自然语言驱动的开源 3D 建筑设计编辑器-Aedifex

34 阅读17分钟

主动规避不合理的位置.png

一句话介绍

Aedifex 是一个运行在浏览器中的 3D 建筑编辑器,集成了基于大语言模型的 AI 设计助手。你可以通过自然语言描述设计意图,AI 直接在三维场景中执行建墙、开窗、摆放家具等操作——不需要学习任何专业建模工具。

项目基于上游开源 3D 编辑器内核深度改造,重新设计了场景数据架构和渲染管线,并在此基础上构建了完整的 AI 辅助设计能力。

开源地址github.com/TangSY/aedi…

体验地址aedifex.app


为什么做 Aedifex

起因

最初是在 GitHub 上看到一个开源的 3D 建筑编辑器项目,基础能力不错——墙体、门窗、家具摆放都有了,Three.js 渲染,浏览器里就能跑。但交互方式还是传统的那一套:左边工具栏选工具,右边属性面板调参数,中间画布上点来点去。能用,但对非专业用户来说门槛不低。

当时正好在研究 AI Agent 的落地场景,想找一个合适的领域做深度整合。看到这个编辑器的时候觉得方向对了:3D 建筑设计天然适合自然语言交互——人描述空间的时候用的就是"客厅放一组沙发,对面摆电视柜"这样的语言,而编辑器的每一个操作(建墙、开窗、放家具)都可以被抽象成结构化的工具调用。把 AI Agent 接入编辑器的操作接口,用户就不需要学习任何工具,直接用自然语言描述就行。

这个想法促使我在原项目的基础上开始了改造。

改造过程

真正动手之后才发现,"接入 AI"远不是加个对话框那么简单。原项目的数据结构、渲染方案、交互逻辑都是为手动编辑设计的,要让 AI 成为核心交互方式,几乎每一层都需要重新设计。

场景数据重构

原项目的节点结构不太适合 AI 操作——AI 需要快速定位和操作任意节点。重新设计成了扁平字典 + parentId 引用的架构:所有节点(墙体、门窗、家具、楼板、屋顶等)平铺存储在一个 Record<NodeId, Node> 字典中,通过 parentId 表达层级关系,任何节点都可以通过 ID 直接索引。同时引入了 schema 版本管理和数据迁移框架,为后续的结构演进留出空间。

这个数据结构也决定了编辑器的建模能力边界:墙体建造支持自动倒角和 0.5m 网格吸附,门窗通过 CSG 布尔运算在墙面上精确切割开洞,天花板、楼板、屋顶都支持自定义多边形轮廓。多层建筑通过 Level 节点组织,支持逐层查看或爆炸视图。

渲染与材质

渲染层面,上游项目已经具备了不错的基础:Three.js WebGPU 渲染、SSGI 全局光照、后处理管线、亮暗主题切换等。Aedifex 在此基础上做了一些可靠性优化(WebGPU 设备丢失监测、后处理错误自动恢复等),但整体渲染架构沿用了上游的设计。材质系统提供 10 种预设(木材、砖石、混凝土、玻璃、金属、大理石等),支持完整的 PBR 参数控制,所有节点类型均可应用。

改造的重点不在渲染——上游项目在这方面做得已经很好了。真正从零构建的是下面这些让 AI 能理解和操作三维空间的能力。

image.png

空间语义层

这是整个 AI 能力的基础,也是改造过程中投入最大的部分。

单纯把场景数据丢给模型,它只能看到一堆坐标数字,并不真正理解空间关系。所以构建了一套场景序列化系统,每次对话时自动分析当前场景,提取出结构化的上下文信息:每个房间的尺寸形状和 AABB 边界、所有家具的位置和类别、墙面朝向及其上的门窗位置、楼层结构等。整个上下文控制在 4000 token 以内,通过内容哈希做缓存,避免重复计算。

空间检测基于网格洪泛填充算法:以 0.5m 为分辨率扫描整个楼层,标记每个网格单元为空地、墙体、室外或室内,自动识别封闭区域生成房间(Zone),并通过 Shoelace 公式计算面积。墙面也会被标记内外朝向。

有了这层空间语义,AI 才能真正理解用户的自然语言描述。当你说"把沙发前面的茶几往右挪一点",AI 准确知道"沙发前面"是哪里、"茶几"是哪个节点、"右"在当前空间中是什么方向。这是基于真实场景数据的空间推理,不是关键词匹配。

28 种 AI 工具

AI 在 Aedifex 中不是一个聊天窗口,而是一个拥有完整操作能力的 Agent。目前定义了 28 种结构化工具调用,覆盖建筑设计的全流程:

类别工具说明
结构建造add_walladd_slabadd_ceilingadd_roof画墙、铺地、加顶、建屋顶(支持 7 种类型:坡顶、人字顶、单坡、荷兰式等)
门窗开设add_dooradd_window在指定墙面精确开洞,支持配置规格参数
家具布置add_itemmove_itemremove_item从 100+ 件家具目录中选取、摆放、调整
属性修改update_wallupdate_materialupdate_item修改尺寸、材质、PBR 参数等
批量操作batch_operations多个操作原子执行,保证一致性
主动交互ask_userpropose_placement遇到歧义主动确认,提供 2-3 种方案供选择

每一个操作的结果都是真实的三维对象——可以继续手动编辑,可以导出为 GLB/STL/OBJ,可以用第一人称走进去查看。

家具目录与智能匹配

内置了 100+ 件家具模型,覆盖客厅、卧室、厨房、卫浴、户外等场景。每件家具都有完整的元数据:尺寸、类别、标签、GLB 模型路径、缩略图、缩放偏移参数,以及是否靠墙放置(attachTo: 'wall')。

AI 选择家具时会经过多级匹配:先精确匹配 ID,再匹配名称,最后做模糊子串搜索。还支持形状描述匹配——用户说"圆形茶几"、"L 型沙发"、"双人床",系统能自动筛选对应形状的款式。匹配不上时会按类别推荐相似选项,而不是静默失败。

多层碰撞验证与布局优化

AI 放家具不能随心所欲——不能摆出房间外面,不能和已有家具重叠,靠墙的家具要自动贴合。这不是简单的碰撞检测,而是一套四层验证体系:

  • 家具碰撞检测:基于网格空间分区(0.5m 单元格,类似模拟人生的网格),每个家具占据的网格单元会被记录,新放置的物品通过 AABB 检测判断是否重叠,支持旋转物品的足迹计算
  • 房间边界钳位:家具不会被放到房间多边形之外,超出边界的坐标会被自动修正到最近的合法位置
  • 墙体交叉检测:新建墙体时检测是否与已有墙体交叉(允许 T 形连接,但拒绝 X 形交叉)
  • 批量操作内碰撞:同一次 batch_operations 中的多个物品之间也会做碰撞检测,冲突时自动偏移

验证通过后,还有一层布局优化引擎做后处理:靠墙家具自动吸附到最近墙面(0.3m 阈值内);家具朝向自动修正(面向房间中心);功能组间距规则强制执行(沙发到茶几 0.4m、沙发到电视柜 2.5m);所有家具组之间保持最小 0.6m 通道宽度。这层优化让 AI 放出来的家具不只是"不重叠",而是"布局合理"。

幽灵预览机制

这是让用户放心使用 AI 的关键设计。AI 生成的操作不会立即写入场景,而是先创建带临时标记的节点,以半透明的"幽灵"形态在 3D 视口中展示预览效果。预览期间撤销历史会被暂停,不污染操作记录。用户确认后临时节点转为正式节点,拒绝则完整恢复原始状态。系统还会保存被删除节点的快照,确保任何情况下都能回退。

这意味着你可以放心用自然语言反复试探,不用担心搞乱已有设计。

Agentic Loop:迭代式 AI 对话

Aedifex 的 AI 不是简单的一问一答。每次用户发出指令后,AI 进入一个最多 8 轮的迭代循环:执行操作 → 观察结果 → 判断是否需要继续。

比如用户说"帮我布置一个完整的客厅",AI 不会只放一件家具就停下。它会在一轮循环中依次放置沙发、茶几、电视柜、落地灯,每放一件都会检查空间冲突和布局合理性,遇到不确定的地方(比如剩余空间放不下用户想要的大件家具)会主动通过 ask_user 工具询问,而不是猜测。整个过程对用户来说就是一次对话,但背后可能经历了多轮工具调用和决策。

上下文管理与对话压缩

支持连续多轮对话,从空房间一步步聊到整套布置完成。但对话越长,发送给模型的 token 越多,成本和延迟都会上升。

系统内置了token 预估器,支持 CJK 字符的准确估算(±20% 精度),实时监控对话长度。当消耗超过模型上下文窗口的 85% 时,自动调用摘要模型压缩历史对话——保留关键的设计决策和当前场景状态,丢弃中间的试探和调整细节。压缩对用户透明,不会中断对话流程。

基于大语言模型的天然多语言能力,AI 支持任何自然语言交互——中文、英文、日语、法语、西班牙语,你用什么语言说,它就用什么语言回应。

实际使用效果

用一个例子说明完整的交互流程——从零设计一个客厅:

"建一个 5m × 4m 的客厅"
  AI 画出四面墙,自动检测封闭区域生成房间

→ "南面墙开一扇 2.4 米的落地窗"
  AI 在南墙精确位置切出窗洞

→ "L 型沙发靠西墙,对面放电视柜"
  AI 从目录匹配家具,自动贴墙放置

→ "茶几放沙发前面,旁边来一盏落地灯"
  AI 计算空间关系,居中放置茶几,落地灯放在不遮挡动线的位置

四句话,一个完整的客厅布局就出来了。

AI 遇到歧义不会自作主张,而是停下来确认:

"把客厅的桌子删了"
  AI:客厅里有餐桌和茶几,你要删哪一张?

→ "在这面墙上开个门"
  AI:这面墙上已经有窗户了,开门需要移走窗户,确认继续吗?

编辑器交互能力

AI 是核心交互方式,但手动编辑能力同样完整。

撤销重做与操作历史

撤销重做支持最近 50 步操作历史,基于 Zundo 的智能差异检测——每次撤销时通过对象引用比较找出实际变更的节点,只重新渲染这些节点及其父节点(触发合并几何体更新),而不是整个场景。场景变更检测也做了优化:用单调递增的 nodesVersion 计数器替代 JSON.stringify 全量比较,从 O(N) 降到 O(1),用于自动保存的变更判断。

AI 操作还有独立的操作历史面板:每次 AI 确认的操作会记录在可折叠的列表中,支持单次操作撤销——不需要回退到某个时间点,可以直接撤销中间的某一步操作并恢复对应的节点快照。

2D 平面图面板

7500 行代码的完整 2D 编辑界面,与 3D 视图实时同步。在 2D 视图中绘制的墙体会即时出现在三维场景中,选中的物体在两个视图中同步高亮。

支持墙体绘制与实时标注尺寸、0.5m 网格吸附、门窗在墙面上的参数化定位、房间多边形和楼板的可视化编辑、参考图片导入(支持缩放 0.01x-100x)、公制/英制单位切换。编辑器提供 3D、2D、分屏三种视图模式。

第一人称漫游

通过 Pointer Lock API 实现沉浸式体验:WASD 控制前后左右移动,鼠标控制视角,Q/E 键升降,Shift 键冲刺(移动速度翻倍至 10m/s)。视点高度固定在 1.65m(模拟真人站立视角),俯仰角钳位在 ±85° 防止画面翻转。

3D 框选与批量操作

在 3D 视口中拉框选择多个物体,支持批量移动、删除、修改材质。框选逻辑独立实现(561 行),处理了透视投影下的物体拾取精度问题。

音效反馈

内置事件驱动的音效系统:网格吸附、家具拾取/放置/删除/旋转、结构建造/拆除都有对应的音效反馈,通过独立的 SFX Bus 管理,用户可在设置中开关。

自动保存

带状态机的自动保存系统:1 秒 debounce 防抖、预览模式暂停保存、待保存队列合并、BeforeUnload 事件触发紧急刷新防止数据丢失。保存状态在 idle → pending → saving → saved → error 之间流转,UI 实时反映当前状态。

其他交互细节

罗盘 HUD 固定在右上角,每 3 帧更新一次朝向,红色三角始终指向北方,旋转角度变化小于 0.5° 时跳过渲染。设计完成后可以导出为 GLB(Unity / Unreal / Blender)、STL(3D 打印)、OBJ(通用交换格式),导出时自动剥离编辑器图层(网格线、选区高亮等),只保留纯净的三维模型数据。

AI 安全设计

在 AI 交互层面也做了一些安全考量。用户输入会经过 prompt 注入防护处理:剥离 Markdown 标题语法、过滤 SYSTEM/INSTRUCTIONS/ASSISTANT 等关键词前缀、清除分隔线标记,防止恶意输入篡改 AI 的行为规则。

AI 的行为规则也经过仔细设计:语言锁定(用户用什么语言提问,AI 就用什么语言回答,不会中英混杂);批量删除前必须通过 ask_user 工具向用户确认;严格遵守数量指令(用户说"放一把椅子"就只放一把,不会自作聪明多放几把);两个以上相关操作自动合并为 batch_operations 原子执行,保证场景一致性。

现在的样子

经过这些改造,Aedifex 已经不是原项目加个 AI 对话框了,而是一个以 AI Agent 为核心交互方式重新设计的 3D 建筑编辑工具

大多数时候,你只需要用自然语言描述你想要的空间,AI 就能理解你的意图并直接操作场景。这是我认为 3D 设计工具应该有的交互方式:不需要学习工具,只需要描述你想要什么

image.png


项目架构

Aedifex 采用 Turborepo + pnpm 管理的 monorepo 结构,代码按职责拆分为多个独立包:

aedifex/
  apps/
    app-editor/         # Next.js 应用,整合所有 packages
  packages/
    core/               # 核心库:Zod schema、Zustand 状态、空间系统
    viewer/             # 3D 渲染器:R3F 组件、后处理、导出
    editor/             # 编辑器:UI 面板、AI 系统、交互工具
    ui/                 # 共享 UI 组件库(Headless + Tailwind)

每个包职责明确、边界清晰:core 不依赖任何 React 渲染逻辑,可以独立用于数据处理和验证;viewer 只负责三维渲染,不包含编辑器 UI;editor 组合前两者提供完整的编辑体验。这种分层让未来的扩展变得容易——比如要做一个只读的模型预览页面,只需引入 core + viewer 即可,不会带入编辑器的代码。

类型安全:从编译期到运行时

整个项目使用 TypeScript 严格模式,但编译期类型检查只能覆盖代码内部的逻辑。对于外部数据(用户输入、AI 返回的操作参数、文件导入的场景数据),光靠 TypeScript 是不够的——类型信息在运行时不存在。

所以所有核心数据结构都用 Zod 定义 schema,实现了编译期 + 运行时的双重类型安全。每种场景节点(墙体、门窗、家具、屋顶等)都有对应的 Zod schema,定义了字段类型、默认值、取值范围。数据写入场景时必须经过 parse() 验证,不合规的数据会在入口处被拦截,而不是在渲染时才报错。

节点类型通过 Zod 的 discriminatedUnion 实现安全的运行时判别——拿到一个节点对象,可以根据 type 字段准确判断它是墙体还是家具,TypeScript 也能自动推导出对应的字段类型,不需要手动类型断言。

节点 ID 生成也做了规范:每种类型有固定前缀(如屋顶节点的 ID 以 rseg_ 开头),通过自定义生成器自动创建,便于调试时快速识别节点类型。


技术栈

层级选型理由
渲染Three.js WebGPU + React Three Fiber浏览器端最强 3D 方案,WebGPU 性能显著优于 WebGL,R3F 让 Three.js 融入 React 生态
框架Next.js 15 + React 19App Router + SSR,首屏加载快,SEO 友好
状态Zustand + Zundo轻量级状态管理,Zundo 提供时间旅行能力(撤销重做),支持按字段分区追踪
几何three-bvh-csgCSG 布尔运算实现墙面开洞,BVH 空间索引加速碰撞查询
AIOpenAI 兼容 API不绑定厂商,支持 OpenAI、Azure、Ollama 等任何兼容端点
类型TypeScript 5.9 + Zod编译期类型检查 + 运行时 schema 验证,双重保障
UITailwind CSS 4 + Lucide Icons原子化样式,图标体系统一,组件库 headless 设计便于主题定制
工具链Turborepo + pnpm增量构建,包间依赖自动拓扑排序,CI 缓存命中率高

快速开始

git clone https://github.com/TangSY/aedifex.git
cd aedifex
pnpm install
pnpm dev

访问 localhost:3000 即可使用。编辑器的所有基础功能(建墙、门窗、家具、材质、导出、第一人称漫游)开箱即用,不需要任何配置。

AI 功能需要额外配置环境变量:

# .env.local
AI_API_KEY=your-api-key
AI_BASE_URL=https://api.openai.com/v1  # 可选,默认 OpenAI
AI_MODEL=gpt-5.4                         # 可选,默认模型

兼容任何 OpenAI 格式的 API 端点——官方 OpenAI、Azure OpenAI、本地 Ollama、DeepSeek 等均可。只要接口遵循 OpenAI 的 Chat Completions 格式并支持 Function Calling,就能直接接入。


参与贡献

Aedifex 采用 MIT 协议开源,欢迎任何形式的参与:

  • Star — 最直接的支持,也帮助更多人发现这个项目
  • Issue — 报告 Bug、提出功能建议、讨论设计方案
  • Pull Request — 代码贡献,无论大小
  • 分享 — 在社交媒体、技术社区、身边的设计师朋友中推荐

如果你对以下方向感兴趣,特别欢迎参与:

  • 家具模型扩充 — 目前内置 100+ 件,覆盖主要场景但还有很大的扩展空间
  • AI 工具增强 — 更多的操作类型、更智能的空间推理
  • 渲染效果优化 — 纹理贴图、环境光遮蔽、更丰富的材质表现
  • 国际化 — UI 界面的多语言支持(AI 对话已天然支持多语言)

GitHubgithub.com/TangSY/aedi…

在线体验aedifex.app