Files
PozzettiAndrea-ComfyUI-Geom…/tests/test_scripts/test_remeshing.py
T

207 lines
6.0 KiB
Python

"""Tests for remeshing nodes."""
import pytest
from nodes.remeshing import (
PyMeshLabRemeshNode,
CGALIsotropicRemeshNode,
MeshDecimationNode,
MeshSubdivisionNode,
LaplacianSmoothingNode,
BlenderVoxelRemeshNode,
BlenderQuadriflowRemeshNode,
InstantMeshesRemeshNode,
)
@pytest.mark.unit
@pytest.mark.optional
def test_pymeshlab_remesh(sphere_mesh, save_mesh_helper, render_helper):
"""Test PyMeshLab isotropic remeshing."""
pytest.importorskip("pymeshlab")
# Save original
save_mesh_helper(sphere_mesh, "00_original", "obj")
render_helper(sphere_mesh, "00_original")
node = PyMeshLabRemeshNode()
try:
remeshed = node.remesh(
trimesh=sphere_mesh,
target_edge_length=0.1,
iterations=10
)[0]
except ValueError as e:
if "PyMeshLab meshing filter not available" in str(e):
pytest.skip("PyMeshLab meshing filter not available (missing OpenGL libraries)")
raise
assert remeshed is not None
assert remeshed.faces.shape[0] > 0
# Save remeshed result
save_mesh_helper(remeshed, "01_pymeshlab_remeshed", "obj")
render_helper(remeshed, "01_pymeshlab_remeshed")
@pytest.mark.optional
def test_cgal_remesh(sphere_mesh, save_mesh_helper, render_helper):
"""Test CGAL isotropic remeshing."""
pytest.importorskip("cgal")
# Save original
save_mesh_helper(sphere_mesh, "00_original", "obj")
render_helper(sphere_mesh, "00_original")
node = CGALIsotropicRemeshNode()
remeshed = node.remesh(
trimesh=sphere_mesh,
target_edge_length=0.1,
iterations=5,
protect_boundaries="false"
)[0]
assert remeshed is not None
assert remeshed.faces.shape[0] > 0
# Save remeshed result
save_mesh_helper(remeshed, "01_cgal_remeshed", "obj")
render_helper(remeshed, "01_cgal_remeshed")
@pytest.mark.unit
def test_mesh_decimation(sphere_mesh, save_mesh_helper, render_helper):
"""Test mesh decimation - reduces triangle count while preserving shape."""
# Save original
save_mesh_helper(sphere_mesh, "00_original", "obj")
render_helper(sphere_mesh, "00_original")
original_face_count = sphere_mesh.faces.shape[0]
target_faces = original_face_count // 4
node = MeshDecimationNode()
decimated, info = node.decimate(
trimesh=sphere_mesh,
target_face_count=target_faces
)
assert decimated is not None
assert decimated.faces.shape[0] < original_face_count
assert "face" in info.lower()
# Save decimated result
save_mesh_helper(decimated, "01_decimated", "obj")
render_helper(decimated, "01_decimated")
@pytest.mark.unit
@pytest.mark.parametrize("iterations", [1, 2, 3])
def test_mesh_subdivision(cube_mesh, iterations, save_mesh_helper, render_helper):
"""Test mesh subdivision - increases mesh resolution."""
# Save original (only on first iteration to avoid duplication across params)
save_mesh_helper(cube_mesh, "00_original", "obj")
render_helper(cube_mesh, "00_original")
original_face_count = cube_mesh.faces.shape[0]
node = MeshSubdivisionNode()
subdivided, info = node.subdivide(
trimesh=cube_mesh,
iterations=iterations,
method="loop"
)
assert subdivided is not None
assert subdivided.faces.shape[0] > original_face_count
# Save with iteration count in name
save_mesh_helper(subdivided, f"01_subdivided_x{iterations}", "obj")
render_helper(subdivided, f"01_subdivided_x{iterations}")
@pytest.mark.unit
def test_laplacian_smoothing(sphere_mesh, save_mesh_helper, render_helper):
"""Test Laplacian smoothing - smooths mesh surface."""
# Save original
save_mesh_helper(sphere_mesh, "00_original", "obj")
render_helper(sphere_mesh, "00_original")
node = LaplacianSmoothingNode()
smoothed = node.smooth(
trimesh=sphere_mesh,
iterations=10,
lambda_factor=0.5
)[0]
assert smoothed is not None
assert smoothed.vertices.shape == sphere_mesh.vertices.shape
# Save smoothed result
save_mesh_helper(smoothed, "01_smoothed", "obj")
render_helper(smoothed, "01_smoothed")
@pytest.mark.blender
@pytest.mark.slow
def test_blender_voxel_remesh(sphere_mesh, save_mesh_helper, render_helper):
"""Test Blender voxel remeshing."""
# Save original
save_mesh_helper(sphere_mesh, "00_original", "obj")
render_helper(sphere_mesh, "00_original")
node = BlenderVoxelRemeshNode()
remeshed = node.voxel_remesh(trimesh=sphere_mesh, voxel_size=0.1)[0]
assert remeshed is not None
# Save remeshed result
save_mesh_helper(remeshed, "01_voxel_remeshed", "obj")
render_helper(remeshed, "01_voxel_remeshed")
@pytest.mark.blender
@pytest.mark.slow
def test_blender_quadriflow_remesh(sphere_mesh, save_mesh_helper, render_helper):
"""Test Blender Quadriflow remeshing."""
# Save original
save_mesh_helper(sphere_mesh, "00_original", "obj")
render_helper(sphere_mesh, "00_original")
node = BlenderQuadriflowRemeshNode()
remeshed = node.quadriflow_remesh(
trimesh=sphere_mesh,
target_face_count=500
)[0]
assert remeshed is not None
# Save remeshed result
save_mesh_helper(remeshed, "01_quadriflow_remeshed", "obj")
render_helper(remeshed, "01_quadriflow_remeshed")
@pytest.mark.optional
@pytest.mark.slow
def test_instant_meshes_remesh(sphere_mesh, save_mesh_helper, render_helper):
"""Test InstantMeshes remeshing."""
pytest.importorskip("PyNanoInstantMeshes")
# Save original
save_mesh_helper(sphere_mesh, "00_original", "obj")
render_helper(sphere_mesh, "00_original")
node = InstantMeshesRemeshNode()
remeshed, info = node.instant_remesh(
trimesh=sphere_mesh,
target_vertex_count=500,
deterministic="true",
crease_angle=30.0
)
assert remeshed is not None
assert "vertices" in info.lower()
# Save remeshed result
save_mesh_helper(remeshed, "01_instant_remeshed", "obj")
render_helper(remeshed, "01_instant_remeshed")