feat(node_assets): add image plane geometry nodes and validation scripts

- Implemented `image_plane.py` to build the Image Plane Geometry Nodes group with customizable parameters for geometry, subdivide, and thickness.
- Created `image_plane_validation.py` to validate the functionality of the image plane, ensuring correct geometry generation and material assignment.
- Developed `material_layers.py` to construct shader node groups for image materials, including depth and normal handling.
- Authored `plane_layouts.py` to define node arrangements for image geometry assets.
- Introduced `shadeless.py` to create a shadeless shader node group that displays color without scene lighting while preserving shadows and reflections.
This commit is contained in:
2026-09-08 23:24:27 +08:00
parent 196b964efc
commit 4c902ed7db
155 changed files with 9700 additions and 10393 deletions

View File

@@ -6,7 +6,7 @@ Cutout 的双击入口集中在 `SelectCutoutSelection.invoke()`、`full_image`
## Goals / Non-Goals
本次目标是建立独立的整图 Depth Surface 转换,并让 Cutout 通过套索提交区域。Depth Surface 的用户控制固定为 Subdivide、Thickness、Depth Scale、Reference Depth。
本次目标是建立独立的整图 Depth Surface 转换,并让 Cutout 通过套索提交区域。Depth Surface 的用户控制固定为 Subdivide、Thickness、Depth Scale、Reference Depth、Normal Smooth。
## Decisions
@@ -42,6 +42,7 @@ Depth Surface 使用 `create_mesh_plane_mesh()` 和 `build_mesh_plane_matrix()`
| Subdivide | 6,范围 0–10 | 沿用 O Mesh Plane 的细分 |
| Thickness | 0,最小 0 | 均匀曲面壳厚度,DISTANCE |
| Depth Scale | 1,最小 0 | 平面到相机曲面的缩放,可大于 1 |
| Normal Smooth | 50,范围 0–50 | 厚度方向的法线平滑次数,放在 Options |
| Reference Depth | Metadata reference_depth × Uniform Scale | 局部深度基准,DISTANCE,放在 Options |
Geometry 为结构输入;Depth Image 与 Uniform Scale 为隐藏数据输入。所有修改器输入使用 SINGLE。
@@ -56,16 +57,16 @@ flowchart TD
Texture[VECTOR Depth × Uniform Scale] --> Projection
Projection --> Thickness{Thickness}
Thickness -- 0 --> Surface[单层曲面]
Thickness -- 大于 0 --> Shell[沿曲面法线生成均匀壳并连接外边界]
Thickness -- 大于 0 --> Shell[沿平滑法线向内生成均匀壳并连接外边界]
Surface --> Output[保留 UV 与材质,清理临时属性]
Shell --> Output
```
提取现有曲面分支中可复用的投影、均匀厚度节点构建函数,按业务职责集中在共用构建模块;新组只组合自身需要的步骤。零厚度保持单层矩形拓扑,正厚度保留投影正面、沿内侧扩展背面并连接四周。厚度方向和法线处理与现有 Uniform Depth Surface 一致。
提取现有曲面分支中可复用的投影、均匀厚度节点构建函数,按业务职责集中在共用构建模块;新组只组合自身需要的步骤。零厚度保持单层矩形拓扑,正厚度保留投影正面、沿内侧扩展背面并连接四周。厚度采用正面 POINT 法线,按 Normal Smooth 迭代次数进行邻域平滑后归一化,使对应正背面顶点之间的距离等于 Thickness。
### 验证边界
以合成相机 XYZ 纹理验证投影和坐标方向,用相同 Subdivide 的普通 Plane 对照基础拓扑与 UV;使用非方图、偏移 Image Empty、旋转缩放矩阵验证定位。检查四项可见参数、隐藏数据输入、SINGLE、材质槽和临时属性清理。
以合成相机 XYZ 纹理验证投影和坐标方向,用相同 Subdivide 的普通 Plane 对照基础拓扑与 UV;使用非方图、偏移 Image Empty、旋转缩放矩阵验证定位。检查五项可见参数、隐藏数据输入、SINGLE、材质槽和临时属性清理。
节点布局按实际 Blender 绘制尺寸检查总览和局部,几何主链连续、计算支线就近接入。实现阶段按项目总则只运行测试;资产构建、资产视觉验收和节点资产文档同步作为后续发布准备,当前提案不执行构建。

View File

@@ -32,12 +32,12 @@ Depth Surface SHALL 使用普通 Convert to Plane 的基础 Mesh 创建、中心
- **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。
### Requirement: Surface controls include normal smoothing
`O Image Depth Surface` SHALL 只公开 Subdivide、Thickness、Depth Scale、Reference Depth 以及 Normal Smooth 五项用户控制。默认值 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
- **THEN** 用户看到规定的五项控制,Reference Depth 与 Normal Smooth 位于 Options;Normal Smooth 默认 50,范围 0–50
- **AND** 不出现 Cutout 的 Mode、Split、Balloon、Inflation、轮廓或轴向控制
### Requirement: Geometry follows camera projection
@@ -56,7 +56,7 @@ Depth Surface SHALL 按现有 Depth Cutout 的相机 XYZ 坐标约定投影。
- **THEN** 曲面 Z 增加 d × s,投影 XY 保持不变
### Requirement: Thickness forms a uniform surface shell
Thickness 为 0 时系统 SHALL 输出单层曲面;Thickness 大于 0 时 SHALL 保留投影正面,按现有 Uniform Depth Surface 的法线厚度语义向内生成背面并连接矩形边界。
Thickness 为 0 时系统 SHALL 输出单层曲面;Thickness 大于 0 时 SHALL 保留投影正面,按正面 POINT 法线按 Normal Smooth 进行邻域平滑并归一化后的方向向内生成背面并连接矩形边界。
#### Scenario: Zero thickness
- **WHEN** Thickness 为 0
@@ -64,7 +64,7 @@ Thickness 为 0 时系统 SHALL 输出单层曲面;Thickness 大于 0 时 SHAL
#### Scenario: Positive thickness
- **WHEN** 对平坦深度输入设置正 Thickness
- **THEN** 正背面沿法线距离等于 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 用于几何。

View File

@@ -1,24 +1,31 @@
## 1. 删除 Cutout 双击整图入口
- [ ] 1.1 删除 Cutout 的 DOUBLE_CLICK 整图绑定、full_image Property、整图 Selection 分支及失去用途的 import,保留共享套索交互。
- [ ] 1.2 调整交互和注册测试,验证图片内外双击均不打开 Shape 菜单或提交任务,有效套索继续生成 Shape。
- [x] 1.1 删除 Cutout 的 DOUBLE_CLICK 整图绑定、full_image Property、整图 Selection 分支及失去用途的 import,保留共享套索交互。
- [x] 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。
- [x] 2.1 增加 ConvertToDepthSurface、菜单入口和正逆序注册,验证静态图片、AI 环境及忙碌状态检查。
- [x] 2.2 扩展共用整图 Job 的 Z/VECTOR 产物选择及 Blender 响应分派,保持普通 Depth Plane 的 Z 路径;验证 VECTOR Depth 和 Tangent Normal 来自一次推理。
- [x] 2.3 复用 common 的图片、深度、材质及对象收尾函数创建 Depth Surface;共用 Plane 的基础 Mesh 和中心矩阵,初始化四项参数及隐藏深度数据。
- [x] 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 编排新节点组布局与验证入口,覆盖未用输出隐藏、主链及支线间距;记录发布准备时所需的实际绘制尺寸视觉验收项目。
- [x] 3.1 按业务职责提取共用相机投影和均匀厚度构建步骤,新增 O Image Depth Surface 构建定义,并接入节点组构建和验证索引。
- [x] 3.2 以 O Mesh Plane 的零厚度输出生成完整矩形基础网格,设置 Subdivide、Thickness、Depth Scale、Reference Depth 以及隐藏数据接口,检查 SINGLE 与 socket subtype。
- [x] 3.3 增加合成纹理几何测试:同级 Plane 拓扑与 UV 对照、Depth Scale 0/0.5/1/>1、Reference Depth、相机 Y 方向和非中心主点。
- [x] 3.4 增加零厚度单层、正厚度闭合、透明区域完整矩形、深度跳变连接、材质和临时属性清理验证。
- [x] 3.5 编排新节点组布局与验证入口,覆盖未用输出隐藏、主链及支线间距;记录发布准备时所需的实际绘制尺寸视觉验收项目。
## 4. 回归与交付检查
- [ ] 4.1 运行相关转换、交互、注册、Server Job 和节点构建定义测试,修复回归;检查现有 Depth Plane 和圈选 Cutout 的行为。
- [ ] 4.2 运行 uv run pytest,记录测试结果及需要 Blender 或已构建新资产才能完成的验收项。按项目总则,代码实施只运行测试,资产构建、二进制产物和节点资产文档同步留给发布准备。
- [x] 4.1 运行相关转换、交互、注册、Server Job 和节点构建定义测试,修复回归;检查现有 Depth Plane 和圈选 Cutout 的行为。
- [x] 4.2 运行 uv run pytest,记录测试结果及需要 Blender 或已构建新资产才能完成的验收项。按项目总则,代码实施只运行测试,资产构建、二进制产物和节点资产文档同步留给发布准备。
发布准备验收:构建节点资产后,在 Blender 节点编辑器按实际绘制尺寸检查新组总览、投影支线、厚度分支及旁路;检查修改器四项参数的实际显示,并对已发布资产运行几何验证。本次不生成资产或文档产物。
测试记录:全量测试两次均为 723 passed、2 xfailed、62 subtests passed;显式调用 pytest.main 返回 0。两次完整进程均在 pytest 返回后以退出码 1 结束,退出阶段异常尚未定位。新曲面几何、接口、对象定位及失败清理测试全部通过。OpenSpec strict 校验通过。
资产更新记录:已按用户要求运行 build_node --skip-tests,Blender 4.5.10 LTS 构建及三项资产验证均成功。更新后资产与转换回归 53 passed;构建定义和磁盘发布资产使用相同几何用例验证,31 passed,命令退出码均为 0。已同步节点资产说明。Computer Use 应用授权超时,实际节点编辑器视觉验收仍待完成。

View File

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

View File

@@ -0,0 +1,69 @@
## Context
Debug 调用链跨越 Blender UI、Scene 参数、Operator、Server Job 和原始预测写出。`server/outputs/` 当前专用于 Debug;正式产物由 geometry 等模块生成。删除依据 `proposal.md` 的完整工作流边界进行,同时全面审查 tests、node_assets 和内部文档。
## Goals / Non-Goals
目标是清除 Debug 入口及其专用依赖,精简有效测试,使节点资产模块和内部文档的名称对应实际职责。实施范围包括代码、测试和用户明确要求整理的内部文档;节点图行为与接口保持稳定,按用户补充要求将 `O Mesh Plane` 统一为 `O Image Plane`。
## Decisions
### 按调用链删除
```mermaid
flowchart TD
A[删除 Debug 主面板与四个子面板] --> B[删除四个 Debug Operator 与注册]
B --> C[删除四个 Debug Job 与注册]
C --> D[删除 Debug 序列化与帧复制]
D --> E[按剩余引用清理属性与辅助函数]
E --> F[验证正式功能与注册生命周期]
```
直接删除实现与注册,使源码和可调用接口保持一致。清理 `server/outputs/` 整个专用包、`copy_frames` 实现和 `media/__init__.py` 导出,避免留下失去调用方的模块。
### 共用代码按引用决定归属
| 对象 | 处理 |
| --- | --- |
| `DebugPanel` 与四个模型子面板、`draw_da3_input_settings` | 删除并清理 `panel.py` 导入 |
| `DebugDa3`、`DebugMoge2`、`DebugBen2`、`DebugUpscale` | 删除模块及所有注册项 |
| Scene 的 `input_path`、`background_input_path`、`model`、`device`、`process_res`、`process_res_method`、`moge_resolution_level`、`moge_model`、`ref_view_strategy` | 核对剩余调用后删除 Debug 专用声明 |
| Scene 的 `video_frames`、Cutout 和 Mask 参数 | 保留正式调用需要的属性 |
| `da3_parameters`、`model_enum_items`、`moge2_model_enum_items` | 核对引用后删除专用函数及孤立导入 |
| `moge2_parameters`、输入校验函数、偏好设置中的设备选择 | 保留正式调用使用的实现 |
| DA3 模型适配器、ONNX 推理、目录及缓存 | 当前调用方仅为 Debug,整条删除 |
| MoGe-2、BEN2、Upscale 模型适配器及模型目录 | 保留正式推理所需能力,Upscale 统一保留源 Alpha,删除专用开关 |
属性按所属类型检查;Operator 上同名的正式属性独立保留。MoGe-2 原始预测结构仍用于正式几何转换,保留其适配和数据校验。
### 测试随接口收缩
删除专用导出与 Debug 推理测试,将原本仅通过 Debug 覆盖的公共模型行为转到正式入口。更新 Blender 注册及逆序注销、Server Job 清单与打包清单测试,明确 Debug 接口和文件缺席;正式流程继续覆盖设备、模型选择、视频多帧及推理后的内存释放。
### 全面审查测试价值与归属
先逐文件记录实际验证的行为,再对每个用例决定保留、合并、重写或删除。保留能检测输出错误、协议破坏、数据丢失、取消与资源清理失败等实际问题的测试。删除失效功能测试、相同风险的重复断言,以及只复述实现细节且无法发现行为回归的测试;mock 和源码检查按其验证价值判断,不机械删去。
文件按稳定功能组织,类名和用例名描述实际行为及关键条件。已发现 `test_server_jobs.py` 混合媒体输入、下载、模型生命周期与 Job 输出,`test_blender_addon.py` 混合设备、运行时和 Operator 行为,应按职责拆分。`test_docs.py` 实际验证文档命令,应命名为对应命令职责。其他文件同样逐项审查,避免只处理这几个示例。共享 fixture 仅抽取确有复用的部分,测试通过情况不能代替覆盖价值判断。
### 节点资产按功能组织源码
梳理全部模块的构建对象、几何处理、布局和验证职责,形成现名到职责的映射,再确定重命名、合并或拆分。`build_depth_plane.py`、`build_cutout_modifiers.py` 等动作式文件名改为资产或业务分类命名,函数继续使用 `build_*` 表达构建动作。公共深度表面与布局模块依据实际调用范围命名,`node_graph.py` 和 `node_layout.py` 依据实际公共能力保留或细化。
一次更新模块导入、`tools/build_node.py` 的脚本列表、测试动态加载路径与文档路径,删除旧入口。将 `O Mesh Plane`、相关模块及函数统一命名为 `O Image Plane` / `image_plane`。使用项目配置的 Blender 修改现有 `.blend` 资产名称,比较保存前后全部节点组的接口、默认值、运算、连接和布局,验证功能一致。其他节点组名称保持稳定。
### 内部文档按最终实现重整
逐页核对总览、架构、Common、Runtime、产物、开发、节点资产和全部 Operator 说明。以当前源码中的注册、调用链、参数和产物协议为依据,合并重复说明,删除过期内容,按实际主题调整文件名与层次,并同步所有内部链接与 MkDocs 导航。
删除 Debug 专页及引用;节点资产页使用最终模块名及职责。实现流程用从上到下的 Mermaid 图,正文以中文正面说明当前职责。通过路径、导航、链接和源码交叉核对验收,不运行文档构建。
## Risks / Trade-offs
- [误删同名正式参数或公共模型函数] → 逐项核查调用方,并运行正式工作流回归测试。
- [注册表或包导出残留导致启动失败] → 验证扩展导入、注册与逆序注销、Server Job 清单和打包文件选择。
- [并行变更修改相同文件] → 实施时基于最新工作区逐项修改,保留其他变更的逻辑与测试。
- [旧脚本调用已删除 Debug 接口] → 调用方改用对应正式 Operator 或 Job;删除直接生效,不保留转发接口。
- [精简测试掩盖回归] → 按行为和风险核对精简前后覆盖,保留独有场景,最终运行完整测试。
- [节点模块重命名遗漏动态路径] → 核查构建启动器、脚本加载、测试和文档引用,并测试入口解析。
- [文档沿用旧描述导致再次偏离] → 每页对照最终源码核验,尤其是节点组名、socket、Job 参数和输出协议。

View File

@@ -0,0 +1,35 @@
## Why
模型调试入口已完成阶段性用途,继续保留会增加 UI、参数、Job 和测试的维护成本。结合删除工作,全面整理测试、节点资产源码和内部文档,让名称、职责、验证与实际功能保持一致。
## What Changes
- **BREAKING**:移除 Debug 主面板、DA3 / MoGe-2 / BEN2 / Upscale 子面板及四个 `anyimage.debug_*` Operator。
- **BREAKING**:移除 `debug-da3`、`debug-moge2`、`debug-ben2`、`debug-upscale` Job 和原始预测导出实现。
- 删除 Debug 专用 Scene 属性、UI 辅助函数、参数组装、序列化与帧复制代码,清理注册、导入和导出。
- 删除当前仅由 Debug 调用的 DA3 模型适配器、ONNX 推理、目录声明及缓存分支;Upscale 统一保留源 Alpha。
- 根据正式功能的实际引用保留共用模型、输入处理、设备设置、视频帧数和推理能力。
- 调整注册、Job、模型及打包测试,覆盖删除后的边界和正式功能回归。
- 全面审查 `tests/` 的文件、测试类、用例和辅助代码,仅保留能发现实际行为回归或约束关键协议的测试,按验证功能整理名称和归属。
- 全面梳理 `tools/node_assets/` 的构建、几何、布局及验证职责,重命名或拆并职责不符的模块,同步所有导入与脚本引用。
- 全面重整 `docs/internals/`,逐页对照最终源码与功能逻辑修订内容、文件名和索引,清理 Debug 说明并同步 `mkdocs.yml` 导航。
## Capabilities
### New Capabilities
- `production-only-ai-workflows`:约束扩展仅暴露正式 AI 工作流,规定 Debug 入口及专用实现的移除和正式功能的可用性。
- `maintainable-project-structure`:规定测试价值与命名、节点资产模块职责和内部文档与实现的一致性。
### Modified Capabilities
无。当前 `openspec/specs/` 尚无已归档规范。
## Impact
- Blender:`panel.py`、`properties.py`、扩展与 Operator 注册、`operators/debug.py`、`common/ai.py`。
- Server:`app.py`、`jobs/debug_predictions.py`、`outputs/`、`media/` 及仅被 Debug 引用的模型适配辅助逻辑。
- 测试:整个 `tests/`,包含测试归属、名称、公共 fixture 和重复覆盖的整理。
- 节点资产:整个 `tools/node_assets/`,以及 `tools/build_node.py`、相关测试和调用引用。
- 文档:整个 `docs/internals/` 及 `mkdocs.yml` 导航;按用户明确要求同步实现说明。
- 本次整理运行测试,不构建文档、扩展包或节点资产;节点资产整理保持现有节点图与资产接口行为。

View File

@@ -0,0 +1,37 @@
## ADDED Requirements
### Requirement: Tests protect meaningful behavior
维护者 MUST 审查全部测试文件、用例和辅助代码,按实际回归风险保留、合并、重写或删除。保留的测试 SHALL 验证可观察行为或关键协议,每项独有且仍适用的风险覆盖 MUST 保留。
#### Scenario: Audit completed
- **WHEN** 全部测试整理完成
- **THEN** 失效功能测试和无独立价值的重复测试已删除,保留用例能说明所保护的行为,完整测试通过
### Requirement: Test names reflect tested functionality
测试文件、类和函数 MUST 与其验证的功能、行为和关键条件相符;跨独立职责的测试集合 SHALL 按稳定功能拆分。
#### Scenario: Locate a behavior test
- **WHEN** 按测试路径、类名和函数名查找某项功能
- **THEN** 名称与测试主体的实际断言对应,共用辅助代码拥有明确的复用职责
### Requirement: Node asset modules reflect responsibilities
`tools/node_assets/` 的全部模块 MUST 按实际资产或业务职责审查命名与边界,所有重命名 MUST 同步导入、构建与验证入口及测试路径,并删除旧路径和转发层。
#### Scenario: Load reorganized asset tools
- **WHEN** 启动器解析脚本并加载节点构建与验证模块
- **THEN** 所有路径指向最终模块,文件名与构建对象、几何处理、布局或验证职责对应
#### Scenario: Preserve node behavior
- **WHEN** 对重组后的节点构建函数运行针对性测试
- **THEN** 普通图像平面统一使用 `O Image Plane` 名称,源码使用 `image_plane`;资产重命名前后接口、默认值、运算、连接及布局一致
### Requirement: Internal documentation matches implementation
`docs/internals/` 全部页面 MUST 与最终源码中的功能、职责、参数、调用链和产物对应,页面名称和目录索引 MUST 与主题对应。实现流程 SHALL 使用从上到下的 Mermaid 图。
#### Scenario: Read final implementation documentation
- **WHEN** 按总览或 MkDocs 导航访问任一内部主题
- **THEN** 链接有效,内容描述当前实现,源码路径和功能名称可核对,Debug 专页和过期 Debug 说明已清理

View File

@@ -0,0 +1,45 @@
## ADDED Requirements
### Requirement: Blender exposes production AI workflows
扩展 MUST 移除 Debug 主面板、DA3 / MoGe-2 / BEN2 / Upscale 子面板及四个 `anyimage.debug_*` Operator,并保持正式类型注册和逆序注销完整。
#### Scenario: Extension registration lifecycle
- **WHEN** 扩展注册、注销并重新注册
- **THEN** Debug 面板和 Operator 均不在注册清单中,正式面板与 Operator 正常可用
### Requirement: Server registers production jobs only
Server MUST 移除 `debug-da3`、`debug-moge2`、`debug-ben2` 和 `debug-upscale` Job 及其处理实现,不提供兼容入口。
#### Scenario: Registered jobs
- **WHEN** Server 加载 Job 注册清单
- **THEN** 四个 Debug Job 均缺席,正式 Job 保持已注册且可执行
### Requirement: Debug implementation is removed completely
源码和扩展文件选择 MUST 移除 Debug 专用模块、Scene 参数、UI 辅助函数、参数组装、原始预测序列化、帧复制及相应导入和导出。
#### Scenario: Source and packaging boundaries
- **WHEN** 检查模块引用与扩展打包文件清单
- **THEN** `operators/debug.py`、`server/jobs/debug_predictions.py`、`server/outputs/` 和 Debug 专用辅助实现均缺席,保留模块可正常导入
#### Scenario: Scene settings
- **WHEN** 读取 `AnyImageSettings` 的属性声明
- **THEN** Debug 专用属性已删除,正式使用的 `video_frames`、Cutout 和 Mask 属性保持可用
#### Scenario: Debug-only model dependencies
- **WHEN** 加载模型目录与缓存 Resource
- **THEN** DA3 模型声明、推理模块与缓存分支均已移除,正式 MoGe-2、BEN2 和 Upscale 模型保持可用
### Requirement: Shared production inference remains available
系统 SHALL 保持正式深度处理、Cutout、Remove Background 和 Upscale 所需的模型、输入校验、设备选择、多帧处理及内存释放行为。
#### Scenario: Production model requests
- **WHEN** 正式 Operator 组装并提交 AI 请求
- **THEN** 请求使用正式模型参数及 Add-on Preferences 设备设置,输入校验和视频帧数传递保持有效
#### Scenario: Production output and memory lifecycle
- **WHEN** 正式 Job 完成单帧或多帧模型推理
- **THEN** 生成对应正式产物,并按既有最终推理边界请求内存释放

View File

@@ -0,0 +1,53 @@
## 1. Blender 入口与设置
- [x] 1.1 删除 Debug 主面板、四个子面板和专用绘制函数,清理 `panel.py` 导入及扩展注册项。
- [x] 1.2 删除 `operators/debug.py` 及 Operator 注册项,验证正式类型注册与逆序注销。
- [x] 1.3 按引用删除 Debug 专用 Scene 属性、枚举回调和 `da3_parameters`,保留正式输入校验、`moge2_parameters`、`video_frames` 及偏好设备设置。
## 2. Server 实现与依赖
- [x] 2.1 删除四个 Debug Job 的注册和 `jobs/debug_predictions.py`。
- [x] 2.2 删除 `server/outputs/` 专用包、`copy_frames` 及媒体模块导出,清理孤立导入。
- [x] 2.3 沿删除后的调用链检查模型适配与公共模块,移除仅服务 Debug 的分支,确认正式预测数据转换和产物写出仍完整。
## 3. 测试与验收
- [x] 3.1 删除 Debug 专用测试及测试模块加载,更新 Blender 注册与 Scene 属性断言。
- [x] 3.2 更新 Server Job 注册和打包文件清单测试,验证 Debug Job、模块及导出缺席;使用文件选择检查,避免生成扩展包。
- [x] 3.3 将 Debug 测试中仍适用的公共模型断言移到正式入口,验证模型选择、设备、输入校验、多帧、产物及最终推理内存释放。
- [x] 3.4 运行 Debug 删除相关测试,复查 `src`、`tests`、`tools` 及运行配置中的 Debug 引用,确认无残留实现或失效导入。
## 4. 全部测试整理
- [x] 4.1 逐文件审查全部测试类、用例和辅助代码,列出保护的行为与风险,决定保留、合并、重写或删除。
- [x] 4.2 删除失效、无独立价值的重复用例和单纯复述实现的断言,保留所有仍适用的独有行为覆盖。
- [x] 4.3 按实际职责整理全部测试文件、类和函数名,拆分跨功能集合,包括 Blender 注册、设备、Runtime、媒体输入、模型下载与 Job 输出。
- [x] 4.4 清理 fixture、动态导入和辅助函数,仅提取确有复用的代码,核对整理前后关键风险覆盖。
## 5. 节点资产源码整理
- [x] 5.1 遍历 `tools/node_assets/` 全部模块,核对文件名与构建对象、几何处理、布局及验证职责,确定目标命名和拆并方案。
- [x] 5.2 按稳定功能重命名或拆并模块,同步全部导入、`tools/build_node.py` 脚本列表和测试加载路径,移除旧路径与转发代码。
- [x] 5.3 通过针对性测试核对 socket 顺序、默认值、运算、连接和布局保持一致,将源码、测试、文档和正式资产中的 `O Mesh Plane` 统一为 `O Image Plane`。
## 6. 内部文档整理
- [x] 6.1 对照最终源码审查 `docs/internals/` 全部页面,核对功能名、路径、参数、调用链、产物和实际职责。
- [x] 6.2 重整总览、架构、Common、Runtime、产物和开发说明,按主题调整文件名与层次,合并重复内容并删除过期说明。
- [x] 6.3 重整全部 Operator 页面和索引,删除 Debug 专页与引用,以 Mermaid 流程说明正式功能主链。
- [x] 6.4 更新节点资产文档,使模块名、节点组、接口、构建与验证流程对应实际实现。
- [x] 6.5 同步 `mkdocs.yml` 导航和全部受影响的内部链接,检查链接与源码引用有效性。
## 7. 最终验收
- [x] 7.1 运行 `uv run pytest`,处理行为回归与测试收集问题,核对关键功能覆盖。
- [x] 7.2 复查全部改名的旧路径、失效导入和文档引用,确认 tests、node_assets、docs/internals 的名称与内容边界一致。
- [x] 7.3 核查最终差异并汇报主要删除、合并、重命名与验证结果;确认未构建文档、扩展包或重建节点资产;已有资产仅修改图像平面组名并验证内容一致。
## 验证结果
- `uv run pytest -q`:724 passed、2 xfailed、48 subtests passed,退出码 0。
- 模拟 Blender 测试仅拦截 Python 导入,保留真实 `bpy` 模块身份,并恢复原有 AnyImage 模块,避免原生退出崩溃。
- 23 个节点源码模块经 AST 比对,变化仅限命名与导入。
- 使用项目配置的 Blender 对原有资产重命名;保存前后节点接口、属性、默认值、连接和布局一致。
- 内部文档链接、Python 语法和 OpenSpec 严格校验通过。

View File

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

View File

@@ -0,0 +1,75 @@
## Context
`build_depth_plane.py` 当前读取纹理 R 通道并生成固定底面浮雕;`build_depth_surface.py` 使用 XYZ 投影并沿平滑法线生成壳。Cutout 的 Depth Solid 请求 VECTOR,Depth Balloon 请求 Z,但 Balloon 节点和 `common/depth.py` 已读取 B/Z。Server 将两类产物写成相同规格的 RGBA float32 EXR。
本设计以当前工作区已实现的 `add-projected-depth-plane` 为基线,覆盖其中关于独立 Surface 入口与 Z/VECTOR 双产物的决定。
## Goals / Non-Goals
统一整图深度几何的交互入口和深度产物契约,保留两种形态及 Cutout 的现有几何效果。删除范围限定于独立 Z 文件输出及失去用途的分支;内部标量深度、标定元数据、Cutout 的形状参数继续承担原有职责。
## Decisions
### 一个入口与模式接口
保留 `ConvertToDepthPlane`、`anyimage.convert_to_depth_plane`、Convert to Depth Plane 和 `O Image Depth Plane`。删除独立 Surface 注册、菜单、类、结果类型映射和公开资产组。模式在修改器中选择,默认 Relief;模式切换只触发节点求值。
| 接口顺序 | 默认值与语义 |
| --- | --- |
| Geometry | 结构输入 |
| Mode | Relief / Camera,默认 Relief |
| Subdivide | 6,范围 0–10 |
| Thickness(Relief) | 0,最小 0,DISTANCE |
| Thickness(Camera) | 0,最小 0,DISTANCE |
| Depth Scale | 1,最小 0 |
| Options / Reference Depth | 元数据 reference_depth × Uniform Scale,DISTANCE |
| Options / Normal Smooth | 50,范围 0–50,仅影响 Camera 厚度方向 |
| Data / Uniform Scale | 隐藏,默认 1 |
| Data / Depth Image | 隐藏 |
输入统一 SINGLE。两个独立输入均显示 Thickness,依次控制 Relief 的基础厚度和 Camera 的向内壳厚度,默认均为 0 m;按不同 socket identifier 保存,切换模式保留各自数值。Normal Smooth 保留在 Options,并通过说明明确适用模式。
### 两条几何分支共用数据
```mermaid
flowchart TD
Input[图片矩形 Mesh 与 depth.exr] --> Mode{Mode}
Mode --> Relief[Relief:固定 XY,读取 B 深度,固定底面]
Mode --> Camera[Camera:相机 XYZ 投影,沿平滑法线生成壳]
Relief --> Output[保留 UV 材质与用户属性,清理临时属性]
Camera --> Output
```
Relief 沿用现有厚度、底面权重、侧面插值和负位移限制,只将标量采样改为 B/Z。Camera 沿用现有完整矩形细分与投影公式:令采样相机 XYZ 乘以 Uniform Scale 得到 C,局部 XY 从基础 XY 按 Depth Scale 插值到 `(C.x, -C.y)`,局部 Z 为 `(Reference Depth - C.z) × Depth Scale`。正 Thickness 保留正面,背面沿正面 POINT 法线按 Normal Smooth 迭代平滑并归一化后向内偏移。
共用投影和壳构建函数,两个分支由一个公开节点组组织。构建模块以职责命名;删除仅服务旧公开 Surface 组的构建和布局入口。节点资产始终按名称加载。
### 统一深度产物与请求
```mermaid
flowchart TD
Request[整图转换或 Cutout 深度请求] --> Infer[一次 MoGe 推理,保留 points]
Infer --> Correct[按现有调用条件修正边缘深度]
Correct --> Artifact[depth.exr:RGB 相机 XYZ,A 有效性]
Correct --> Metadata[depth.json:尺寸 内参 基准深度]
Artifact --> Load[结果键 depth,主线程加载并 Pack]
Load --> XYZ[Camera 与 Depth Cutout:读取 XYZ]
Load --> Z[Relief 与 Depth Balloon:读取 B/Z]
```
将深度产物选择收敛为布尔 `generate_depth`,默认 false;整图 Job 固定请求 true,Cutout 根据 Depth Solid / Depth Balloon 判断。替换 `depth_mode` 参数与 `depth_mode_for_shape`,生成法线的参数保持独立。只生成法线时仍可不保留 points。
写出函数统一为 `write_depth_texture`,沿用当前 vector 写出的 RGBA float32 数值、有效性和非有限值处理;文件名 `depth.exr`,返回键 `depth`。删除 Z 写出函数与旧结果键,直接更新全部调用和测试。所有需要深度的推理保留 XYZ,内部 `GeometryFrame.depth` 继续用于标量运算;元数据仍通过 `depth_metadata` 返回 `depth.json`。深度与法线继续来自同一次预测,保持各自现有边缘修正语义。
### 交付与验证
客户端、Server、节点构建及测试作为一次契约变更交付,不增加旧键、旧名称转发。已有 blend 内嵌旧组不主动迁移;需要新模式接口时重新转换源图片。归档时协调前序未归档规格,确保最终规格只保留统一入口和产物契约。
实现阶段更新脚本、验证、测试与节点资产文档并运行测试。资产更新阶段构建并验证 `O_AnyImage.blend`,对定义与保存资产使用同组几何用例,最后在 Blender 检查总览和局部实际绘制布局;视觉验收单独记录,不能由坐标检查代替。
## Risks / Trade-offs
- R 与 Z 在旧标量 EXR 中相同,普通灰度测试会掩盖读错通道 → 使用 X、Y、Z 明显不同的合成纹理覆盖全部消费者。
- Balloon 从仅保留 depth 改为保留 points,增加中间内存 → 验证单次推理、释放路径和正常生成;文件格式与通道数保持一致。
- 两种模式中 Thickness 的几何含义不同 → 明确接口说明,并测试切换保留值及两种模式各自的厚度行为。
- 新代码与旧节点资产混用可能造成接口错误 → 资产更新时同时检查菜单、注册、公开组清单及实际资产求值。

View File

@@ -0,0 +1,26 @@
## Why
整图 Depth Plane 与 Depth Surface 共用图片、网格和深度预测,只在几何模式上不同,独立入口使选择与切换复杂。相机 XYZ 已包含标量 Z 深度,统一产物可以消除生成和读取中的格式分支。
## What Changes
- 合并为一个 Convert to Depth Plane 入口与 `O Image Depth Plane` 节点组,提供 Relief(固定底面浮雕)和 Camera(相机投影曲面)模式,默认 Relief;切换模式复用已加载深度。
- Camera 保留沿平滑法线的 Thickness 与 Normal Smooth(默认 50,范围 0–50),整图保持连续矩形网格。
- **BREAKING**:删除独立 Depth Surface Operator、菜单项和公开资产组,直接使用合并接口。
- **BREAKING**:删除 `z-depth.exr` 输出,将 `vector-depth.exr` 更名为 `depth.exr`,结果键统一为 `depth`。RGB 为相机 XYZ,Alpha 为有效性。
- 所有整图和 Cutout 深度消费者统一读取该产物;标量深度读取 B/Z 通道。内部 `GeometryFrame.depth` 与 `depth.json` 继续承担计算和标定职责。
## Capabilities
### New Capabilities
- `unified-depth-plane`: 一个整图转换入口与节点组中的 Relief / Camera 模式、接口及几何行为。
- `depth-artifact-contract`: 统一深度文件、结果键、通道约定及全部消费者的读取契约。
### Modified Capabilities
无。当前 `openspec/specs/` 为空;本变更承接已实现但未归档的 `add-projected-depth-plane`,以本次契约定义合并后的行为。
## Impact
涉及整图转换 Operator、菜单与注册、对象创建与结果加载、Cutout 请求与响应、Server Job 与预测产物层、深度纹理写出、节点构建与验证及相关测试。节点资产文档随节点接口同步;本次只创建提案,资产构建和 Blender 视觉验收在实现后的资产更新阶段执行。无需新增依赖。

View File

@@ -0,0 +1,38 @@
## ADDED Requirements
### Requirement: Depth has one file contract
系统 SHALL 将所有深度图片写为 `depth.exr`,通过结果键 `depth` 返回。文件 MUST 使用 RGBA float32,RGB 为相机 XYZ,Alpha 为有效性,并沿用相机坐标、像素方向和非有限值处理约定。内部标量深度和 `depth.json` SHALL 保留。
#### Scenario: Generate depth artifacts
- **WHEN** 整图转换、Depth Solid 或 Depth Balloon 请求深度
- **THEN** 结果包含 `depth` 与 `depth_metadata`,对应 `depth.exr` 和 `depth.json`
- **AND** 不生成 `z-depth.exr`、`vector-depth.exr` 或旧结果键
#### Scenario: Preserve independent channels
- **WHEN** 输出合成数据中 X、Y、Z 不同的深度图
- **THEN** 解码后的 RGB 分别保持 XYZ 数值和有效性,不将 Z 复制到 RGB
### Requirement: Depth generation is a boolean request
共享产物生成 SHALL 使用布尔 `generate_depth` 决定是否生成深度,法线请求保持独立;深度消费者 SHALL 请求保留 XYZ 的单次推理,并沿用现有边缘深度修正条件。
#### Scenario: Generate depth and normals together
- **WHEN** 同时请求深度和法线
- **THEN** 只运行一次预测,生成统一深度、元数据和请求的法线产物
#### Scenario: Generate normals alone
- **WHEN** generate_depth 为 false 且请求法线
- **THEN** 生成法线,不写出深度图片或深度元数据
### Requirement: All consumers use the unified channels
整图与 Cutout 结果加载器 SHALL 从 `depth` 加载深度并沿用 Pack、数据色彩空间及尺度标定。Camera 与 Depth Cutout SHALL 读取 XYZ;Relief、Depth Balloon 和公共标量深度读取函数 SHALL 读取 B/Z。
#### Scenario: Scalar depth is distinct from X
- **WHEN** X 与 Z 明显不同的纹理用于 Relief 或 Depth Balloon
- **THEN** 几何位移由 Z 决定,效果与使用相同标量 Z 的现有结果一致
#### Scenario: Projected geometry keeps camera coordinates
- **WHEN** 统一深度纹理用于 Camera 或 Depth Cutout
- **THEN** 投影位置、有效性和尺度与更名前的 XYZ 输入一致

View File

@@ -0,0 +1,58 @@
## ADDED Requirements
### Requirement: One conversion exposes two geometry modes
系统 SHALL 仅提供 Convert to Depth Plane 整图深度入口,使用 `anyimage.convert_to_depth_plane` 与资产组 `O Image Depth Plane`。Mode SHALL 提供 Relief 与 Camera,默认 Relief。独立 Depth Surface 入口、注册类和公开资产组 SHALL 删除。
#### Scenario: Convert and switch modes
- **WHEN** 静态 Image Empty 完成转换后,用户在修改器切换 Relief / Camera
- **THEN** 同一对象和深度图片产生对应几何,不重新推理、不创建新深度图片
- **AND** 两种模式共享并保留已有控制值
#### Scenario: Preserve conversion lifecycle
- **WHEN** 转换成功或失败
- **THEN** 成功时沿用源名称、替换源对象且一次 Undo 可恢复;失败时清理部分结果并保留源对象
- **AND** AI 环境检查和静态媒体限制继续生效
### Requirement: Unified modifier has a stable interface
接口 SHALL 依次为 Geometry、Mode、Subdivide、两个独立的 Thickness、Depth Scale、Options 内 Reference Depth 与 Normal Smooth、Data 内 Uniform Scale 与 Depth Image。两个 Thickness SHALL 同名显示,依次控制 Relief 与 Camera,默认均为 0 m、最小 0,使用不同 identifier 独立保存。Subdivide SHALL 默认为 6、范围 0–10;Depth Scale 默认为 1、最小 0;Normal Smooth 默认为 50、范围 0–50。Reference Depth SHALL 由元数据基准深度乘以 Uniform Scale 初始化。Data 输入 SHALL 隐藏;所有输入 SHALL 使用 SINGLE,长度使用 DISTANCE。
#### Scenario: Inspect mode controls
- **WHEN** 创建或切换修改器模式
- **THEN** 接口顺序和默认值符合契约,Normal Smooth 只影响 Camera 的厚度法线
- **AND** 整图模式不提供 Split 或 Cutout 轮廓控制
#### Scenario: Keep mode thickness independent
- **WHEN** 在一种模式中修改另一模式对应的 Thickness,并切换模式后返回
- **THEN** 当前模式几何保持不变,两个厚度值分别保留
### Requirement: Relief preserves the fixed base
Relief SHALL 读取 B/Z 深度,保持基础 XY、固定底面、现有侧壁插值和负位移限制。Thickness SHALL 表示浮雕的基础厚度。
#### Scenario: Evaluate relief
- **WHEN** 用与旧标量输入相同的 Z、不同的 X/Y 求值 Relief
- **THEN** 顶点位置、面连接、UV 与材质和原 Depth Plane 结果一致
### Requirement: Camera preserves the projected shell
Camera SHALL 使用完整矩形细分;相机 XYZ 乘以 Uniform Scale 后得到 C,XY SHALL 按 Depth Scale 从基础 XY 插值到 `(C.x, -C.y)`,Z SHALL 为 `(Reference Depth - C.z) × Depth Scale`。零 Thickness SHALL 输出单层;正 Thickness SHALL 沿平滑归一化后的正面 POINT 法线向内生成背面并闭合边界。
#### Scenario: Match the ordinary plane
- **WHEN** Camera 的 Thickness 和 Depth Scale 均为 0
- **THEN** 相同 Subdivide 下几何与普通 Plane 一致,包括非中心显示偏移和对象变换后的世界位置
#### Scenario: Project and thicken
- **WHEN** 使用非中心主点合成数据,Depth Scale 为 0、0.5、1 或 2,Normal Smooth 为 0、2 或 50
- **THEN** 投影符合公式;正 Thickness 的对应正背面距离等于 Thickness,0 次平滑使用原始法线
- **AND** 透明区域与深度跳变区域保持完整矩形连接
### Requirement: Asset evaluation preserves geometry data
统一组 SHALL 从资产按名称加载,保留 UV、材质和用户属性,并清理自身临时属性。定义和保存资产 SHALL 满足相同接口与几何契约,布局 SHALL 在 Blender 中按实际绘制尺寸检查。
#### Scenario: Validate the delivered asset
- **WHEN** 加载更新后的节点资产
- **THEN** 公开组清单包含统一 Depth Plane 且没有独立 Depth Surface,两种模式通过几何求值
- **AND** 总览和局部步骤没有节点遮挡,未用输出隐藏,主轴与支线清楚

View File

@@ -0,0 +1,30 @@
## 1. 统一深度输出与读取
- [x] 1.1 将深度写出统一为 write_depth_texture、depth.exr 和结果键 depth,删除 Z 写出分支;保留内部 depth 与 depth.json,验证 RGBA 数值和有效性。
- [x] 1.2 将共享生成层、整图 Job 和 Cutout 请求改为 generate_depth 布尔值,验证深度保留 points、法线共用单次推理及边缘修正路径。
- [x] 1.3 更新整图与 Cutout 结果加载、测试夹具和公共读取调用,验证 Pack、色彩空间、标定和非有限值处理;删除旧参数和结果键。
## 2. 合并整图节点与入口
- [x] 2.1 将 Relief 与 Camera 组合为 O Image Depth Plane,增加 Mode 与统一接口;Relief 改读 B/Z,Camera 复用投影及平滑法线壳。
- [x] 2.2 重排合并组的布局,更新构建入口、公开组清单与验证;删除独立 Surface 构建和布局入口,同步节点资产文档。
- [x] 2.3 保留单一 ConvertToDepthPlane,删除独立 Surface 类、菜单、注册和对象类型分支,统一结果对象与默认值。
## 3. 回归验证
- [x] 3.1 使用 X/Y/Z 不同的纹理覆盖 Relief、Camera、Depth Cutout、Depth Balloon 和公共标量读取,验证各自位置、有效性及尺度。
- [x] 3.2 覆盖模式切换无需推理且保留参数、Relief 固定底面、Camera 投影与法线厚度、矩形拓扑、UV、材质及临时属性清理。
- [x] 3.3 更新注册与逆序注销、静态媒体和 AI 检查、成功替换与单次 Undo、失败清理测试,运行相关测试及必要的完整回归。
- [x] 3.4 搜索生产代码中的旧文件名、结果键、模式分支和独立 Surface 入口,确认无兼容转发或残留消费路径。
## 4. 资产更新验收
- [x] 4.1 在资产更新阶段构建并验证 O_AnyImage.blend,以相同用例检查保存资产和构建定义的接口与两种模式求值。
- [x] 4.2 在 Blender 节点编辑器检查总览及局部实际布局,确认主轴、分支顺序、间距、旁路和未用输出隐藏,记录视觉验收结果。
## 验证记录
- 已构建 O_AnyImage.blend,Blender 4.5.10 LTS 的资产、Mesh Plane、Cutout 验证通过。
- 完整回归报告 746 passed、2 xfailed、60 subtests passed;pytest 完成后进程退出码为 1,与本变更前已记录的退出现象一致。随后清理了 3 个合并入口造成的重复测试。
- 清理重复测试后的受影响范围回归:349 passed、30 subtests passed,退出码 0;覆盖保存资产与构建定义。
- 视觉验收待完成:Computer Use 能捕获 Blender 启动画面,但激活、点击与 Escape 后界面均未变化,尚未进入节点编辑器。坐标与几何校验已通过,不能替代实际视觉验收。