Refactor Cutout Tool to Use World Space Edge Length

- Replaced the Mesh Detail parameter with a new Edge Length property to define cutout sampling in physical units.
- Introduced Minimum Relative Edge Length preference to control effective spacing based on the bounding box of the cutout content.
- Updated tests to validate the new edge length functionality and ensure consistent behavior across different resolutions and canvas sizes.
- Removed deprecated parameters and adjusted related properties to align with the new edge length implementation.
- Enhanced geometry sampling logic to utilize effective world spacing for both standard and fine outline modes.
This commit is contained in:
2026-09-12 23:03:24 +08:00
parent 938d95db0f
commit 18799e8828
28 changed files with 505 additions and 279 deletions

View File

@@ -242,24 +242,39 @@ def cutout_fine_outline_property():
)
def cutout_mesh_detail_property():
return bpy.props.EnumProperty(
name="Mesh Detail",
description="Control mesh density. Higher levels use more vertices to represent finer shapes.",
items=(
("LOW", "Low", "32 source image pixels between neighboring mesh points"),
("MEDIUM", "Medium", "16 source image pixels between neighboring mesh points"),
("HIGH", "High", "8 source image pixels between neighboring mesh points"),
("ULTRA", "Ultra", "4 source image pixels between neighboring mesh points"),
),
default="LOW",
def _cutout_length_scale(owner):
scene = getattr(owner, "id_data", None)
if not isinstance(scene, bpy.types.Scene):
scene = bpy.context.scene
return scene.unit_settings.scale_length
def _get_cutout_edge_length(owner):
return owner.get("cutout_edge_length_meters", 0.1) / _cutout_length_scale(owner)
def _set_cutout_edge_length(owner, value):
owner["cutout_edge_length_meters"] = value * _cutout_length_scale(owner)
def cutout_edge_length_property(*, store_meters=False, **options):
if store_meters:
options.update(get=_get_cutout_edge_length, set=_set_cutout_edge_length)
return bpy.props.FloatProperty(
name="Edge Length",
description="Target mesh edge length in world space",
default=0.1,
min=1e-6,
unit="LENGTH",
subtype="DISTANCE",
**options,
)
class AnyImageSettings(bpy.types.PropertyGroup):
cutout_gesture: cutout_gesture_property()
cutout_alpha_threshold: cutout_alpha_threshold_property()
cutout_mesh_detail: cutout_mesh_detail_property()
cutout_edge_length: cutout_edge_length_property(store_meters=True)
cutout_fine_outline: cutout_fine_outline_property()
cutout_generate_normal: cutout_generate_normal_property()
mask_gesture: mask_gesture_property()