feat: Implement weight cutout boundary smoothing for image depth cutout

- Added a new proposal for boundary smoothing in the weight cutout process, differentiating between Split edges and Outline smoothing requirements.
- Introduced a new capability `cutout-boundary-smoothing` to control smoothing strength and default values.
- Updated specifications to define the behavior of boundary-specific smoothing strength and default settings.
- Created tasks to verify the implementation of boundary behavior and asset updates.
- Developed comprehensive tests for depth symmetry and normal scaling to ensure expected behavior and performance.
- Introduced new attributes for normal mapping to facilitate persistent face attributes sharing between depth symmetry and image materials.
- Built a new node group for O Image Depth Symmetry, integrating the new smoothing capabilities and ensuring compatibility with existing workflows.
This commit is contained in:
2026-09-14 12:44:20 +08:00
parent 09778c4b48
commit dc000e50b1
53 changed files with 1350 additions and 364 deletions

View File

@@ -27,7 +27,7 @@ def test_saved_parameter_descriptions_match_definitions():
"Thickness", "Depth Split", "Smooth", "Smooth Weight",
"Boundary Smooth", "Normal Smooth", "Front Inflation",
},
"O Image Depth Balloon": {"Thickness", "Smooth", "Smooth Weight"},
"O Image Depth Symmetry": {"Thickness", "Smooth", "Smooth Weight", "Boundary Smooth"},
"O Image Depth Panorama": {
"Subdivide", "Depth Scale", "Depth Split", "Smooth", "Smooth Weight",
"Depth Mask", "Mask Threshold", "Boundary Smooth", "Invalid Distance",
@@ -50,7 +50,7 @@ def test_saved_parameter_descriptions_match_definitions():
assert all(item.description for item in sockets), group.name
if group.name in {"O Image Depth Plane", "O Image Depth Cutout"}:
boundary = next(item for item in sockets if item.name == "Boundary Smooth")
assert boundary.default_value == (4 if group.name == "O Image Depth Plane" else 0)
assert boundary.default_value == 4
assert boundary.min_value == 0
assert boundary.max_value == 16
assert boundary.parent.name == "Options"
@@ -141,6 +141,9 @@ def test_geometry_attribute_contract_includes_nested_groups(source):
"UVMap": ("FLOAT2", "CORNER"),
"o_balloon": ("FLOAT", "POINT"),
".o_anyimage_depth_cut": ("BOOLEAN", "CORNER"),
"o_depth_rotation": ("FLOAT_VECTOR", "FACE"),
"o_depth_face": ("FLOAT", "FACE"),
"o_depth_axis": ("FLOAT", "FACE"),
}
while pending:
group = pending.pop()
@@ -154,7 +157,7 @@ def test_geometry_attribute_contract_includes_nested_groups(source):
if node.bl_idname != "GeometryNodeStoreNamedAttribute":
continue
name = node.inputs["Name"].default_value
if name == "o_normal_scale":
if name == "o_normal_reduction":
assert node.data_type == "FLOAT" and node.domain in {"POINT", "FACE"}
else:
assert name in allowed, (group.name, name)