- Implemented `image_plane.py` to build the Image Plane Geometry Nodes group with customizable parameters for geometry, subdivide, and thickness. - Created `image_plane_validation.py` to validate the functionality of the image plane, ensuring correct geometry generation and material assignment. - Developed `material_layers.py` to construct shader node groups for image materials, including depth and normal handling. - Authored `plane_layouts.py` to define node arrangements for image geometry assets. - Introduced `shadeless.py` to create a shadeless shader node group that displays color without scene lighting while preserving shadows and reflections.
87 lines
2.5 KiB
Python
87 lines
2.5 KiB
Python
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
import numpy as np
|
|
|
|
SOURCE_ROOT = Path(__file__).parents[1] / "src"
|
|
|
|
sys.path.insert(0, str(SOURCE_ROOT))
|
|
|
|
|
|
from anyimage.operators.cutout_tool import geometry as cutout_geometry
|
|
from anyimage.operators.cutout_tool.geometry import poisson_balloon_profile
|
|
|
|
|
|
def test_poisson_balloon_profile_is_zero_on_boundary_and_positive_inside():
|
|
points = np.asarray(
|
|
((0, 0), (2, 0), (2, 2), (0, 2), (1, 1)),
|
|
dtype=float,
|
|
)
|
|
faces = ((0, 1, 4), (1, 2, 4), (2, 3, 4), (3, 0, 4))
|
|
boundary = np.asarray((True, True, True, True, False))
|
|
|
|
profile = poisson_balloon_profile(points, faces, boundary)
|
|
|
|
assert np.all(profile[:4] == 0.0)
|
|
assert profile[4] > 0.0
|
|
|
|
|
|
def test_poisson_balloon_profile_scales_in_world_units():
|
|
points = np.asarray(
|
|
((0, 0), (2, 0), (2, 2), (0, 2), (1, 1)),
|
|
dtype=float,
|
|
)
|
|
faces = ((0, 1, 4), (1, 2, 4), (2, 3, 4), (3, 0, 4))
|
|
boundary = np.asarray((True, True, True, True, False))
|
|
|
|
original = poisson_balloon_profile(points, faces, boundary)
|
|
scaled = poisson_balloon_profile(points * 2.0, faces, boundary)
|
|
|
|
assert np.isclose(scaled[4], original[4] * 2.0, atol=1e-6)
|
|
|
|
|
|
def test_poisson_balloon_profile_makes_wide_selections_thicker():
|
|
faces = ((0, 1, 4), (1, 2, 4), (2, 3, 4), (3, 0, 4))
|
|
boundary = np.asarray((True, True, True, True, False))
|
|
wide = np.asarray(
|
|
((0, 0), (4, 0), (4, 2), (0, 2), (2, 1)),
|
|
dtype=float,
|
|
)
|
|
narrow = np.asarray(
|
|
((0, 0), (4, 0), (4, 0.6), (0, 0.6), (2, 0.3)),
|
|
dtype=float,
|
|
)
|
|
|
|
wide_profile = poisson_balloon_profile(wide, faces, boundary)
|
|
narrow_profile = poisson_balloon_profile(narrow, faces, boundary)
|
|
|
|
assert wide_profile[4] > narrow_profile[4]
|
|
|
|
|
|
def test_teddy_balloon_profile_uses_chordal_axis_radius():
|
|
points = np.asarray(
|
|
((0, 0), (4, 0), (4, 2), (0, 2), (2, 1)),
|
|
dtype=float,
|
|
)
|
|
faces = ((0, 1, 4), (1, 2, 4), (2, 3, 4), (3, 0, 4))
|
|
boundary = np.asarray((True, True, True, True, False))
|
|
nodes = np.asarray(((1, 1), (3, 1)), dtype=float)
|
|
|
|
with patch.object(
|
|
cutout_geometry,
|
|
"chordal_axis",
|
|
return_value=(nodes, [(0, 1)], np.asarray((1.0, 1.0))),
|
|
):
|
|
profile = cutout_geometry.teddy_balloon_heights(
|
|
points,
|
|
faces,
|
|
points[:4],
|
|
boundary,
|
|
0.45,
|
|
)
|
|
|
|
assert np.all(profile[:4] == 0.0)
|
|
assert np.isclose(profile[4], 0.45, atol=1e-6)
|