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

@@ -6,7 +6,7 @@ import pytest
from tools.nodes.groups.image_depth_cutout import build_volume_fields
from tools.nodes.groups.image_depth_cutout import build_volume_rounding
from anyimage.common.object import modifier_input_identifier, set_modifier_input
from tools.nodes.common.nodes import capture_fields
from tools.nodes.common.nodes import sample_field
def store_test_fields(group, geometry, fields):
@@ -27,8 +27,8 @@ def set_test_structure(monkeypatch, value):
from tools.nodes.groups import image_depth_cutout
build = image_depth_cutout.build_front_fields
def fields(group, rim, normal):
result = build(group, rim, normal)
def fields(group, rim, normal, normal_weight):
result = build(group, rim, normal, normal_weight)
structure = group.nodes.new("ShaderNodeValue")
structure.outputs[0].default_value = value
result["structure"] = structure.outputs[0]
@@ -106,9 +106,12 @@ def test_rounding_shares_front_and_back_falloff(amount):
group.interface.new_socket(name="Geometry", in_out="OUTPUT", socket_type="NodeSocketGeometry")
source = group.nodes.new("NodeGroupInput")
fields = build_volume_fields(group)
geometry, center = capture_fields(group, source.outputs["Geometry"], "POINT", center=("FLOAT", fields["center"]))
geometry = source.outputs["Geometry"]
center = {"center": sample_field(group, geometry, fields["center"], "FLOAT")}
mode = group.nodes.new("FunctionNodeInputBool")
result, rounded = build_volume_rounding(group, geometry, {**fields, **center}, mode.outputs[0])
result, rounded = build_volume_rounding(group, geometry, fields, mode.outputs[0])
rounded = {name: sample_field(group, geometry, value, "FLOAT_VECTOR" if name == "normal" else "FLOAT")
for name, value in rounded.items()}
result = store_test_fields(group, result, {**center, **rounded})
group.links.new(result, group.nodes.new("NodeGroupOutput").inputs["Geometry"])
obj.modifiers.new("Round", "NODES").node_group = group