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

@@ -1,7 +1,7 @@
"""Build O Image Cutout."""
import bpy
from mathutils import Matrix
from anyimage.operators.cutout_tool.shape import CUTOUT_Z_TO_X, NORMAL_SCALE_ATTRIBUTE_NAME
from anyimage.operators.cutout_tool.shape import CUTOUT_Z_TO_X, NORMAL_REDUCTION_ATTRIBUTE_NAME
from ..common.nodes import interface_socket, group_input, math_node, float_input, menu_switch, read_float_attribute, store_float_attribute, prepare_node_group
from ..common.smoothing import expand_smooth
from ..common.cutout import _extrude_layers, _island_cleanup, _offset_geometry_z, _remove_zero_thickness, _set_layer_z, _shade_output
@@ -198,7 +198,10 @@ def build_image_cutout_group():
mode.inputs['Shell'].default_value = 1
group.links.new(inflated.outputs[0], mode.inputs['Balloon'])
scale = mode.outputs[0]
geometry = store_float_attribute(group, geometry, NORMAL_SCALE_ATTRIBUTE_NAME, scale)
reduction = math_node(group.nodes, 'SUBTRACT')
reduction.inputs[0].default_value = 1.0
group.links.new(scale, reduction.inputs[1])
geometry = store_float_attribute(group, geometry, NORMAL_REDUCTION_ATTRIBUTE_NAME, reduction.outputs[0])
orient = group.nodes.new('GeometryNodeTransform')
orient.inputs['Rotation'].default_value = Matrix(CUTOUT_Z_TO_X).to_euler()
group.links.new(geometry, orient.inputs['Geometry'])