feat(cutout_tool): Implement cutout region to shape functionality

- Added interaction helpers for cutout region validation and shape menu interaction.
- Created main operator for converting image regions into cutout shapes, including AI artifact generation.
- Introduced object creation logic for cutout shapes, handling depth and normal textures.
- Defined cutout shape identifiers and node groups for various shape types.
- Implemented depth texture writing and prediction artifact generation for MoGe-2.
- Developed server jobs for generating cutout artifacts, depth planes, and refining image regions.
- Added region refinement logic to enhance gesture masks using BEN2.
This commit is contained in:
2026-08-31 11:36:27 +08:00
parent 08309f719d
commit 87d7721128
80 changed files with 4823 additions and 4297 deletions

View File

@@ -0,0 +1,125 @@
"""Create Blender Image, Material, Mesh, and Object data for Plane conversion."""
import bpy
from ..common.image_data import (
color_data_name,
image_empty_bounds,
image_pixels,
load_color_result_image,
require_image_empty,
)
from ..common.depth_data import (
depth_uniform_scale,
load_depth_metadata,
load_depth_result_image,
)
from ..common.mesh_result import (
create_image_material,
finalize_object_result,
modifier_input_identifier,
set_modifier_input,
)
from .mesh_plane import create_mesh_plane_mesh, create_mesh_plane_object
from .nodes import depth_plane_node_group
def create_color_image(source_object):
source = source_object.data
image = source.copy()
if getattr(source, "source", None) == "GENERATED" or getattr(
source, "is_dirty", False
):
pixels = image_pixels(source)
image.pixels.foreach_set(pixels)
image.update()
image.name = color_data_name(source_object)
return image
def create_plane_object(context, source_object, subdivisions, material):
source_name = source_object.name
plane = create_mesh_plane_object(
context,
source_name,
image_empty_bounds(source_object),
material,
matrix_world=source_object.matrix_world,
subdivisions=subdivisions,
)
for polygon in plane.data.polygons:
polygon.use_smooth = True
plane["anyimage_mesh_shape"] = "PLANE"
return finalize_object_result(context, source_object, plane)
def create_depth_plane_object(
context,
source_object,
subdivisions,
material,
depth_image,
depth_metadata,
):
source_name = source_object.name
mesh = create_mesh_plane_mesh(source_name, image_empty_bounds(source_object))
for polygon in mesh.polygons:
polygon.use_smooth = True
mesh.materials.append(material)
plane = bpy.data.objects.new(source_name, mesh)
context.collection.objects.link(plane)
plane.matrix_world = source_object.matrix_world.copy()
plane["anyimage_mesh_shape"] = "DEPTH_PLANE"
node_group = depth_plane_node_group()
modifier = plane.modifiers.new(name=node_group.name, type="NODES")
modifier.node_group = node_group
modifier.show_group_selector = False
for name, value in (
("Subdivide", max(0, min(10, int(subdivisions)))),
("Material", material),
("Thickness", 0.1),
("Depth Amount", 1.0),
("Reference Depth", depth_metadata["reference_depth"]),
("Uniform Scale", depth_uniform_scale(source_object, depth_metadata)),
("Depth Image", depth_image),
):
set_modifier_input(
modifier,
modifier_input_identifier(node_group, name),
value,
)
return finalize_object_result(context, source_object, plane)
def create_depth_plane_from_result(context, result, operator):
source_object = require_image_empty(operator.source_object_name)
color_image = load_color_result_image(source_object, result.directory)
color_image.name = color_data_name(source_object)
material = create_image_material(
source_object,
color_image,
0.0,
scene=context.scene,
)
depth_metadata = load_depth_metadata(result.file("depth_metadata"))
depth_image = load_depth_result_image(
result.file("z_depth"),
source_object,
depth_metadata,
)
try:
create_depth_plane_object(
context,
source_object,
operator.mesh_detail,
material,
depth_image,
depth_metadata,
)
except Exception:
if depth_image.users == 0:
bpy.data.images.remove(depth_image, do_unlink=True)
raise
if "FINISHED" not in bpy.ops.ed.undo_push(message="Convert to Depth Plane"):
raise RuntimeError("Unable to create the Convert to Depth Plane Undo step")