Add cutout shell and volume node assets for depth volume processing

- Implemented `cutout_shell.py` to build front normals and shell positions for balloon geometry.
- Created `cutout_volume.py` to establish smooth center fields and manage balloon surface attributes.
- Introduced `pisa_sr_export.py` for exporting PiSA-SR components with dependencies and asset finalization.
This commit is contained in:
2026-09-08 17:18:03 +08:00
parent 7dec3b7ca4
commit 196b964efc
71 changed files with 3440 additions and 1988 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-08

View File

@@ -0,0 +1,74 @@
## Context
当前 `onnx_upscale.py` 用 256 像素 tile 执行三个 4× 模型,`models/upscale.py` 负责输入尺寸限制和 alpha 回填,`ModelManager` 缓存单个 Upscale Session。Operator 的倍率和提示均为 4×。
本地实验位于 `build/upscale-explore/pisa-research/`。已验证固定 512×512 的 PiSA-SR FP16 ONNX 全流程在 DirectML 上出图,0.7 预设对应像素强度 1.0、语义强度 0.7、空提示词和 seed 42。两套 UNet 常驻时,512 输出约 1.57–2.37 秒;默认强度 1.0 的单 UNet 速度不代表 0.7。分块和跨设备部署尚待验证。
## Goals / Non-Goals
**Goals:** 四个选项统一 2× 输出;复现已选定的 PiSA-SR 0.7 观感;通过已有 ONNX 运行时服务图片和逐帧任务。
**Non-Goals:** 本次范围限定为固定预设与既有 Upscale 操作,强度滑杆、提示词编辑和视频时序增强属于独立能力。
## Decisions
### 1. 最终倍率与模型原生倍率分别定义
```mermaid
flowchart TD
A[读取并限制输入尺寸] --> B{模型}
B -->|现有三个模型| C[原生 4× 分块推理]
C --> D[Lanczos 缩至输入宽高的 2 倍]
B -->|PiSA-SR| E[Bicubic 放大至 2×]
E --> F[VAE 编码与固定噪声采样]
F --> G[像素与完整 UNet 预测]
G --> H[按语义强度 0.7 组合并解码]
H --> I[AdaIN 颜色校正与裁切]
D --> J[按最终尺寸回填原始 alpha]
I --> J
J --> K[保存结果并替换图片]
```
公共结果倍率为 2,旧 ONNX 图的 shape 校验仍为原生 4。先实现完整 4× 拼接后一次 Lanczos 缩小,作为明确的像素基线;避免先逐 tile 缩小引入新的滤波接缝。最终尺寸相对于 `limit_image()` 之后的输入,沿用 Operator 对输入长边的既有限制。
保留三个模型的 key、原生名称和默认选择,说明文字明确最终输出 2×。新增 key `PISA_SR`、显示名 `PiSA-SR`,说明固定细节强度 0.7;生产和 Debug 复用相同输出入口。
### 2. 固定 0.7 的定义与实验一致
使用同一采样 latent 计算 `pixel + 0.7 * (full - pixel)`,再按已验证的公式解码。空提示词 embedding 与 timestep 固定在资产中,seed 固定为 42;采样算法、精度和噪声布局通过测试锁定。保留实验中的 Bicubic 输入插值、VAE scaling、输出量化和 AdaIN 颜色校正。
该强度是在预测结果上插值。将 LoRA 权重乘以 0.7 或插值两套 UNet 权重,不能视为等价的单 UNet 优化;任何这样的优化必须另行通过效果对照。
### 3. PiSA-SR 使用独立适配器与多文件资产
新增 `server/models/onnx_pisa_sr.py` 承担 VAE、UNet、采样及分块。`ModelManager` 按模型类型创建单 Session 或 PiSA-SR 管线,并统一缓存 key、释放和状态展示。Session 创建和运行复用 `onnx_runtime.py`,补齐 DirectML 所需的 sequential execution 与禁用 memory pattern 配置。
资产以 encoder、decoder、pixel UNet、full UNet 为明确文件集合,通过既有 catalog 下载与完整性校验。实验包约 3.63 GB,发布清单必须使用最终导出文件的尺寸和 SHA256。导出工具固定 PiSA 源码 commit、基础模型 revision、LoRA 校验值和导出环境;训练依赖仅用于离线工具。实验目录仅作为参考,不作为运行时路径。
### 4. 分阶段执行限制模型常驻
优先采用按阶段处理全部 tile 的调度:编码并把 latent 存入主机内存,运行像素 UNet 保存预测,释放该 Session 后运行完整 UNet并组合,最后解码。GPU 上同一时刻只常驻一套 UNet;切换在整图阶段边界发生。大图中间数组可落入任务临时目录,结束或取消后清理。
此方案以降低显存峰值为优先,代价是阶段加载成本;实施时同时测冷启动、连续图片和多帧耗时。任务结束按实际 Session 最后使用点释放临时推理内存,资源错误使整个 PiSA 管线缓存失效,Clear Models 释放全部组件。
### 5. 固定尺寸 ONNX 通过重叠分块覆盖任意输入
以已验证的 512×512 输出 tile 为初始部署尺寸,采用重叠区域加权融合,边缘填充后裁回精确的 2× 尺寸。噪声按整图 latent 坐标生成并切片,重叠区域共享噪声;AdaIN 在拼接完成后按整图执行。单 tile 情况保持实验基线,多 tile 的重叠宽度通过接缝对照确定并固化为内部常量。
alpha 从受尺寸限制的源图直接 Lanczos 放大到最终 2×,独立于生成模型;透明 RGB 的处理沿用现有输入语义,并加入半透明边缘目视验收。多帧逐帧处理并复用固定噪声规则,支持取消;生成纹理的时序稳定性列入验收观察。
## Risks / Trade-offs
- [分块改变生成纹理或形成接缝] → 对两张实验样图及跨 tile 的纹理、渐变、透明边缘做完整图与局部对照;接缝未通过时继续调整分块方案。
- [分阶段 Session 加载拖慢连续任务] → 记录端到端冷暖耗时、峰值显存和主机内存;不将单 UNet 默认模式的数字作为 0.7 性能承诺。
- [FP16 图在 CPU/CoreML 上兼容性未知] → 实测项目支持的设备路径;需要时导出匹配的精度资产,并在 catalog 中表达准确支持范围。不可运行的设备返回明确原因。
- [新细节改变原始图案或引起逐帧闪动] → 保留已有模型选择,验收脸部、文字、纹理和短序列样例,界面说明生成型细节补充。
- [多 GB 权重分发与依赖来源] → 发布前核对基础模型和 PiSA 权重的分发条款,登记固定来源及最终文件校验信息。
## Migration Plan
先准备与验证 PiSA 资产及分块管线,再接入 catalog、模型管理器和界面,统一最终 2× 结果并运行测试。现有用户保存的模型 key 继续有效,后续执行采用 2×;已有图片产物无需迁移。回退时同步回退模型选项和推理入口,已下载资产可由已有缓存管理处理。
## Open Questions
实施实验需确定分块重叠宽度、阶段加载的可接受耗时,以及 CPU/CoreML 的实际精度与支持范围。这些验证不改变 0.7 和最终 2× 的产品约定。

View File

@@ -0,0 +1,27 @@
## Why
现有 Upscale 每次把宽高放大 4 倍,尺寸增长过快。PiSA-SR 在已测试的 0.7 细节强度下能够补充更丰富的纹理,适合作为新的生成型选项;所有模型统一每次输出 2×,方便逐步放大。
## What Changes
- 新增 `PiSA-SR` 模型选项,固定 `lambda_pix=1.0`、`lambda_sem=0.7`,输出宽高各为输入的 2 倍。
- **BREAKING**:现有 General WDN x4v3、SAFMN Real x4、Real-ESRGAN x4plus 仍使用已有 4× 权重,完成推理后以 Lanczos 缩小至一半,最终输出 2×。
- Upscale 的尺寸计算、界面说明、生产与调试任务统一采用最终 2× 语义;保留现有默认模型。
- PiSA-SR 通过 ONNX Runtime 接入模型下载、设备选择、缓存、取消和资源释放流程,支持任意合法输入尺寸与透明度保留。
## Capabilities
### New Capabilities
- `two-times-upscale`: 四个模型的统一 2× 输出、PiSA-SR 固定细节预设及模型资源生命周期。
### Modified Capabilities
无已发布的对应 capability。
## Impact
- `server/model_catalog.py`、模型下载与导出工具:增加 PiSA-SR 多文件模型资产及校验信息。
- `server/models/`、`server/model_manager.py`:PiSA-SR 推理、分块及多 Session 生命周期;旧模型结果缩小。
- `operators/upscale.py`、模型选择与相关界面:模型选项和最终倍率。
- 生产、调试、透明图片和多帧处理相关测试。运行时沿用 ONNX Runtime;PyTorch 等仅用于离线导出与数值验证。

View File

@@ -0,0 +1,74 @@
## ADDED Requirements
### Requirement: Unified two-times output
系统 SHALL 对全部 Upscale 模型返回处理输入宽高各 2 倍的结果,并将该倍率用于界面说明和尺寸计算;处理输入为应用已有最大输入尺寸限制后的图像。
#### Scenario: Existing models produce two-times images
- **WHEN** 任一现有模型处理 W×H 输入
- **THEN** 系统先得到原生 4W×4H 结果,再使用 Lanczos 缩小到 2W×2H
- **AND** 使用已有 4× 权重
#### Scenario: Repeated upscale
- **WHEN** 用户对一次 2× 结果再次执行 Upscale 且输入尺寸仍满足限制
- **THEN** 新结果宽高各为本次输入的 2 倍,即最初输入的 4 倍
### Requirement: Fixed PiSA-SR preset
系统 SHALL 提供 `PISA_SR` 模型选项,使用固定像素强度 1.0、语义强度 0.7、空提示词和 seed 42,通过 ONNX Runtime 生成 2× 结果。现有默认模型 SHALL 保持有效。
#### Scenario: Selected preset is executed
- **WHEN** 用户选择 PiSA-SR 并执行 Upscale
- **THEN** 模型对同一 latent 的预测按 `pixel + 0.7 * (full - pixel)` 组合
- **AND** 输入插值、采样、解码与颜色校正遵循已验证的实验基线
#### Scenario: Repeatable inference
- **WHEN** 相同图像在相同运行环境重复执行 PiSA-SR
- **THEN** 系统使用相同噪声和处理规则,结果在该设备的数值容差内一致
### Requirement: Arbitrary dimensions and alpha preservation
系统 SHALL 支持合法输入范围内的小图、非方形图、奇数尺寸和跨 tile 图像,输出精确 2× 尺寸;有 alpha 的生产输入 SHALL 保留由源 alpha 插值而来的透明度。
#### Scenario: Tiled PiSA-SR image
- **WHEN** 输入需要多个 PiSA-SR tile
- **THEN** 系统融合重叠区域并裁去填充,输出无多余边缘的 2W×2H 图像
- **AND** 连续纹理与渐变测试图的 tile 边界不出现可辨识拼接线
#### Scenario: Transparent input
- **WHEN** 输入包含全透明和半透明像素
- **THEN** 输出 alpha 等于源 alpha 直接 Lanczos 放大到最终尺寸的结果
- **AND** RGB 生成过程不生成或覆盖 alpha
### Requirement: Model readiness and resource lifecycle
系统 SHALL 对 PiSA-SR 全部必需资产完成下载及校验后才判定就绪,按所选设备创建管线;其模型切换、取消、资源错误和显式清理 SHALL 覆盖全部组件。
#### Scenario: Incomplete model package
- **WHEN** PiSA-SR 任一必需文件缺失或校验失败
- **THEN** 系统提示准备模型并阻止使用不完整管线进行推理
#### Scenario: Bounded UNet residency
- **WHEN** PiSA-SR 执行像素与完整预测阶段
- **THEN** GPU 同时常驻的 UNet 至多一套,阶段间中间数据被保留以完成 0.7 组合
#### Scenario: Cancel or resource failure
- **WHEN** 推理被取消或发生资源错误
- **THEN** 系统停止后续阶段并清理任务中间文件
- **AND** 资源错误释放整个 PiSA-SR 管线并报告可理解的失败原因
#### Scenario: Unsupported device
- **WHEN** 所选设备无法执行已分发的 PiSA-SR 资产
- **THEN** 系统报告明确的设备支持原因或执行已验证并明确呈现的回退路径
### Requirement: Consistent job behavior
系统 SHALL 在生产与调试任务采用同一模型预设和最终倍率,并对多帧输入逐帧应用该约定。
#### Scenario: Multiple frames
- **WHEN** Upscale 处理多帧输入
- **THEN** 每帧输出均为其处理输入的 2× 尺寸,帧顺序正确且阶段之间可以取消
#### Scenario: Debug matches production
- **WHEN** 相同 RGB 输入、模型和设备分别通过生产与 Debug 入口处理
- **THEN** 两者的 RGB 处理规则和最终尺寸一致

View File

@@ -0,0 +1,26 @@
## 1. PiSA-SR 资产与数值基线
- [x] 1.1 将实验的固定来源、revision、LoRA 校验信息与离线依赖纳入正式导出工具,核对分发条款并实现四个 ONNX 组件的可复现导出。
- [x] 1.2 固化 0.7 预测组合、seed 42 采样、空提示词、插值、量化和 AdaIN 规则;对两张样图验证 PyTorch 与 ONNX 0.7 的最终 RGB 平均绝对误差不超过 1 个 8-bit 灰度级,并目视确认细节。
- [x] 1.3 验证 DirectML、CUDA 及 CPU/CoreML 的实际支持路径,确定精度资产与设备支持信息,记录不可用路径的明确处理方式。
## 2. 分块与资源管理
- [x] 2.1 实现 PiSA-SR 独立 ONNX 适配器,复用共享运行时,补齐 DirectML Session 配置并覆盖其他模型配置回归。
- [x] 2.2 实现编码、像素预测、完整预测、解码的分阶段调度,GPU 至多常驻一套 UNet;覆盖阶段切换、中间数据保存及临时文件清理。
- [x] 2.3 实现固定尺寸重叠分块、共享坐标噪声、加权拼接与最终裁切;用单 tile 基线、奇数尺寸、小图、渐变和跨边界纹理确定重叠参数并确认无可辨识接缝。
- [x] 2.4 接入模型管理器的管线缓存、切换、Clear Models、取消与 OOM 释放;验证完整任务各组件的最后使用点和多帧行为。
- [x] 2.5 实测 0.7 的 512、1024 和多 tile 输出,记录加载时间、端到端冷暖耗时、连续帧耗时及峰值显存/主机内存,确认阶段调度消除双 UNet 常驻。
## 3. 模型选项与统一倍率
- [x] 3.1 将最终 PiSA-SR 文件及 SHA256、尺寸、来源加入 catalog 和模型同步工具,覆盖多文件下载、损坏校验与就绪判定。
- [x] 3.2 将三个旧模型的完整原生 4× 输出以 Lanczos 缩至 2×,保留原生 shape 校验;测试结果与先完整 4× 再缩半的基线一致。
- [x] 3.3 在公共 Upscale 入口按模型分派,统一输入限制及最终 alpha 回填,覆盖生产与 Debug 两种路径。
- [x] 3.4 新增 PiSA-SR 选项和 0.7 说明,更新 Operator 最终倍率、尺寸计算及所有相关 4× 行为提示,保留现有模型 key 与默认选择。
## 4. 验收
- [x] 4.1 覆盖四模型最终尺寸、连续两次 2×、输入限制、透明度、帧顺序、取消与资源错误的必要回归测试。
- [x] 4.2 在 Blender 中验证模型选择、准备模型、图片替换与撤销,对样图、文字、半透明边缘和短序列目视检查细节、接缝及闪动。
- [x] 4.3 运行相关测试及 `uv run pytest`;依赖或 Manifest 如有变更,核对锁文件与打包测试。记录实际设备验证范围及未解决问题。

View File

@@ -0,0 +1,32 @@
## 实施结果
四个 Upscale 选项统一输出 2×。PiSA-SR 固定像素强度 1.0、语义强度 0.7;旧模型完成原生 4× 拼接后使用 Lanczos 缩半。默认模型与现有 key 保持有效。
PiSA-SR 使用 512 输出 tile、128 像素重叠。固定 seed 42 的 64×64 latent 噪声作为 noise.npy 分发,按整图坐标周期索引,重叠区域使用相同噪声。中间 latent 与像素预测存入任务临时目录,GPU 同时只加载一个组件;最终颜色校正在整图拼接后执行。
正式导出器从固定源码、基础权重和 LoRA 重新生成的四个 ONNX 文件与实验图逐文件 SHA256 相同。发布资产另外写入许可和修改元数据,并随包提供 Apache 2.0、CreativeML Open RAIL++-M 与 NOTICE。最终 8 个文件已上传 R2;远端大小核对零差异,应用实际下载函数完成 noise.npy 的下载与 SHA256 校验。
## 验证
- `uv run --no-sync pytest -q`:680 passed、2 xfailed、60 subtests passed。
- 两张 0.7 样图,DirectML 与 PyTorch 最终成品平均绝对差异分别为 0.693、0.596 个 8-bit 灰度级;CPU 为 0.257、0.569。
- DirectML 测试覆盖 1024×1024、1114×1518、1026×514 和 2×6 输出;完整主体、渐变的目视检查未见明显拼接线。
- 三帧轻微平移、文字和半透明边缘通过生产入口验证;alpha 与源 alpha 直接 Lanczos 放大完全一致。细纹理随帧有变化,文字出现生成型模型的笔画变化。
- Blender 4.5.3 实际 Python 接口验证四个模型枚举、Operator 注册、结果尺寸与图片替换;真实 Undo 测试恢复原图尺寸和像素。窗口菜单未通过鼠标操作,菜单与请求参数由接口测试覆盖。
## 速度与设备
RTX 5070 Ti、其他 GPU 应用同时运行。计时包含阶段加载、采样、拼接和颜色校正;不含模型下载。
| DirectML 输出 | 完整耗时 |
| --- | --- |
| 512 首次 | 5.24 秒 |
| 512 重复 | 4.67 秒 |
| 1024 | 5.55 秒 |
| 三帧逐帧 | 每帧 4.79–5.05 秒 |
采样进程 RSS 峰值约 437 MiB;显卡总占用从约 7985 MiB 到峰值 11930 MiB,包含其他应用,不能视作本进程独占显存。阶段加载约占单张 512 耗时的大部分。
DirectML 和 CPU 完整出图。独立 CUDA ONNX Runtime 1.24.4 配合 torch 2.7.1 的 cuDNN 9.7.1 在本机 VAE 卷积上报 `No valid engine configs for ConvFwd`;该组合未通过 CUDA 验收,运行错误明确提示改选 DirectML 或 CPU,关闭 Session 的运行中隐式回退。CoreML 无可用测试设备,当前 PiSA-SR 明确提示选择 CPU。Windows 的既有生产路径使用 DirectML。
实验日志、输出图片和各阶段计时在 `build/upscale-explore/pisa-research/`。项目运行时依赖与 Manifest 未修改。

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-08

View File

@@ -0,0 +1,77 @@
## Context
普通 Plane 的 `create_mesh_plane_mesh()` 创建中心四边形和完整 UV,`O Mesh Plane` 负责矩形细分。现有 Depth Plane 使用固定底面的浮雕置换;Depth Cutout 的曲面分支使用相机 XYZ 投影。整图 Job 已通过通用 Artifact 层执行一次 MoGe-2 推理,该层支持 VECTOR Depth。
Cutout 的双击入口集中在 `SelectCutoutSelection.invoke()`、`full_image` Property 和 WorkspaceTool keymap。工作区中的 Cutout Shape 重组仍在进行,本提案以当前文件中的实际实现为基线。
## Goals / Non-Goals
本次目标是建立独立的整图 Depth Surface 转换,并让 Cutout 通过套索提交区域。Depth Surface 的用户控制固定为 Subdivide、Thickness、Depth Scale、Reference Depth。
## Decisions
### 入口与命名
采用 `ConvertToDepthSurface`、`anyimage.convert_to_depth_surface`、界面文字 **Convert to Depth Surface** 和资产名 `O Image Depth Surface`,表达输出是相机投影曲面。菜单中的顺序为 Plane、Depth Plane、Depth Surface,现有 Depth Plane 继续承担固定底面浮雕。
Cutout 直接使用共享拖动 keymap,删除双击整图绑定、`full_image` 声明和完整矩形 Selection 构造代码;`invoke()` 仅记录 Pie Event 后启动共享手势。清理因此失去用途的 import 和测试夹具。
### 整图生成主链
```mermaid
flowchart TD
Image[Image Empty] --> Convert[Convert to Depth Surface]
Convert --> Check[静态图片与 AI 环境检查]
Check --> Job[整图 Depth Job:VECTOR 模式]
Job --> Prediction[一次 MoGe-2 推理]
Prediction --> Files[完整 Color、vector-depth.exr、depth.json、tangent-normal.png]
Files --> Load[主线程加载并 Pack 深度与法线]
Load --> Mesh[共用矩形 Mesh、中心矩阵与材质]
Mesh --> Modifier[加载 O Image Depth Surface]
Modifier --> Result[替换源 Empty 并创建一个 Undo 步骤]
```
在现有整图 Job 上增加明确的深度产物选择,Depth Plane 使用 Z,Depth Surface 使用 VECTOR;两者均从一次预测生成 Tangent Normal。Blender 侧将转换类型随请求保存至响应阶段,据此选择节点组和结果标识。复用 `common` 的图片加载、深度尺度、材质与对象替换函数;Server 只引用自身目录内的共享 Artifact 层。
### 基础网格与节点接口
Depth Surface 使用 `create_mesh_plane_mesh()` 和 `build_mesh_plane_matrix()`,保持整张图片的矩形边界、中心原点、UV 和材质槽。节点内部调用 `O Mesh Plane`,以 Thickness 0 生成基础曲面;同一 Subdivide 下,它与普通 Plane 的零厚度网格具有相同顶点、面连接与 UV。Alpha 参与材质显示,模型 Validity 用于数据有效性处理,几何始终覆盖完整矩形。
| 输入 | 默认值 | 语义 |
| --- | --- | --- |
| Subdivide | 6,范围 0–10 | 沿用 O Mesh Plane 的细分 |
| Thickness | 0,最小 0 | 均匀曲面壳厚度,DISTANCE |
| Depth Scale | 1,最小 0 | 平面到相机曲面的缩放,可大于 1 |
| Reference Depth | Metadata reference_depth × Uniform Scale | 局部深度基准,DISTANCE,放在 Options |
Geometry 为结构输入;Depth Image 与 Uniform Scale 为隐藏数据输入。所有修改器输入使用 SINGLE。
### 投影与厚度
沿用 Depth Cutout 的 VECTOR Depth 坐标约定:将采样相机 XYZ 乘以 Uniform Scale,翻转 Y 得到局部 XY,局部 Z 为 `(Reference Depth − scaled_camera_z) × Depth Scale`。局部 XY 从基础矩形位置按 Depth Scale 插值到缩放后的相机 XY;0 为原平面,1 为完整投影,大于 1 为外推。Reference Depth 使用与采样相同的局部单位。
```mermaid
flowchart TD
Base[O Mesh Plane 零厚度矩形细分] --> Projection[相机 XY 插值与相对 Z 深度]
Texture[VECTOR Depth × Uniform Scale] --> Projection
Projection --> Thickness{Thickness}
Thickness -- 0 --> Surface[单层曲面]
Thickness -- 大于 0 --> Shell[沿曲面法线生成均匀壳并连接外边界]
Surface --> Output[保留 UV 与材质,清理临时属性]
Shell --> Output
```
提取现有曲面分支中可复用的投影、均匀厚度节点构建函数,按业务职责集中在共用构建模块;新组只组合自身需要的步骤。零厚度保持单层矩形拓扑,正厚度保留投影正面、沿内侧扩展背面并连接四周。厚度方向和法线处理与现有 Uniform Depth Surface 一致。
### 验证边界
以合成相机 XYZ 纹理验证投影和坐标方向,用相同 Subdivide 的普通 Plane 对照基础拓扑与 UV;使用非方图、偏移 Image Empty、旋转缩放矩阵验证定位。检查四项可见参数、隐藏数据输入、SINGLE、材质槽和临时属性清理。
节点布局按实际 Blender 绘制尺寸检查总览和局部,几何主链连续、计算支线就近接入。实现阶段按项目总则只运行测试;资产构建、资产视觉验收和节点资产文档同步作为后续发布准备,当前提案不执行构建。
## Risks / Trade-offs
- 相机纹理的 Y 方向或中心对齐错误会使结果镜像、偏移 → 使用带非中心主点的合成相机数据验证,并保持与现有 Depth Cutout 相同的投影公式。
- 深度不连续处的矩形面会被拉伸 → 将连续矩形拓扑作为明确输出约定,用阶跃深度验证连接关系稳定。
- 新增类型和共享 Job 分支可能影响现有转换 → 检查注册与逆序注销、Z/VECTOR 产物选择、单次推理及 Undo 回归。
- 工作区同时调整 Cutout 节点 → 实施前核对当前构建函数和 Shape 设置,在现有修改基础上提取共用步骤。

View File

@@ -0,0 +1,30 @@
## Why
整图相机投影曲面需要与普通 Plane 一样稳定的矩形基础网格,以及少量直接的深度控制。将它作为独立转换入口,也让 Cutout 的交互集中在用户圈选区域。
## What Changes
- **BREAKING**:完全删除 Cutout 双击整图生成入口,包括快捷键、`full_image` 属性和整图 Selection 构造分支。
- 新增 **Convert to Depth Surface**,与 Convert to Plane、Convert to Depth Plane 并列,用完整图片生成相机投影深度曲面。
- 新增 `O Image Depth Surface`:基础网格复用普通 Plane 的矩形、UV、中心原点和 `O Mesh Plane` 细分,只公开 `Subdivide`、`Thickness`、`Depth Scale`、`Reference Depth` 四项用户参数。
- 相机投影沿用 Depth Cutout 的坐标与深度缩放语义;厚度采用均匀曲面壳,默认零厚度。
- 整图转换复用现有 MoGe-2 单次推理、材质与对象替换流程。
## Capabilities
### New Capabilities
- `projected-depth-surface`: 整图 Depth Surface 转换、矩形基础网格、相机投影和精简节点接口。
- `cutout-lasso-entry`: Cutout 通过有效套索进入 Shape 选择,彻底移除双击整图入口。
### Modified Capabilities
无。当前 `openspec/specs/` 尚无已归档规范;本次独立规定新增及调整后的行为。
## Impact
- `operators/cutout_tool/main.py` 及其交互测试。
- `operators/convert_to_plane/`、`menu.py`、`__init__.py` 的转换入口、结果创建与类型注册。
- `common/depth.py` 等共用深度数据处理;按需扩展整图 Job 的产物选择,保持后端模块边界。
- `tools/node_assets/` 的构建和验证、新节点组及节点测试;实施阶段按项目约束执行测试,节点资产构建和产物更新单独安排。
- 无新增第三方依赖;实现以当前工作区为基线,衔接正在进行的 Cutout Shape 调整。

View File

@@ -0,0 +1,23 @@
## ADDED Requirements
### Requirement: Cutout starts shape generation from a lasso
Cutout SHALL 在用户提交有效套索后打开 Shape Pie Menu,并将圈选路径传给 Shape 生成入口。
#### Scenario: Submit a lasso
- **WHEN** 用户在 active Image Empty 上完成有效 Cutout 套索
- **THEN** 系统打开当前可用 Shape 菜单并传递该套索路径
### Requirement: Full-image double-click entry is removed
系统 MUST 删除 Cutout 的双击整图 keymap、`full_image` Property、整图 Selection 构造分支及专属调用代码。双击 MUST NOT 打开整图 Shape 菜单或提交整图生成任务。
#### Scenario: Double-click an image
- **WHEN** Cutout 已激活,用户在 Image Empty 上双击且未形成有效套索
- **THEN** 不打开 Shape 菜单、不创建对象、不提交生成 Job
#### Scenario: Double-click viewport space
- **WHEN** active Image Empty 存在,用户在图片外空白区域双击
- **THEN** 不启动整图 Cutout,选择处理沿用共享图片手势规则
#### Scenario: Inspect registration
- **WHEN** 检查 Cutout 的 Operator Property 和 WorkspaceTool keymap
- **THEN** 不存在 `full_image` 或用于整图生成的 `DOUBLE_CLICK` 绑定

View File

@@ -0,0 +1,85 @@
## ADDED Requirements
### Requirement: Full-image depth surface has a conversion entry
系统 SHALL 提供 `anyimage.convert_to_depth_surface`,界面显示 Convert to Depth Surface,与 Plane、Depth Plane 并列;该入口 SHALL 从当前静态 Image Empty 创建完整图片的相机投影曲面。
#### Scenario: Convert a still image
- **WHEN** 当前 Image Empty 是静态图片且 AI 环境可用
- **THEN** 执行一次完整图片转换,成功后结果沿用源对象名称并替换源 Empty
- **AND** 一次 Undo 恢复转换前状态
#### Scenario: Reject unsupported media
- **WHEN** 输入为多帧 Movie 或 Sequence
- **THEN** 提示仅支持静态图片,不提交推理任务
#### Scenario: AI setup is required
- **WHEN** AI 环境未就绪
- **THEN** 沿用现有 AI 设置流程,源 Empty 保持可用
### Requirement: Base geometry matches Plane conversion
Depth Surface SHALL 使用普通 Convert to Plane 的基础 Mesh 创建、中心矩阵、UV 和 O Mesh Plane 细分。相同 Subdivide 下投影前零厚度几何 MUST 与普通 Plane 的零厚度几何一致。整图矩形拓扑 SHALL 覆盖透明区域及深度跳变区域。
#### Scenario: Compare planar meshes
- **WHEN** 对同一图片以相同 Subdivide 创建普通 Plane 和 Thickness 0、Depth Scale 0 的 Depth Surface
- **THEN** 两者顶点位置、面连接、UV 和材质索引一致
#### Scenario: Preserve placement
- **WHEN** 源 Image Empty 具有非中心显示偏移以及平移、旋转、缩放
- **THEN** Depth Scale 0、Thickness 0 的结果四角与源显示矩形的世界空间四角一致
- **AND** 对象原点位于显示矩形中心
#### Scenario: Preserve rectangular coverage
- **WHEN** 图片包含透明孔洞或纹理深度跳变
- **THEN** 基础网格仍为完整矩形细分,Alpha 由材质表达
### Requirement: Surface controls are limited to four parameters
`O Image Depth Surface` SHALL 只公开 Subdivide、Thickness、Depth Scale、Reference Depth 四项用户控制。默认值 SHALL 分别为 6、0、1 和 Metadata reference_depth 乘以 Uniform Scale。Geometry SHALL 为结构输入,Depth Image 与 Uniform Scale SHALL 为隐藏数据输入。输入 MUST 使用 SINGLE;Thickness、Reference Depth MUST 使用 DISTANCE。
#### Scenario: Inspect a new modifier
- **WHEN** 创建 Depth Surface 修改器
- **THEN** 用户看到规定的四项控制,Reference Depth 位于 Options
- **AND** 不出现 Cutout 的 Mode、Split、Balloon、Inflation、轮廓或轴向控制
### Requirement: Geometry follows camera projection
Depth Surface SHALL 按现有 Depth Cutout 的相机 XYZ 坐标约定投影。采样 XYZ 乘以 Uniform Scale 后,XY SHALL 以 Depth Scale 从基础平面插值至相机 X、负相机 Y;Z SHALL 为 `(Reference Depth − scaled_camera_z) × Depth Scale`。
#### Scenario: Full projection
- **WHEN** Thickness 为 0、Depth Scale 为 1,输入合成相机 XYZ 纹理
- **THEN** 每个顶点的位置符合相机投影公式,包括 Y 方向与深度基准
#### Scenario: Adjust depth strength
- **WHEN** Depth Scale 分别为 0、0.5、1 和大于 1 的值
- **THEN** XY 与 Z 按同一缩放语义连续变化,0 恢复基础平面,大于 1 正常外推
#### Scenario: Adjust reference depth
- **WHEN** Reference Depth 增加局部距离 d,Depth Scale 为 s
- **THEN** 曲面 Z 增加 d × s,投影 XY 保持不变
### Requirement: Thickness forms a uniform surface shell
Thickness 为 0 时系统 SHALL 输出单层曲面;Thickness 大于 0 时 SHALL 保留投影正面,按现有 Uniform Depth Surface 的法线厚度语义向内生成背面并连接矩形边界。
#### Scenario: Zero thickness
- **WHEN** Thickness 为 0
- **THEN** 仅存在一层曲面,无重复背面或退化侧壁
#### Scenario: Positive thickness
- **WHEN** 对平坦深度输入设置正 Thickness
- **THEN** 正背面沿法线距离等于 Thickness,边界闭合且法线朝向一致
### Requirement: One prediction produces complete image artifacts
整图 Depth Surface SHALL 通过共用 Artifact 层执行一次 MoGe-2 推理,生成 VECTOR Depth、Metadata 与 Tangent Normal,并保留完整 Color。Blender SHALL 在主线程加载、Pack 并设置图片色彩空间,将 Normal 用于材质,将 VECTOR Depth 用于几何。
#### Scenario: Complete a generation job
- **WHEN** 整图 Depth Surface Job 成功
- **THEN** 只执行一次推理,并返回 `vector_depth`、`depth_metadata`、`tangent_normal` 及完整颜色产物
#### Scenario: Preserve existing depth plane generation
- **WHEN** 用户执行现有 Convert to Depth Plane
- **THEN** 继续生成 Z Depth 与 Tangent Normal,并创建固定底面浮雕
### Requirement: Node assets preserve geometry data
新节点组 SHALL 从 `assets/O_AnyImage.blend` 按名称加载。节点求值 SHALL 保留 UV 与第 0 个材质槽,并清理自身临时属性;构建验证 SHALL 检查接口、实际几何与 Blender 中的节点布局。
#### Scenario: Evaluate the asset
- **WHEN** 加载并求值 `O Image Depth Surface`
- **THEN** 结果保留 UV、用户属性和材质,不残留自身 `o_depth_*` 临时属性

View File

@@ -0,0 +1,24 @@
## 1. 删除 Cutout 双击整图入口
- [ ] 1.1 删除 Cutout 的 DOUBLE_CLICK 整图绑定、full_image Property、整图 Selection 分支及失去用途的 import,保留共享套索交互。
- [ ] 1.2 调整交互和注册测试,验证图片内外双击均不打开 Shape 菜单或提交任务,有效套索继续生成 Shape。
## 2. 新增整图 Depth Surface 转换
- [ ] 2.1 增加 ConvertToDepthSurface、菜单入口和正逆序注册,验证静态图片、AI 环境及忙碌状态检查。
- [ ] 2.2 扩展共用整图 Job 的 Z/VECTOR 产物选择及 Blender 响应分派,保持普通 Depth Plane 的 Z 路径;验证 VECTOR Depth 和 Tangent Normal 来自一次推理。
- [ ] 2.3 复用 common 的图片、深度、材质及对象收尾函数创建 Depth Surface;共用 Plane 的基础 Mesh 和中心矩阵,初始化四项参数及隐藏深度数据。
- [ ] 2.4 验证完整颜色、材质槽、深度与法线 Pack、源对象替换、失败清理和单步 Undo。
## 3. 构建定义与几何验证
- [ ] 3.1 按业务职责提取共用相机投影和均匀厚度构建步骤,新增 O Image Depth Surface 构建定义,并接入节点组构建和验证索引。
- [ ] 3.2 以 O Mesh Plane 的零厚度输出生成完整矩形基础网格,设置 Subdivide、Thickness、Depth Scale、Reference Depth 以及隐藏数据接口,检查 SINGLE 与 socket subtype。
- [ ] 3.3 增加合成纹理几何测试:同级 Plane 拓扑与 UV 对照、Depth Scale 0/0.5/1/>1、Reference Depth、相机 Y 方向和非中心主点。
- [ ] 3.4 增加零厚度单层、正厚度闭合、透明区域完整矩形、深度跳变连接、材质和临时属性清理验证。
- [ ] 3.5 编排新节点组布局与验证入口,覆盖未用输出隐藏、主链及支线间距;记录发布准备时所需的实际绘制尺寸视觉验收项目。
## 4. 回归与交付检查
- [ ] 4.1 运行相关转换、交互、注册、Server Job 和节点构建定义测试,修复回归;检查现有 Depth Plane 和圈选 Cutout 的行为。
- [ ] 4.2 运行 uv run pytest,记录测试结果及需要 Blender 或已构建新资产才能完成的验收项。按项目总则,代码实施只运行测试,资产构建、二进制产物和节点资产文档同步留给发布准备。

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-07

View File

@@ -0,0 +1,89 @@
## Context
当前 `shape.py` 将四种形态映射为四个子组,再由 `O Image Cutout` 用 Shape 菜单选择。菜单统一传入 Normal Map 勾选值;`normal_mode_for_shape()` 仅在勾选时为 Depth Surface 选择 OBJECT,其余形态使用 TANGENT。
`build/cutout_surface_balloon/surface-balloon-smooth-back.blend` 已验证五张输入、15 个参数组合;背面算法、控制测试与实际节点布局可作为实施参考。当前工作区也已修正前置 Cleanup 和不依赖 Depth Scale 的 Split,实施从这些修正继续。
## Goals / Non-Goals
**Goals:** 四个明确的创建预设,三个独立修改器节点组,统一厚度语义,深度入口自动生成法线,保留已验证的几何质量。
**Non-Goals:** 本次范围限定在 Cutout 的创建、节点资产与材质连接;AI 模型、图像区域交互和其他工具沿用现有职责。
## Decisions
### 创建预设与节点资产分离
| 入口 / 内部标识 | 节点组 | 初始设置 |
| --- | --- | --- |
| Flat / FLAT | O Image Cutout | Balloon,Thickness 0 |
| Solid / SOLID | O Image Cutout | Balloon,Thickness 1 |
| Depth Solid / DEPTH_SOLID | O Image Depth Cutout | Balloon,Thickness 1 |
| Depth Balloon / DEPTH_BALLOON | O Image Depth Balloon | Thickness 1,Double Sided 开启 |
Solid 是新创建的默认预设,Pie 保持四个选择。Flat 和 Solid 使用同一基础网格属性与节点组,创建后通过厚度即可转换。预设名称用于菜单、对象命名与 Operator 协议;资产名称仅用于按名称加载。
三个节点组直接设置为修改器资产,各自输出最终几何。删除总 Shape 分支及 `O Image Surface`、`O Image Balloon`、`O Image Depth Surface` 旧资产。复用构建函数展开公共步骤,避免为了共享代码再建立总包装组。保留 `Inward Axis` 的几何与对象矩阵配对转换。
### 两种厚度方式
`O Image Cutout` 和 `O Image Depth Cutout` 使用 `Thickness Mode` 菜单,顺序为 Balloon、Uniform,默认 Balloon。Balloon 的 Thickness 是无量纲倍率,Uniform 的厚度是距离;输入显示与保存必须区分两种语义,距离 socket 使用 DISTANCE,倍率使用 NONE。具体 socket 组织在实现时按 Blender 修改器接口能力选择,验收必须确认用户能辨认单位,切换时不发生隐式单位换算。
普通 Cutout 的 Balloon 模式使用正背面 `±o_balloon × Thickness`;Uniform 使用当前 Surface 的等厚板片行为。两种方式在零厚度时均返回单层平面。全部预设都准备 `o_balloon`,即使以 Flat 创建也能直接增厚。
深度 Cutout 保留当前 Depth Surface 的采样、射线投影与 Split;Uniform 保留沿内向轴等厚的正背面。Balloon 采用实验中的平滑背面,两种方式零厚度均返回深度表面。
### 平滑背面进入正式构建
```mermaid
flowchart TD
A[基础网格和 o_balloon] --> B[Cleanup 按原平面岛面积清理]
B --> C[原始深度判断 Split]
C --> D[相机射线修正与深度投影]
D --> E[估计并平滑中心位置]
E --> F[生成正背面及切口侧壁]
F --> G[边缘平滑与整体 Smooth]
G --> H[清理暂存属性与轴向输出]
```
令 D 为投影后正面 Z,B 为 o_balloon。以 `C₀ = D − B` 初始化中心位置,固定原轮廓和 Split 切口上的值,仅对内部执行 256 次邻域平滑。Thickness 为 1 时目标背面为 `C − B`;一般厚度场为 `Thickness × max(D − C + B, 0.05 × B)`。比例下限用于限制深凹处反穿,原轮廓 B 为零时厚度仍归零,不引入 Rim Thickness。
复用原型中对轮廓耳三角形、内部零轮廓弦的补点方法,保证封闭轮廓不会产生零面积面。通过来源顶点和厚度层身份连接几何,Split 两侧保持独立;正面在边缘和整体平滑关闭时保持原始深度表面位置。
保留原型的 Edge Smooth 控制与抑制轮廓收缩的平滑过程,整体 Smooth 复用项目实现。临时属性使用 o_* 专用前缀并在输出前移除,保留 UVMap、o_balloon 和用户属性。默认参数及平滑成本用五张缓存输入复验。
### 每个节点组承担自己的公共处理
三个资产复用同一 Cleanup 构建函数,在塑形前按原平面岛总面积清理;UI 值继续乘 0.01 转为面积。Smooth 与轴向输出在各自塑形后执行。仅深度 Cutout 提供 Split;比较式继续为 `abs(原始相邻面 Z 差) × Uniform Scale × Split > 原始面中心距离 × 2.5`,Depth Scale 只参与后续显示位移。
### 法线策略在 Operator 层统一解析
| 入口 | 勾选关闭 | 勾选开启 |
| --- | --- | --- |
| Flat | NONE | TANGENT |
| Solid | NONE | TANGENT |
| Depth Solid | OBJECT | OBJECT |
| Depth Balloon | TANGENT | TANGENT |
统一解析函数同时供 Job 构建和结果接收使用,保证直接调用 Operator 与 Pie 调用一致。深度入口的自动生成不会改写用户保存的勾选值。工具提示说明 Normal Map 仅控制 Flat / Solid;AI 未就绪时仍只提供两个本地入口,并忽略遗留的开启值。
复用现有法线结果加载、材质连接与轴向变换。Flat 与 Solid 共用节点后,法线的 Balloon 适配不得仅由创建时的预设名决定;按当前厚度方式和几何属性处理,验证 Flat 增厚后材质仍正确。Depth Solid 保留 OBJECT 法线的方向转换,Depth Balloon 保留 TANGENT 法线的适配。
Depth Solid 在 FACE 域保存正面法线权重 1,背面与侧壁为 0;材质读取该权重,使平滑背面使用几何法线。法线权重作为公开材质属性保留在输出网格中。
## Risks / Trade-offs
- 平滑中心场会弱化内部深度细节 → 正面保留原深度,背面用已验证的轮廓约束;通过合成曲面与五张实图同时验收。
- 迭代与闭合细分增加成本 → 使用固定初始迭代数,测量默认预设求值时间;字段就近存取,避免重复推理与重复求值。
- 同名 `O Image Cutout` 的资产职责改变 → 加载路径按新结构校验,避免复用已加载的旧 Shape 包装组;旧 .blend 中嵌入的数据保持原样,新创建对象使用新资产。源码不保留旧标识转发或迁移兼容层。
- 法线图随默认预设开启后的材质效果可能不同 → 分别验证两个深度入口的正背面着色及两个 Inward Axis。
## Migration Plan
按标识和默认值、节点构建、运行时加载与材质、验证的顺序实施。发布资产只保留三个 Cutout 节点组;同步删除旧构建和验证分支。需要回退时整体恢复源码与对应资产,避免新旧接口混装。
未归档的 `gate-cutout-ai-options`、`replace-depth-surface-stretch-with-split` 和 `standardize-cutout-z-axis` 涉及本次边界。未来归档时以本提案的入口名称、直接修改器架构、前置 Cleanup 和原始深度 Split 要求为准,同时保留 AI 门控与轴向约定;不回退当前工作区已完成的修复。
## Open Questions
无产品决策待确认。厚度输入的具体展示方式属于实施细节,须满足倍率与距离可辨认的验收要求。

View File

@@ -0,0 +1,32 @@
## Why
Cutout 当前将四种形态封装在一个总节点组中,创建入口与几何算法一一绑定。已经验证的平滑 Balloon 背面适合成为深度实体的默认厚度,需要将四个创建预设与三个几何节点组分开,并明确法线生成规则。
## What Changes
- 创建入口确定为 `Flat`、`Solid`、`Depth Solid`、`Depth Balloon`,默认形态为 Solid。
- **BREAKING**:以 `O Image Cutout`、`O Image Depth Cutout`、`O Image Depth Balloon` 三个可直接用于修改器的节点组替代总 Shape 切换器与四个子组,移除旧节点名称和 Shape 菜单协议。
- Flat 与 Solid 共用 `O Image Cutout`,分别以 Thickness 0 和 1 创建;普通与深度 Cutout 均提供 Balloon / Uniform 两种厚度方式,默认 Balloon。
- Depth Solid 使用经过五张图验证的新背面算法,保留正面深度位置,背面按平滑中心位置与 o_balloon 构造;Uniform 保留等厚 Depth Surface 行为。
- Depth Balloon 保留原塑形算法,默认开启 Double Sided。
- 三个节点组各自提供适用的 Cleanup、Smooth 和轴向输出;深度 Cutout 保持 Cleanup 在 Split 前、Split 使用原始深度差的修正。
- Normal Map 勾选仅控制 Flat 与 Solid;Depth Solid 与 Depth Balloon 始终生成并使用各自所需的法线图。
## Capabilities
### New Capabilities
- `cutout-shape-presets`: 四个入口、三个节点组、创建默认值与两种厚度方式。
- `depth-cutout-volume`: 深度表面上的平滑 Balloon 背面、等厚模式、清理分离及闭合行为。
- `cutout-normal-policy`: 按入口选择法线生成策略,保持 AI 可用性约束及材质连接正确。
### Modified Capabilities
无。当前 `openspec/specs/` 尚无已归档规范;本提案记录完整目标要求,并在设计中说明与现有未归档变更的关系。
## Impact
- `src/anyimage/operators/cutout_tool/` 的形态标识、菜单、节点加载、默认参数、法线策略和材质绑定,以及 Cutout 工具属性。
- `tools/node_assets/` 的构建、布局与验证;`src/anyimage/assets/O_AnyImage.blend` 中的 Cutout 资产。
- Cutout 交互、Job 参数、网格求值和节点资产测试,以及节点资产说明。
- 原型位于 `build/cutout_surface_balloon/`,实施时将必要算法纳入正式源码。无需新增依赖。

View File

@@ -0,0 +1,45 @@
## ADDED Requirements
### Requirement: Normal Map 勾选仅控制本地形态
Normal Map 勾选 SHALL 仅控制 Flat 和 Solid 的法线生成;两个 Depth 入口 SHALL 始终生成并使用法线图,且不改写用户保存的勾选值。工具说明 SHALL 明确该作用范围。
#### Scenario: Flat 与 Solid 关闭法线
- **WHEN** AI 可用且勾选关闭,用户创建 Flat 或 Solid
- **THEN** 系统使用 NONE 法线模式
#### Scenario: Flat 与 Solid 开启法线
- **WHEN** AI 可用且勾选开启,用户创建 Flat 或 Solid
- **THEN** 系统请求 TANGENT 法线并连接结果材质
#### Scenario: Depth Solid 自动法线
- **WHEN** 用户创建 Depth Solid,无论勾选保存为真或假
- **THEN** 系统请求 OBJECT 法线并正确加载、按输出轴向处理和连接材质
#### Scenario: Depth Balloon 自动法线
- **WHEN** 用户创建 Depth Balloon,无论勾选保存为真或假
- **THEN** 系统请求 TANGENT 法线并连接结果材质
### Requirement: 所有调用路径采用一致策略
法线策略 SHALL 在 Operator 业务层统一解析,Job 参数与结果接收使用同一策略。
#### Scenario: 绕过 Pie 调用
- **WHEN** 直接调用 Operator 创建任一 Depth 形态并传入 generate_normal 为 false
- **THEN** 法线仍按该深度入口生成和应用,与 Pie 调用结果一致
### Requirement: AI 可用性继续限制入口
AI 未就绪时系统 SHALL 仅提供 Flat 与 Solid,忽略遗留的开启法线选项;AI 就绪时 SHALL 提供四个入口。
#### Scenario: 未就绪的本地创建
- **WHEN** AI 未就绪、保存的 Normal Map 为真,用户创建 Flat 或 Solid
- **THEN** 创建过程不因该遗留值启动 AI Job,法线模式为 NONE
### Requirement: 法线适配跟随当前几何
Flat 与 Solid 共用节点组后的法线适配 SHALL 支持厚度变化,Depth 入口 SHALL 保持各自法线空间和轴向转换正确。
#### Scenario: Flat 增厚
- **WHEN** 带法线的 Flat 调整为 Balloon 正厚度
- **THEN** 材质按当前几何参与法线适配,不因初始 Flat 预设而缺失 Balloon 所需连接
#### Scenario: 深度入口轴向与双面
- **WHEN** 分别检查两个 Depth 入口的 -Z、+X 输出,以及 Depth Balloon 的 Double Sided 开关
- **THEN** 对应法线图被正确加载和连接,前后表面的着色方向与几何一致

View File

@@ -0,0 +1,56 @@
## ADDED Requirements
### Requirement: 四个创建入口映射三个节点组
系统 SHALL 提供 Flat、Solid、Depth Solid、Depth Balloon 四个入口,并默认使用 Solid。Flat 与 Solid SHALL 共用 O Image Cutout;Depth Solid SHALL 使用 O Image Depth Cutout;Depth Balloon SHALL 使用 O Image Depth Balloon。
#### Scenario: 普通默认创建
- **WHEN** 用户以默认形态创建 Cutout
- **THEN** 对象使用 O Image Cutout,Thickness Mode 为 Balloon,Thickness 为 1
#### Scenario: 显式选择入口
- **WHEN** 用户分别选择四个入口
- **THEN** 系统按上述映射加载三个资产,Flat 的 Thickness 为 0,另外三个入口的 Thickness 为 1
### Requirement: 三个节点组直接输出最终几何
三个 Cutout 节点组 SHALL 可直接作为 Geometry Nodes 修改器使用,并承担各自的清理、塑形、平滑与轴向输出。发布资产 MUST 移除旧 Shape 总切换器及旧 Surface、Balloon、Depth Surface 子组。
#### Scenario: 检查新建修改器与发布资产
- **WHEN** 新建任一 Cutout 并检查其修改器与资产
- **THEN** 修改器直接引用对应节点组,不存在跨四种形态的 Shape 输入;Cutout 资产集合恰为三个指定节点组
#### Scenario: 输出轴向
- **WHEN** 对同一输入分别使用 -Z 与 +X 的 Inward Axis
- **THEN** 几何与对象矩阵配对转换,保持相同世界空间位置及正确朝向
### Requirement: 普通与深度 Cutout 具有双厚度方式
O Image Cutout 与 O Image Depth Cutout SHALL 提供 Balloon、Uniform 两种 Thickness Mode,默认 Balloon。Balloon 厚度 SHALL 表示倍率,Uniform 厚度 SHALL 表示距离,输入语义与单位必须明确区分。
#### Scenario: 普通平面与体积转换
- **WHEN** O Image Cutout 的 Balloon Thickness 从 0 调整到 1
- **THEN** 相同基础网格由单层平面变为当前 Balloon 的正背面体积,无需重算 AI 或重建对象
#### Scenario: 等厚板片
- **WHEN** O Image Cutout 选择 Uniform 并设置非零厚度
- **THEN** 输出当前 Surface 的等厚板片形态;厚度为零时输出单层平面
#### Scenario: 厚度单位
- **WHEN** 用户检查或切换两种 Thickness Mode
- **THEN** Balloon 的输入明确为倍率,Uniform 的输入明确为距离,不将一种单位的值隐式解释为另一种单位
### Requirement: Depth Balloon 默认双面
O Image Depth Balloon SHALL 保留原 Depth Balloon 的参考平面塑形行为,并默认开启 Double Sided。
#### Scenario: 默认与单面输出
- **WHEN** 用户创建 Depth Balloon,再关闭 Double Sided
- **THEN** 初始输出采用原算法的双面塑形,关闭后采用原算法的单面塑形,其余参数语义保持一致
### Requirement: 公共网格属性与前置清理
所有入口 SHALL 准备 o_balloon;三个节点组 SHALL 在塑形前复用按原平面岛总面积清理小区域的 Cleanup 规则,并在输出保留 UVMap、o_balloon 与用户属性。
#### Scenario: Flat 后续增厚
- **WHEN** 用户将 Flat 的 Thickness 调为正值
- **THEN** 已有 o_balloon 可直接参与塑形,UV 与材质映射保持有效
#### Scenario: 小岛清理
- **WHEN** 输入包含总面积低于 Cleanup 阈值的独立平面岛
- **THEN** 三个节点组均在塑形前删除该岛,保留大于阈值的岛

View File

@@ -0,0 +1,45 @@
## ADDED Requirements
### Requirement: 平滑背面保留空间位置
O Image Depth Cutout 的 Balloon 模式 SHALL 以投影正面减 o_balloon 估计中心位置,固定轮廓与切口并平滑内部中心场,再用该中心场与 Balloon 轮廓构造背面。关闭边缘与整体平滑时,正面 MUST 保持原深度表面位置。
#### Scenario: 带噪声的已知体积
- **WHEN** 输入正面由线性变化的中心深度、Balloon 轮廓和内部高频噪声构成,Thickness 为 1,额外几何平滑关闭
- **THEN** 背面接近中心深度减 Balloon 轮廓,背面噪声 RMS 小于正面噪声的 1%,正面顶点位置误差小于 0.00001 个局部单位
#### Scenario: 前后距离保留
- **WHEN** 输入有宽厚主体和处于不同深度的细长结构
- **THEN** 背面形成按轮廓变化的厚度,各部分保留局部前后位置,不统一回到同一个参考平面
### Requirement: 两种厚度方式保留深度表面
深度 Cutout SHALL 在 Balloon 模式使用平滑背面,在 Uniform 模式保留原 Depth Surface 的等厚行为;两种方式的零厚度 SHALL 输出单层深度表面。
#### Scenario: 零厚度
- **WHEN** 两种厚度方式分别设为零
- **THEN** 输出相同投影与 Split 结果的单层深度表面,不生成重叠背面或零面积侧壁
#### Scenario: 等厚方式
- **WHEN** 选择 Uniform 并设为正厚度
- **THEN** 正背面保持原 Depth Surface 的沿内向轴等厚关系
### Requirement: Split 独立于显示深度幅度
Split SHALL 使用原始相邻面采样 Z 差经 Uniform Scale 标定后与变形前跨度比较,Cleanup MUST 位于 Split 前;Depth Scale SHALL 仅控制投影呈现幅度。
#### Scenario: Depth Scale 不改变切边
- **WHEN** 固定输入和 Split,将 Depth Scale 依次设为 0、0.25、1、2、4
- **THEN** 零厚度输出的切边拓扑保持一致,深度位移随 Depth Scale 变化
#### Scenario: 保留分离产生的小片
- **WHEN** 原平面岛面积通过 Cleanup,但 Split 后的部分小片低于该面积阈值
- **THEN** 这些分离小片仍被保留并参与后续厚度构造
### Requirement: 厚度网格闭合且轮廓无固定厚边
正厚度网格 SHALL 在原轮廓合并正背面,并独立封闭 Split 切口;SHALL 保留原型中的深凹比例厚度下限、边缘平滑和整体 Smooth,且不提供 Rim Thickness。
#### Scenario: 五张实图验收
- **WHEN** 使用噬菌体、蜘蛛、幼虫、心脏、棕榈树缓存输入,分别求值无平滑、边缘与整体平滑、平滑加 Split
- **THEN** 15 个正厚度组合均为有限坐标、无非流形边、无法线连接错误和零面积面,输出保留 UVMap 与 o_balloon 并移除专用暂存属性
#### Scenario: 边缘与整体控制
- **WHEN** 调整 Edge Smooth、Smooth 和 Smooth Iterations
- **THEN** 相应几何平滑生效,Smooth Iterations 为零时整体平滑不改变位置,原轮廓不产生固定厚度的边框

View File

@@ -0,0 +1,30 @@
## 1. 创建预设与参数协议
- [x] 1.1 将形态标识与入口文案统一为 FLAT / Flat、SOLID / Solid、DEPTH_SOLID / Depth Solid、DEPTH_BALLOON / Depth Balloon,默认 Solid,更新 Pie 与直接 Operator 调用测试。
- [x] 1.2 建立四预设到三资产的映射及默认值,删除旧 Shape 索引协议、旧名称与转发路径,覆盖对象命名和 AI 可用性门控。
- [x] 1.3 确定并实现两个 Cutout 的 Balloon / Uniform 厚度输入,验证默认顺序、倍率与距离语义、零厚度及模式切换;距离 socket 使用 DISTANCE,输入结构使用 SINGLE。
## 2. 三个独立几何节点资产
- [x] 2.1 将 O Image Cutout 构建为直接修改器,合并普通 Balloon 与等厚 Surface 行为;所有预设准备 o_balloon,保证 Flat 可直接增厚。
- [x] 2.2 将已验证的平滑中心场、背面厚度与闭合方法纳入正式构建函数,构建 O Image Depth Cutout 的 Balloon 分支并保留 Uniform 分支。
- [x] 2.3 将原型中防止轮廓耳三角形和内部零轮廓弦退化的处理纳入合适的正式网格模块,增加针对闭合退化的求值测试。
- [x] 2.4 复用公共 Cleanup、Smooth、轴向输出与暂存属性清理;保留 Depth Cutout 的前置 Cleanup、原始深度 Split 和 Edge Smooth 控制。
- [x] 2.5 将 O Image Depth Balloon 改为直接修改器并默认 Double Sided 开启,保留其塑形和单面开关行为。
- [x] 2.6 删除总 Shape 切换器和三个旧子组资产,更新构建清单、节点加载及结构验证;处理同名旧 O Image Cutout 已加载时的新资产识别,避免复用旧接口。
## 3. Normal Map 与材质
- [x] 3.1 在业务层统一法线策略:Flat / Solid 受勾选控制,Depth Solid 固定 OBJECT,Depth Balloon 固定 TANGENT;Job 参数与结果接收共用解析。
- [x] 3.2 更新 Normal Map 工具说明,保持用户勾选值不被深度创建改写,覆盖未就绪时遗留开启值和直接调用 Operator 的测试。
- [x] 3.3 调整 Flat / Solid 共用节点后的材质法线适配,验证从 Flat 增厚以及 Balloon / Uniform 切换时的连接。
- [x] 3.4 验证两个深度入口的法线结果加载、材质连接、双面着色与 Inward Axis 转换。
## 4. 求值与视觉验收
- [x] 4.1 更新接口、默认值、资产集合和几何测试,覆盖三资产直接输出、普通与深度零厚度、Uniform 等厚、Depth Balloon 默认双面。
- [x] 4.2 保留 Cleanup 在 Split 前和 Depth Scale 0 / 0.25 / 1 / 2 / 4 不改变切边拓扑的回归测试。
- [x] 4.3 用已知中心深度加 Balloon 轮廓与噪声的合成曲面验证平滑背面、正面保留及参考深度平移。
- [x] 4.4 复用五张缓存输入,在独立 Blender 脚本中检查 15 个平滑与分离组合的闭合、退化、属性保留和求值时间;渲染背面与侧面,对照已接受原型,不直接控制用户 Blender。
- [x] 4.5 在独立 Blender 节点编辑器按实际绘制尺寸检查三个节点组的总览与局部,验证主轴、重复区域、socket 顺序和未使用输出隐藏。
- [x] 4.6 同步节点资产说明,重建 O_AnyImage.blend,运行全部节点验证和项目测试,记录结果;核对相关未归档规范在后续归档时采用本提案的目标行为。

View File

@@ -0,0 +1,24 @@
# 验收记录
2026-09-07,Windows;资产构建与独立节点编辑器使用 Blender 4.5.10 LTS,Python 求值与测试使用 bpy 4.5.3。
## 自动验证
- `tools/node_assets/build.py` 完成资产重建;`validate.py`、`validate_mesh_plane.py`、`validate_cutout.py` 全部通过。
- 全量 pytest:664 passed、2 xfailed。覆盖四入口、三资产、双厚度模式、前置 Cleanup、原始深度 Split、闭合、背面平滑和法线策略。
- 测试完成后本地 bpy 运行时退出阶段发生原生崩溃(Windows 3221225477)。独立脚本调用 `pytest.main` 并将其返回码写入文件,确认返回 0;进程随后仍以访问冲突退出。测试断言均通过,进程退出问题保留为本地验证环境限制。
## 几何与视觉
- 噬菌体、蜘蛛、幼虫、心脏、棕榈树,共 15 个平滑与分离组合:非流形边、非流形顶点、零面积面均为 0,坐标有限,保留 UVMap 和 o_balloon。
- 与已接受原型逐对象比较,顶点和面数量一致;双向最近点最大位置差 0.00001258(图像尺度约 4)。
- 本机单次网格求值约 0.018–0.203 秒,包含依赖图更新与网格提取;用于观察成本,不作为性能保证。
- 背面、侧面和斜视渲染通过。Depth Solid 的 FACE 法线权重令贴图仅影响正面,背面与侧壁使用几何法线。
- 两个深度入口使用正式 O Image Layer 材质,检查两个 Inward Axis 的正背面法线方向渲染;归一化像素平均绝对差均小于 0.00000009。
- 独立隐藏 Blender 节点编辑器检查三组总览、中心场 Repeat 和闭合局部;实际绘制矩形无重叠。结构验证同时检查接口顺序、SINGLE 和未使用输出隐藏。
实验文件与详细 JSON、截图、日志位于 `build/cutout_surface_balloon/`;可编辑样例为 `cutout-production.blend`。以上验证复用缓存输入,未控制用户 Blender 实例。
## 归档衔接
`gate-cutout-ai-options`、`replace-depth-surface-stretch-with-split`、`standardize-cutout-z-axis` 后续归档时,采用本变更的四入口、三直接资产、前置 Cleanup 与原始深度 Split,保留 AI 门控和轴向约定。