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:
2026-09-12 19:20:06 +08:00
parent e8268504c2
commit 938d95db0f
175 changed files with 3812 additions and 6864 deletions

View File

@@ -5,9 +5,6 @@ import numpy as np
import pytest
from tools.nodes.common.depth_surface import _remove_strip_faces
from tools.nodes.groups.image_depth_cutout import build_image_depth_cutout_group
from tools.nodes.groups.image_depth_plane import build_image_depth_plane_group
from tools.nodes.groups.image_plane import build_image_plane_group
def cleaned_faces(vertices, faces, *, triangles=False):
@@ -122,30 +119,13 @@ def test_triangle_cleanup_marks_both_faces_without_recursive_peeling():
assert cleaned_faces(vertices, faces, triangles=True) == {0, 2, 3}
@pytest.mark.parametrize("kind", ["plane", "cutout"])
def test_split_input_precedes_smooth_without_cleanup_switch(kind):
bpy.ops.wm.read_factory_settings(use_empty=True)
group = (build_image_depth_plane_group(build_image_plane_group()) if kind == "plane"
else build_image_depth_cutout_group())
inputs = [s for s in group.interface.items_tree if s.item_type == "SOCKET" and s.in_out == "INPUT"]
names = [s.name for s in inputs]
assert names.count("Split Threshold") == 1
assert names[names.index("Smooth") - 1] == "Split Threshold"
split = inputs[names.index("Split Threshold")]
assert split.parent == inputs[names.index("Smooth")].parent
assert split.parent.name != "Options"
assert split.default_value == pytest.approx(0.1)
assert (split.min_value, split.max_value, split.subtype) == (0, 1, "FACTOR")
assert "Remove Strip Faces" not in names
@pytest.mark.parametrize("kind", ["plane", "cutout"])
def test_strips_are_removed_before_projection_and_closed_thickness(kind):
from tests.support.depth_surface import surface, evaluated, assert_closed, component_count
from tests.support.planes import create_surface
if kind == "plane":
obj, set_value, _, _, image = create_surface("definition", "DEPTH")
obj, set_value, _, _, image = create_surface("DEPTH")
set_value("Subdivide", 1)
else:
obj, set_value = surface(step=0.0)
@@ -159,7 +139,7 @@ def test_strips_are_removed_before_projection_and_closed_thickness(kind):
set_value("Depth Scale", 1.0)
set_value("Reference Depth", 11.0)
assert len(evaluated(obj)[1]) == 8
set_value("Split Threshold", 0.5)
set_value("Depth Split", 0.5)
vertices, faces = evaluated(obj)
assert len(faces) == 4 and len(vertices) == 9
assert component_count(faces) == 1
@@ -183,18 +163,18 @@ def test_zero_split_bypasses_cleanup_and_positive_split_can_empty_mesh(kind):
from tests.support.planes import create_surface
if kind == "plane":
obj, set_value, _, _, _ = create_surface("definition", "DEPTH")
obj, set_value, _, _, _ = create_surface("DEPTH")
set_value("Subdivide", 0)
else:
obj, set_value = surface(step=0.0, resolution=1)
original, faces = evaluated(obj)
assert len(faces) == 2
set_value("Split Threshold", 0.001)
set_value("Depth Split", 0.001)
assert not evaluated(obj)[1]
set_value("Thickness", 0.2)
assert not evaluated(obj)[1]
set_value("Thickness", 0.0)
set_value("Split Threshold", 0.0)
set_value("Depth Split", 0.0)
restored, restored_faces = evaluated(obj)
assert restored_faces == faces
np.testing.assert_array_equal(restored, original)
@@ -212,7 +192,7 @@ def test_cutout_removes_an_all_boundary_triangle_strip():
mesh.free()
# Every vertex lies on the boundary, even before any depth separation.
for split in (0.0, 0.001, 0.0):
set_value("Split Threshold", split)
set_value("Depth Split", split)
for thickness in (0.0, 0.2):
set_value("Thickness", thickness)
points, faces = evaluated(obj)