一个基于 Vue 3 + Three.js 的现代化3D场景编辑器,支持三维模型的拖放、调整和属性配置。 本工程完全使用AI自行编写代码。
- 3D场景渲染和管理
- 多种基础与扩展几何体创建
- 完整的对象变换系统(移动、旋转、缩放)、撤销重做历史记录
- 对象变换支持Y轴锁定
- 多格式3D模型和纹理加载与管理(GLTF、OBJ、FBX等)
- 支持加载3DTiles,基于3d-tiles-renderer
- 拖拽上传、资源管理与资源浏览(支持模型预览和几何体创建)
- 相机控制与预设视角(OrbitControls、MapControls、FlyControls切换,FlyControls支持基于键盘、鼠标的三维飞行控制)
- 材质编辑和属性调整(多种材质类型与参数动态配置)
- 场景序列化、导入导出与完整层级管理
- 单对象选择和编辑
- 支持GLTF等模型的动画选择与播放,动画状态可导出与恢复
- 底部状态栏显示当前视点(相机旋转)
- 虚拟文件系统,对接后端文件库
- 文件面板拖拽模型文件到场景直接加载
- 支持从虚拟文件系统面板拖拽模型文件到场景直接加载
- 拖拽添加对象时,自动放置到当前视点位置
- 后处理机制(集成Three.js EffectComposer,支持Bloom、FXAA等多种后处理效果链路,统一API动态管理Pass)
- 前端框架: Vue 3 + Vite
- 3D引擎: Three.js
- 构建工具: Vite
- 样式: Sass
- 网络请求: Fetch API
- 工具库:
- Element Plus - 主流UI组件库
- Lodash - 实用工具函数库
- Day.js - 轻量级日期时间库
- mitt - 事件机制
- three-viewport-gizmo - 立方体视角控件库
- 3d-tiles-renderer - 3dtiles加载库
- stats-gl - 性能监控
/
├── src/
│ ├── components/ # Vue 组件
│ │ ├── editor/ # 编辑器 UI 组件
│ │ │ ├── PropertyPanel.vue # 属性面板
│ │ │ ├── MultiSelectPanel.vue # 多对象批量操作面板
│ │ │ ├── Toolbar.vue # 工具栏
│ │ │ ├── EditorFooter.vue # 编辑器底部状态栏
│ │ │ ├── AssetBrowser.vue # 资源浏览器
│ │ │ ├── PrimitiveBrowser.vue # 基础几何体与灯光浏览组件
│ │ │ ├── ResourcePanel.vue # 资源面板
│ │ │ ├── VfsFileBrowser.vue # 虚拟文件系统面板
│ │ │ ├── Inspector.vue # 对象检查器
│ │ ├── property/ # 各种属性编辑组件
│ │ │ ├── ScenePropertyPane.vue # 场景属性编辑面板
│ │ │ ├── BasePropertyPane.vue # 对象基础属性编辑面板
│ │ │ ├── UserDataPropertyPane.vue # userData属性编辑面板
│ │ │ ├── TransformPropertyPane.vue # 变换属性面板(位置、旋转、缩放)
│ │ │ ├── AnimationPropertyPane.vue # 动画属性面板(动画选择与播放)
│ │ │ ├── MaterialPropertyPane.vue # 材质编辑面板
│ │ │ ├── PrimitivePropertyPane-*.vue # 各种Primitive的专属属性编辑面板
│ │ │ ├── LightPropertyPane-*.vue # 各种灯光的专属属性面板
│ │ ├── dialog/ # 各类对话框组件
│ │ │ ├── TextureSelectDialog.vue # 纹理选择对话框
│ │ │ ├── EditorConfigDialog.vue # 编辑器配置对话框
│ │ │ ├── VfsFileChooserDialog.vue # 虚拟文件系统文件选择对话框
│ │ │ ├── VfsFileSaverDialog.vue # 虚拟文件系统文件保存对话框
│ │ ├── scene/ # 3D 场景组件
│ │ │ ├── SceneViewer.vue # 主场景视图,支持拖拽添加对象到当前视点位置
│ │ │ ├── StatHints.vue # 性能监控面板
│ │ │ ├── InteractionHints.vue # 操作提示组件,支持切换控制器
│ │ │ ├── ViewportControls.vue # 视图控制面板组件
│ │ │ ├── CubeViewportControls.vue # 立方体视角控件
│ ├── composables/ # Vue Composition API 可组合函数
│ │ ├── useScene.js # 场景管理
│ │ ├── useObjectSelection.js # 对象选择、TransformControls与选中对象辅助功能
│ │ ├── useTransform.js # 变换操作
│ │ ├── useAssets.js # 资源管理,包含模型/纹理等资源的加载、缓存与去重机制
│ │ ├── useEditorConfig.js # 编辑器配置响应式状态与操作方法
│ ├── core/ # 核心 Three.js 逻辑
│ │ ├── SceneManager.js # 场景管理器
│ │ ├── ObjectManager.js # 对象管理器
│ │ ├── InputManager.js # 输入处理
│ │ ├── AssetLoader.js # 资源加载器
│ ├── services/ # 数据请求和外部接口
│ │ ├── static-drive-api.js# 静态文件系统封装
│ │ ├── vfs-server-api.js # 虚拟文件系统封装
│ │ ├── vfs-service.js # 虚拟文件系统服务
│ ├── controls/ # 控制器
│ │ ├── FlyControls.js # 飞行控制器,支持基于键盘、鼠标的三维飞行
│ ├── utils/ # 工具函数
│ │ ├── mathUtils.js # 数学工具
│ │ ├── geometryUtils.js # 几何工具
│ │ ├── fileUtils.js # 文件处理工具
│ ├── constants/ # 常量定义
│ │ ├── PRIMITIVES.json # 预定义几何体与灯光类型数据
│ ├── App.vue # 根组件(仅负责引入Editor.vue)
│ ├── Editor.vue # 主编辑器组件(包含全部业务与UI)
│ ├── main.js # 应用入口
│ ├── main-func.js # 应用入口文件相关的功能函数
│ ├── style.scss # 全局样式
├── public/ # 存放无需构建的静态资源
│ ├── images/ # 图片资源目录
│ ├── vfs/ # 静态资源目录(虚拟文件系统,.folder.json文件用于描述目录和文件信息)
├── script/ # 脚本
│ ├── package.json # 脚本子项目配置
│ ├── generate-vfs.js # 脚本:生成虚拟文件系统的元数据,用于编辑器的文件浏览器
│ ├── vfs-server.js # 脚本:虚拟文件系统后端服务,支持多 drive 配置(读取vfs-server.json)
├── index.html # HTML 模板
├── package.json # 项目配置
├── vite.config.js # Vite 配置
├── README.md # 项目说明
- 主编辑器组件 (
Editor.vue): 负责所有业务逻辑和UI的集成 - UI 层 (
components/editor/,components/dialog/): 负责用户界面和交互 - 3D 渲染层 (
components/scene/): 处理 3D 场景渲染和显示 - 逻辑层 (
composables/,core/): 业务逻辑和状态管理 - 服务层 (
services/): 数据请求和外部接口 - 工具层 (
utils/): 通用工具函数
- 响应式状态: 使用 Vue 3 Composition API 管理应用状态
- 模块化设计: 清晰的代码组织和职责分离
- 类型安全: 良好的代码结构支持 TypeScript 迁移
- 性能优化: 合理的组件懒加载和渲染优化
- 遵循 Vue 3 组合式 API 最佳实践
- 使用 ES6+ 语法特性
- 组件命名采用 PascalCase
- 文件和目录命名采用 camelCase
- Git 提交信息格式:
feat: 功能描述
- vite.config.js中,配置vite-plugin-static-copy,把几个js库的复制到目标路径:
- 如需加载Draco压缩的glTF模型,请将node_modules/three/examples/jsm/libs/draco/目录中的文件复制到 /draco/ 目录下。
- 如需加载KTX2纹理,请将node_modules/three/examples/jsm/libs/basis目录中的文件放入 /basis/ 目录下。
- 如需加载Meshopt压缩的glTF模型,请将node_modules/three/examples/jsm/libs/meshopt_decoder.module.js文件放入 public/meshopt/ 目录下。
- SceneManager.js中:
- loadScene()方法加载场景时,灯光和对象会完整恢复userData到Three.js对象,包括自定义属性、动画索引等,确保序列化与反序列化一致。
- findObjectsByUserData(key, value) 方法:支持多层key(如xxx.yyy),递归读取对象userData的嵌套属性值,并与value对比,返回所有匹配对象数组。
- 运行时创建的动画相关对象(如_mixer、_activeAction等)不再挂载到userData,而是直接挂在主对象上(如obj._mixer、obj._activeAction),所有运行时临时对象均采用此设计,避免序列化污染,提升运行时管理效率。
- ObjectManager.js中:
- 导出对象数据时,仅保留可序列化字段(如animationIndex),所有运行时对象(如_mixer、_activeAction等)均直接挂主对象,不再出现在userData中。
- ObjectManager.js中:
- createPrimitive(type, options) 只负责创建对象,不自动添加到管理器(不调用addObject),需在外部调用addObject方法完成对象注册;
- 新增 getUnlockedObjects() 方法,支持获取所有未被锁定(userData.locked !== true)的对象;
- getIntersectedObjects() 和 getIntersectedFirstObject() 仅返回未锁定对象;
- 变换后分发object-transform-updated事件。
- useScene.js中:
- 新增axesLockState变量,支持Y轴锁定与解锁,供Toolbar、SceneManager、TransformControls等模块联动。
- 聚焦对象时计算中心点并设置OrbitControls target。
- useObjectSelection.js中:
- 支持多选,selectedObjects 中每个对象对应一个辅助对象 helper,统一由 currentHelpers 管理。
- 使用ObjectManager.getIntersectedFirstObject(raycaster)高效获取第一个相交对象。
- 内部定义了
selectionStore(响应式对象):- 用于存储选中对象的临时材质信息,key 为对象 id。
- selectionStore 生命周期与 useObjectSelection 组合式函数一致,自动随页面刷新或状态重置而清空。
- TransformControls与选中对象辅助功能已迁移至useObjectSelection.js统一管理,SceneManager.js仅负责场景本身,SceneViewer.vue仅负责初始化调用。
- TransformControls拖拽时会自动禁用OrbitControls,避免拖拽时镜头跟随问题,并在拖拽开始/结束时自动调用 useTransform 的 startTransform/endTransform,支持撤销/重做历史记录。
- FlyControls.js中,已支持基于键盘的三维飞行控制(WASD/QE/方向键等),核心逻辑参考 three/examples/jsm/controls/OrbitControls.js、three/examples/jsm/controls/FlyControls.js 实现,支持速度、旋转、拖拽等多种操作。空格键与R键逻辑一致,均可向上飞行。
- useAssets.js 中:
- 资源加载函数(如 loadModel、loadTexture)已实现缓存机制:若 assetLibrary 中已存在同名且大小一致的资源,则直接返回缓存,避免重复加载和内存浪费。
- 所有资源(基础几何体、模型、资源)添加方式已统一为拖拽,点击添加功能已移除。
- 对象动画:GLTF等模型加载后自动挂载animations,属性面板支持动画下拉选择并记录到userData.animationIndex,SceneManager.js统一驱动所有对象动画,ObjectManager.js导出/导入时自动保存与恢复动画索引,支持动画状态完整序列化。
- 本项目核心管理器(SceneManager、ObjectManager、InputManager、AssetLoader)均集成了 mitt 事件机制,实现模块间的解耦通信。
- 本工程基本使用AI自行编写代码(人工编写代码目前少于5%);
- 开发环境:VSCode + Cline + GitHub Copilot + Claude 4 / GPT-4.1
- 使用Claude 4搭建本工程的主体框架,但由于GitHub Copilot Pro版2天内就消耗完(300 Premium requests),后转向使用GPT-4.1实现各项功能。
- .clinerules目录:存储AI规则
- .clinetask目录:存储历史对话
