Add new functionality for image rectification and depth metadata handling
- Implemented a preview tool for rectifying images with interactive aspect controls in `preview.py`. - Added tests for depth metadata loading to ensure consistent schema usage in `test_depth_metadata.py`. - Developed comprehensive tests for cutout calibration processes in `test_cutout_calibration.py`, including stability checks and depth calibration. - Created tests for frame compositing operations in `test_frame_compositing.py`, ensuring correct handling of depth and transparency. - Introduced material slot inheritance functionality in `material_slots.py` to manage geometry material assignments. - Built shared shader nodes for material processing in `shader.py`, including roughness and bump mapping setups.
This commit is contained in:
@@ -15,23 +15,24 @@ from ...common.object import (
|
||||
set_modifier_input,
|
||||
)
|
||||
from ...common.node import load_node_group
|
||||
from .geometry import (
|
||||
CUTOUT_ALPHA_THRESHOLD,
|
||||
from .depth_calibration import (
|
||||
DEFAULT_DEPTH_BASELINE,
|
||||
DEFAULT_DEPTH_DIRECTION,
|
||||
depth_balloon_projection_parameters,
|
||||
metric_depth_reference,
|
||||
use_adaptive_depth_calibration,
|
||||
)
|
||||
from .geometry import (
|
||||
CUTOUT_ALPHA_THRESHOLD,
|
||||
crop_plane_bounds,
|
||||
cutout_cleanup_value,
|
||||
cutout_sampling_spacing,
|
||||
depth_balloon_projection_parameters,
|
||||
metric_depth_reference,
|
||||
selection_calibration,
|
||||
use_adaptive_depth_calibration,
|
||||
world_plane_metric,
|
||||
)
|
||||
from .shape import (
|
||||
BALLOON_ATTRIBUTE_NAME,
|
||||
NORMAL_SCALE_ATTRIBUTE_NAME,
|
||||
CUTOUT_X_TO_Z,
|
||||
CUTOUT_NODE_GROUP_NAMES,
|
||||
DEPTH_CUTOUT_SHAPES,
|
||||
)
|
||||
@@ -43,38 +44,11 @@ class NormalMode(StrEnum):
|
||||
OBJECT = "OBJECT"
|
||||
|
||||
|
||||
class CutoutInwardAxis(StrEnum):
|
||||
NEGATIVE_Z = "NEGATIVE_Z"
|
||||
POSITIVE_X = "POSITIVE_X"
|
||||
|
||||
|
||||
def _cutout_world_matrix(source_matrix, crop_center, inward_axis):
|
||||
def _cutout_world_matrix(source_matrix, crop_center):
|
||||
from mathutils import Matrix
|
||||
|
||||
center_x, center_y = (float(value) for value in crop_center)
|
||||
matrix = source_matrix @ Matrix.Translation((center_x, center_y, 0.0))
|
||||
if CutoutInwardAxis(inward_axis) == CutoutInwardAxis.POSITIVE_X:
|
||||
matrix @= Matrix(CUTOUT_X_TO_Z)
|
||||
return matrix
|
||||
|
||||
|
||||
def orient_object_normal_image(image, inward_axis):
|
||||
"""Convert native Z-axis Cutout normals to the selected object axes."""
|
||||
if CutoutInwardAxis(inward_axis) == CutoutInwardAxis.NEGATIVE_Z:
|
||||
return image
|
||||
import numpy as np
|
||||
|
||||
pixels = np.empty(int(image.size[0]) * int(image.size[1]) * 4, dtype=np.float32)
|
||||
image.pixels.foreach_get(pixels)
|
||||
rgba = pixels.reshape((-1, 4))
|
||||
normal = rgba[:, :3] * 2.0 - 1.0
|
||||
rgba[:, :3] = np.column_stack(
|
||||
(-normal[:, 2], -normal[:, 0], normal[:, 1])
|
||||
) * 0.5 + 0.5
|
||||
image.pixels.foreach_set(pixels)
|
||||
image.update()
|
||||
image.pack()
|
||||
return image
|
||||
return source_matrix @ Matrix.Translation((center_x, center_y, 0.0))
|
||||
|
||||
|
||||
def _assign_uv(mesh, uv):
|
||||
@@ -99,7 +73,7 @@ def _assign_float_point_attribute(mesh, name, values):
|
||||
|
||||
|
||||
def load_cutout_node_group(shape):
|
||||
return load_node_group(CUTOUT_NODE_GROUP_NAMES[shape], asset_revision=23 if shape == "DEPTH_SOLID" else 12 if shape == "DEPTH_BALLOON" else 11)
|
||||
return load_node_group(CUTOUT_NODE_GROUP_NAMES[shape], asset_revision=26 if shape == "DEPTH_SOLID" else 14 if shape == "DEPTH_BALLOON" else 13)
|
||||
|
||||
|
||||
def _connect_cutout_normal_scale(material):
|
||||
@@ -134,13 +108,12 @@ def create_shape_object(
|
||||
depth_metadata=None,
|
||||
normal_image=None,
|
||||
normal_mode=NormalMode.NONE,
|
||||
inward_axis=CutoutInwardAxis.NEGATIVE_Z,
|
||||
color_image,
|
||||
gesture="LASSO",
|
||||
):
|
||||
import numpy as np
|
||||
|
||||
normal_mode = NormalMode(normal_mode)
|
||||
inward_axis = CutoutInwardAxis(inward_axis)
|
||||
bounds = crop_plane_bounds(
|
||||
source_object,
|
||||
content_bounds,
|
||||
@@ -229,7 +202,6 @@ def create_shape_object(
|
||||
mesh_object.matrix_world = _cutout_world_matrix(
|
||||
source_object.matrix_world,
|
||||
crop_center,
|
||||
inward_axis,
|
||||
)
|
||||
mesh_object["anyimage_mesh_shape"] = shape
|
||||
node_group = load_cutout_node_group(shape)
|
||||
@@ -237,10 +209,6 @@ def create_shape_object(
|
||||
modifier.node_group = node_group
|
||||
modifier.show_group_selector = False
|
||||
for name, value in (
|
||||
(
|
||||
"Inward Axis",
|
||||
0 if inward_axis == CutoutInwardAxis.NEGATIVE_Z else 1,
|
||||
),
|
||||
("Cleanup Threshold", cleanup_value),
|
||||
(
|
||||
"Thickness",
|
||||
@@ -249,9 +217,24 @@ def create_shape_object(
|
||||
):
|
||||
set_modifier_input(
|
||||
modifier,
|
||||
modifier_input_identifier(node_group, name),
|
||||
modifier_input_identifier(
|
||||
node_group, name,
|
||||
subtype="NONE" if name == "Thickness" and shape == "DEPTH_SOLID" else None,
|
||||
),
|
||||
value,
|
||||
)
|
||||
if shape in {"FLAT", "SOLID", "DEPTH_SOLID"} and gesture == "POLYLINE":
|
||||
set_modifier_input(
|
||||
modifier,
|
||||
modifier_input_identifier(node_group, "Mode"),
|
||||
1,
|
||||
)
|
||||
if shape == "SOLID":
|
||||
set_modifier_input(
|
||||
modifier,
|
||||
modifier_input_identifier(node_group, "Thickness", subtype="DISTANCE"),
|
||||
0.5,
|
||||
)
|
||||
if shape in DEPTH_CUTOUT_SHAPES:
|
||||
for name, value in (
|
||||
("Depth Scale", 1.0),
|
||||
|
||||
Reference in New Issue
Block a user