Add tests and implement boundary smoothing and cutout functionality

- Introduced tests for boundary smoothing in `test_boundary_smoothing.py`, verifying that smoothing reduces stair-step artifacts while preserving boundary integrity.
- Added tests for cutout boundary behavior in `test_cutout_boundary.py`, ensuring proper handling of boundary triangles and normal blending.
- Created `test_temporary_attributes.py` to check the cleanup of temporary attributes across depth modifier branches, ensuring no warnings are raised.
- Implemented point culling functionality in `test_validity.py`, confirming that invalid points are removed without affecting adjacent geometry.
- Developed boundary smoothing logic in `boundary_smoothing.py`, allowing for depth smoothing while maintaining edge integrity.
- Added cutout boundary management in `cutout_boundary.py`, including functions for removing boundary triangles and tapering thickness profiles.
- Implemented validity checks in `validity.py` to ensure proper deletion of invalid vertices and associated wire edges.
This commit is contained in:
2026-09-11 20:37:20 +08:00
parent e8129fe495
commit 31074bd511
85 changed files with 2501 additions and 1451 deletions

View File

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

View File

@@ -0,0 +1,72 @@
## Context
当前三个深度表面均在投影后执行 Boundary Smooth。Depth Cutout 保护原 Alpha 轮廓的三维位置,Depth Plane 平滑有效性剔除形成的新边界,Depth Panorama 平滑球面的实际开口。
独立实验复用了猫、幼虫和人物的已有深度数据。Cutout 的六个网格在 4、12 次深度 Blur 后明显减少尖刺;Depth Plane 在 Subdivide 4、6 和 Boundary Smooth 5、12 下也有改善。两轮实验均验证关闭还原、拓扑保持和厚度/Split 组合。全景尚需专项验证。
实验文件位于本机临时目录 `anyimage-boundary-depth-trial`:`boundary-smooth-comparison.blend`、`convert-boundary-comparison.blend` 及对应指标 JSON。正式回归测试使用可重建的合成数据;实图用于人工验收。
## Goals
- 三个已有 Boundary Smooth 的深度表面使用同一标量平滑规则和参数语义。
- 在边界窄带降低采样深度突变,保留内部数据及对应投影方向。
- 通过现有公共节点构建模块复用实现,并更新可直接加载的节点资产。
## Decisions
### 求值顺序
```mermaid
flowchart TD
A[基础网格与深度采样] --> B[有效性剔除]
B --> C[Split 与切口深度处理]
C --> D[在当前连通网格上 Blur 深度标量]
D --> E[按边界两圈影响权重混合]
E --> F[沿原投影方向置换]
F --> G[现有 Boundary Smooth 网格平滑]
G --> H[厚度与后续形状处理]
```
共享实现位于 `tools/nodes/common/boundary_smoothing.py`,输入深度标量和边界保护字段,输出平滑后的标量。字段在剔除和 Split 后、置换前的 Point 域求值,使已删区域及已分离表面按当前拓扑隔离。各组负责把标量接入自身的投影表达式。
### 参数与影响范围
`Boundary Smooth` 同时给深度 Blur 和现有网格平滑提供迭代数,默认 `5`、范围 `0–20`,保持已有 socket 标识。实验中的独立 `Boundary Depth Blur` 输入收敛为现有控制项。
深度 Blur 使用 `FLOAT`、固定 Weight `0.5`。令 `B` 为可处理的边界点字段,`P` 为保护字段:
- 在当前网格上对 `B` 执行 2 次、Weight `1` 的 Blur。
- 应用权重为 `max(B, blurred_B) * (1 - P)`,外边界完全应用,邻近两圈逐渐减弱。
- 原深度与平滑深度按该权重混合。
- 迭代数为 `0` 或权重为 `0` 时直接返回原采样值,保证关闭及影响范围外的精确保持。
深度计算和影响权重使用共享字段连接。`Smooth Weight` 延续现有网格平滑职责,深度 Blur 的固定 Weight 与独立实验一致。
### 三个节点组的边界与投影
| 节点组 | 深度 Blur 影响边界 | 标量与重建方式 |
| --- | --- | --- |
| O Image Depth Cutout | 原 Alpha 轮廓及 Split 后的新边界 | 平滑相机 Z;按新旧 Z 比例缩放原相机点,再进入现有投影 |
| O Image Depth Plane | 有效性剔除及 Split 后的新边界;保护 UV 原矩形外框 | 平滑相机 Z;按原相机射线重建点,再进入现有投影 |
| O Image Depth Panorama | 球面有效性剔除及 Split 后产生的实际开口 | 平滑有效径向距离;保持球面方向,再进入 Depth Scale 的半径表达式 |
Cutout 原轮廓的深度可以变化,后续网格平滑继续使用现有原轮廓保护字段。这样保留图像投影轮廓,同时允许轮廓深度变平顺。Depth Plane 的矩形外框保护同时约束影响起点和最终权重。
Panorama 的经度接缝和极点依照真实球面拓扑求值;UV 接缝本身不形成平滑边界。有效距离平滑在 `Invalid Distance` 替代分支之前接入,保留区域的无效距离继续由该参数决定。无效区域与有效区域之间沿现有剔除逻辑断开混合面,验证其不会参与有效边界的平均。
相机 Z 重建必须处理零值及不可用于比例计算的采样,直接保留对应原点值,保证结果有限。投影方向保持的断言放在深度平滑/置换阶段;后续网格平滑仍按既有规则移动顶点。
### 节点与资产组织
公共函数以标量字段为复用边界,三个消费组分别完成相机与球面重建。使用显式域转换及明确源几何采样,所有几何组与嵌套组保持 Capture Attribute 为零。直接连接可复用字段;必要的现有临时命名协议在最后消费者后清理,保留用户属性。
实施时读取当前工作区基线,保留其他修改。完成源码与测试后运行 `uv run node-group build`,更新 `O_AnyImage.blend` 并独立加载验证接口、求值和节点布局。
三个消费组的资产版本统一设为 12,运行时通过 `load_node_group(..., asset_revision=12)` 请求。加载器保留当前文件中旧组及其现有使用者,为新建对象读取新版本;对应 Operator 回归覆盖旧组存在时的行为。
## Risks / Trade-offs
- 稀疏网格的两圈覆盖范围较宽,较高迭代数可能软化真实轮廓深度 → 保留默认值 5,并用 Subdivide 4、6 对比 5、12 的效果。
- 深度 Blur 与后置网格平滑叠加 → 分别检查置换阶段的射线保持、最终尖刺改善和整体形状,不把梯度下降单独视为几何更准确。
- 模型 validity 开口可能位于物体内部 → 使用内部孔洞、真实深度断层与孤立尖刺的合成用例,检查影响范围及不同连通表面的隔离。
- 球面方向和无效距离与相机 Z 语义不同 → Panorama 使用径向适配,覆盖经度接缝、极点、Invalid Distance 和 Valid Only 两个分支后再交付。

View File

@@ -0,0 +1,27 @@
## Why
Alpha 轮廓和有效性剔除留下的网格边界仍可能采到突变深度,形成尖刺。独立 Blender 实验已验证:在置换前平滑边界采样深度,再执行现有边界网格平滑,可明显改善 Depth Cutout,并进一步改善 Depth Plane。
## What Changes
- 为 `O Image Depth Cutout`、`O Image Depth Plane`、`O Image Depth Panorama` 统一加入置换前的边界深度平滑。
- 复用 `Boundary Smooth` 控制深度 Blur 与现有边界网格平滑的迭代数,保留默认值 `5`、范围 `0–20`;`0` 完全关闭两者。
- 在有效性剔除及 Split 后的连通网格上平滑深度标量,仅应用于可处理边界及邻近两圈,并保持各顶点原投影方向。
- Cutout 的原 Alpha 轮廓参与深度平滑;Depth Plane 保留原矩形外框保护;Panorama 按球面径向距离处理实际网格边界。
- 复用公共构建函数,补齐行为测试、全景专项验证与节点资产重建。
## Capabilities
### New Capabilities
- `boundary-depth-smoothing`:三个深度表面的统一参数、边界选择、采样阶段、投影保持及资产验证。
### Modified Capabilities
## Impact
- `tools/nodes/common/boundary_smoothing.py` 及三个深度表面节点构建模块。
- `tests/tools/nodes` 中的边界平滑、深度表面、Cutout 和全景行为测试。
- `src/anyimage/assets/O_AnyImage.blend` 中对应节点组及必要的资产版本标识。
- Cutout、Depth Plane 和 Panorama 的资产读取入口:新建对象请求本次节点版本,保留场景内旧组的现有使用者。
- 使用现有 Blender 节点与依赖;深度平滑在几何节点求值阶段完成。

View File

@@ -0,0 +1,90 @@
## ADDED Requirements
### Requirement: Shared Boundary Smooth control
`O Image Depth Cutout`、`O Image Depth Plane`、`O Image Depth Panorama` SHALL 使用同一 `Boundary Smooth` 输入控制边界深度 Blur 和现有边界网格平滑的迭代数,默认值为 5,范围为 0–20,并保留该输入的既有标识。
#### Scenario: Positive iteration count
- **WHEN** 用户将任一组的 Boundary Smooth 设为 12
- **THEN** 深度 Blur 和现有边界网格平滑均使用 12 次迭代
- **AND** 修改器只提供现有 Boundary Smooth 控制项
#### Scenario: Disabled smoothing
- **WHEN** Boundary Smooth 为 0
- **THEN** 输出几何与两种边界平滑均关闭的基线一致
- **AND** 深度采样直接使用原值
### Requirement: Topology-local scalar smoothing
系统 SHALL 在有效性剔除及 Split 后、投影前的网格 Point 域对深度标量执行 Weight 为 0.5 的 Blur,并在可处理边界及邻近两圈内应用结果。边界影响权重 SHALL 由边界字段的 2 次 Weight 为 1 的 Blur 与原边界字段取最大值后,排除保护点得到。
#### Scenario: Isolated boundary spike
- **WHEN** 原本平缓的表面在一个可处理边界点具有深度尖刺并启用 Boundary Smooth
- **THEN** 深度突变通过当前网格邻域的标量平均减弱
- **AND** 深度平滑阶段的顶点、边、面及 UV 拓扑保持不变
#### Scenario: Interior preservation
- **WHEN** 顶点位于影响范围之外
- **THEN** 深度平滑阶段直接保留其原采样值
#### Scenario: Deleted and separated samples
- **WHEN** 邻近像素所属网格已被有效性剔除,或邻接表面已由 Split 分离
- **THEN** 平滑仅使用当前连通网格的样本,不跨已删区域或分离表面平均
### Requirement: Cutout silhouette depth smoothing
Depth Cutout SHALL 将原 Alpha 轮廓和 Split 后的新边界纳入深度平滑,并保留现有后置网格平滑的原轮廓保护规则。
#### Scenario: Fine Outline with zero thickness
- **WHEN** Fine Outline 的原轮廓存在异常深度,Thickness 为 0 且 Boundary Smooth 大于 0
- **THEN** 原轮廓点的深度参与平滑
- **AND** 深度平滑后的相机投影轮廓在浮点容差内保持一致
### Requirement: Depth Plane rectangle protection
Depth Plane SHALL 对有效性剔除或 Split 形成的可处理边界应用深度平滑,并同时从边界起点和最终应用权重中排除原 UV 矩形外框。
#### Scenario: Alpha or model-validity opening
- **WHEN** Valid Only 因 Alpha 或模型 validity 删除网格并形成新开口
- **THEN** 新开口及邻近两圈参与深度平滑
- **AND** 保留下来的原矩形外框点保持既有保护行为
#### Scenario: Intact rectangle
- **WHEN** Valid Only 和 Split 均关闭,网格仅有原矩形外边界
- **THEN** 新增深度 Blur 对输出不产生变化
### Requirement: Projection-aware reconstruction
Cutout 和 Depth Plane SHALL 在深度平滑阶段保持原相机射线,通过平滑后的 Z 重建相机点;Depth Panorama SHALL 平滑径向距离并保持原球面方向。方向保持以现有后置网格平滑之前的结果为准。
#### Scenario: Camera depth reconstruction
- **WHEN** 正的有效相机 Z 被平滑
- **THEN** 新旧相机点的 X/Z、Y/Z 在浮点容差内一致
#### Scenario: Degenerate camera depth
- **WHEN** 原采样 Z 无法安全用于比例重建
- **THEN** 保留原采样,不因深度平滑产生非有限值
#### Scenario: Panorama seam and poles
- **WHEN** 有效表面跨越经度接缝或覆盖极点
- **THEN** 深度 Blur 使用实际球面邻接,不将 UV 接缝当作网格开口
- **AND** 径向重建保持每个点的球面方向
#### Scenario: Retained invalid panorama region
- **WHEN** Panorama 保留无效区域并使用 Invalid Distance
- **THEN** 无效区域继续使用指定距离
- **AND** 无效替代距离不混入有效边界的深度平均
### Requirement: Integrated geometry and asset verification
系统 SHALL 保持厚度、Split、Depth Scale、UV、材质和用户属性的既有职责,所有几何节点及嵌套组 MUST 保持 Capture Attribute 为零。更新后的节点源码、行为测试及保存资产 SHALL 一致。
#### Scenario: Surface modes and downstream shaping
- **WHEN** 三个深度表面组合使用边界平滑与自身支持的 Split、Depth Scale、厚度或 Cutout 模式
- **THEN** 输出为有效几何,属性和材质传递符合原有协议
- **AND** 深度平滑不改变有效性剔除与 Split 的拓扑判定
#### Scenario: Rebuilt asset
- **WHEN** 执行节点资产构建并在独立 Blender 进程中重新加载保存资产
- **THEN** 资产与源码构建结果通过相同的行为验证
- **AND** 公共参数、节点连接和 Capture 禁用检查通过

View File

@@ -0,0 +1,28 @@
## 1. 实施基线
- [x] 1.1 检查当前工作区修改、三个节点组的参数标识和调用顺序,保留已有工作;运行相关边界与深度节点测试,记录基线。
- [x] 1.2 复查独立实验的 Cutout 和 Depth Plane 对比,准备可重建的尖刺、内部孔洞、深度断层及全景接缝/极点合成场景。
## 2. 公共深度平滑
- [x] 2.1 在 common/boundary_smoothing.py 中实现 Point 域标量 Blur、两圈影响权重及保护字段,复用现有节点辅助函数。
- [x] 2.2 实现迭代数为 0 和影响权重为 0 时的原值直通,验证内部精确保持、拓扑不变及分离表面的采样隔离。
## 3. 节点组接入
- [x] 3.1 接入 Depth Cutout,在 Split 后、投影前平滑相机 Z,按原射线重建;让原 Alpha 轮廓参与深度平滑,并保留后置网格平滑的既有保护规则。
- [x] 3.2 接入 Depth Plane,复用原 UV 矩形外框保护,处理 Valid Only 和 Split 的新边界;验证完整矩形的新增深度平滑为恒等操作。
- [x] 3.3 接入 Depth Panorama,在当前球面拓扑上平滑有效径向距离,接回 Depth Scale 表达式;验证 Invalid Distance、Valid Only 两分支、UV 接缝和极点。
- [x] 3.4 三组共用 Boundary Smooth 迭代数,保留默认 5、范围 0–20 和既有 socket 标识;更新对应界面描述并精简重复连接。
## 4. 回归与实图验收
- [x] 4.1 为源码构建和保存资产补齐零值直通、边界尖刺、两圈外保持、零深度、相机射线/球面方向及原矩形保护的行为测试。
- [x] 4.2 覆盖 Alpha 与模型 validity 开口、Split 隔离、Cutout 两种模式、零/正厚度及 Depth Scale;检查几何、UV、材质与用户属性传递。
- [x] 4.3 对三张既有实图复验 Cutout 与 Depth Plane,比较 Boundary Smooth 5、12 及不同密度;检查尖刺改善和过度软化,并完成全景专项验收。
- [x] 4.4 递归检查几何组及嵌套组 Capture 为零,审查命名属性的必要性与清理位置,确认节点布局可读。
## 5. 资产与交付
- [x] 5.1 运行 uv run node-group build,更新 O_AnyImage.blend 和必要资产版本标识,在独立 Blender 进程中加载并验证。
- [x] 5.2 运行相关节点及 Operator 测试,确认正常退出;核对源码与资产的一致性、最终差异和旧引用,保留已有其他修改。