feat(selection): separate selection geometry from image content processing
- Introduced a new design for selection rasterization that decouples the selection geometry from the image content, ensuring that the SelectionMask is independent of the source image's alpha and color. - Updated the `rasterize_selection_path` function to only accept selection paths and image dimensions, removing parameters related to source alpha and alpha thresholds. - Implemented a new approach for handling selection paths using non-zero winding fill, ensuring overlapping areas are preserved. - Enhanced performance by utilizing a scanline algorithm for rasterization, significantly reducing processing time for high-resolution images. - Updated internal documentation and added comprehensive tests to validate the new behavior and performance improvements. - Ensured backward compatibility by maintaining existing interfaces where necessary while introducing breaking changes in the selection processing logic.
This commit is contained in:
@@ -7,6 +7,7 @@ from ...common.image import (
|
||||
image_empty_bounds,
|
||||
image_pixels,
|
||||
load_color_result_image,
|
||||
load_normal_result_image,
|
||||
require_image_empty,
|
||||
)
|
||||
from ...common.depth import (
|
||||
@@ -21,7 +22,11 @@ from ...common.object import (
|
||||
set_modifier_input,
|
||||
)
|
||||
from ...common.node import load_node_group
|
||||
from .mesh_plane import create_mesh_plane_mesh, create_mesh_plane_object
|
||||
from .mesh_plane import (
|
||||
build_mesh_plane_matrix,
|
||||
create_mesh_plane_mesh,
|
||||
create_mesh_plane_object,
|
||||
)
|
||||
|
||||
|
||||
DEPTH_PLANE_NODE_GROUP_NAME = "O Image Depth Plane"
|
||||
@@ -65,26 +70,27 @@ def create_depth_plane_object(
|
||||
depth_metadata,
|
||||
):
|
||||
source_name = source_object.name
|
||||
mesh = create_mesh_plane_mesh(source_name, image_empty_bounds(source_object))
|
||||
bounds = image_empty_bounds(source_object)
|
||||
mesh = create_mesh_plane_mesh(source_name, bounds)
|
||||
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.matrix_world = build_mesh_plane_matrix(source_object.matrix_world, bounds)
|
||||
plane["anyimage_mesh_shape"] = "DEPTH_PLANE"
|
||||
|
||||
node_group = load_node_group(DEPTH_PLANE_NODE_GROUP_NAME)
|
||||
modifier = plane.modifiers.new(name=node_group.name, type="NODES")
|
||||
modifier.node_group = node_group
|
||||
modifier.show_group_selector = False
|
||||
uniform_scale = depth_uniform_scale(source_object, depth_metadata)
|
||||
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 Scale", 1.0),
|
||||
("Base Plane Depth", depth_metadata["reference_depth"] * uniform_scale),
|
||||
("Uniform Scale", uniform_scale),
|
||||
("Depth Image", depth_image),
|
||||
):
|
||||
set_modifier_input(
|
||||
@@ -99,19 +105,29 @@ 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,
|
||||
)
|
||||
material = None
|
||||
depth_image = None
|
||||
normal_image = None
|
||||
try:
|
||||
depth_metadata = load_depth_metadata(result.file("depth_metadata"))
|
||||
depth_image = load_depth_result_image(
|
||||
result.file("z_depth"),
|
||||
source_object,
|
||||
depth_metadata,
|
||||
)
|
||||
normal_image = load_normal_result_image(
|
||||
result.file("tangent_normal"),
|
||||
source_object,
|
||||
)
|
||||
material = create_image_material(
|
||||
source_object,
|
||||
color_image,
|
||||
0.0,
|
||||
normal_image=normal_image,
|
||||
normal_space="TANGENT",
|
||||
ior=1.2,
|
||||
scene=context.scene,
|
||||
)
|
||||
create_depth_plane_object(
|
||||
context,
|
||||
source_object,
|
||||
@@ -121,8 +137,11 @@ def create_depth_plane_from_result(context, result, operator):
|
||||
depth_metadata,
|
||||
)
|
||||
except Exception:
|
||||
if depth_image.users == 0:
|
||||
bpy.data.images.remove(depth_image, do_unlink=True)
|
||||
if material is not None and material.users == 0:
|
||||
bpy.data.materials.remove(material, do_unlink=True)
|
||||
for image in (depth_image, normal_image):
|
||||
if image is not None and image.users == 0:
|
||||
bpy.data.images.remove(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")
|
||||
|
||||
Reference in New Issue
Block a user