From d361e5dbdc9ec7ebe8875bd0160cf85e9665d128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20M=C3=B6bius?= Date: Thu, 1 Dec 2011 16:16:29 +0000 Subject: [PATCH] OBJ Reader support for vertex colors after vertices or Vertex colors as separate lines. (Thanks to Bruno Dutailly) Added unittests for vertex colors git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@475 fdac6126-5c0c-442c-9429-916003d36597 --- src/OpenMesh/Core/IO/reader/OBJReader.cc | 39 +++++-- ...-vertex-colors-after-vertex-definition.obj | 27 +++++ ...cube-minimal-vertex-colors-as-vc-lines.obj | 35 ++++++ src/Unittests/TestFiles/cube-minimal.obj | 27 +++++ src/Unittests/unittests_loading.hh | 102 ++++++++++++++++++ 5 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 src/Unittests/TestFiles/cube-minimal-vertex-colors-after-vertex-definition.obj create mode 100644 src/Unittests/TestFiles/cube-minimal-vertex-colors-as-vc-lines.obj create mode 100644 src/Unittests/TestFiles/cube-minimal.obj diff --git a/src/OpenMesh/Core/IO/reader/OBJReader.cc b/src/OpenMesh/Core/IO/reader/OBJReader.cc index 0cd0c40d..432c2887 100644 --- a/src/OpenMesh/Core/IO/reader/OBJReader.cc +++ b/src/OpenMesh/Core/IO/reader/OBJReader.cc @@ -271,12 +271,14 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) std::string line; std::string keyWrd; - float x, y, z, u, v; - - BaseImporter::VHandles vhandles; - std::vector normals; - std::vector texcoords; - std::vector face_texcoords; + float x, y, z, u, v; + int r, g, b; + BaseImporter::VHandles vhandles; + std::vector normals; + std::vector colors; + std::vector texcoords; + std::vector face_texcoords; + std::vector vertexHandles; std::string matname; @@ -355,7 +357,16 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) stream >> x; stream >> y; stream >> z; if ( !stream.fail() ) - _bi.add_vertex(OpenMesh::Vec3f(x,y,z)); + { + vertexHandles.push_back(_bi.add_vertex(OpenMesh::Vec3f(x,y,z))); + stream >> r; stream >> g; stream >> b; + + if ( !stream.fail() ) + { + _opt += Options::VertexColor; + colors.push_back(OpenMesh::Vec3uc((unsigned char)r,(unsigned char)g,(unsigned char)b)); + } + } } // texture coord @@ -376,6 +387,16 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) } } + // color per vertex + else if (keyWrd == "vc") + { + stream >> r; stream >> g; stream >> b; + + if ( !stream.fail() ){ + colors.push_back(OpenMesh::Vec3uc((unsigned char)r,(unsigned char)g,(unsigned char)b)); + _opt += Options::VertexColor; + } + } // normal else if (keyWrd == "vn") @@ -466,8 +487,10 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) } // Obj counts from 1 and not zero .. array counts from zero therefore -1 vhandles.push_back(VertexHandle(value-1)); + if (_opt.vertex_has_color()) + _bi.set_color(vhandles.back(), colors[value-1]); break; - + case 1: // texture coord if ( value < 0 ) { // Calculation of index : diff --git a/src/Unittests/TestFiles/cube-minimal-vertex-colors-after-vertex-definition.obj b/src/Unittests/TestFiles/cube-minimal-vertex-colors-after-vertex-definition.obj new file mode 100644 index 00000000..e6060a14 --- /dev/null +++ b/src/Unittests/TestFiles/cube-minimal-vertex-colors-after-vertex-definition.obj @@ -0,0 +1,27 @@ +g cube +v 0.0 0.0 0.0 0 0 0 +v 0.0 0.0 1.0 0 0 255 +v 0.0 1.0 0.0 0 255 0 +v 0.0 1.0 1.0 0 255 255 +v 1.0 0.0 0.0 255 0 0 +v 1.0 0.0 1.0 255 0 255 +v 1.0 1.0 0.0 255 255 0 +v 1.0 1.0 1.0 255 255 255 +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 +f 1//2 7//2 5//2 +f 1//2 3//2 7//2 +f 1//6 4//6 3//6 +f 1//6 2//6 4//6 +f 3//3 8//3 7//3 +f 3//3 4//3 8//3 +f 5//5 7//5 8//5 +f 5//5 8//5 6//5 +f 1//4 5//4 6//4 +f 1//4 6//4 2//4 +f 2//1 6//1 8//1 +f 2//1 8//1 4//1 diff --git a/src/Unittests/TestFiles/cube-minimal-vertex-colors-as-vc-lines.obj b/src/Unittests/TestFiles/cube-minimal-vertex-colors-as-vc-lines.obj new file mode 100644 index 00000000..132bda88 --- /dev/null +++ b/src/Unittests/TestFiles/cube-minimal-vertex-colors-as-vc-lines.obj @@ -0,0 +1,35 @@ +g cube +v 0.0 0.0 0.0 +v 0.0 0.0 1.0 +v 0.0 1.0 0.0 +v 0.0 1.0 1.0 +v 1.0 0.0 0.0 +v 1.0 0.0 1.0 +v 1.0 1.0 0.0 +v 1.0 1.0 1.0 +vc 0 0 0 +vc 0 0 255 +vc 0 255 0 +vc 0 255 255 +vc 255 0 0 +vc 255 0 255 +vc 255 255 0 +vc 255 255 255 +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 +f 1//2 7//2 5//2 +f 1//2 3//2 7//2 +f 1//6 4//6 3//6 +f 1//6 2//6 4//6 +f 3//3 8//3 7//3 +f 3//3 4//3 8//3 +f 5//5 7//5 8//5 +f 5//5 8//5 6//5 +f 1//4 5//4 6//4 +f 1//4 6//4 2//4 +f 2//1 6//1 8//1 +f 2//1 8//1 4//1 diff --git a/src/Unittests/TestFiles/cube-minimal.obj b/src/Unittests/TestFiles/cube-minimal.obj new file mode 100644 index 00000000..a875725d --- /dev/null +++ b/src/Unittests/TestFiles/cube-minimal.obj @@ -0,0 +1,27 @@ +g cube +v 0.0 0.0 0.0 +v 0.0 0.0 1.0 +v 0.0 1.0 0.0 +v 0.0 1.0 1.0 +v 1.0 0.0 0.0 +v 1.0 0.0 1.0 +v 1.0 1.0 0.0 +v 1.0 1.0 1.0 +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 +f 1//2 7//2 5//2 +f 1//2 3//2 7//2 +f 1//6 4//6 3//6 +f 1//6 2//6 4//6 +f 3//3 8//3 7//3 +f 3//3 4//3 8//3 +f 5//5 7//5 8//5 +f 5//5 8//5 6//5 +f 1//4 5//4 6//4 +f 1//4 6//4 2//4 +f 2//1 6//1 8//1 +f 2//1 8//1 4//1 diff --git a/src/Unittests/unittests_loading.hh b/src/Unittests/unittests_loading.hh index a2ef1d34..d5b0cb4c 100644 --- a/src/Unittests/unittests_loading.hh +++ b/src/Unittests/unittests_loading.hh @@ -37,6 +37,8 @@ class OpenMeshLoader : public OpenMeshBase { */ TEST_F(OpenMeshLoader, LoadSimpleOFFFile) { + mesh_.clear(); + bool ok = OpenMesh::IO::read_mesh(mesh_, "cube1.off"); EXPECT_TRUE(ok); @@ -53,6 +55,8 @@ TEST_F(OpenMeshLoader, LoadSimpleOFFFile) { */ TEST_F(OpenMeshLoader, LoadSimplePointPLYFileWithBadEncoding) { + mesh_.clear(); + bool ok = OpenMesh::IO::read_mesh(mesh_, "pointCloudBadEncoding.ply"); EXPECT_TRUE(ok) << "Unable to load pointCloudBadEncoding.ply"; @@ -68,6 +72,8 @@ TEST_F(OpenMeshLoader, LoadSimplePointPLYFileWithBadEncoding) { */ TEST_F(OpenMeshLoader, LoadSimplePointPLYFileWithGoodEncoding) { + mesh_.clear(); + bool ok = OpenMesh::IO::read_mesh(mesh_, "pointCloudGoodEncoding.ply"); EXPECT_TRUE(ok) << "Unable to load pointCloudGoodEncoding.ply"; @@ -77,4 +83,100 @@ TEST_F(OpenMeshLoader, LoadSimplePointPLYFileWithGoodEncoding) { EXPECT_EQ(0, mesh_.n_faces()) << "The number of loaded faces is not correct!"; } + +/* + * Just load a obj file of a cube + */ +TEST_F(OpenMeshLoader, LoadSimpleOBJ) { + + mesh_.clear(); + + bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal.obj"); + + EXPECT_TRUE(ok) << "Unable to load cube-minimal.obj"; + + EXPECT_EQ(8, mesh_.n_vertices()) << "The number of loaded vertices is not correct!"; + EXPECT_EQ(18, mesh_.n_edges()) << "The number of loaded edges is not correct!"; + EXPECT_EQ(12, mesh_.n_faces()) << "The number of loaded faces is not correct!"; +} + + +/* + * Just load a obj file of a cube with vertex colors defined directly after the vertex definitions + */ +TEST_F(OpenMeshLoader, LoadSimpleOBJWithVertexColorsAfterVertices) { + + mesh_.clear(); + + mesh_.request_vertex_colors(); + + bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-vertex-colors-after-vertex-definition.obj"); + + EXPECT_TRUE(ok) << "Unable to load cube-minimal-vertex-colors-after-vertex-definition.obj"; + + EXPECT_EQ(8, mesh_.n_vertices()) << "The number of loaded vertices is not correct!"; + EXPECT_EQ(18, mesh_.n_edges()) << "The number of loaded edges is not correct!"; + EXPECT_EQ(12, mesh_.n_faces()) << "The number of loaded faces is not correct!"; + + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0"; + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1"; + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2"; + + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0"; + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1"; + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2"; + + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0"; + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1"; + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2"; + + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0"; + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1"; + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2"; + + mesh_.release_vertex_colors(); +} + +/* + * Just load a obj file of a cube with vertex colors defined as separate lines + */ +TEST_F(OpenMeshLoader, LoadSimpleOBJWithVertexColorsAsVCLines) { + + mesh_.clear(); + + mesh_.request_vertex_colors(); + + bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-vertex-colors-as-vc-lines.obj"); + + EXPECT_TRUE(ok) << "Unable to load cube-minimal-vertex-colors-as-vc-lines.obj"; + + EXPECT_EQ(8, mesh_.n_vertices()) << "The number of loaded vertices is not correct!"; + EXPECT_EQ(18, mesh_.n_edges()) << "The number of loaded edges is not correct!"; + EXPECT_EQ(12, mesh_.n_faces()) << "The number of loaded faces is not correct!"; + + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0"; + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1"; + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2"; + + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0"; + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1"; + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2"; + + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0"; + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1"; + EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2"; + + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0"; + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1"; + EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2"; + + mesh_.release_vertex_colors(); + +} + + + + + + #endif // INCLUDE GUARD