Files
SpineParticlesWeb/网页粒子系统阶段五.md
T
2026-08-28 17:50:23 +08:00

449 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 网页粒子系统 · 阶段五
> 阶段定位:**粒子拖尾模块定版**
> 完成日期:2026-08-28
> 工程目录:`/Users/tianmokeji/Desktop/SpineParticle`
> 技术栈:Vue 3 + TypeScript + Pinia + PixiJS 7 + Vite
---
## 一、阶段结论
阶段五完成了粒子拖尾模块的第一版完整实现。拖尾不再是独立于粒子的静态图片,而是由每个粒子自己的历史轨迹、拖尾骨骼链和网格蒙皮共同驱动,并与粒子的最终渲染位置保持连接。
本阶段主要完成:
1. 默认 `trail.png` 拖尾资源;
2. 多拖尾图片资源和占比分配;
3. 每张拖尾资源独立的骨骼、尺寸、旋转、颜色、透明度和曲线配置;
4. 按网格行列自动生成蒙皮拓扑;
5. 按拖尾骨骼数生成独立骨骼链;
6. 使用相邻骨骼权重对图片网格进行 CPU 蒙皮;
7. 拖尾跟随粒子最终渲染位置,包含移动噪声等视觉位移;
8. 拖尾状态参与固定帧录制与回放;
9. 画布蒙皮网格调试显示;
10. 卡片全量重置和旧配置迁移。
拖尾模块默认关闭,不会改变未启用拖尾时的粒子表现。阶段三的外观资源和阶段四的修改器功能保持原有行为。
---
## 二、拖尾默认状态
### 2.1 模块默认状态
- “开启拖尾(Trail)”默认关闭;
- 开启后默认创建一张拖尾资源卡片;
- 默认图片为 `public/trails/trail.png`
- 默认名称为 `trail`
- 单资源时占比固定为 100%
- 画布“蒙皮网格”显示默认关闭。
### 2.2 每张拖尾资源的默认参数
| 参数 | 默认值 |
|---|---:|
| 图片 | `trail.png` |
| 名称 | `trail` |
| 占比 | 100%(单资源) |
| 占比锁定 | 关闭 |
| 旋转 | 0° |
| 拖尾骨骼数 | 3 |
| 初始长度 | 100 |
| 初始宽度 | 100 |
| 宽度缩放 | 跟随粒子 |
| 生命周期长度曲线 | 关闭,默认水平线 1 |
| 形状曲线 | 关闭,默认水平线 1 |
| 颜色模式 | 跟随粒子 |
| 混合模式 | 正常 |
| 固定颜色 | `#ffffff` |
| 透明度模式 | 跟随粒子 |
| 固定透明度 | 1 |
| 透明度曲线 | 默认水平线 1 |
### 2.3 网格默认参数
网格拓扑属于拖尾模块的公共结构参数:
| 参数 | 默认值 | 可调范围 |
|---|---:|---:|
| 网格行数 | 4 | 216 |
| 网格列数 | 4 | 232 |
行数决定图片宽度方向的细分,列数决定图片从头部到尾部方向的细分。
---
## 三、多拖尾图片资源
### 3.1 资源卡片
拖尾图片复用了外观与资源模块的通用 `ImageResourceCard.vue`,因此两类图片资源保持统一的交互方式:
- 点击缩略图选择本地 PNG、JPEG 或 WebP
- 点击右上角 `` 新增拖尾资源卡片;
- 修改资源名称;
- 查看当前图片文件名;
- 调整资源占比;
- 锁定或解除锁定当前占比;
- 重置当前资源;
- 删除当前资源,至少保留一张。
拖尾资源不显示“子文件夹”字段,其余通用卡片结构与粒子图片资源一致。
### 3.2 占比规则
- 单张拖尾资源时,占比固定为 100%,锁定按钮不可用;
- 多张拖尾资源时,总占比始终保持 100%;
- 锁定某张资源后,调整其他资源只会重新分配未锁定资源;
- 新增、删除或重置资源后会重新平衡占比;
- 每个粒子出生时,根据全局随机种子和资源占比选择一张拖尾图片;
- 粒子出生后保持已选中的拖尾资源,不会在生命周期中跳换图片。
### 3.3 卡片重置
点击拖尾卡片的重置按钮会恢复该卡片的完整默认状态,不再只替换图片。重置内容包括:
- `trail.png`、名称 `trail`
- 占比和锁定状态;
- 旋转、骨骼数、长度、宽度和宽度模式;
- 生命周期长度曲线及其开关;
- 形状曲线及其开关;
- 颜色模式、固定色、颜色渐变和混合模式;
- 透明度模式、固定透明度和透明度曲线。
多资源场景中,卡片恢复默认后仍会执行占比平衡,保证全部资源之和为 100%。
---
## 四、每张拖尾资源的独立控制
### 4.1 图片方向
拖尾图片约定:
- 图片左侧为拖尾头部;
- 图片右侧为拖尾尾部;
- 第 0 根拖尾骨骼位于粒子位置;
- 后续骨骼沿粒子历史轨迹向后排列。
“旋转”用于修正所选图片的默认朝向。旋转通过图片中心的 UV 变换完成,不会改变粒子自身旋转。
### 4.2 骨骼与尺寸
每张拖尾资源独立设置:
- **拖尾骨骼数**:决定沿轨迹采样的骨骼节点数量,范围 2~16;
- **初始长度**:决定从粒子头部向历史轨迹回溯的距离;
- **初始宽度**:决定蒙皮网格横向展开宽度;
- **宽度缩放**:可选择固定宽度或跟随粒子当前缩放。
“跟随粒子”模式使用粒子当前 X/Y 缩放绝对值的平均值作为宽度倍率。
### 4.3 生命周期长度曲线
开启后,曲线横轴为粒子归一化生命时间,纵轴为长度倍率:
```text
当前拖尾长度 = 初始长度 × 生命周期长度曲线值
```
曲线默认是值为 1 的水平线。关闭时始终使用初始长度。
### 4.4 形状曲线
形状曲线控制拖尾从首端到尾端的宽度变化:
```text
当前列宽度 = 当前拖尾宽度 × 形状曲线值
```
横轴表示从头部到尾部的位置,纵轴表示宽度倍率。默认曲线为值 1 的水平线,因此首尾等宽。
### 4.5 颜色与混合模式
每张拖尾资源支持三种颜色模式:
| 模式 | 行为 |
|---|---|
| 跟随粒子 | 使用当前粒子图片的实时颜色 |
| 固定 | 使用拖尾资源自己的固定颜色 |
| 曲线 | 按粒子生命周期使用多色渐变 |
固定色支持颜色选择器和十六进制文本输入。曲线模式复用生命周期多色渐变控件,可添加多个颜色标记。
每张资源还可独立选择四种混合模式:正常、相加、相乘、滤色。
### 4.6 透明度
每张拖尾资源支持三种透明度模式:
| 模式 | 行为 |
|---|---|
| 跟随粒子 | 使用粒子当前透明度 |
| 固定 | 使用拖尾资源自己的固定透明度 |
| 曲线 | 按粒子生命周期读取透明度曲线 |
透明度曲线默认是值为 1 的水平线。
---
## 五、拖尾骨骼与蒙皮实现
### 5.1 粒子历史轨迹
每个活动粒子维护自己的轨迹历史:
- 记录粒子每帧的最终渲染位置;
- 相邻位置变化过小时更新首点,避免堆积大量重复点;
- 按配置长度保留约 1.5 倍的历史距离;
- 单粒子历史点设置上限,防止长时间运行无限增长;
- 粒子死亡、拖尾关闭或重新绑定时清空对应历史。
记录的是粒子最终渲染位置,因此移动噪声造成的视觉位移也会进入拖尾轨迹,拖尾头部不会与画面中的粒子脱节。
### 5.2 独立骨骼链
每个粒子根据自己所选拖尾资源的骨骼数生成独立骨骼链:
1. 第 0 根骨骼固定在粒子最终渲染位置;
2. 其余骨骼沿历史轨迹按距离等距采样;
3. 每根骨骼根据前后采样点计算旋转方向;
4. 不同粒子、不同拖尾资源可以使用不同骨骼数量。
### 5.3 网格拓扑
网格根据行列数自动生成:
- 每个交叉点生成一个顶点;
- 相邻四个顶点组成两个三角形;
- 列方向对应图片左侧头部到右侧尾部;
- 行方向对应图片宽度;
- UV 根据资源旋转参数绕中心重新计算。
### 5.4 蒙皮权重
每一列顶点绑定相邻两根拖尾骨骼:
- 根据列在拖尾长度中的归一化位置,计算前后骨骼索引;
- 在两根骨骼之间使用线性权重插值;
- 顶点中心沿骨骼链移动;
- 顶点宽度方向使用轨迹切线的法线展开;
- 形状曲线进一步调节每一列的宽度。
当前使用 CPU 更新 PixiJS `SimpleMesh` 顶点,蒙皮结果实时写回画布。
### 5.5 绘制层级
拖尾网格始终绘制在对应粒子图片下方,避免拖尾覆盖粒子头部。图片不可用、轨迹长度不足或最终透明度为 0 时,拖尾网格自动隐藏。
---
## 六、重新绑定规则
以下参数改变时会触发拖尾网格和蒙皮重新绑定:
1. 网格行数;
2. 网格列数;
3. 当前拖尾资源的骨骼数;
4. 当前拖尾资源的旋转方向;
5. 粒子切换到结构签名不同的拖尾资源。
重新绑定时:
- 保留当前正在使用的图片,不会错误恢复为 `trail.png`
- 重新生成顶点、索引、UV 和骨骼权重;
- 清空旧轨迹和旧骨骼状态;
- 从粒子当前最终位置重新开始采样;
- 避免旧骨骼位置套用到新网格后产生偏移或拉伸。
只有用户主动点击卡片重置按钮时,图片和参数才会恢复为完整默认状态。
---
## 七、粒子跟随与修改器协作
此前出现的“拖尾像独立图片、没有跟随粒子”问题已经修正。当前拖尾更新顺序为:
1. 计算粒子的基础物理位置;
2. 应用重力、风力、力场、吸附和阻尼;
3. 计算移动噪声等最终视觉位移;
4. 得到粒子最终渲染位置;
5. 将该位置写入拖尾历史;
6. 重新采样拖尾骨骼;
7. 将首骨骼强制对齐粒子最终位置;
8. 更新蒙皮顶点、颜色、透明度和混合模式。
因此拖尾与粒子画面位置使用同一坐标来源。粒子死亡时,对应拖尾历史、骨骼和网格会一起停止并清理。
---
## 八、固定帧录制与回放
粒子实时状态新增 `trailState`,记录:
- 当前拖尾资源 ID
- 拖尾骨骼位置和旋转;
- 当前宽度;
- 当前透明度;
- 当前颜色。
固定帧录制会保存这些状态,回放时按资源 ID 恢复对应纹理和蒙皮参数,避免多拖尾资源在回放时全部退回第一张图片。
---
## 九、画布蒙皮网格调试
画布左上角新增“蒙皮网格”复选框:
- 默认关闭;
- 开启后使用青色线条绘制正在显示的拖尾网格;
- 显示网格的行列连接和所有顶点;
- 多个粒子的网格可同时显示;
- 只用于编辑器调试,不参与录制和导出;
- 关闭拖尾或关闭开关时立即清空辅助线。
该功能用于检查图片方向、网格密度、骨骼变形和拖尾是否与粒子头部正确连接。
---
## 十、核心数据结构
### 10.1 `TrailImageResource`
每张拖尾图片已经成为完整的独立资源配置,主要包含:
- 资源 ID、纹理、名称和预览地址;
- 占比和锁定状态;
- 图片旋转;
- 颜色模式、固定色、多色渐变和混合模式;
- 透明度模式、固定透明度和曲线;
- 骨骼数、初始长度、初始宽度和宽度模式;
- 生命周期长度曲线;
- 首端到尾端的形状曲线。
### 10.2 `TrailState`
`TrailState` 是实时预览与时间轴之间的拖尾状态载体,包含骨骼链、宽度、透明度、颜色和拖尾资源 ID。
### 10.3 兼容迁移
`ensureEmitterConfig()` 会:
- 把早期单拖尾字段迁移为 `trailResources`
- 为旧资源补齐旋转、混合模式、独立骨骼尺寸和曲线字段;
- 把旧版非水平拖尾曲线迁移为当前默认水平曲线;
- 把旧网格默认值迁移为 4 行、4 列;
- 保证热更新和旧内存配置不会把 `undefined` 传入运行逻辑。
---
## 十一、本阶段新增或重点调整的文件
| 文件 | 本阶段职责 |
|---|---|
| `public/trails/trail.png` | 默认拖尾图片资源 |
| `src/views/ImageResourceCard.vue` | 粒子图片与拖尾图片共用的资源卡片 |
| `src/views/ParticlePanel.vue` | 拖尾开关、多资源卡片、独立参数、曲线、占比和重置逻辑 |
| `src/core/particleEmitter.ts` | 轨迹记录、骨骼采样、网格生成、CPU 蒙皮、资源选择、录制和回放状态 |
| `src/views/Stage.vue` | 默认拖尾纹理注入、画布蒙皮网格显示及实时刷新 |
---
## 十二、验证结果
本阶段已完成以下检查:
- 默认拖尾资源能加载 `trail.png`
- 图片左侧为头部、右侧为尾部;
- 拖尾首骨骼与粒子最终渲染位置保持一致;
- 移动噪声开启时,拖尾沿粒子视觉轨迹移动;
- 多张拖尾图片可新增、删除、选择和按占比分配;
- 每张资源可独立设置骨骼、长度、宽度、旋转、颜色、混合模式和透明度;
- 生命周期长度曲线和形状曲线已移动到各自资源卡片;
- 修改行列数、骨骼数或旋转后会重新绑定,并保留当前图片;
- 卡片重置会恢复图片和全部默认参数;
- 网格默认值为 4 × 4
- 画布“蒙皮网格”开关默认关闭,可正常开启和关闭;
- 本地页面交互过程中没有控制台错误;
- `npm run build` 通过;
- `git diff --check` 通过。
Vite 仍会提示主包体积超过 500 kB,该提示不影响当前功能运行。
---
## 十三、当前边界与已知风险
1. **拖尾不会在粒子死亡后继续残留**:粒子死亡时拖尾一起清理,尚未支持尾迹独立淡出。
2. **蒙皮在 CPU 中逐帧更新**:高粒子数、高网格细分和多拖尾资源同时使用时需要性能压测。
3. **历史轨迹按帧采样**:极端帧率波动下,弯曲细节可能出现密度差异;当前骨骼按距离重新采样可缓解但不能完全消除。
4. **所有拖尾资源共用网格行列数**:骨骼数和外观参数可独立配置,但网格拓扑尚未移动到每张资源卡片。
5. **资源仍依赖运行时纹理对象**:本地上传图片尚未进入正式工程保存、加载和资源打包流程。
6. **旋转使用 UV 中心变换**:非矩形有效内容或带大面积透明边距的图片可能需要额外裁切、翻转或轴向选项。
7. **时间轴保存的是运行状态**:尚未形成独立、版本化、可跨工程交换的拖尾动画格式。
8. **缺少自动化测试**:当前以类型检查、生产构建和浏览器交互验证为主。
---
## 十四、下一步开发建议
### 优先级 P0:拖尾性能与稳定性
- 对 100、200、400 粒子分别测试 4 × 4、8 × 8、16 × 32 网格;
- 记录 CPU 蒙皮耗时、顶点数量和内存占用;
- 将不在视口内或透明度为 0 的拖尾提前跳过;
- 缓存资源 ID 到配置对象的映射,减少每帧数组查找;
- 评估把顶点变形迁移到 GPU Shader 的收益。
### 优先级 P1:拖尾生命周期收尾
- 增加粒子死亡后拖尾残留时间;
- 支持尾迹独立淡出和收缩;
- 明确吸附完成、碰撞死亡和自然死亡时的不同拖尾结束策略;
- 增加拖尾采样间隔或最小距离参数;
- 增加轨迹平滑和尖角处理。
### 优先级 P2:工程保存与资源打包
- 定义正式 `ProjectSchema` 和版本号;
- 将 Pixi Texture 与可序列化拖尾配置分离;
- 保存多拖尾资源、占比、锁定、颜色、曲线和网格参数;
- 采用 Data URL、ZIP 工程包或资源目录保存自定义拖尾图片;
- 为阶段三到阶段五建立明确的配置迁移测试。
### 优先级 P3:导出准备
- 明确拖尾骨骼链在 Spine 中的命名和层级;
- 固化网格顶点、三角形、UV、权重和骨骼数据格式;
-`TrailState` 烘焙为骨骼关键帧或网格变形关键帧;
- 验证多拖尾资源的槽位、附件和混合模式表达;
- 评估不同 Spine 版本对加权网格和变形时间轴的兼容性。
### 优先级 P4:后续模块
- 实现碰撞体和粒子碰撞响应;
- 实现轨道路径与路径跟随;
- 为修改器辅助图形增加统一显示入口;
- 增加撤销/重做、预设和参数复制粘贴。
---
## 十五、阶段五验收标准
阶段五可视为完成,当以下条件持续满足:
- 拖尾默认关闭,开启后默认使用 `trail.png`
- 每个粒子拥有独立的轨迹、骨骼链和蒙皮网格;
- 拖尾图片左侧连接粒子,右侧沿历史轨迹延伸;
- 多拖尾资源按占比确定性选择,并支持占比锁定;
- 每张拖尾资源可独立调整旋转、骨骼、尺寸、曲线、颜色、混合模式和透明度;
- 网格按行列自动生成,并由相邻骨骼权重驱动;
- 拖尾与粒子最终渲染位置保持连接;
- 修改结构参数后保留当前图片并重新绑定,不产生旧蒙皮偏移;
- 卡片重置可恢复完整默认状态;
- 画布可选择显示实际蒙皮网格,且默认关闭;
- 拖尾状态能够参与时间轴录制和回放;
- 阶段三外观资源和阶段四修改器功能没有发生回归;
- TypeScript 类型检查和生产构建保持通过。