Exemplo n.º 1
0
 def setUp(self):
     rows, cols = 3, 4
     self.base_color = np.empty((rows, cols, 3), dtype=np.uint8)
     self.metallic_roughness = np.empty((rows, cols, 3), dtype=np.uint8)
     self.vertices = np.column_stack([
         Vector3f(0, 0, 0),
         Vector3f(1, 0, 0),
         Vector3f(0, 1, 0),
         Vector3f(1, 1, 0)
     ])
     self.normals = np.column_stack([Vector3f(0, 0, 1)] * 4)
     self.uv_coords = np.column_stack(
         [Vector2f(0, 0),
          Vector2f(1, 0),
          Vector2f(0, 1),
          Vector2f(1, 1)])
     self.temp_directory = tempfile.mkdtemp()
     self.indices = np.array([0, 1, 2, 1, 3, 2], dtype=np.uint32)
     self.mesh = TexturedMesh(
         self.indices,
         self.vertices,
         self.normals,
         self.uv_coords,
         self.base_color,
         self.metallic_roughness,
     )
Exemplo n.º 2
0
 def test_merge_quadrant_meshes(self):
     """Test merging 4 quads that (could be) result of subdivision."""
     indices = np.array([0, 1, 2, 1, 3, 2], dtype=np.uint32)
     # 2 7 3
     # 4 6 8
     # 0 5 1
     vertices = np.column_stack([
         Vector3f(0, 0, 0),
         Vector3f(1, 1, 1),
         Vector3f(2, 2, 2),
         Vector3f(3, 3, 3),
         Vector3f(4, 4, 4),
         Vector3f(5, 5, 5),
         Vector3f(6, 6, 6),
         Vector3f(7, 7, 7),
         Vector3f(8, 8, 8),
     ])
     args = self.normals, self.uv_coords, self.base_color, self.metallic_roughness
     mesh0 = TexturedMesh(indices, vertices[:, [0, 5, 4, 6]], *args)
     mesh1 = TexturedMesh(indices, vertices[:, [5, 1, 6, 8]], *args)
     mesh2 = TexturedMesh(indices, vertices[:, [4, 6, 2, 7]], *args)
     mesh3 = TexturedMesh(indices, vertices[:, [6, 8, 7, 3]], *args)
     mesh = TexturedMesh.merge_quadrant_meshes(mesh0, mesh1, mesh2, mesh3)
     self.assertEqual(mesh.num_indices(), 4 * 3 * 2)
     self.assertEqual(mesh.num_vertices(), 9)
     expected_indices = ([0, 5, 4, 5, 6, 4] + [5, 1, 6, 1, 8, 6] +
                         [4, 6, 2, 6, 7, 2] + [6, 8, 7, 8, 3, 7])
     np.testing.assert_array_equal(mesh.indices(), expected_indices)
     np.testing.assert_array_equal(mesh.vertices(), vertices)
Exemplo n.º 3
0
    def test_merge(self):
        """Test merging two meshes with common vertices."""
        vertices = np.column_stack([self.vertices, self.vertices])
        self.assertEqual(vertices.shape, (3, 8))
        normals = np.column_stack([self.normals, self.normals])
        uv_coords = np.column_stack([self.uv_coords, self.uv_coords])

        indices1 = np.array([0, 1, 2, 4, 5, 7], dtype=np.uint32)
        mesh = TexturedMesh(
            indices1,
            vertices,
            normals,
            uv_coords,
            self.base_color,
            self.metallic_roughness,
        )

        indices2 = np.array([1, 3, 2, 4, 5, 7], dtype=np.uint32)
        mesh2 = TexturedMesh(
            indices2,
            vertices,
            normals,
            uv_coords,
            self.base_color,
            self.metallic_roughness,
        )

        mesh.merge(mesh2, 4)
        self.assertEqual(mesh.vertices().shape, (3, 12))
        expected = np.column_stack(
            [self.vertices, self.vertices, self.vertices])
        np.testing.assert_array_equal(mesh.vertices(), expected)
        expected_indices = np.array([0, 1, 2, 4, 5, 7, 1, 3, 2, 8, 9, 11],
                                    dtype=np.uint32)
        np.testing.assert_array_equal(mesh.indices(), expected_indices)
Exemplo n.º 4
0
    def test_mesh_roundtrip(self):
        """Check that we can save then read a textured mesh."""
        mesh = TexturedMesh.example()
        expected_color = mesh.base_color()[0, 0, :]
        expected_mr = mesh.metallic_roughness()[0, 0, :]

        model = GltfModel.from_textured_mesh(mesh)
        model.save_as_gltf(self.temp_directory, "dummy")

        # now load...
        input_path = os.path.join(self.temp_directory, "dummy.gltf")
        model2 = GltfModel.load_from_gltf(input_path)
        self.assertEqual(model2.num_images(), 2)
        self.assertEqual(model.image_size(0), 288)
        self.assertEqual(model.image_size(1), 72)
        self.assertEqual(model.image_uri(0), "0.png")
        self.assertEqual(model.image_uri(1), "1.png")

        # ...and check mesh.
        mesh2 = model2.extract_textured_primitive_mesh()
        self.assertEqual(mesh2.num_vertices(), 24)
        self.assertTrue(mesh.has_dual_texture_material())
        np.testing.assert_array_equal(mesh2.base_color()[0, 0, :],
                                      expected_color)
        np.testing.assert_array_equal(mesh2.metallic_roughness()[0, 0, :],
                                      expected_mr)
Exemplo n.º 5
0
 def test_add_mesh(self):
     """Test python wrapper to go from TexturedMesh to GltfModel."""
     model = GltfModel()
     mesh = TexturedMesh.example()
     model.add_textured_primitive_mesh(mesh)
     self.assertEqual(model.num_primitive_meshes(), 1)
     self.assertEqual(model.num_nodes(), 1)
     self.assertEqual(model.num_buffers(), 1)
Exemplo n.º 6
0
 def test_save_textured_mesh_as_glb(self):
     """Check that we can save a textured mesh directly to glb."""
     mesh = TexturedMesh.example()
     model = GltfModel.from_textured_mesh(mesh)
     path = os.path.join(self.temp_directory, "dummy.glb")
     model.save_as_glb(path)
     # Check the existence of glb
     self.assertTrue(os.path.isfile(path))
Exemplo n.º 7
0
 def test_update_textured_material(self):
     mesh = TexturedMesh.example()
     model = GltfModel.from_textured_mesh(mesh)
     self.assertEqual(model.num_images(), 2)
     uri = "Cube_BaseColor.png"
     base_dir = TEST_PATH
     material = {"color": Vector3(0, 0, 0), "uri": uri}
     model.update_materials(base_dir, [material])
     self.assertEqual(model.num_images(), 3)
Exemplo n.º 8
0
    def test_cube(self):
        """Check generation of a cube mesh."""
        rows, cols = 4, 24
        base_color = np.empty((rows, cols, 3), dtype=np.uint8)
        metallic_roughness = np.empty((rows, cols, 3), dtype=np.uint8)
        mesh = TexturedMesh.cube(base_color, metallic_roughness)

        # Check indices
        indices = mesh.indices()
        self.assertEqual(indices.shape, (6 * 6, ))
        np.testing.assert_array_equal(indices[:6], [0, 1, 2, 1, 3, 2])
        np.testing.assert_array_equal(indices[-6:], [20, 21, 22, 21, 23, 22])

        # Check 3D mesh
        vertices = mesh.vertices()
        self.assertEqual(vertices.shape, (3, 4 * 6))
        # Check BACK, where y = -1
        np.testing.assert_array_equal(
            vertices[:, :4],
            np.column_stack([
                Vector3f(+1, -1, +1),
                Vector3f(-1, -1, +1),
                Vector3f(+1, +1, +1),
                Vector3f(-1, +1, +1),
            ]),
        )
        # Check LEFT, FRONT, RIGHT, UP
        np.testing.assert_array_equal(vertices[0, 4:8], (-1, -1, -1, -1))
        np.testing.assert_array_equal(vertices[2, 8:12], (-1, -1, -1, -1))
        np.testing.assert_array_equal(vertices[0, 12:16], (1, 1, 1, 1))
        np.testing.assert_array_equal(vertices[1, 16:20], (1, 1, 1, 1))
        # Check DOWN, where Z = -1
        np.testing.assert_array_equal(
            vertices[:, -4:],
            np.column_stack([
                Vector3f(-1, -1, +1),
                Vector3f(+1, -1, +1),
                Vector3f(-1, -1, -1),
                Vector3f(+1, -1, -1),
            ]),
        )

        # check cpp_normals
        normals = mesh.normals()
        # normals for BACK, LEFT, FRONT, RIGHT, UP, DOWN
        dir = [(0, 0, -1), (1, 0, 0), (0, 0, 1), (-1, 0, 0), (0, -1, 0),
               (0, 1, 0)]
        for j in range(6):
            np.testing.assert_array_equal(normals[:, j * 4], dir[j])

        # Check texture coordinates
        uv_coords = mesh.uv_coords()
        np.testing.assert_array_almost_equal(
            uv_coords[:, :4], [[0, 1 / 6.0, 0, 1 / 6.0], [1, 1, 0, 0]])
        np.testing.assert_array_equal(np.min(uv_coords, axis=1), [0, 0])
        np.testing.assert_array_equal(np.max(uv_coords, axis=1), [1, 1])
Exemplo n.º 9
0
 def test_add_colored_material(self):
     mesh = TexturedMesh.example()
     model = GltfModel.from_textured_mesh(mesh)
     index = model.add_colored_material("my_material",
                                        Vector3f(0.5, 0.5, 0.5), 0.0, 0.95)
     self.assertEqual(index, 1)
     index = model.add_colored_material("another_material",
                                        Vector3f(0.75, 0.75, 0.75), 0.1,
                                        0.7)
     self.assertEqual(index, 2)
Exemplo n.º 10
0
    def test_from_mesh(self):
        """Test converting mesh to textured mesh."""
        mesh = Box3d([0, 0, 0], [1, 1, 1]).to_mesh()
        color = np.array([255, 0, 0], dtype=np.uint8)  # red
        textured_mesh = TexturedMesh.from_mesh(mesh, color)

        self.assertIsInstance(textured_mesh, TexturedMesh)
        self.assertEqual(textured_mesh.num_vertices(), mesh.num_vertices())
        self.assertEqual(textured_mesh.num_indices(), mesh.num_indices())
        self.assertEqual(textured_mesh.normals().shape, mesh.vertices().shape)
        self.assertEqual(textured_mesh.uv_coords().shape[1],
                         mesh.num_vertices())
Exemplo n.º 11
0
 def test_merge6(self):
     """Test merging 6 meshes."""
     # Create 6 separate meshes
     # loop over all cube faces
     faces = []
     for _ in range(6):
         # TODO: faces.append(self.mesh) bombs, probably memory alloc issues
         faces.append(
             TexturedMesh(
                 self.indices,
                 self.vertices,
                 self.normals,
                 self.uv_coords,
                 self.base_color,
                 self.metallic_roughness,
             ))
     # merge faces:
     mesh = faces[5]
     for i in range(5):
         mesh.merge(faces[i], 0)
     self.assertEqual(mesh.num_indices(), 36)
     self.assertEqual(mesh.num_vertices(), 24)
Exemplo n.º 12
0
 def test_update_material(self):
     mesh = TexturedMesh.example()
     model = GltfModel.from_textured_mesh(mesh)
     material = {"color": Vector3(0.5, 0.5, 0.5), "uri": ""}
     model.update_materials("", [material])
Exemplo n.º 13
0
class TestTexturedMesh(unittest.TestCase):
    def setUp(self):
        rows, cols = 3, 4
        self.base_color = np.empty((rows, cols, 3), dtype=np.uint8)
        self.metallic_roughness = np.empty((rows, cols, 3), dtype=np.uint8)
        self.vertices = np.column_stack([
            Vector3f(0, 0, 0),
            Vector3f(1, 0, 0),
            Vector3f(0, 1, 0),
            Vector3f(1, 1, 0)
        ])
        self.normals = np.column_stack([Vector3f(0, 0, 1)] * 4)
        self.uv_coords = np.column_stack(
            [Vector2f(0, 0),
             Vector2f(1, 0),
             Vector2f(0, 1),
             Vector2f(1, 1)])
        self.temp_directory = tempfile.mkdtemp()
        self.indices = np.array([0, 1, 2, 1, 3, 2], dtype=np.uint32)
        self.mesh = TexturedMesh(
            self.indices,
            self.vertices,
            self.normals,
            self.uv_coords,
            self.base_color,
            self.metallic_roughness,
        )

    def tearDown(self):
        """Clean up: remove temporary outout directory."""
        shutil.rmtree(self.temp_directory)

    def test_constructor(self):
        """Create a minimal example and test constructor with it."""
        self.assertEqual(self.mesh.num_indices(), 6)
        self.assertEqual(self.mesh.num_vertices(), 4)
        np.testing.assert_array_equal(self.mesh.indices(), self.indices)
        np.testing.assert_array_equal(self.mesh.vertices(), self.vertices)
        np.testing.assert_array_equal(self.mesh.normals(), self.normals)
        np.testing.assert_array_equal(self.mesh.uv_coords(), self.uv_coords)
        self.assertTrue(self.mesh.has_dual_texture_material())

    def test_merge(self):
        """Test merging two meshes with common vertices."""
        vertices = np.column_stack([self.vertices, self.vertices])
        self.assertEqual(vertices.shape, (3, 8))
        normals = np.column_stack([self.normals, self.normals])
        uv_coords = np.column_stack([self.uv_coords, self.uv_coords])

        indices1 = np.array([0, 1, 2, 4, 5, 7], dtype=np.uint32)
        mesh = TexturedMesh(
            indices1,
            vertices,
            normals,
            uv_coords,
            self.base_color,
            self.metallic_roughness,
        )

        indices2 = np.array([1, 3, 2, 4, 5, 7], dtype=np.uint32)
        mesh2 = TexturedMesh(
            indices2,
            vertices,
            normals,
            uv_coords,
            self.base_color,
            self.metallic_roughness,
        )

        mesh.merge(mesh2, 4)
        self.assertEqual(mesh.vertices().shape, (3, 12))
        expected = np.column_stack(
            [self.vertices, self.vertices, self.vertices])
        np.testing.assert_array_equal(mesh.vertices(), expected)
        expected_indices = np.array([0, 1, 2, 4, 5, 7, 1, 3, 2, 8, 9, 11],
                                    dtype=np.uint32)
        np.testing.assert_array_equal(mesh.indices(), expected_indices)

    def test_renumber(self):
        """Test renumbering some of the vertices."""
        mesh = self.mesh
        mesh.renumber(6, [5, 0])
        # 6 to make room for new indices, 4 for old indices, - 2 renumbered
        # index 1 is renumbered to 0
        # index 0 is renumbered to 5
        self.assertEqual(mesh.num_indices(), 6)
        expected_indices = np.array([5, 0, 2 + 6, 0, 3 + 6, 2 + 6],
                                    dtype=np.uint32)
        np.testing.assert_array_equal(mesh.indices(), expected_indices)
        self.assertEqual(mesh.num_vertices(), 6 + 4 - 2)
        np.testing.assert_array_equal(mesh.vertices()[:, 0], self.vertices[:,
                                                                           1])
        np.testing.assert_array_equal(mesh.normals()[:, 5], self.normals[:, 0])
        np.testing.assert_array_equal(mesh.uv_coords()[:, 5],
                                      self.uv_coords[:, 0])

    def test_merge_quadrant_meshes(self):
        """Test merging 4 quads that (could be) result of subdivision."""
        indices = np.array([0, 1, 2, 1, 3, 2], dtype=np.uint32)
        # 2 7 3
        # 4 6 8
        # 0 5 1
        vertices = np.column_stack([
            Vector3f(0, 0, 0),
            Vector3f(1, 1, 1),
            Vector3f(2, 2, 2),
            Vector3f(3, 3, 3),
            Vector3f(4, 4, 4),
            Vector3f(5, 5, 5),
            Vector3f(6, 6, 6),
            Vector3f(7, 7, 7),
            Vector3f(8, 8, 8),
        ])
        args = self.normals, self.uv_coords, self.base_color, self.metallic_roughness
        mesh0 = TexturedMesh(indices, vertices[:, [0, 5, 4, 6]], *args)
        mesh1 = TexturedMesh(indices, vertices[:, [5, 1, 6, 8]], *args)
        mesh2 = TexturedMesh(indices, vertices[:, [4, 6, 2, 7]], *args)
        mesh3 = TexturedMesh(indices, vertices[:, [6, 8, 7, 3]], *args)
        mesh = TexturedMesh.merge_quadrant_meshes(mesh0, mesh1, mesh2, mesh3)
        self.assertEqual(mesh.num_indices(), 4 * 3 * 2)
        self.assertEqual(mesh.num_vertices(), 9)
        expected_indices = ([0, 5, 4, 5, 6, 4] + [5, 1, 6, 1, 8, 6] +
                            [4, 6, 2, 6, 7, 2] + [6, 8, 7, 8, 3, 7])
        np.testing.assert_array_equal(mesh.indices(), expected_indices)
        np.testing.assert_array_equal(mesh.vertices(), vertices)

    def test_cube(self):
        """Check generation of a cube mesh."""
        rows, cols = 4, 24
        base_color = np.empty((rows, cols, 3), dtype=np.uint8)
        metallic_roughness = np.empty((rows, cols, 3), dtype=np.uint8)
        mesh = TexturedMesh.cube(base_color, metallic_roughness)

        # Check indices
        indices = mesh.indices()
        self.assertEqual(indices.shape, (6 * 6, ))
        np.testing.assert_array_equal(indices[:6], [0, 1, 2, 1, 3, 2])
        np.testing.assert_array_equal(indices[-6:], [20, 21, 22, 21, 23, 22])

        # Check 3D mesh
        vertices = mesh.vertices()
        self.assertEqual(vertices.shape, (3, 4 * 6))
        # Check BACK, where y = -1
        np.testing.assert_array_equal(
            vertices[:, :4],
            np.column_stack([
                Vector3f(+1, -1, +1),
                Vector3f(-1, -1, +1),
                Vector3f(+1, +1, +1),
                Vector3f(-1, +1, +1),
            ]),
        )
        # Check LEFT, FRONT, RIGHT, UP
        np.testing.assert_array_equal(vertices[0, 4:8], (-1, -1, -1, -1))
        np.testing.assert_array_equal(vertices[2, 8:12], (-1, -1, -1, -1))
        np.testing.assert_array_equal(vertices[0, 12:16], (1, 1, 1, 1))
        np.testing.assert_array_equal(vertices[1, 16:20], (1, 1, 1, 1))
        # Check DOWN, where Z = -1
        np.testing.assert_array_equal(
            vertices[:, -4:],
            np.column_stack([
                Vector3f(-1, -1, +1),
                Vector3f(+1, -1, +1),
                Vector3f(-1, -1, -1),
                Vector3f(+1, -1, -1),
            ]),
        )

        # check cpp_normals
        normals = mesh.normals()
        # normals for BACK, LEFT, FRONT, RIGHT, UP, DOWN
        dir = [(0, 0, -1), (1, 0, 0), (0, 0, 1), (-1, 0, 0), (0, -1, 0),
               (0, 1, 0)]
        for j in range(6):
            np.testing.assert_array_equal(normals[:, j * 4], dir[j])

        # Check texture coordinates
        uv_coords = mesh.uv_coords()
        np.testing.assert_array_almost_equal(
            uv_coords[:, :4], [[0, 1 / 6.0, 0, 1 / 6.0], [1, 1, 0, 0]])
        np.testing.assert_array_equal(np.min(uv_coords, axis=1), [0, 0])
        np.testing.assert_array_equal(np.max(uv_coords, axis=1), [1, 1])

    def test_merge6(self):
        """Test merging 6 meshes."""
        # Create 6 separate meshes
        # loop over all cube faces
        faces = []
        for _ in range(6):
            # TODO: faces.append(self.mesh) bombs, probably memory alloc issues
            faces.append(
                TexturedMesh(
                    self.indices,
                    self.vertices,
                    self.normals,
                    self.uv_coords,
                    self.base_color,
                    self.metallic_roughness,
                ))
        # merge faces:
        mesh = faces[5]
        for i in range(5):
            mesh.merge(faces[i], 0)
        self.assertEqual(mesh.num_indices(), 36)
        self.assertEqual(mesh.num_vertices(), 24)

    def test_from_mesh(self):
        """Test converting mesh to textured mesh."""
        mesh = Box3d([0, 0, 0], [1, 1, 1]).to_mesh()
        color = np.array([255, 0, 0], dtype=np.uint8)  # red
        textured_mesh = TexturedMesh.from_mesh(mesh, color)

        self.assertIsInstance(textured_mesh, TexturedMesh)
        self.assertEqual(textured_mesh.num_vertices(), mesh.num_vertices())
        self.assertEqual(textured_mesh.num_indices(), mesh.num_indices())
        self.assertEqual(textured_mesh.normals().shape, mesh.vertices().shape)
        self.assertEqual(textured_mesh.uv_coords().shape[1],
                         mesh.num_vertices())

    def test_has_same_material(self):
        """Test for has same material properties."""
        self.assertTrue(self.mesh.has_same_material(self.mesh))

    def test_replace_geometry(self):
        """Test for replacing mesh geometry."""
        mesh = Box3d([0, 0, 0], [1, 1, 1]).to_textured_mesh()
        mesh2 = Box3d([0, 0, 0], [1, 1, 1]).to_textured_mesh()
        mesh2.merge(mesh)
        mesh.replace_geometry(mesh2)
        self.assertEqual(mesh.num_vertices(), mesh2.num_vertices())
        self.assertEqual(mesh.num_indices(), mesh2.num_indices())
        self.assertEqual(mesh.normals().shape, mesh2.vertices().shape)
        self.assertEqual(mesh.uv_coords().shape[1], mesh2.num_vertices())