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,61 @@
## Context
本设计对应 proposal 中的 Cutout 切口行为,基于当前工作区已有的边界深度平滑。实图实验位于 `.tmp/skull-mask-check`;正式测试使用可重建的合成几何,实图用于视觉验收。
采用 `split_round_trial.py` 的 DELETE 分支中的三角面删除与厚度轮廓计算作为边界处理参考,平滑沿用当前公共实现;采用 `live_contact_comparison.py` 中独立的厚度关联法向混合逻辑。最新共点修复虽然降低了拓扑异常计数,用户截图中的视觉接触仍然存在,因此该实验不能作为视觉问题已解决的依据。
## Goals / Non-Goals
**Goals:** 保留参数实时求值,改善新切口的平滑、厚度与圆润过渡,并使薄厚度下的法向平滑影响连续趋零。
**Non-Goals:** 按用户决定,暂缓共点/共线修复与空间接触消除;不引入 Valid Only、Validity Threshold 或实验用 Repair Contacts 控件。
## Decisions
### 求值顺序
```mermaid
flowchart TD
A[原网格与原轮廓参照] --> B[实时 Split]
B --> C[一次删除全边界三角面]
C --> D[现有边界深度平滑与投影]
D --> E[现有边界网格平滑]
E --> F[新切口厚度轮廓收敛]
F --> G[按厚度混合法向]
G --> H[厚度与 Edge Round 成形]
H --> I[现有前后表面连接和输出]
```
### 边界三角面清理
在 Split 输出的当前拓扑上,以 Point 域边界标记转换至 Face 域,选出三个顶点全部位于边界的三角面,一次删除后再投影和平滑。使用一次清理保留实验中已经认可的形状,避免递归删除持续侵蚀轮廓。
清理后使用现有 Boundary Smooth。`Boundary Smooth = 0` 直接跳过平滑,保留既有深度平滑控制语义。验收时比较清理后、平滑前后的面朝向,确认已观察到的锯齿翻面问题得到改善。
### 新切口的厚度与圆润过渡
在清理后的网格上识别新边界,使用明确的原几何参照保护原 Alpha 轮廓。实验通过 UV 空间最近点采样原边界标记;正式实现需覆盖新旧边界交接处,确保内部切口不会误判为原轮廓。
沿新边界计算 UV 距离 `d`,过渡宽度 `w = 0.025 + 0.035 * Edge Round`;保留比例 `r = sqrt(clamp(d / w, 0, 1))`。新边界取零,保护点取一,更新厚度轮廓为 `o_balloon * r`。没有新边界时直接保留原轮廓字段,避免空目标距离产生错误衰减。
在现有厚度、中心面与圆润计算之前更新轮廓,使新切口成为前后表面的零厚度交汇线。复用现有前后表面成形链,并验证最终交汇处实际厚度,不能只检查 `o_balloon` 数值。Edge Round 增大时过渡带加宽,内部厚度逐渐恢复;原轮廓保持现有规则。
`o_balloon` 是现有 Point 域 FLOAT 厚度协议,此处在当前前表面写入、Selection 为全部点,由后续厚度和圆润消费者读取。其余字段优先直接连接;跨几何采样明确参照几何及域,保持 Capture Attribute 为零。实验诊断属性不进入正式资产。
### 厚度关联法向平滑
保留 Normal Smooth 迭代数,以厚度控制原法向与 Blur 结果的混合,再 Normalize:`normalize(mix(raw_normal, blurred_normal, smoothstep(0, 1, t)))`。
Balloon 模式 `t = Thickness`;Uniform 模式 `t = Thickness / max(Reference Depth, 1e-8)`。应用于前表面、中心面及膨胀方向的三处法向平滑消费位置,各自在原有源几何和域上求值。混合始终启用,保留用户 Normal Smooth 参数;厚度达到归一化值 1 后恢复完整 Blur 结果。薄厚度减弱的是平滑额外产生的方向偏差,不能据此承诺所有前后表面完全重合。
### 参数与资产
Split Threshold、Boundary Smooth、Thickness、Normal Smooth、Edge Round 保留现有接口与实时输入。清理与轮廓计算全部在节点求值阶段完成。正式资产使用项目现有布局与加载版本机制,按实施时基线更新版本。
实现完成后运行相关测试和 `uv run node-group build`,更新源码、测试、资产并独立加载验证。当前提案阶段只产出 OpenSpec 文件。
## Risks / Trade-offs
- 全边界三角面可能构成细小真实结构 → 用窄条、尖角与孔洞检查一次清理的形状代价。
- UV 距离过渡在不同长宽比和网格密度下外观不同 → 覆盖长宽图及多个 Mesh Detail,保持归一化 UV 语义。
- 拓扑计数正常仍可能有空间接触或交叉 → 本次验收以已确认的切口形状改善为目标,保留用户指出的共点问题记录。

View File

@@ -0,0 +1,25 @@
## Why
Depth Cutout 的 Split 新边界仍继承原 Balloon 厚度,容易膨胀成尖脊;Boundary Smooth 在锯齿三角形上可能翻面,进一步改变厚度方向。恐龙头骨实图实验已确认边界厚度收敛、切口圆润和薄厚度下减弱法向平滑的效果,需要将这些行为整理为正式节点实现。
## What Changes
- Split 后清理三个顶点都位于边界的三角面,降低锯齿切口的退化风险。
- 新切口的 Balloon 厚度在边界收敛为零,邻近区域逐渐恢复;Edge Round 同时控制新切口的圆润过渡。
- 法向平滑结果按厚度连续混合:薄厚度接近原法向,正常厚度恢复既有平滑效果,默认始终启用。
- 保留 Split Threshold、Boundary Smooth 及厚度、Edge Round 的实时调节,参数变化后重新计算边界与形状。
## Capabilities
### New Capabilities
- `cutout-split-boundary-shaping`:切口清理、边界厚度收敛、圆润过渡及厚度关联法向平滑。
### Modified Capabilities
## Impact
- `tools/nodes/groups/image_depth_cutout.py` 及必要的 `tools/nodes/common` 构建函数。
- `tests/tools/nodes` 的 Cutout、边界平滑及属性生命周期测试。
- `src/anyimage/assets/O_AnyImage.blend` 中的 Cutout 节点资产及对应加载版本。
- 基于当前工作区的边界深度平滑继续实施,保留已有修改。

View File

@@ -0,0 +1,69 @@
## ADDED Requirements
### Requirement: Split boundary triangle cleanup
Depth Cutout SHALL 在 Split 后、投影与边界平滑前,一次删除三个顶点均在当前边界上的三角面。
#### Scenario: Remove a boundary ear
- **WHEN** Split 输出包含三个边界顶点的三角面及包含内部顶点的相邻三角面
- **THEN** 前者被删除,后者保留,清理不递归传播
### Requirement: Boundary smoothing after cleanup
Depth Cutout SHALL 在三角面清理后的几何上沿用现有 Boundary Smooth,保留其参数语义。
#### Scenario: Smooth the cleaned boundary
- **WHEN** 全边界三角面清理完成且 Boundary Smooth 大于 0
- **THEN** 现有平滑在保留几何上求值,已删除三角面不参与平滑
#### Scenario: Disable boundary smoothing
- **WHEN** Boundary Smooth 为 0
- **THEN** 深度及网格平滑步骤保持各自输入值,其他切口形状处理继续按当前参数求值
### Requirement: Rounded split thickness profile
Depth Cutout SHALL 使新切口的 Balloon 厚度轮廓在边界为零,在邻近区域连续恢复,并使 Edge Round 影响新切口的圆润过渡。
#### Scenario: Form a new meeting boundary
- **WHEN** Split 产生内部切口并执行 Balloon 厚度成形
- **THEN** 新切口前后表面在零厚度边界交汇,影响带外保留原厚度轮廓
#### Scenario: Adjust edge rounding
- **WHEN** 用户增加 Edge Round
- **THEN** 新切口的过渡带随之加宽,最终几何呈现圆润过渡的变化,原 Alpha 轮廓继续使用既有规则
#### Scenario: No new boundary
- **WHEN** 当前 Split 结果没有新增边界
- **THEN** 切口轮廓步骤保留原厚度字段
### Requirement: Thickness weighted normal smoothing
Depth Cutout SHALL 始终按归一化厚度的 smoothstep 权重混合原法向与平滑法向,再归一化;保留 Normal Smooth 对平滑迭代数的控制。
#### Scenario: Thin thickness
- **WHEN** Balloon Thickness 趋于 0,或 Uniform Thickness 与 Reference Depth 的比例趋于 0
- **THEN** 法向平滑引入的方向偏差连续趋于 0,结果保持有限
#### Scenario: Full smoothing strength
- **WHEN** 归一化厚度达到或超过 1
- **THEN** 使用完整的既有法向平滑结果
#### Scenario: Normal smoothing disabled
- **WHEN** Normal Smooth 为 0
- **THEN** 混合结果等于对应消费几何上的原法向归一化结果
### Requirement: Live cutout controls
Depth Cutout SHALL 在每次参数变更后重新求值 Split、边界平滑和厚度成形,保留现有参数接口。
#### Scenario: Edit the loaded modifier
- **WHEN** 用户加载节点资产后连续修改 Split Threshold、Boundary Smooth 和 Edge Round
- **THEN** 几何按新参数实时更新,恢复相同参数可重现相同结果,不依赖冻结的中间网格
### Requirement: Loadable node asset
本功能 SHALL 随正式节点资产交付,所有相关节点组及测试辅助图保持 Capture Attribute 为零,并保留用户属性。
#### Scenario: Independently load built asset
- **WHEN** 在独立 Blender 进程加载重建资产
- **THEN** 接口、动态形状求值和必要属性均正确,输出不含实验诊断或已结束生命周期的内部临时属性

View File

@@ -0,0 +1,23 @@
## 1. 切口清理
- [x] 1.1 核对当前 Cutout 与公共边界平滑调用链,在 Split 后接入一次全边界三角面清理,保留现有工作区修改。
- [x] 1.2 在清理后的几何上沿用现有边界平滑,检查域求值和 Boundary Smooth 为 0 时的行为。
- [x] 1.3 用锯齿、窄条、孔洞合成网格验证一次删除范围,并检查清理后平滑的面朝向,覆盖 Boundary Smooth 0、5、12、20。
## 2. 切口厚度与圆润
- [x] 2.1 区分原 Alpha 轮廓与新切口,在明确源几何上求值 UV 距离过渡并更新现有 o_balloon 字段,处理无新边界分支。
- [x] 2.2 将过渡轮廓接入厚度和 Edge Round 消费链,验证最终交汇厚度、过渡带外保持及新旧边界交接。
- [x] 2.3 覆盖 Edge Round 0、0.2、0.6,不同图像长宽比、Mesh Detail 与 Balloon/Uniform 模式,检查有限结果及原轮廓行为。
## 3. 厚度关联法向
- [x] 3.1 在三处法向平滑消费位置接入始终启用的厚度结果混合,保留 Normal Smooth 迭代数和现有源几何语义。
- [x] 3.2 添加薄厚度趋零、归一化厚度 1 还原完整平滑、Normal Smooth 0 和 Reference Depth 零值保护的自动化回归。
## 4. 资产与验收
- [x] 4.1 整理节点布局和最少属性生命周期,检查源码与测试辅助图 Capture 为零、保留用户属性并清理临时字段。
- [x] 4.2 运行相关 Cutout、边界平滑、属性及加载测试,执行 `uv run node-group build`,更新并验证正式资产及加载版本。
- [x] 4.3 独立加载资产,连续调整并恢复 Split Threshold、Boundary Smooth、厚度与 Edge Round,检查实时更新及结果可重现。
- [x] 4.4 使用已缓存恐龙头骨数据做边界形状验收,覆盖 Split Threshold 0、0.25、0.5、1 和 Boundary Smooth 0、5、12、20,记录 High 网格求值耗时;厚度关联效果以自动化回归确认。