Add comprehensive tests for image processing nodes and refactor node imports
- Introduced new test files for image layer, image plane, normal scale, object normal rotation, shadeless, and temporary attributes. - Implemented tests to validate the behavior of alpha curves, depth layers, and normal scales in various rendering engines. - Refactored import paths for node groups to align with the new directory structure. - Added checks for temporary attribute lifetimes and ensured proper cleanup without warnings. - Enhanced CLI commands to require the Blender group and validate the presence of generated node assets before packaging. - Updated packaging scripts to enforce the existence of necessary assets, preventing build failures.
This commit is contained in:
72
tests/nodes/test_cutout_boundary.py
Normal file
72
tests/nodes/test_cutout_boundary.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""Verify split profile shaping and displacement direction shaping."""
|
||||
|
||||
import bpy
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from tests.support.depth_surface import surface, evaluated
|
||||
from tests.nodes.test_boundary_smoothing import diagonal_surface
|
||||
|
||||
|
||||
def profile_values(obj):
|
||||
result = obj.evaluated_get(bpy.context.evaluated_depsgraph_get())
|
||||
mesh = result.to_mesh()
|
||||
try:
|
||||
return np.array([v.value for v in mesh.attributes["o_balloon"].data])
|
||||
finally:
|
||||
result.to_mesh_clear()
|
||||
|
||||
|
||||
def vertex_uv(obj):
|
||||
result = obj.evaluated_get(bpy.context.evaluated_depsgraph_get())
|
||||
mesh = result.to_mesh()
|
||||
try:
|
||||
uv = np.zeros((len(mesh.vertices), 2))
|
||||
for loop in mesh.loops:
|
||||
uv[loop.vertex_index] = mesh.uv_layers["UVMap"].data[loop.index].uv
|
||||
return uv
|
||||
finally:
|
||||
result.to_mesh_clear()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("iterations", [0, 16])
|
||||
def test_cleaned_sawtooth_smoothing_preserves_face_orientation(iterations):
|
||||
obj, set_value = diagonal_surface(triangles=True)
|
||||
original, faces = evaluated(obj)
|
||||
set_value("Boundary Smooth", iterations)
|
||||
points, actual = evaluated(obj)
|
||||
assert actual == faces
|
||||
indices = np.array(faces)
|
||||
def normals(p):
|
||||
return np.cross(p[indices[:,1]]-p[indices[:,0]], p[indices[:,2]]-p[indices[:,0]])
|
||||
assert np.all(np.sum(normals(original)*normals(points), axis=1) > 0)
|
||||
|
||||
|
||||
def test_split_profile_tapers_within_boundary_band():
|
||||
resolution, aspect = 12, .5
|
||||
obj, set_value = surface(step=6, resolution=resolution)
|
||||
for vertex in obj.data.vertices:
|
||||
vertex.co.x *= aspect
|
||||
image = bpy.data.images["Camera"]
|
||||
pixels = np.array(image.pixels[:], np.float32).reshape(32, 64, 4)
|
||||
pixels[..., 0] *= aspect
|
||||
image.pixels.foreach_set(pixels.ravel())
|
||||
image.update()
|
||||
obj.data.attributes.new("o_balloon", "FLOAT", "POINT").data.foreach_set(
|
||||
"value", np.full(len(obj.data.vertices), .3, dtype=np.float32))
|
||||
set_value("Depth Scale", 1)
|
||||
np.testing.assert_allclose(profile_values(obj), .3)
|
||||
set_value("Depth Split", .1)
|
||||
values = profile_values(obj)
|
||||
uv = vertex_uv(obj)
|
||||
# The depth step sits at u=0.5, so only that column is tapered.
|
||||
cut = (np.abs(uv[:, 0] - .5) < 1e-4) & (uv[:, 1] > 1e-3) & (uv[:, 1] < 1 - 1e-3)
|
||||
assert cut.any()
|
||||
np.testing.assert_array_equal(values[cut], 0)
|
||||
untouched = (np.abs(uv[:, 0] - .25) < 1e-3) | (np.abs(uv[:, 0] - .75) < 1e-3)
|
||||
assert untouched.any()
|
||||
np.testing.assert_allclose(values[untouched], .3)
|
||||
assert np.isfinite(values).all()
|
||||
assert values.max() == pytest.approx(.3)
|
||||
set_value("Depth Split", 0)
|
||||
np.testing.assert_allclose(profile_values(obj), .3)
|
||||
Reference in New Issue
Block a user