diff --git a/data/simple.obj b/data/simple.obj new file mode 100644 index 0000000..5754f7c --- /dev/null +++ b/data/simple.obj @@ -0,0 +1,8 @@ +o Plane +v 0.0 0.0 0.0 1.0 0.0 0.0 +v 1.0 1.0 0.0 0.0 1.0 0.0 +v 1.0 -1.0 0.0 0.0 0.0 1.0 +vn 0.0 0.0 1.0 +vt 1.0 0.0 +s 0 +f 2/1/1 1/1/1 3/1/1 \ No newline at end of file diff --git a/src/common/obj_loader.h b/src/common/obj_loader.h index 2944162..f92254a 100644 --- a/src/common/obj_loader.h +++ b/src/common/obj_loader.h @@ -73,22 +73,6 @@ std::unordered_map load_mesh_obj(const std::strin v(i, 1) = attrib.vertices[3*i+1]; v(i, 2) = attrib.vertices[3*i+2]; - if (attrib.normals.size() > 0) { - n(i, 0) = attrib.normals[3*i+0]; - n(i, 1) = attrib.normals[3*i+1]; - n(i, 2) = attrib.normals[3*i+2]; - } - - if (attrib.texcoords.size() > 0) { - tc(i, 0) = attrib.texcoords[2*i+0]; - tc(i, 1) = attrib.texcoords[2*i+1]; - if (attrib.texcoord_ws.size() > 0) { - tc(i, 2) = attrib.texcoord_ws[i]; - } else { - tc(i, 2) = 0; - } - } - if (attrib.colors.size() > 0) { c(i, 0) = attrib.colors[3*i+0]; c(i, 1) = attrib.colors[3*i+1]; @@ -116,6 +100,9 @@ std::unordered_map load_mesh_obj(const std::strin } f.resize(total_faces, 3); mat_ids.resize(total_mat_ids, 1); + bool normals_present = attrib.normals.size() > 0; + bool texcoords_present = attrib.texcoords.size() > 0; + bool texcoord_ws_present = attrib.texcoord_ws.size() > 0; size_t f_offset = 0; for (size_t sidx = 0; sidx < shapes.size(); sidx += 1) { // Loop over shapes @@ -131,6 +118,20 @@ std::unordered_map load_mesh_obj(const std::strin for (size_t vidx = 0; vidx < num_vertices_in_face; vidx += 1) { tinyobj::index_t idx = shapes[sidx].mesh.indices[index_offset + vidx]; f(f_offset, vidx) = size_t(idx.vertex_index); + if (normals_present) { + n(idx.vertex_index, 0) = attrib.normals[3*idx.normal_index+0]; + n(idx.vertex_index, 1) = attrib.normals[3*idx.normal_index+1]; + n(idx.vertex_index, 2) = attrib.normals[3*idx.normal_index+2]; + } + if (texcoords_present) { + tc(idx.vertex_index, 0) = attrib.texcoords[2*idx.texcoord_index+0]; + tc(idx.vertex_index, 1) = attrib.texcoords[2*idx.texcoord_index+1]; + if (texcoord_ws_present) { + tc(idx.vertex_index, 2) = attrib.texcoord_ws[idx.texcoord_index]; + } else { + tc(idx.vertex_index, 2) = 0; + } + } } if (shapes[sidx].mesh.material_ids.size() > 0) { @@ -358,5 +359,4 @@ void save_mesh_obj(std::string filename, outstream << std::endl; } } - -} \ No newline at end of file +} diff --git a/tests/test_examples.py b/tests/test_examples.py index d73ba5c..b0e24b8 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -762,5 +762,31 @@ def test_orient_mesh_faces(self): self.assertTrue(np.all(f_oriented == f)) self.assertTrue(np.all(f_comp_ids == 0)) + def test_obj_loading(self): + import point_cloud_utils as pcu + import numpy as np + + mesh_path = os.path.join(self.test_path, "simple.obj") + mesh = pcu.load_triangle_mesh(mesh_path) + vn_true = np.array([ + [0,0,1], + [0,0,1], + [0,0,1]], dtype=np.float32) + uv_true = np.array([ + [1,0,0], + [1,0,0], + [1,0,0]], dtype=np.float32) + colors_true = np.array([ + [1,0,0,1], + [0,1,0,1], + [0,0,1,1]], dtype=np.float32) + + self.assertEqual(mesh.v.shape, (3, 3)) + self.assertEqual(mesh.f.shape, (3,)) + self.assertEqual(mesh.vn.shape, (3, 3)) + self.assertTrue(np.allclose(mesh.vn, vn_true)) + self.assertTrue(np.allclose(mesh.vertex_data.texcoords, uv_true)) + self.assertTrue(np.allclose(mesh.vc, colors_true)) + if __name__ == '__main__': unittest.main()