Files
AnyImage/openspec/changes/archive/2026-09-17-refine-cutout-symmetry-seam/design.md
nan 076a8c90f1 Add specifications for two-times upscale and unified depth plane features
- Introduced the two-times upscale specification detailing requirements for unified output, fixed model presets, arbitrary dimensions, and consistent job behavior.
- Added scenarios for existing models, repeated upscale, and handling of alpha preservation.
- Created the unified depth plane specification outlining geometry modes, stable interface, and asset evaluation.
- Defined scenarios for mode switching, relief and camera preservation, and validation of delivered assets.
2026-09-17 17:19:05 +08:00

73 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Context
`tools/nodes/groups/image_cutout_symmetry.py` 当前先对齐方向、按 `Offset` 与 `Scale` 成形,再用 `_delete_positive_faces` 删除越过对称面的几何,最后镜像、补侧壁并合并。
两处现状造成中缝杂乱:
- `_delete_positive_faces` 把 POINT 域的越界布尔求值到 FACE 域再取 `> 0`,等价于「任一顶点越界即删除整个面」。保留区整体退让,退让量随局部深度梯度逐处变化,切口不落在对称面上。
- `build` 里的补面边界取「只有一个相邻面的边」,没有排除切口那条。直壁模式下每条切口边生成宽度等于两倍退让量的侧壁,宽度逐边不同且平面着色;`_walls` 的平滑只按 `0.5 / 0` 比例写入新增环的对称轴坐标,并用 `(.5, 0, .5)` 掩码只移动面内分量,因此无法消除宽度差。
同一节点曾用布尔原型验证过正确构成:`C:/Users/icrdr/AppData/Local/Temp/anyimage-car-symmetry/close_projected.py` 的补面选择为「边界边且位于界内一侧」,切口依靠合并自焊,验证 `open_edges = 0`、`nonmanifold_edges = 0`。本轮用面删除加边缘归零在无布尔的条件下复现该构成。
约束:不引入布尔或裁切算子;不使用 Capture Attribute;切边平滑只改面内分量,对称轴坐标保持为零。
## Goals / Non-Goals
**Goals:** 切口严格落在对称面上并由镜像合并自焊,零厚度与非零厚度输入走同一条折叠路径;补面只覆盖外轮廓;切口环由独立参数按两圈渐变平滑;节点资产名不变。
**Non-Goals:** 精确裁切、布尔实现、细分加密、外轮廓侧壁的形态重设计、既有 `.blend` 内嵌节点的自动迁移。
## Decisions
### 开口薄片:折叠过界部分
薄片的做法是把配平到对称面上的工作量压到最小:只删除越过对称面的顶点所对应的折叠结果,不预先删除与之相连的面。
| 顶点 | 处理 |
| --- | --- |
| 越过对称面 | 保留,对称轴坐标归零 |
| 界内 | 保留,不改位置 |
| 归零后整面落在对称面上 | 该面删除 |
跨界面的顶点被拉回平面而不是被删除,因此保留的面比整面删除多(同一 33×33 薄片样例:3356 面对 3044 面),界内顶点完全不动,形变只发生在跨界面上;切口边缘写死为 0,镜像后两侧严格重合,合并即焊成接缝。
### 统一折叠,并清理内部贴平边
闭合壳体(非零厚度输入)同样折叠,折叠会在壳体边缘留下「内部贴平边」:一条落在对称面上的边仍邻接两个面,镜像后这条边会变成四面共边。这类边不是有效切口,而是折叠后两层表面叠在一起形成的非法退化,因此统一清理掉贴平边邻接的面,让切口在此重新成为边界边,再与镜像焊接。这样不按输入是否闭合分支,零厚度与非零厚度共用一条路径;测试壳体上非流形边从 4–6 条降为 0。
清理用 `InputMeshEdgeVertices` 判断边两端都在对称面上,用 `InputMeshEdgeNeighbors` 判断边仍邻接两个面,再经 `CornersOfFace` / `EdgesOfCorner` / `FieldAtIndex` 把边的非法性聚合到面并删除。布尔裁切精度最高,但既有对照测量为 5–7 倍耗时且依赖输入流形,不采用。
实现只依赖逐点与逐边求值。这里不能用「把 POINT 域布尔求值到 FACE 域再判断」的写法:函数节点链在不同域上按该元素自身的位置求值,FACE 域得到的是面中心是否越界,而不是任一顶点越界,部分越界的面会既没被删除也进不了切口环。判断面是否整体贴平面时改为「面中心贴平面且面法线沿对称轴」,避免把斜跨对称面的面一起删掉。
### 补面只覆盖不落在对称面上的边界边
边界判据保持「只有一个相邻面」,再与「顶点越出对称面容差」求交,判断按顶点而非边的平均位置。落在对称面上的切口环在合并后已是共享边,再生成侧壁只会得到退化面或三面共享边。
### 切口环与衔接带两个平滑
`Seam Smooth` 与 `Fill Smooth` 都只移动面内分量、锁定对称轴。
`Seam Smooth` 作用于折叠后的切口环,减少切边的面内量化折线,按两圈渐变衰减,并按 `pinned-geometry-smoothing` 的 `Pin Boundary` 与 `Pin Sharp` 处理。`Fill Smooth` 作用于 front 的衔接带,即界外轮廓与对称面上的切缝共同围出的边界带,按四圈渐变向内松弛,随后从平滑后的轮廓构建侧壁,因此侧壁自然跟随轮廓;衔接处不是网格边界,只保留 `Pin Sharp`。补面的细分始终存在,不再以 `Fill Smooth > 0` 为开关;`Fill Smooth = 0` 只表示不平滑。
两个平滑都在镜像之前完成,两半保持一致,且都与 Fill Sides 无关:关闭补面时 `Fill Smooth` 没有轮廓可作用,`Seam Smooth` 照常作用。
### 折叠与清理属于几何正确性,与 Fill Sides 无关
Fill Sides 关闭时跳过侧壁与侧壁平滑,折叠、贴平面片清理与切边平滑照常执行,否则两半会互相穿插。
## Risks / Trade-offs
- 跨界面被拉向对称面,界内顶点不移动 → 用样例记录越界量分布,确认参考深度切得较深时形变可接受。
- 切口环的面内折线仍是网格分辨率级近似 → 由 Seam Smooth 与上游 Boundary Smooth 共同改善,测试明确其为近似边界。
- 壳体折叠后的非法贴平边由清理移除,缝隙在有 Fill Sides 时由侧壁补上 → 测试断言无越过对称面的顶点、无四面共边、切口自焊。
- 参考深度把整片几何置于界外时输出为空 → 沿用现有空结果处理与测试。
- 源码与资产不同步 → 修改后运行 `uv run node-group build`,源码、测试与 `.blend` 一并更新。
## Migration Plan
直接替换删除与补面逻辑,不保留旧路径或开关;重新构建节点资产;不重写用户工程中的旧节点组。新增 `Seam Smooth` 的默认值为 2,与既有默认观感一致;用户工程中的旧节点实例沿用保存时的接口。回滚时恢复本次构建函数与测试并重建资产。
## Open Questions
无阻塞决策。若试作后切边形变在参考深度切入较深时仍显眼,再把归零目标改为平行于对称面的一个偏移面作为后续选项。