Refactor image mesh processing and background removal functionality

- Updated NODE_GROUP_NAME from "O Refine DA3 Surface" to "O DA3 Surface".
- Introduced `remove_surface_background` function to filter out background faces and compact geometry.
- Enhanced `build_image_mesh` to conditionally remove background faces based on a new property.
- Added `snapform_remove_background` and `snapform_keep_original` properties to operators for better control over background handling.
- Updated UI to reflect new properties and improved resolution scaling logic.
- Refactored tests to cover new background removal functionality and ensure proper geometry handling.
- Adjusted geometry nodes and validation scripts to remove references to background handling.
This commit is contained in:
2026-08-12 16:15:14 +08:00
parent 7cd5681a8b
commit c3a151ad2c
13 changed files with 477 additions and 271 deletions

View File

@@ -14,6 +14,7 @@ from snapform.image_depth import (
load_depth_plane_node_group,
modifier_input_identifier,
)
from snapform.image_mesh import load_geometry_node_group
def main():
@@ -27,6 +28,15 @@ def main():
and item.name == "Background Depth"
)
assert background_depth.subtype == "DISTANCE"
assert background_depth.structure_type == "SINGLE"
frame_input = next(
item
for item in group.interface.items_tree
if item.item_type == "SOCKET"
and item.in_out == "INPUT"
and item.name == "Frame"
)
assert frame_input.structure_type == "SINGLE"
geometry_input = next(
item
for item in group.interface.items_tree
@@ -45,22 +55,15 @@ def main():
assert visible_inputs[:6] == [
"Geometry",
"Displacement",
"Depth Scale",
"Subdivision",
"Remove Background",
"Depth Scale",
"Background Depth",
]
remove_background = next(
item
assert not getattr(background_depth.parent, "name", "")
assert not any(
item.name == "Remove Background"
for item in group.interface.items_tree
if item.item_type == "SOCKET"
and item.in_out == "INPUT"
and item.name == "Remove Background"
)
assert remove_background.socket_type == "NodeSocketBool"
assert remove_background.is_panel_toggle
assert remove_background.parent.name == "Remove Background"
assert background_depth.parent == remove_background.parent
depth_scale = next(
item
for item in group.interface.items_tree
@@ -77,7 +80,6 @@ def main():
if node.bl_idname == "GeometryNodeStoreNamedAttribute"
}
attribute_names = (
"o_remove_background",
"o_material_displacement",
"o_background_depth",
"o_depth_scale",
@@ -160,14 +162,31 @@ def main():
and node.node_tree == material_group
]
assert len(material_group_nodes) == 1
assert material_group_nodes[0].name == "O DA3 Depth Plane"
assert material_group_nodes[0].name == "O DA3 Depth Plane Layer"
bump = next(
node
for node in material_group.nodes
if node.bl_idname == "ShaderNodeBump"
)
bump_height_link = next(
link
for link in material_group.links
if link.to_node == bump and link.to_socket == bump.inputs["Height"]
)
assert bump_height_link.from_node.bl_idname == "NodeGroupInput"
assert bump_height_link.from_socket.name == "Color"
attributes = [
node
for node in material_group.nodes
if node.bl_idname == "ShaderNodeAttribute"
]
assert len(attributes) == 4
assert len(attributes) == 3
assert all(node.attribute_type == "GEOMETRY" for node in attributes)
assert {node.attribute_name for node in attributes} == {
"o_material_displacement",
"o_background_depth",
"o_depth_scale",
}
assert not any(
node.bl_idname == "ShaderNodeAttribute"
for node in material.node_tree.nodes
@@ -193,7 +212,25 @@ def main():
and node.node_tree == surface_group
]
assert len(surface_group_nodes) == 1
assert surface_group_nodes[0].name == "O DA3 Surface"
assert surface_group_nodes[0].name == "O DA3 Surface Layer"
surface_outputs = [
item.name
for item in surface_group.interface.items_tree
if item.item_type == "SOCKET"
and item.in_out == "OUTPUT"
]
assert surface_outputs == ["Color", "Roughness", "Alpha", "Normal"]
assert not any(
node.bl_idname == "ShaderNodeDisplacement"
for node in surface_group.nodes
)
refine_group = load_geometry_node_group()
assert not any(
item.item_type == "SOCKET"
and item.in_out == "INPUT"
and item.name == "Background"
for item in refine_group.interface.items_tree
)
surface_depth_input = next(
item
for item in surface_group.interface.items_tree
@@ -206,7 +243,13 @@ def main():
node.bl_idname in forbidden_outer_nodes
for node in surface_material.node_tree.nodes
)
modifier = add_depth_plane_processing(obj, depth, foreground, material)
modifier = add_depth_plane_processing(
obj,
depth,
foreground,
material,
animate_frame=True,
)
modifier[modifier_input_identifier(group, "Depth Scale")] = -2.0
for name, expected in (
("Frame Start", 1),
@@ -214,6 +257,20 @@ def main():
("Cyclic", False),
):
assert modifier[modifier_input_identifier(group, name)] == expected
assert not any(
node.bl_idname == "GeometryNodeInputSceneTime"
for node in group.nodes
)
frame_identifier = modifier_input_identifier(group, "Frame")
frame_driver = next(
fcurve
for fcurve in obj.animation_data.drivers
if fcurve.data_path == (
f'modifiers["{modifier.name}"]["{frame_identifier}"]'
)
)
assert frame_driver.driver.type == "SCRIPTED"
assert frame_driver.driver.expression == "frame"
image_textures = [
node
for node in group.nodes