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:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-11
|
||||
61
openspec/changes/refine-cutout-split-boundaries/design.md
Normal file
61
openspec/changes/refine-cutout-split-boundaries/design.md
Normal 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 语义。
|
||||
- 拓扑计数正常仍可能有空间接触或交叉 → 本次验收以已确认的切口形状改善为目标,保留用户指出的共点问题记录。
|
||||
25
openspec/changes/refine-cutout-split-boundaries/proposal.md
Normal file
25
openspec/changes/refine-cutout-split-boundaries/proposal.md
Normal 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 节点资产及对应加载版本。
|
||||
- 基于当前工作区的边界深度平滑继续实施,保留已有修改。
|
||||
@@ -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** 接口、动态形状求值和必要属性均正确,输出不含实验诊断或已结束生命周期的内部临时属性
|
||||
23
openspec/changes/refine-cutout-split-boundaries/tasks.md
Normal file
23
openspec/changes/refine-cutout-split-boundaries/tasks.md
Normal 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 网格求值耗时;厚度关联效果以自动化回归确认。
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-11
|
||||
@@ -0,0 +1,70 @@
|
||||
## Context
|
||||
|
||||
本次只读核对了当前构建源码和保存资产。以下为组内节点数量,嵌套引用单独追踪,实施前须重新确认基线。
|
||||
|
||||
| 几何节点组 | Capture | Store |
|
||||
| --- | ---: | ---: |
|
||||
| O Image Plane | 1 | 2 |
|
||||
| O Image Depth Plane | 6 | 0 |
|
||||
| O Image Relief Plane | 0 | 0 |
|
||||
| O Image Cutout | 0 | 1 |
|
||||
| O Image Depth Cutout | 8 | 3 |
|
||||
| O Image Depth Balloon | 0 | 1 |
|
||||
| O Image Depth Panorama | 6 | 1 |
|
||||
| 合计 | 21 | 8 |
|
||||
|
||||
Depth Plane、Relief Plane 引用 Image Plane。三个材质组作为命名属性消费者纳入核查。工作区已有节点逻辑、测试和资产修改,基线采用实施开始时的实际工作区状态。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
目标是全部几何组及其嵌套组 Capture 为零、字段消费关系清晰、存储具有实际必要性,源码、资产、规范与测试一致。保持公开接口、几何效果、UV、材质及用户输入属性行为;交付包括节点资产构建与测试。
|
||||
|
||||
## Decisions
|
||||
|
||||
### 字段在消费位置求值
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[字段及实际消费者] --> B{需要按名称访问}
|
||||
B -->|是| C[保留必要命名属性]
|
||||
B -->|否| D{消费上下文求值等价}
|
||||
D -->|是| E[字段直连并显式转换域]
|
||||
D -->|否| F[调整消费顺序或在源几何采样]
|
||||
F --> G{仍需保存源数据}
|
||||
G -->|否| E
|
||||
G -->|是| H[仅存储必要命名数据]
|
||||
H --> I[最后消费者后清理临时属性]
|
||||
```
|
||||
|
||||
Capture Attribute 在生产构建、嵌套组、保存资产和相关测试辅助图中均禁止使用。多个消费者、跨区域或连线较长不构成存值理由。Evaluate on Domain 用于域转换;它不固定几何版本。源几何采样必须明确源几何、域与索引对应关系,并同时评估布局和求值开销。
|
||||
|
||||
每处保留的 Store 记录名称、类型、域、Selection、写入阶段、实际读者和必要性。跨变形或拓扑变化仍需保存时,先减少携带的数据,再使用必要命名属性;不按现有 Capture 的字段清单逐项替换 Store。内部临时属性使用专用前缀,在最后消费者后清理;避免覆盖或删除已有用户属性,必要时通过名称冲突检查与更具体的命名解决。
|
||||
|
||||
### 按业务链拆解现有捕获
|
||||
|
||||
| 范围 | 当前用途 | 实施方向 |
|
||||
| --- | --- | --- |
|
||||
| boundary_smoothing、smoothing;三个深度组共 12 个 Capture | 原边界、影响范围、循环边界、源索引及最近边界映射 | 拓扑不变时直接消费 Boundary 和 Influence;Panorama 的闭合初始球面使用 False 表示原边界。其他原边界及固定映射逐项审查源几何采样或最小命名数据,保持原轮廓保护和循环映射语义 |
|
||||
| depth_surface 的切分;3 个 Capture | Camera、Cut 跨 Split Edges 与删面传播 | 分开审查面采样与切分标记,在源几何计算或采样,保持 FACE、CORNER、POINT 转换顺序;实际需要传播的最少信息才存值 |
|
||||
| depth_surface 的厚度;2 个 Capture | Position、Vertex、Normal 跨展平、挤出、合并、恢复 | 优先简化厚度构建顺序和源表面采样,保持独立重叠表面身份及零厚度行为;论证剩余源身份或数据的必要存储 |
|
||||
| image_depth_cutout;2 个 Capture | center、front_normal、structure、inflation_normal、edge_weight、front_delta、thickness、normal | 前表面计算尽量在原消费几何完成,保留独立中心表面供采样;逐字段核对圆化和壳体消费者,合并可复用的源数据,保持 Balloon、Uniform 两分支行为 |
|
||||
| material;2 个 Capture | Source 标记 Join 后待删除的输入网格 | 改为可明确验证的来源选择或材质传递流程,优先由几何数量及分支关系得到选择;验证空输入、多材质和生成几何保留 |
|
||||
| 现有 8 次 Store | UVMap、o_normal_scale | 保留命名协议,审查重复写入合并机会,保持角 UV、正背面与侧壁掩码 |
|
||||
|
||||
表中替代路径是待求值验证的候选。对于跨拓扑数据,实施中以真实结果确认直接求值是否等价;结构可读性和语义一致性共同决定最终方案。Capture 为零是硬性条件。
|
||||
|
||||
### 规范和测试一起纠正
|
||||
|
||||
更新 AGENTS.md、docs/internals/node-assets.md 及实际受影响的当前内部说明。规范明确禁止 Capture,描述直连、显式域转换、源几何采样、必要命名存储及清理规则,流程图从上到下。旧变更文件保留历史记录,本提案作为后续实施依据。
|
||||
|
||||
资产清单测试同时检查构建定义与保存资产,递归遍历嵌套几何组并去重;断言 Capture 为零。删除 capture_fields 辅助函数及测试用法,替换 test_depth_relief_planes、test_boundary_smoothing 中强制 Capture 的断言。原测试只允许 UVMap、o_normal_scale 的 Store 名称白名单应按经审查的必要存储更新,不把数量下降作为行为正确的替代。
|
||||
|
||||
复用真实求值用例,覆盖域转换、非均匀深度、断层、原边界保护、平滑影响范围与固定映射、厚度、Balloon/Uniform、法线、UV、材质和用户属性。布局通过完整图检查区域关系、连线跨度、交叉、节点重叠和标题可读性;零重叠仅是其中一项。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 直连改变求值几何或属性版本 → 使用非均匀输入和跨阶段场景对比实施前基线,明确每处采样域。
|
||||
- 变形后最近邻映射漂移、重叠表面串值 → 优先稳定索引对应,验证循环平滑与独立重叠表面。
|
||||
- 源几何采样增加连线或重复计算 → 结合逐组图审查及代表场景耗时选择简单方案;必要命名存储需逐项证明。
|
||||
- 临时命名属性冲突或清理影响用户数据 → 明确名称与生命周期,测试输入用户属性保留及临时属性消失。
|
||||
- 资产与源码不同步 → 执行 uv run node-group build,独立加载保存资产验证,再运行 uv run pytest 并确认正常退出。
|
||||
@@ -0,0 +1,30 @@
|
||||
## Why
|
||||
|
||||
之前的属性整理将大量 Store Named Attribute 替换为 Capture Attribute,保留了中间值存储并增加跨阶段连线,偏离了直接消费字段、提高结构可读性的要求。当前七个几何节点组共有 21 个 Capture;规范与部分测试还在强制沿用这一方向,需要一并纠正。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 全面检查全部几何节点、嵌套组与共享构建函数,禁止使用 Capture Attribute。
|
||||
- 优先让字段在消费位置直接求值,显式表达必要域转换;通过调整处理顺序或源几何采样减少中间存储。
|
||||
- 逐项论证 Store Named Attribute 的必要性:保留实际命名协议,以及确实需要跨几何变化保存的最少数据;禁止机械替换 Capture。
|
||||
- 更新 AGENTS.md、节点资产规范和相关当前实现说明,统一禁止 Capture、优先直连的规则。
|
||||
- 更新测试,移除依赖 Capture 的结构断言及测试辅助用法,检查全部资产与嵌套几何组中 Capture 为零,并验证真实几何行为。
|
||||
- 重建节点资产,核对布局、接口、UV、材质与几何结果。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `geometry-field-flow`: 几何节点字段直连、必要命名存储、禁止 Capture 及对应资产验证规则。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
无。
|
||||
|
||||
## Impact
|
||||
|
||||
- tools/nodes/common、tools/nodes/groups,以及实际受影响的排列代码。
|
||||
- tests/tools/nodes、tests/support 及相关材质、Operator 测试。
|
||||
- src/anyimage/assets/O_AnyImage.blend。
|
||||
- AGENTS.md、docs/internals/node-assets.md 及检索确认受影响的当前内部说明。
|
||||
- 公开接口、几何功能与属性协议保持一致;实施时保留工作区已有修改。该提案取代 simplify-node-attribute-flow 中关于 Capture 的设计决策。
|
||||
@@ -0,0 +1,57 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Geometry graphs prohibit Capture Attribute
|
||||
|
||||
全部生产几何节点定义、嵌套几何组、保存资产及相关测试辅助图 MUST 不使用 GeometryNodeCaptureAttribute。
|
||||
|
||||
#### Scenario: Inspect definitions and saved assets
|
||||
- **WHEN** 分别构建节点定义并加载保存资产,递归检查全部几何组及嵌套组
|
||||
- **THEN** 每个已访问几何组的 Capture Attribute 数量均为零
|
||||
|
||||
### Requirement: Fields are consumed directly when evaluation is equivalent
|
||||
|
||||
字段 SHALL 在消费位置直接连接,明确必要域转换;跨几何变化时 SHALL 优先审查调整消费顺序及源几何采样,以减少中间存储。多个消费者或跨区域连线 MUST 不作为存值的充分理由。
|
||||
|
||||
#### Scenario: Reuse a field without geometry changes
|
||||
- **WHEN** 多个消费者所在几何状态、域、类型与输入属性版本允许等价求值
|
||||
- **THEN** 消费者直接使用字段及必要域转换,保持原结果而不新增存储
|
||||
|
||||
#### Scenario: Consume a field after topology changes
|
||||
- **WHEN** 切分、删面、挤出或合并改变源字段求值上下文
|
||||
- **THEN** 实现明确源几何与映射,验证结果等价,并仅保存无法通过合理调整消费或采样消除的必要数据
|
||||
|
||||
### Requirement: Named storage has an explicit purpose and lifetime
|
||||
|
||||
每处 Store Named Attribute SHALL 有明确的实际消费者与存储必要性,记录名称、类型、域、Selection 和阶段。必要命名协议 SHALL 保留;临时属性 SHALL 在最后消费者后清理,并保留已有用户属性。
|
||||
|
||||
#### Scenario: Preserve material protocols
|
||||
- **WHEN** 输出几何供材质消费 UVMap 或 o_normal_scale
|
||||
- **THEN** 属性域与数值保持正确,包括角 UV 以及正背面和侧壁掩码
|
||||
|
||||
#### Scenario: Finish consuming temporary data
|
||||
- **WHEN** 几何处理完成临时命名数据的最后一次消费
|
||||
- **THEN** 最终输出不携带新增内部临时属性,且输入已有用户属性的名称、类型和值按原行为保留
|
||||
|
||||
### Requirement: Geometry behavior and graph readability are preserved
|
||||
|
||||
重构 SHALL 保持修改器接口、几何结果、UV 和材质行为,并逐组检查字段消费关系与完整节点布局的可读性。
|
||||
|
||||
#### Scenario: Validate depth processing
|
||||
- **WHEN** 使用非均匀深度测试 Split 开关、零与正厚度、独立重叠表面、Balloon/Uniform、圆化、膨胀及法线平滑
|
||||
- **THEN** 实际几何与实施前行为基线等价,索引重排按拓扑和对应几何数据比较
|
||||
|
||||
#### Scenario: Validate cut boundary smoothing and panorama
|
||||
- **WHEN** 对原轮廓、切分边界、平滑迭代和 Panorama 接缝、极点、无效像素及 Valid Only 求值
|
||||
- **THEN** 原轮廓保护、影响范围、固定映射、球面采样与 UV 保持预期行为
|
||||
|
||||
#### Scenario: Inspect material inheritance
|
||||
- **WHEN** 输入为空或带有多个材质槽,执行 Image Plane 或 Panorama 的材质继承
|
||||
- **THEN** 材质槽及面材质索引符合原行为,生成几何保留且输入来源几何正确处理
|
||||
|
||||
### Requirement: Rules tests and saved assets agree
|
||||
|
||||
项目规范及当前节点资产说明 SHALL 明确禁止 Capture 并采用一致的字段传递规则。测试 SHALL 覆盖结构约束与真实行为;节点资产 SHALL 重建并经过独立加载验证,相关测试及全量测试正常退出后完成交付。
|
||||
|
||||
#### Scenario: Deliver a geometry graph change
|
||||
- **WHEN** 本次节点整理完成
|
||||
- **THEN** 源码、规范、测试和 O_AnyImage.blend 同步,Capture 旧结构断言已替换,uv run node-group build 与 uv run pytest 成功且正常退出
|
||||
29
openspec/changes/remove-geometry-capture-attributes/tasks.md
Normal file
29
openspec/changes/remove-geometry-capture-attributes/tasks.md
Normal file
@@ -0,0 +1,29 @@
|
||||
## 1. 基线与规范
|
||||
|
||||
- [x] 1.1 核对实施时工作区已有修改、七个几何组及嵌套引用,记录 Capture/Store 数量、各存值字段的域、阶段、实际消费者和必要性;运行现有节点测试,记录基线及已有失败。
|
||||
- [x] 1.2 保存代表场景的几何、UV、材质索引与属性行为基线,覆盖深度切分、厚度、边界平滑、重叠表面、两种 Cutout 模式与 Panorama。
|
||||
- [x] 1.3 更新 AGENTS.md、docs/internals/node-assets.md 及实际受影响的当前内部说明,统一禁止 Capture、字段直连、显式域转换、源几何采样与必要命名存储规则;核对当前规则一致。
|
||||
|
||||
## 2. 几何节点整理
|
||||
|
||||
- [x] 2.1 整理原边界与 Influence:Panorama 原边界使用闭合源面的常量语义,拓扑不变的字段直接求值,其余保护数据选择必要传递方式;验证原轮廓保护与平滑影响范围。
|
||||
- [x] 2.2 整理平滑循环的 Boundary、SourceIndex、BoundaryIndex,明确稳定源几何与映射,移除 Capture;验证迭代前后映射、边界运动和拓扑行为。
|
||||
- [x] 2.3 整理共用深度切分的 Camera、Cut,保持面采样、角域及点域转换与切分前后语义;验证非均匀深度、Split 开关和删面。
|
||||
- [x] 2.4 整理厚度构建的源位置、顶点身份及法线,简化几何阶段或源采样,论证剩余必要命名数据;验证零厚度、封口、法线及独立重叠表面。
|
||||
- [x] 2.5 整理 Depth Cutout 的中心、结构、圆化、厚度和膨胀字段,减少跨阶段存值;验证 Balloon/Uniform、厚度连续性、Edge Round、Front Inflation 和 Normal Smooth。
|
||||
- [x] 2.6 整理材质继承的来源选择,移除 Source 捕获;验证 Image Plane、Panorama 的空输入、多材质槽、材质索引及生成几何保留。
|
||||
- [x] 2.7 完成所有几何组和三个材质消费者的复查,保留 UVMap、o_normal_scale 等必要协议,逐项审查重复 Store;清理临时命名数据并验证用户属性保留。
|
||||
- [x] 2.8 删除 capture_fields 及失去用途的辅助函数、导入和节点相关支持项;沿实际调用链确认旧实现引用消失,使用明确节点或 socket 引用接线。
|
||||
|
||||
## 3. 测试与可读性
|
||||
|
||||
- [x] 3.1 将 Capture 禁用检查加入构建定义及保存资产测试,递归遍历嵌套几何组并去重;更新 Store 名称规则以反映逐项批准的必要存储。
|
||||
- [x] 3.2 替换 test_depth_relief_planes、test_boundary_smoothing 中强制 Capture 的断言,移除 test_depth_cutout 等测试辅助图中的 Capture 用法,保留有效行为覆盖与状态隔离。
|
||||
- [x] 3.3 补齐本次受影响的域转换、边界固定映射、临时属性清理和用户属性保留测试;运行相关节点、材质及 Operator 测试并修复回归。
|
||||
- [x] 3.4 逐组检查完整节点图的消费关系、跨区连线、交叉、重叠和接口显示,按需调整布局;验证排列前后实际连接与求值一致。
|
||||
|
||||
## 4. 资产与交付
|
||||
|
||||
- [x] 4.1 运行 uv run node-group build,更新 O_AnyImage.blend,完成保存后独立 Blender 加载与几何验证,确认全部几何组及嵌套组 Capture 为零。
|
||||
- [x] 4.2 运行 uv run pytest 并确认正常退出;对比实施前行为基线,检查接口、几何、UV、材质及用户属性。
|
||||
- [x] 4.3 检查最终差异、旧引用与当前规范一致性,交付逐组调整和保留 Store 的必要性清单、数量及验证结果;确认源码、规范、测试和资产同步,保留已有其他修改,不构建文档或打包扩展。
|
||||
@@ -0,0 +1,52 @@
|
||||
# 几何节点核查
|
||||
|
||||
## 实施基线
|
||||
|
||||
- 基线采用实施开始时工作区源码,保留已有无效点清理、边界平滑、模型目录与粘贴预览等修改。
|
||||
- 节点基线测试:295 项通过,正常退出。
|
||||
- 保存 41 个场景、236 组数组,包含 Balloon/Uniform、Split、零与正厚度、法线平滑、膨胀、四边面与三角面边界平滑、Depth/Relief Plane、Panorama 有效性及重叠表面。
|
||||
- 本地核查文件:build/attributes-capture-before.json、build/geometry-capture-before.npz;实现后的对应文件以 capture-after 命名。
|
||||
|
||||
## 存储决策
|
||||
|
||||
| 范围 | 最终实现与必要性 |
|
||||
| --- | --- |
|
||||
| 原边界 | Depth Plane 直接消费 UV 矩形边缘,Panorama 使用闭合源面的 False;Depth Cutout 的任意输入轮廓跨切分后无法从当前拓扑恢复,保留一个 POINT/BOOLEAN 标记 |
|
||||
| 平滑 Boundary、Influence | 直接由不变拓扑和受保护轮廓计算,不保存字段 |
|
||||
| 平滑 SourceIndex、BoundaryIndex | 分别分离源边界与当前边界,保持相同紧凑索引顺序;用原网格按 Index 采样的位置查询源边界,再按结果索引消费当前边界位置,不保存索引 |
|
||||
| 切分 Camera | 面相机采样在当前面直接求值,保持显式 FACE 域,不保存 Camera |
|
||||
| 切分 Cut | 原顶点受切分影响的标记跨分裂及删面使用,每个深度组保留一个 CORNER/BOOLEAN 标记;完成投影后精确删除 |
|
||||
| 厚度 Position、Vertex、Normal | 将源索引编码进构造网格坐标后再挤出,按整数解码后的索引从独立源表面采样位置、厚度与法线,不保存字段;保留独立重叠表面身份 |
|
||||
| Depth Cutout 中心、结构、圆化、膨胀字段 | 直接在投影源表面求值并按壳体源索引采样;仅厚度构建需要的圆化厚度额外在对应前表面索引上求值 |
|
||||
| 材质 Source | 按输入网格顶点数量和 Join 的实际输入顺序识别待删除范围,不保存标记;验证空输入、多材质槽与排列前后结果 |
|
||||
| UVMap | Image Plane 两个分支、Panorama 各有实际输出 UV 写入,共 3 次,CORNER/FLOAT2,材质按名称消费 |
|
||||
| o_normal_scale | Image Cutout、Depth Balloon 各一次 POINT/FLOAT;Depth Cutout 原面 1、合并背面与侧壁后 0 两次 FACE/FLOAT,共 4 次;形状和材质按名称消费 |
|
||||
|
||||
所有保留 Store 的 Selection 均为 True。新增临时名称为 `.o_anyimage_depth_cut`、`.o_anyimage_original_boundary`,清理按完整名称执行;用户的其他属性,包括同前缀属性,保留原行为。
|
||||
|
||||
## 数量
|
||||
|
||||
| 节点组 | Capture 前 → 后 | Store 前 → 后 |
|
||||
| --- | --- | --- |
|
||||
| O Image Plane | 1 → 0 | 2 → 2 |
|
||||
| O Image Depth Plane | 6 → 0 | 0 → 1 |
|
||||
| O Image Relief Plane | 0 → 0 | 0 → 0 |
|
||||
| O Image Cutout | 0 → 0 | 1 → 1 |
|
||||
| O Image Depth Cutout | 8 → 0 | 3 → 4 |
|
||||
| O Image Depth Balloon | 0 → 0 | 1 → 1 |
|
||||
| O Image Depth Panorama | 6 → 0 | 1 → 2 |
|
||||
| 合计 | 21 → 0 | 8 → 11 |
|
||||
|
||||
按节点组自身计数,嵌套 Image Plane 在递归结构检查中去重。11 次 Store 由 7 次实际输出协议写入和 4 次必要拓扑标记写入组成。
|
||||
|
||||
## 验证结果
|
||||
|
||||
- 41 个场景的顶点位置、带方向的面、角 UV、材质索引和法线掩码与基线一致;面按顶点坐标及角 UV 对应比较,允许输出索引重排。
|
||||
- 源码和保存资产递归检查 Capture 为零;相关测试辅助图中已无 Capture。
|
||||
- 已修正全量测试发现的旧模型名称断言,匹配工作区当前模型名称。
|
||||
- 已刷新本地 BlendJob 0.1.17 wheel 的锁文件哈希;版本、依赖声明及 Manifest 保持一致。
|
||||
- uv run node-group build 成功且正常退出:Blender 4.5.10 LTS 重建资产,独立进程重新加载并验证全部 10 个节点组,递归几何组 Capture 为零。
|
||||
- 构建命令串行调用的全量 pytest:1237 项通过,耗时 221.33 秒,正常退出;覆盖新增跨 4096 索引行的厚度采样、临时属性精确清理、多材质继承、空输入和排列前后求值。
|
||||
- 逐组检查最终布局、字段连接与共享源几何路径,7 个几何组均无节点重叠,排列前后行为及保存布局稳定性测试通过;交互预览位于 build/capture-nodes.html。
|
||||
- git diff --check 与 OpenSpec 严格校验通过。源码检索中的 GeometryNodeCaptureAttribute 仅存在于禁止该节点的检查断言。
|
||||
- 源码、规范、测试与资产同步完成,未构建文档或打包扩展。
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-11
|
||||
72
openspec/changes/unify-boundary-depth-smoothing/design.md
Normal file
72
openspec/changes/unify-boundary-depth-smoothing/design.md
Normal 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 两个分支后再交付。
|
||||
27
openspec/changes/unify-boundary-depth-smoothing/proposal.md
Normal file
27
openspec/changes/unify-boundary-depth-smoothing/proposal.md
Normal 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 节点与依赖;深度平滑在几何节点求值阶段完成。
|
||||
@@ -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 禁用检查通过
|
||||
28
openspec/changes/unify-boundary-depth-smoothing/tasks.md
Normal file
28
openspec/changes/unify-boundary-depth-smoothing/tasks.md
Normal 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 测试,确认正常退出;核对源码与资产的一致性、最终差异和旧引用,保留已有其他修改。
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-10
|
||||
38
openspec/changes/update-pasted-brush-preview/design.md
Normal file
38
openspec/changes/update-pasted-brush-preview/design.md
Normal file
@@ -0,0 +1,38 @@
|
||||
## Context
|
||||
|
||||
`set_tool_texture()` 先取得可编辑笔刷,再绑定图片纹理、设置 STENCIL 和颜色。外部库笔刷通过 `asset_save_as` 创建并激活本地副本;已有可编辑笔刷直接复用。剪贴板图片已打包,加载时的临时文件随即删除。
|
||||
|
||||
## Goals
|
||||
|
||||
在 Texture Paint 粘贴流程中,让当前笔刷预览与绑定图片一致,保持图片比例,并随当前文件保存。
|
||||
|
||||
## Decisions
|
||||
|
||||
### 在纹理绑定成功后更新本地笔刷预览
|
||||
|
||||
更新入口保留在 `clipboard_image/actions.py`,以 `PAINT_TEXTURE` 判断模式,使用 `_ensure_editable_brush()` 返回的笔刷。所有 Blender 数据操作在 Operator 主线程阶段完成。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[取得已打包的粘贴图片] --> B[取得可编辑笔刷]
|
||||
B --> C[绑定纹理并设置 STENCIL]
|
||||
C --> D{Texture Paint 模式}
|
||||
D -->|是| E[从图片导出临时预览文件]
|
||||
E --> F[为当前笔刷加载自定义预览]
|
||||
F --> G[清理临时文件并刷新界面]
|
||||
D -->|否| G
|
||||
```
|
||||
|
||||
### 使用 Blender 自定义预览加载能力
|
||||
|
||||
复用 `common` 中适合的图片导出函数,生成临时 PNG,通过覆盖上下文的 `id` 指向目标笔刷,调用 `bpy.ops.ed.lib_id_load_custom_preview`。由 Blender 生成缩略图,保持比例与透明区域。预览加载完成后清理临时文件,预览数据由笔刷保存。
|
||||
|
||||
### 单独处理预览更新失败
|
||||
|
||||
预览更新与已有纹理绑定异常处理分开。加载失败时保留已绑定纹理和可用笔刷,通过现有 Operator 报告渠道提示预览更新失败。临时文件在成功与失败路径均清理。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 自定义预览 Operator 的上下文和界面缓存可能影响可见效果 → 在项目支持的 Blender 版本中验证当前笔刷选择器、资产架与切换笔刷后的显示。
|
||||
- 图片导出可能影响色彩或源数据 → 复用图片导出能力,验证透明图和非正方形图,确保源图片像素、尺寸及打包状态保持。
|
||||
- 预览保存行为需真实 Blender 验证 → 保存并重新打开 `.blend`,确认本地笔刷预览在临时文件清理后仍可显示。
|
||||
24
openspec/changes/update-pasted-brush-preview/proposal.md
Normal file
24
openspec/changes/update-pasted-brush-preview/proposal.md
Normal file
@@ -0,0 +1,24 @@
|
||||
## Why
|
||||
|
||||
Texture Paint 模式粘贴图片后,笔刷已使用该图片作为纹理,但图标仍显示原有预览,难以直接识别绘制内容。将笔刷图标同步为粘贴图片,让选择笔刷时的视觉提示与实际纹理一致。
|
||||
|
||||
## What Changes
|
||||
|
||||
- Texture Paint 模式绑定粘贴图片后,同步更新当前可编辑笔刷的自定义预览。
|
||||
- 预览保持图片比例,支持已打包的剪贴板图片及重复粘贴更新。
|
||||
- 验证预览即时刷新,以及保存并重新打开文件后的保留效果。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `pasted-brush-preview`: Texture Paint 粘贴图片与笔刷预览同步。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
## Impact
|
||||
|
||||
- `src/anyimage/operators/clipboard_image/actions.py`:笔刷纹理绑定与预览更新。
|
||||
- `src/anyimage/common/image.py`:复用现有图片读取或导出能力。
|
||||
- `tests/anyimage/operators/test_clipboard_image.py`:增加预览行为覆盖。
|
||||
- 使用 Blender 自定义预览 API,沿用现有依赖。
|
||||
@@ -0,0 +1,41 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Texture Paint 粘贴同步笔刷预览
|
||||
|
||||
系统 SHALL 在 Texture Paint 模式成功绑定粘贴图片后,将当前可编辑笔刷的自定义预览更新为该图片,并刷新相关界面。
|
||||
|
||||
#### Scenario: 外部库笔刷首次粘贴
|
||||
- **WHEN** 当前笔刷来自外部库,用户在 Texture Paint 模式粘贴图片
|
||||
- **THEN** 创建并激活的本地笔刷副本使用该图片作为纹理和自定义预览
|
||||
|
||||
#### Scenario: 已有笔刷重复粘贴
|
||||
- **WHEN** 用户向当前可编辑笔刷粘贴另一张图片
|
||||
- **THEN** 同一笔刷的纹理和预览同步更新为新图片
|
||||
|
||||
#### Scenario: 其他绘制模式粘贴
|
||||
- **WHEN** 用户在 Sculpt 或 Vertex Paint 模式粘贴图片
|
||||
- **THEN** 系统沿用该模式现有纹理绑定行为并保留笔刷原预览
|
||||
|
||||
### Requirement: 预览使用已打包图片并保留显示效果
|
||||
|
||||
系统 SHALL 支持从已打包的剪贴板图片生成预览,保持图片宽高比和透明区域;源图片像素、尺寸及打包状态 MUST 保持。
|
||||
|
||||
#### Scenario: 非正方形透明图片
|
||||
- **WHEN** 用户粘贴已打包且原临时文件已删除的非正方形透明图片
|
||||
- **THEN** 笔刷预览展示完整图片,保持比例和透明区域,源图片数据保持
|
||||
|
||||
### Requirement: 预览随文件保存
|
||||
|
||||
笔刷自定义预览 SHALL 随当前 `.blend` 文件保存,在预览临时文件清理后仍可恢复。
|
||||
|
||||
#### Scenario: 保存后重新打开
|
||||
- **WHEN** 用户成功更新笔刷预览,保存并重新打开 `.blend` 文件
|
||||
- **THEN** 对应本地笔刷仍显示该图片预览
|
||||
|
||||
### Requirement: 预览失败保留可用纹理
|
||||
|
||||
预览更新失败时系统 SHALL 保留已绑定纹理并提示预览更新失败;预览临时文件 MUST 在成功或失败后清理。
|
||||
|
||||
#### Scenario: Blender 拒绝加载预览
|
||||
- **WHEN** 纹理已绑定但自定义预览加载失败
|
||||
- **THEN** 笔刷仍可使用粘贴纹理绘制,用户收到预览失败提示,临时文件被清理
|
||||
13
openspec/changes/update-pasted-brush-preview/tasks.md
Normal file
13
openspec/changes/update-pasted-brush-preview/tasks.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## 1. 笔刷预览更新
|
||||
|
||||
- [x] 1.1 在项目支持的 Blender 中验证以笔刷为上下文加载自定义预览的 API、图片比例及保存行为。
|
||||
- [x] 1.2 复用 common 图片导出能力,从已打包图片生成临时预览并更新笔刷,保证临时文件清理及源图片数据保持。
|
||||
- [x] 1.3 在 Texture Paint 纹理绑定成功后接入预览更新和界面刷新,独立处理预览失败提示并保留已绑定纹理。
|
||||
|
||||
## 2. 验证
|
||||
|
||||
- [x] 2.1 更新剪贴板测试,覆盖本地副本、已有笔刷重复粘贴、模式范围、预览失败和临时文件清理,运行相关测试。
|
||||
- [ ] 2.2 在真实 Blender 中验证非正方形透明图片、笔刷选择器与资产架刷新、切换笔刷及保存重开后的预览,并检查源图片数据保持。
|
||||
- [x] 2.3 检查最终差异与旧引用,确认改动集中于笔刷预览和相关测试。
|
||||
|
||||
验证记录:55 项测试、15 个子场景通过;Blender 4.5.10 后台验证了非正方形透明图片、源数据保持及保存重开后的预览。2.2 尚待界面目视检查笔刷选择器、资产架与切换笔刷后的显示,当前会话未提供 Blender 界面控制工具。测试使用 `uv run --no-sync`,因为本地 BlendJob wheel 与锁文件哈希不一致。
|
||||
Reference in New Issue
Block a user