# Booboo Animation **Repository Path**: duzc2/booboo-animation ## Basic Information - **Project Name**: Booboo Animation - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-20 - **Last Updated**: 2026-09-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MeshAnim 网格动画编辑器:一张图片 → 多个命名动画 → 每个动画独立区域 → 每区域一系列片段 → 片段内关键帧。 ## 目录结构 ``` booboo-animation/ ├── editor/ │ ├── editor.html 编辑器页面 │ ├── editor.css 编辑器样式 │ └── editor.mjs 编辑器逻辑(渲染/播放委托给 runtime3d) ├── runtime/ │ └── runtime3d.mjs ★ 运行时引擎(WebGL2 网格变形:贴图铺在密集三角网格上,顶点位移驱动变形) ├── demo/ │ ├── demo.html 运行时演示页(顶部下拉框或 ?demo= 参数切换内置角色) │ ├── kenney_config.json 示例配置·组1(Kenney 角色) │ ├── kenney_character.png Kenney Toon Characters 角色(CC0) │ ├── LICENSE-Kenney.txt 素材许可 │ ├── manga_girl_config.json 示例配置·组2(坐姿少女) │ ├── manga_girl.png OpenGameArt manga girl 角色(CC0) │ ├── LICENSE-manga-girl.txt 素材许可 │ ├── pixabay_*.png / pixabay_*_config.json 示例配置·组3+(Pixabay 立绘多张) │ ├── LICENSE-Pixabay.txt 素材许可(各 Pixabay 图的来源与许可) │ ├── oga_codel/ Codel 立绘套图(12 表情 + PSD,CC-BY 4.0 LisadiKaprio) │ └── oga_kuudere/ KUUDERE 立绘套图(98 张:2 朝向×7 服装×7 表情 + PSD,CC-BY 4.0 LisadiKaprio) ├── server.mjs 零依赖本地静态服务器 ├── start.bat 双击启动服务器 ├── doc/ 文档(索引见 doc/README.md:设计意图 / 算法 / 用法 / 审查 / 重构计划) ├── test/ 测试与黄金镜像(零依赖,node:test) └── tmp/ 临时文件(.gitignore 忽略) ``` ## 文档 按角色选读,索引见 [doc/README.md](doc/README.md): - **[设计意图](doc/runtime-intent.md)** — 为什么这么做,否决了哪些方案 - **[算法实现](doc/runtime-algorithm.md)** — 每步的输入输出 - **[用法](doc/runtime-usage.md)** — API 与调用顺序 - **[问题审查](doc/review-2026-09-02.md)** — 当前已知问题清单 - **[重构计划](doc/refactor-plan.md)** — 整改顺序与验收标准(活文档) ## 启动 浏览器不允许 `file://` 下加载 ES 模块,必须通过 http 访问: - **双击 `start.bat`**(需要已安装 Node.js),或 - 命令行:`node server.mjs [端口]`(默认 8000) 然后打开: - 编辑器: - demo:(`?demo=manga` 切到坐姿少女 demo,或页面顶部下拉框切换) ## 编辑器用法 1. 导入图片 2. 创建动画(名称唯一) 3. 创建区域:点区域面板「+」弹出类型菜单选择类型——主动(关键帧驱动变形)/ 被动(自动过渡到主动区)/ 颜色(色温/色相/色度动画),随后用路径工具绘制(双击闭合) 4. 选中主动或颜色区域后创建片段——片段自动关联该区域(一个片段只对应一个区域);主动区关键帧=位移/缩放/旋转,颜色区关键帧=色温/色相/色度 5. 选中片段,时间轴上拖动片段块改起点、拖关键帧拉长内容(片段长度 = 内容,动画长度 = 内容结束位置);播放头拨到空白处 +帧 即可延伸 6. 「导出」得到配置 JSON(version:4,只含动画数据,不含图片) 导入兼容旧版导出格式(自动迁移;旧格式里内嵌的图片会被忽略,图片一律用「导入图片」单独管理)。 ## 运行时用法 ```js import { MeshAnimRuntime3D } from './runtime/runtime3d.mjs'; const r = new MeshAnimRuntime3D(canvas, config); // config = 导出的 JSON(只描述动画) await r.setImage('角色.png'); // 图片单独设置:dataURL/相对路径/Image 元素 r.setAnimation('动画名或id'); r.render(1.5); // 渲染第 1.5 秒(任意时间点) r.play(); r.pause(); r.stop(); // 播放循环;动画 loop 控制整段循环 r.onFrame(t => console.log(t)); // 播放帧回调 r.onEnd(() => console.log('播放结束')); // 非循环播放结束回调 ``` ### 渲染原理(网格顶点变形) - 整张贴图铺在一个密集三角网格上(约 48×48 段),每个顶点 UV = 原始纹理坐标 - 主动区域变换通过移动网格顶点实现,GPU 三角形光栅化自然处理拉伸/补洞 - 顶点变形逻辑:点在主动区内→按主动区变换;点在被动区内→按加权逆映射混合;其他点不动 - 颜色区域:四层效果由关键帧插值(同一区域多片段覆盖时起点最靠后者生效):①色温/色相/色度调整;②叠加颜色(normal 混合,颜色+不透明度);③加色(原色+颜色×强度);④覆盖颜色(替换,颜色+不透明度,默认不透明)——同区域层序 ①→②→③→④(覆盖在最上),多区域按区域顺序链式叠加。每个顶点在原始坐标空间算出四层各自的颜色权重:以边界为中心的对称带宽 `[-向内, +向外]`,权重 = `curveFn(过渡曲线, (带符号距离+向内)/(向内+向外))`——深处全量、边界处 `curveFn(向内/带宽)`、向外衰减到 0;曲线与被动区相同(linear/smooth/sharper/gentle,默认 smooth);权重用 Uint8 归一化属性上传;同时活跃上限 8 个。权重是顶点属性,随顶点变形走,色块跟随内容(如眼睛变色后眨眼色块跟着动)。柔边宽度(每层两个,像素,0=硬边)**在关键帧上设置并随关键帧补间**(硬度/叠加柔边/加色柔边/覆盖柔边=向外,默认 0=效果不向区域外泄露;hardnessIn/overlaySoftIn/addSoftIn/coverSoftIn=向内,默认 3);权重过渡受网格密度限制约 2px 最小羽化。 - 不再需要 fragment shader 逐像素逆映射 ### 3D 扩展 - **关键帧字段**:`rotX`/`rotY`(角度,绕区域中心倾斜平面)、`z`(像素深度,正=朝观众),与现有 `tx/ty/sx/sy/rot` 一样可插值 - **相机**:`r.camera = { rotX, rotY, focal, autoOrbit, orbitSpeed }` - `focal=0`:正交投影;`focal>0`:透视投影(焦距像素值) - `rotX/rotY`:整场景绕图片中心的轨道旋转(度),配合透视即「相机绕 3D 场景旋转」;`autoOrbit=true` 时播放中自动旋转 - 拖拽画布可手动旋转相机(编辑器勾选「观察」模式后可拖拽) > **当前实现状态**(2026-09-03 核查) > > - ✅ **相机级 3D 完整可用**:轨道旋转、透视投影、深度排序均正常,编辑器「观察」模式即在用它 > - ⚠️ **关键帧级 3D 未接线**:`rotX`/`rotY`/`z` 的插值与顶点变换在 `647eec7`(统一运行时重构)中被移除, > 旧实现的 `interpKF3d`/`buildActiveTF3d`/`applyModel3D` 已不存在,**写入配置当前不生效**(已知回归) > - ⚠️ **`autoOrbit`/`orbitSpeed` 未接线**:渲染循环不再推进自动旋转(同上,回归) ### 演示页 打开 :顶部下拉框或 `?demo=` 参数切换内置角色。 > 原 `demo/demo3d.html`(3D 演示页)已在 `647eec7` 中删除,提交说明称「将 3D 演示功能整合至主 > demo 页面」,但**整合并未完成**——`demo.html` 目前没有任何 3D 控件。3D 演示入口缺失属已知缺口。 > 历史版本中的 3D 演示页曾支持: > > - 勾选「3D 平面」给主动区域关键帧临时注入 `rotX/rotY/z`(不写回导出配置) > - 勾选「透视相机」启用透视 + 自动轨道旋转 > - URL 参数:`?3d=1&orbit=1&t=0.2&anim=shake&camx=12&camy=35&play=1`(便于分享固定视角) ## 导出格式`{version, width, height, animations:{[id]:{name, loop, regions, clips}}}`(不含图片:配置只描述动画与区域坐标空间,图片完全独立);片段长度由关键帧决定(无固定时长字段);同一区域被多个同时活跃片段绑定时,起点最靠后的片段生效。区域 `type` 支持 `active`/`passive`/`color`;被动/颜色区带 `falloffCurve`(过渡曲线)。颜色区关键帧字段为 `hue/sat/temp`(色相°/色度/色温)+ 三颜色层 `overR/overG/overB/overA`(叠加,A=不透明度)、`addR/addG/addB/addS`(加色,S=强度)、`covR/covG/covB/covA`(覆盖,A=不透明度)+ 柔边宽度(关键帧补间;向外默认 0 / 向内默认 3):`hardness/hardnessIn`、`overlaySoft/overlaySoftIn`、`addSoft/addSoftIn`、`coverSoft/coverSoftIn`;主动区关键帧字段为 `tx/ty/sx/sy/rot`。导入旧配置时,关键帧缺宽度字段会自动继承区域级宽度(迁移)。 ## 素材许可 demo 角色 `demo/kenney_character.png` 来自 [Kenney Toon Characters 1](https://kenney.nl/assets/toon-characters), 许可 [CC0 1.0](http://creativecommons.org/publicdomain/zero/1.0/)(可自由用于个人与商业项目,署名非必须),详见 `demo/LICENSE-Kenney.txt`。 `demo/manga_girl.png` 来自 OpenGameArt 的 [manga girl](https://opengameart.org/content/manga-girl)(作者 mcproject), 同样为 [CC0 1.0](http://creativecommons.org/publicdomain/zero/1.0/),详见 `demo/LICENSE-manga-girl.txt`。 其他 `demo/pixabay_*.png` 来自 Pixabay,使用 [Pixabay Content License](https://pixabay.com/service/license-summary/)(免费商用、免署名,但不得单独转售原图),作者与来源页见 `demo/LICENSE-Pixabay.txt`。 `demo/oga_codel/` 与 `demo/oga_kuudere/` 是 OpenGameArt 的立绘套图(作者 LisadiKaprio,[CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/),需署名),许可文件在各自文件夹内。