diff --git a/models/issue-400-num-face-vertices.obj b/models/issue-400-num-face-vertices.obj new file mode 100644 index 00000000..77e25b48 --- /dev/null +++ b/models/issue-400-num-face-vertices.obj @@ -0,0 +1,15 @@ +# Regression test model for issue #400 - numpy_num_face_vertices() +# Mixed quad and triangle faces to verify correct uint type handling. +# With the bug (unsigned char instead of unsigned int in the numpy binding), +# numpy_num_face_vertices() returned all zeros for quad (4-vertex) faces. +v 0.0 0.0 0.0 +v 1.0 0.0 0.0 +v 1.0 1.0 0.0 +v 0.0 1.0 0.0 +v 0.5 0.5 1.0 +# quad face (num_face_vertices = 4) +f 1 2 3 4 +# triangle face (num_face_vertices = 3) +f 1 2 5 +# triangle face (num_face_vertices = 3) +f 2 3 5 diff --git a/tests/python/tinyobjloader_tests/test_loader.py b/tests/python/tinyobjloader_tests/test_loader.py index 8d7b8f50..c9159ea1 100644 --- a/tests/python/tinyobjloader_tests/test_loader.py +++ b/tests/python/tinyobjloader_tests/test_loader.py @@ -1,7 +1,11 @@ +from pathlib import Path + import numpy as np from .loader import Loader, LoadException +MODELS_DIR = Path(__file__).parent.parent.parent.parent / "models" + TWO_QUADS = """ v 0 0 0 v 0 0 0 @@ -130,7 +134,32 @@ def test_numpy_index_array_two_quads(): assert [x.vertex_index for x in shape.mesh.indices] == expected_vertex_index # Test. - expected_numpy_indices = [0, -1, -1, 1, -1, -1, 2, -1, -1, 3, -1, -1, 4, -1, -1, 5, -1, -1, 6, -1, -1, 7, -1, -1] + expected_numpy_indices = [ + 0, + -1, + -1, + 1, + -1, + -1, + 2, + -1, + -1, + 3, + -1, + -1, + 4, + -1, + -1, + 5, + -1, + -1, + 6, + -1, + -1, + 7, + -1, + -1, + ] np.testing.assert_array_equal(shape.mesh.numpy_indices(), expected_numpy_indices) @@ -174,3 +203,33 @@ def test_numpy_vertex_array_two_quads(): # Test. np.testing.assert_array_almost_equal(loader.attrib.numpy_vertices(), expected_vertices, decimal=6) + + +def test_numpy_num_face_vertices_from_file(): + """ + Regression test for https://github.com/tinyobjloader/tinyobjloader/issues/400 + + Loads a mixed quad/triangle mesh from a .obj file and checks that + numpy_num_face_vertices() returns correct unsigned int values. + With the bug (unsigned char element type), values were read as zeros. + """ + + # Set up. + obj_path = str(MODELS_DIR / "issue-400-num-face-vertices.obj") + loader = Loader(triangulate=False) + loader.load(obj_path) + + shapes = loader.shapes + assert len(shapes) == 1 + + (shape,) = shapes + # The file has one quad face (4 vertices) and two triangle faces (3 vertices each). + expected_num_face_vertices = [4, 3, 3] + + # Confidence check using the non-numpy accessor. + assert shape.mesh.num_face_vertices == expected_num_face_vertices + + # Test: numpy_num_face_vertices() must return the same values with the correct dtype. + result = shape.mesh.numpy_num_face_vertices() + np.testing.assert_array_equal(result, expected_num_face_vertices) + assert result.dtype == np.dtype("uint32")