Refactor geometry generation to standardize Blender object coordinates
- Unified the canonical local frame for generated geometries (Plane, Depth Plane, Relief Plane, Cutout, Depth Cutout) to align with Blender's object coordinate system, setting X as horizontal, Z as up, and +Y as depth. - Removed the `Depth Axis` parameter from `O Image Cutout` and `O Image Depth Cutout`, simplifying the geometry generation process. - Updated the depth direction defaults to use +Y instead of -Z for `O Image Relief Plane` and Depth Symmetry. - Adjusted the geometry nodes to ensure thickness, projection, and shell displacements operate along the Y-axis. - Implemented new capabilities for handling object space normals to align with the new canonical frame. - Enhanced the Depth Symmetry functionality to mirror across the canonical Y-axis and perform a final rotation to maintain the correct orientation. - Added tests to validate the new coordinate system and ensure compatibility with existing assets.
This commit is contained in:
@@ -14,28 +14,20 @@ from anyimage.common.object import modifier_input_identifier, set_modifier_input
|
||||
|
||||
@pytest.mark.parametrize("source", ("definition", "asset"))
|
||||
@pytest.mark.parametrize("shape", ("SOLID", "DEPTH_SOLID"))
|
||||
def test_depth_axis_is_visible_in_options(shape, source):
|
||||
def test_depth_axis_is_removed_from_cutout_options(shape, source):
|
||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||
group = CUTOUT_BUILDERS[shape]() if source == "definition" else load_cutout_node_group(shape)
|
||||
inputs = {item.name: item for item in group.interface.items_tree
|
||||
if item.item_type == "SOCKET" and item.in_out == "INPUT"}
|
||||
axis = inputs["Depth Axis"]
|
||||
assert axis.parent.name == "Options"
|
||||
assert axis.menu_expanded
|
||||
assert not axis.hide_in_modifier
|
||||
assert axis.default_value == "-Z"
|
||||
assert "Depth Axis" not in inputs
|
||||
assert "Inward Axis" not in inputs
|
||||
options = [item.name for item in inputs.values() if item.parent == axis.parent]
|
||||
predecessor = "Cleanup Threshold" if shape == "SOLID" else "Reference Depth"
|
||||
assert options[options.index(predecessor) + 1] == "Depth Axis"
|
||||
if shape == "SOLID":
|
||||
assert not any(item.item_type == "PANEL" and item.name == "Data" for item in group.interface.items_tree)
|
||||
assert all(item.name != "Depth Axis" for item in group.interface.items_tree)
|
||||
|
||||
|
||||
def test_cutout_thickness_modes():
|
||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||
mesh = bpy.data.meshes.new("Profile")
|
||||
mesh.from_pydata([(-1,-1,0), (1,-1,0), (1,1,0), (-1,1,0), (0,0,0)], [], [(0,1,4), (1,2,4), (2,3,4), (3,0,4)])
|
||||
mesh.from_pydata([(-1,0,-1), (1,0,-1), (1,0,1), (-1,0,1), (0,0,0)], [], [(0,1,4), (1,2,4), (2,3,4), (3,0,4)])
|
||||
profile = mesh.attributes.new("o_balloon", "FLOAT", "POINT")
|
||||
profile.data.foreach_set("value", [0,0,0,0,0.6])
|
||||
obj = bpy.data.objects.new("Profile", mesh)
|
||||
@@ -51,14 +43,14 @@ def test_cutout_thickness_modes():
|
||||
evaluated = obj.evaluated_get(bpy.context.evaluated_depsgraph_get())
|
||||
result = evaluated.to_mesh()
|
||||
try:
|
||||
z = np.array([vertex.co.z for vertex in result.vertices])
|
||||
assert np.isfinite(z).all() and len(z)
|
||||
y = np.array([vertex.co.y for vertex in result.vertices])
|
||||
assert np.isfinite(y).all() and len(y)
|
||||
if thickness == 0:
|
||||
assert len(result.polygons) == 4 and np.max(abs(z)) < 1e-7
|
||||
assert len(result.polygons) == 4 and np.max(abs(y)) < 1e-7
|
||||
assert all(abs(item.value) < 1e-7 for item in result.attributes["o_normal_reduction"].data)
|
||||
else:
|
||||
back, front = (-0.6, 0.6) if mode == 0 else (-thickness, 0.0)
|
||||
assert np.isclose(z.min(), back) and np.isclose(z.max(), front)
|
||||
back, front = (-0.6, 0.6) if mode == 0 else (0.0, thickness)
|
||||
assert np.isclose(y.min(), back) and np.isclose(y.max(), front)
|
||||
uses = Counter(tuple(sorted((a,b))) for face in result.polygons for a,b in zip(face.vertices, (*face.vertices[1:],face.vertices[0])))
|
||||
assert set(uses.values()) == {2}
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user