feat: Implement depth cutout symmetry and associated functionalities

- Introduced a new proposal for depth cutout symmetry, allowing for the reuse of depth replacement and geometry operations.
- Added requirements for maintaining default thickness values for cutout nodes and ensuring proper initialization during object creation.
- Enhanced symmetry node to handle existing geometry, including alignment, mirroring, and boundary filling.
- Implemented fill smoothing to control the geometry of generated walls while preserving original surfaces.
- Created tests to validate the functionality of the new symmetry features against baseline geometry.
- Updated existing assets and node groups to support the new symmetry capabilities without introducing additional dependencies.
This commit is contained in:
2026-09-14 14:58:48 +08:00
parent dc000e50b1
commit ab282e4fdf
28 changed files with 716 additions and 689 deletions

View File

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

View File

@@ -0,0 +1,77 @@
## Context
现有 Cutout 负责图像深度投影与 Balloon / Shell 成形;现有 Depth Symmetry 同时承担投影及对称。桌面独立实验已将后者的 Projected 后半段取出,接在原 Cutout 后面。
`C:/Users/icrdr/Desktop/anyimage/post-cutout-symmetry-20260914/comparison.json` 记录了两张图片、两种模式、补面开关的零厚度对比:八组顶点位置误差均为 0,面数量及带方向拓扑一致。非零厚度对比也验证了镜像和封闭直壁。该证据对应实验参数;本次精简平滑接口后还需验证匹配预处理条件下的一致性。
Shell 的 `build_normal_weight` 使用 `smoothstep(Shell Thickness / Reference Depth)` 混合法线。实验恐龙的 0.075 厚度与约 5.505 参考深度只留下约 0.055% 的平滑权重,解释了薄壳调节不明显。
## Goals / Non-Goals
目标是两个入口共用 Cutout 成形,独立对称节点负责后续镜像与补面,并让薄壳法线平滑有效。本轮实现范围为节点资产、创建流程及对应验证;Cutout 继续使用 Balloon / Shell,深度推理流程保持现有实现。
## Decisions
### 1. 对称作为成形后的节点
使用资产名称 `O Image Cutout Symmetry`,将其改为几何处理节点。Depth Solid 使用 Cutout;Depth Symmetry 使用以下顺序:
```mermaid
flowchart TD
A[原 Depth Symmetry 入口] --> B[O Image Depth Cutout:Thickness = 0]
B --> C[O Image Cutout Symmetry]
```
先完成 Balloon 或 Shell,再将结果整体交给对称节点。这与已验证实验一致,避免在 Cutout 内组合成形和镜像的模式分支。旧 Symmetry 的 Balloon 分支由上游 Cutout 的 Balloon 承担。
对称沿用原 Projected 的方向对齐、Z 向偏移、负侧面移除、镜像翻面及对应边界连接顺序。Shell 的内外表面都属于输入结果,分别保留其边界连接关系。负侧面移除沿用原面选择语义。
### 2. 简化接口与坐标约定
| 输入 | 行为 |
| --- | --- |
| Geometry | 接收 Cutout 已成形的几何 |
| Symmetry Direction | 复用原 Depth Direction 的方向对齐语义,默认 (0, 0, 1) |
| Depth Offset | 方向调整后沿对称轴偏移,默认 0 |
| Fill Sides | 连接前后对应边界,默认开启 |
| Fill Smooth | 仅控制新增侧壁的几何平滑次数,默认 2 |
始终保留镜像后的两侧。移除 Mode、图像及深度标定输入、Double Sided、Depth Axis、Smooth、Boundary Smooth、Smooth Weight、Uniform Scale。对称坐标系沿用原 Projected 的局部 XY 平面和 Z 轴;创建流程将上游 Cutout 初始化为与之匹配的 -Z 输出。接缝容差由输入几何尺度获得。
### 3. 补面平滑约束在新增侧壁内部
Fill Smooth 为 0 时直接使用原直壁补面。开启时,在对应前后边界间生成含中间环的侧壁条带,对中间顶点进行受限平滑,固定与原几何相接的两端;保持成对顶点关于对称平面对称。条带采样采用内部固定策略,不新增采样参数。
这使侧壁平滑具备可移动的内部顶点,并保持输入保留下来的面形状。只有改变着色法线不足以满足几何平滑要求。Fill Sides 关闭时跳过条带及平滑。复用 common 中的字段与平滑函数;不用 Capture Attribute,临时属性仅在确有跨几何保存需求时使用并清理。
### 4. 入口分配参数与零厚度基线
Cutout 节点资产的 Balloon 与 Shell 两种 Thickness 默认值均为 0,手动添加节点时也使用零厚度初态。Depth Solid 创建时按 Thickness 的 subtype 分别设置 Balloon 为 1、Shell 为 0.2;两个输入均初始化,切换模式时使用各自的创建值。手势对应模式沿用 Cutout 的 Balloon / Shell 选择约定。
Depth Symmetry 入口创建两个依次求值的 Geometry Nodes 修改器。深度图、参考深度和尺度交给 Cutout,原标定得到的方向交给 Symmetry。Cutout 使用两种 Thickness 的零默认值,切换模式也保持零厚度初态。
Depth Solid 与 Depth Symmetry 均请求并读取 `object_normal` 结果;对象创建时为深度 Cutout 材质指定 OBJECT,开启 `O Image Layer` 的 Object Space。
Depth Symmetry 创建时保留 Cutout 的参数默认值,包括 Depth Split、Boundary Smooth、Smooth 与 Depth Axis;仅沿用通用的手势模式选择、清理阈值和图像标定输入。下述一致性测试所需的关闭分割/平滑条件只在测试中显式设置。
一致性验收使用同一输入网格、深度、参考值、尺度、方向和偏移;新链路关闭额外 Cutout 分割/平滑,旧 Projected 的 Smooth 与 Boundary Smooth 也设为 0,新 Fill Smooth 为 0。分别验证 Balloon/Shell 零厚度与 Fill Sides 开关。额外开启上游平滑后的结果由该上游处理决定。
### 5. Shell 使用完整的平滑厚度方向
Shell 使用在原正面点域求值、按 Normal Smooth 模糊并归一化的法线作为厚度偏移方向,不再以厚度与参考深度之比衰减。厚度仅控制偏移距离;零厚度输出保持原正面。Balloon 保留现有厚度相关权重。
Normal Smooth 平滑的是壳体挤出方向,原始深度正面的几何平滑仍由 Cutout 的 Smooth 控制。测试覆盖实际较薄厚度及较大参考深度,避免只测试厚壳而遗漏衰减问题。
## Risks / Trade-offs
- 侧壁平滑可能收缩狭窄凹口或在复杂轮廓附近自交 → 固定接缝、保持镜像配对,使用现有两张样例检查小幅平滑效果;不将全局无自交作为任意参数的保证。
- 精简接口与旧图文件中的内嵌组不同 → 创建流程统一使用新资产接口,不自动重写用户已有对象;构建前保存基线测试资料,按新的参数分配更新节点测试。
- 同名资产及待归档旧提案可能描述不同职责 → 本变更作为后续修订;实现与归档时协调 `add-projected-depth-symmetry` 的最终规格,防止旧的单节点要求覆盖此设计。
## Migration Plan
先保留旧 Projected 的小型基线数据,再替换构建逻辑、接入双修改器入口并修正 Shell 法线。运行相关测试和 `uv run node-group build`,同步源码与资产。出现回归时成套恢复此次构建逻辑、入口参数和资产。
## Open Questions
无阻塞产品决策。侧壁条带的内部采样数量在实现时以现有样例验证,不增加公开控制项。

View File

@@ -0,0 +1,28 @@
## Why
Depth Cutout 已负责深度置换及 Balloon / Shell 成形,对称应当作为后续几何操作复用这些结果。独立实验已验证零厚度 Cutout 接对称节点可以复现原 Depth Symmetry 的 Projected 构成方式,同时发现薄 Shell 的 Normal Smooth 被厚度权重压低,需要修正。
## What Changes
- 保留 Depth Solid、Depth Symmetry 两个入口;Depth Symmetry 创建串联的 `O Image Depth Cutout`(两个模式的 Thickness 均为 0)和 `O Image Cutout Symmetry`。
- Cutout 节点资产中 Balloon / Shell 两种 Thickness 的默认值均为 0;Depth Solid 创建时分别设置为 1 和 0.2,Depth Symmetry 使用零厚度默认值。
- **BREAKING**:`O Image Cutout Symmetry` 改为接收已成形几何的对称节点,提取原 Projected 的方向对齐、偏移、负侧面移除、镜像及边界直壁补面逻辑;移除图像置换和 Mode。
- 对称节点提供 Geometry、Symmetry Direction、Depth Offset、Fill Sides、Fill Smooth;始终生成镜像,移除 Double Sided、Depth Axis、全局 Smooth、Boundary Smooth 及其配套输入。
- Fill Smooth 只平滑生成的侧壁,默认 2;Cutout 保持 Balloon / Shell 两种模式及其自身平滑控制。
- 两种深度 Cutout 入口均使用 Object Space 法线贴图,并开启材质 `O Image Layer` 的 Object Space。
- Shell 的 Normal Smooth 独立于厚度与参考深度的比例,实际控制壳体厚度偏移方向的平滑。
## Capabilities
### New Capabilities
- `post-cutout-symmetry`: 对已成形几何执行方向对齐、镜像、补面和补面平滑,定义原入口的节点串联及零厚度一致性。
- `shell-normal-smoothing`: 定义薄 Shell 的法线平滑作用及零厚度行为。
### Modified Capabilities
无。当前主规格目录为空;本变更接续 `add-projected-depth-symmetry` 中的节点实现。
## Impact
影响 `tools/nodes/groups/image_cutout_symmetry.py`、`image_depth_cutout.py`、相关共用节点函数、Cutout 对象创建与参数初始化、相关测试及 `src/anyimage/assets/O_AnyImage.blend`。不增加依赖。既有 `.blend` 内嵌节点不会自动迁移,后续从资产加载使用新接口。

View File

@@ -0,0 +1,74 @@
## ADDED Requirements
### Requirement: 原入口串联 Cutout 与对称节点
系统 SHALL 保留 Depth Solid 与 Depth Symmetry 入口。Depth Symmetry SHALL 按顺序创建 `O Image Depth Cutout` 和 `O Image Cutout Symmetry` 修改器,将 Cutout 两种 Thickness 输入均初始化为 0,并分别将深度标定参数与对称方向交给对应节点。
#### Scenario: 创建默认对称对象
- **WHEN** 用户通过原 Depth Symmetry 入口完成轮廓创建
- **THEN** 对象先执行零厚度 Cutout,再执行对称;Cutout 保留节点默认参数,包括 Depth Split、Boundary Smooth、Smooth 与 Depth Axis,仅沿用通用的手势模式选择、清理阈值和图像标定输入
- **AND** 切换 Balloon / Shell 后厚度仍为 0
### Requirement: 节点厚度默认值与入口初始化
`O Image Depth Cutout` 节点资产的 Balloon / Shell 两种 Thickness 默认值 SHALL 均为 0。Depth Solid 创建时 SHALL 按输入 subtype 分别设置 Balloon Thickness 为 1、Shell Thickness 为 0.2,其他创建默认设置保持不变;Depth Symmetry SHALL 使用两种厚度的零默认值。
#### Scenario: 手动添加 Cutout 节点
- **WHEN** 用户从资产添加未经入口覆写的 Cutout 节点
- **THEN** Balloon / Shell 两种 Thickness 均为 0
#### Scenario: 创建 Depth Solid
- **WHEN** 用户通过 Depth Solid 入口创建对象
- **THEN** Balloon Thickness 为 1,Shell Thickness 为 0.2,两个输入均完成初始化
- **AND** 切换模式时使用对应厚度值,边界平滑等其他默认设置保持不变
### Requirement: 成形后镜像与补面
对称节点 SHALL 接收上游完整几何,沿用原 Projected 的方向对齐、偏移、负侧面移除、镜像翻面与对应边界直壁连接语义。Fill Sides SHALL 控制是否添加连接侧壁。
#### Scenario: 非零厚度的两种成形结果
- **WHEN** Balloon 或 Shell 的非零厚度输出连接至对称节点
- **THEN** 节点对已成形结果执行对称;Shell 的壳体内外表面一同参与
- **AND** Fill Sides 关闭时不添加连接壁,开启时连接对应边界且保持面方向一致
### Requirement: 精简对称控制
对称节点 SHALL 仅公开 Geometry、Symmetry Direction、Depth Offset、Fill Sides、Fill Smooth 输入及 Geometry 输出,始终生成镜像两侧。默认方向 SHALL 为 (0, 0, 1),偏移 SHALL 为 0,Fill Smooth SHALL 为 2,Fill Sides SHALL 开启。
#### Scenario: 默认补面平滑
- **WHEN** 从资产加载新的对称节点
- **THEN** Fill Smooth 默认为 2
#### Scenario: 调整对称方向
- **WHEN** 用户调整 Symmetry Direction 和 Depth Offset
- **THEN** 几何使用原方向对齐及轴向偏移语义更新,对称平面位于调整后的局部 XY 平面
- **AND** 界面不提供 Double Sided、Depth Axis、全局 Smooth 或 Boundary Smooth
### Requirement: 深度 Cutout 使用 Object Space 法线
Depth Solid 与 Depth Symmetry SHALL 使用 Object Space 法线贴图,并在创建材质时开启 `O Image Layer` 的 Object Space。
#### Scenario: 创建深度 Cutout 材质
- **WHEN** 用户通过任一深度 Cutout 入口生成对象
- **THEN** 生成流程请求并读取 object_normal,材质的 Object Space 为开启状态
### Requirement: 仅平滑新增侧壁
Fill Smooth SHALL 控制新增侧壁的几何平滑,固定与保留输入几何相接的端点并保持镜像对称;数值为 0 SHALL 使用原直壁构成。
#### Scenario: 平滑连接壁
- **WHEN** Fill Sides 开启且 Fill Smooth 大于 0
- **THEN** 有曲率的轮廓所生成侧壁内部顶点可被平滑移动,原保留表面及接缝端点不受该平滑移动
- **AND** 对应连接保持封闭,镜像对称关系保持成立
#### Scenario: 禁用补面
- **WHEN** Fill Sides 关闭而 Fill Smooth 改变
- **THEN** 输出几何保持一致
### Requirement: 零厚度匹配原 Projected
在相同输入、标定与方向偏移、相同预处理条件下,Cutout 零厚度接对称节点 SHALL 与原 Depth Symmetry 的 Projected 在顶点位置、面连接及朝向上等价。
#### Scenario: 两种模式与补面开关的一致性
- **WHEN** 分别选择 Balloon / Shell 且两个厚度均为 0,Cutout 分割与平滑关闭、Depth Axis 为 -Z,旧 Projected 的 Smooth 与 Boundary Smooth 为 0,新 Fill Smooth 为 0
- **THEN** 对 Fill Sides 开关分别比较,新旧结果的顶点位置在浮点容差内一致,面数、连接及朝向一致

View File

@@ -0,0 +1,19 @@
## ADDED Requirements
### Requirement: 薄壳法线平滑不受相对厚度衰减
Shell 的 Normal Smooth SHALL 控制原正面点域法线的模糊次数,归一化后的结果用于壳体厚度偏移方向。系统 SHALL 不使用 Shell Thickness / Reference Depth 衰减该平滑;厚度控制偏移距离,Balloon 保留现有权重行为。
#### Scenario: 小厚度下调节平滑
- **WHEN** 非平面且法线有起伏的正面以小厚度生成 Shell,用户增大 Normal Smooth
- **THEN** 壳体的归一化偏移方向发生相应平滑变化,且不会因厚度与参考深度的比值接近零而退回原始法线
- **AND** 保持前表面相同而改变厚度时,平滑方向保持一致、偏移距离随厚度变化
### Requirement: 法线平滑保留正面与零厚度行为
Shell 的 Normal Smooth SHALL 仅通过厚度偏移作用于壳体,保留原深度正面;零厚度 SHALL 不因该参数改变几何。
#### Scenario: 零厚度与平面
- **WHEN** Shell 厚度为 0 时改变 Normal Smooth
- **THEN** 顶点位置与面连接保持一致
- **AND** 对常法线平面使用非零厚度时,改变 Normal Smooth 也不改变壳体形状

View File

@@ -0,0 +1,27 @@
## 1. 对称节点
- [x] 1.1 保存原 Projected 的小型确定性基线数据,覆盖关闭额外平滑后的顶点位置、面连接和朝向。
- [x] 1.2 将 `O Image Cutout Symmetry` 改为几何处理节点,保留方向对齐、偏移、负侧面移除、镜像和直壁补面,按设计精简接口并处理几何尺度容差。
- [x] 1.3 实现 Fill Smooth:生成侧壁内部采样,固定接缝并保持镜像配对;关闭补面时跳过,平滑为 0 时使用原直壁。
## 2. 入口与 Shell
- [x] 2.1 将 Cutout 资产中两种 Thickness 默认值设为 0;Depth Solid 创建时按 subtype 分别设置 Balloon 为 1、Shell 为 0.2。更新 Depth Symmetry 创建为 Cutout → Symmetry 两个修改器,保留 Cutout 节点默认参数,沿用通用的手势模式选择、清理阈值与图像标定,为对称节点初始化方向。
- [x] 2.2 修正 Shell 厚度方向使用完整平滑法线,解除相对厚度衰减,保留原正面、零厚度行为和 Balloon 权重逻辑。
## 3. 验证与资产
- [x] 3.1 更新相关入口及接口测试,验证资产两种厚度默认值为 0、Depth Solid 创建值为 1 / 0.2、Depth Symmetry 使用零厚度且切换模式正确;验证两种模式零厚度、Fill Sides 开关与原 Projected 基线一致。
- [x] 3.2 验证 Balloon/Shell 非零厚度的镜像与补面,以及 Fill Smooth 的侧壁位移、接缝固定、封闭性和镜像关系;使用已有两张去背景图片复核外观。
- [x] 3.3 增加薄 Shell 法线方向平滑的有效覆盖,同时验证零厚度、常法线平面及 Balloon 行为。
- [x] 3.4 运行相关测试和 `uv run node-group build`,验证源码与保存资产无 Capture Attribute、临时属性正确清理,检查最终差异;不打包扩展。
## 验证记录
- 后续调整:Fill Smooth 默认值改为 2;两个深度入口均请求 Object 法线并开启材质 Object Space。资产重建及独立校验通过,66 项对应测试通过。
- 81 项相关测试通过,覆盖入口、节点定义与资产、零厚度基线、补面平滑、薄 Shell、材质属性与布局。
- `uv run node-group build` 完成资产生成与独立进程校验;随后的全量测试发现 5 个需要同步的新接口/行为断言及 1 个既有 Depth Plane 边界平滑失败。前 5 个已修正并通过相关复测。
- 既有失败为 `test_validity_cut_smoothing_preserves_original_outline_and_interior`;在内存中恢复 HEAD 版本的两份节点构建模块后仍能复现,本变更未修改该用例或 Depth Plane 平滑逻辑。
- 最终 `uv run node-group build --skip-tests` 正常退出,10 个保存节点组均通过校验;`git diff --check` 通过。
- 两张已去背景的原样例分别检查 Balloon=1、Shell=0.2 和 Fill Smooth=0/3:八组均无边界边或非流形边,镜像位置误差为 0;已检查渲染。结果位于 `C:/Users/icrdr/Desktop/anyimage/post-cutout-symmetry-20260914/applied/`。