diff --git a/src/OpenMesh/Core/IO/Options.hh b/src/OpenMesh/Core/IO/Options.hh index 665884cb..cda46566 100644 --- a/src/OpenMesh/Core/IO/Options.hh +++ b/src/OpenMesh/Core/IO/Options.hh @@ -105,7 +105,8 @@ public: EdgeColor = 0x0080, ///< Has (r) / store (w) edge colors FaceNormal = 0x0100, ///< Has (r) / store (w) face normals FaceColor = 0x0200, ///< Has (r) / store (w) face colors - ColorAlpha = 0x0400 ///< Has (r) / store (w) alpha values for colors + FaceTexCoord = 0x0400, ///< Has (r) / store (w) face texture coordinates + ColorAlpha = 0x0800 ///< Has (r) / store (w) alpha values for colors }; public: @@ -199,6 +200,7 @@ public: bool edge_has_color() const { return check(EdgeColor); } bool face_has_normal() const { return check(FaceNormal); } bool face_has_color() const { return check(FaceColor); } + bool face_has_texcoord() const { return check(FaceTexCoord); } bool color_has_alpha() const { return check(ColorAlpha); } diff --git a/src/OpenMesh/Core/IO/reader/OBJReader.cc b/src/OpenMesh/Core/IO/reader/OBJReader.cc index 0df7a157..24f01f13 100644 --- a/src/OpenMesh/Core/IO/reader/OBJReader.cc +++ b/src/OpenMesh/Core/IO/reader/OBJReader.cc @@ -283,6 +283,13 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) std::string matname; + // Options supplied by the user + Options userOptions = _opt; + + // Options collected via file parsing + Options fileOptions; + + while( _in && !_in.eof() ) { std::getline(_in,line); @@ -363,8 +370,10 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) if ( !stream.fail() ) { - _opt += Options::VertexColor; - colors.push_back(OpenMesh::Vec3uc((unsigned char)r,(unsigned char)g,(unsigned char)b)); + if ( userOptions.vertex_has_color() ) { + fileOptions += Options::VertexColor; + colors.push_back(OpenMesh::Vec3uc((unsigned char)r,(unsigned char)g,(unsigned char)b)); + } } } } @@ -374,10 +383,15 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) { stream >> u; stream >> v; - if ( !stream.fail() ){ + if ( !stream.fail() ){ - texcoords.push_back(OpenMesh::Vec2f(u, v)); - _opt += Options::VertexTexCoord; + if ( userOptions.vertex_has_texcoord() || userOptions.face_has_texcoord() ) { + texcoords.push_back(OpenMesh::Vec2f(u, v)); + + // Can be used for both! + fileOptions += Options::VertexTexCoord; + fileOptions += Options::FaceTexCoord; + } }else{ @@ -392,9 +406,11 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) { 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; + if ( !stream.fail() ){ + if ( userOptions.vertex_has_color() ) { + colors.push_back(OpenMesh::Vec3uc((unsigned char)r,(unsigned char)g,(unsigned char)b)); + fileOptions += Options::VertexColor; + } } } @@ -403,9 +419,11 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) { stream >> x; stream >> y; stream >> z; - if ( !stream.fail() ){ - normals.push_back(OpenMesh::Vec3f(x,y,z)); - _opt += Options::VertexNormal; + if ( !stream.fail() ) { + if (userOptions.vertex_has_normal() ){ + normals.push_back(OpenMesh::Vec3f(x,y,z)); + fileOptions += Options::VertexNormal; + } } } @@ -491,7 +509,7 @@ 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)); faceVertices.push_back(VertexHandle(value-1)); - if (_opt.vertex_has_color()) + if (fileOptions.vertex_has_color() ) _bi.set_color(vhandles.back(), colors[value-1]); break; @@ -503,13 +521,28 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) value = texcoords.size() + value + 1; } assert(!vhandles.empty()); - if ( ! texcoords.empty() && (unsigned int)(value-1) < texcoords.size() ) { - // Obj counts from 1 and not zero .. array counts from zero therefore -1 - _bi.set_texcoord(vhandles.back(), texcoords[value-1]); - face_texcoords.push_back( texcoords[value-1] ); - } else { - omerr() << "Error setting Texture coordinates" << std::endl; - } + + + if ( fileOptions.vertex_has_texcoord() && userOptions.vertex_has_texcoord() ) { + + if (!texcoords.empty() && (unsigned int) (value - 1) < texcoords.size()) { + // Obj counts from 1 and not zero .. array counts from zero therefore -1 + _bi.set_texcoord(vhandles.back(), texcoords[value - 1]); + } else { + omerr() << "Error setting Texture coordinates" << std::endl; + } + + } + + if (fileOptions.face_has_texcoord() && userOptions.face_has_texcoord() ) { + + if (!texcoords.empty() && (unsigned int) (value - 1) < texcoords.size()) { + face_texcoords.push_back( texcoords[value-1] ); + } else { + omerr() << "Error setting Texture coordinates" << std::endl; + } + } + break; @@ -520,10 +553,13 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) // As obj counts from 1 and not zero add +1 value = normals.size() + value + 1; } - assert(!vhandles.empty()); - assert((unsigned int)(value-1) < normals.size()); + // Obj counts from 1 and not zero .. array counts from zero therefore -1 - _bi.set_normal(vhandles.back(), normals[value-1]); + if (fileOptions.vertex_has_normal() ) { + assert(!vhandles.empty()); + assert((unsigned int)(value-1) < normals.size()); + _bi.set_normal(vhandles.back(), normals[value-1]); + } break; } @@ -546,8 +582,8 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) size_t n_faces = _bi.n_faces(); - if( !vhandles.empty() && fh.is_valid() ) - _bi.add_face_texcoords( fh, vhandles[0], face_texcoords ); + if (!vhandles.empty() && fh.is_valid() ) + _bi.add_face_texcoords(fh, vhandles[0], face_texcoords); if ( !matname.empty() ) { @@ -561,25 +597,36 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) if ( mat.has_Kd() ) { Vec3uc fc = color_cast(mat.Kd()); - for (std::vector::iterator it = newfaces.begin(); - it != newfaces.end(); ++it) - _bi.set_color( *it, fc ); + if ( userOptions.face_has_color()) { - _opt += Options::FaceColor; + for (std::vector::iterator it = newfaces.begin(); it != newfaces.end(); ++it) + _bi.set_color(*it, fc); + + fileOptions += Options::FaceColor; + } } // Set the texture index in the face index property if ( mat.has_map_Kd() ) { - for (std::vector::iterator it = newfaces.begin(); - it != newfaces.end(); ++it) - _bi.set_face_texindex( *it, mat.map_Kd_index() ); + if (userOptions.face_has_texcoord()) { + + for (std::vector::iterator it = newfaces.begin(); it != newfaces.end(); ++it) + _bi.set_face_texindex(*it, mat.map_Kd_index()); + + fileOptions += Options::FaceTexCoord; + + } } else { + // If we don't have the info, set it to no texture - for (std::vector::iterator it = newfaces.begin(); - it != newfaces.end(); ++it) - _bi.set_face_texindex( *it, 0 ); + if (userOptions.face_has_texcoord()) { + + for (std::vector::iterator it = newfaces.begin(); it != newfaces.end(); ++it) + _bi.set_face_texindex(*it, 0); + + } } } else { @@ -589,9 +636,9 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) newfaces.push_back(FaceHandle(n_faces+i)); // Set the texture index to zero as we don't have any information - for (std::vector::iterator it = newfaces.begin(); - it != newfaces.end(); ++it) - _bi.set_face_texindex( *it, 0 ); + if ( userOptions.face_has_texcoord() ) + for (std::vector::iterator it = newfaces.begin(); it != newfaces.end(); ++it) + _bi.set_face_texindex(*it, 0); } } @@ -600,23 +647,24 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) // If we do not have any faces, // assume this is a point cloud and read the normals and colors directly - if (_bi.n_faces()==0) + if (_bi.n_faces() == 0) { - int i=0; + int i = 0; // add normal per vertex - if ( normals.size() == _bi.n_vertices() ) - for (std::vector::iterator it = vertexHandles.begin(); - it != vertexHandles.end(); ++it, i++) { - _bi.set_normal( *it, normals[i] ); - } + if (normals.size() == _bi.n_vertices()) { + if ( fileOptions.vertex_has_normal() && userOptions.vertex_has_normal() ) { + for (std::vector::iterator it = vertexHandles.begin(); it != vertexHandles.end(); ++it, i++) + _bi.set_normal(*it, normals[i]); + } + } // add color per vertex - i=0; - if ( colors.size() >= _bi.n_vertices() ) - for (std::vector::iterator it = vertexHandles.begin(); - it != vertexHandles.end(); ++it, i++) { - _bi.set_color( *it, colors[i] ); + i = 0; + if (colors.size() >= _bi.n_vertices()) + if (fileOptions.vertex_has_color() && userOptions.vertex_has_color()) { + for (std::vector::iterator it = vertexHandles.begin(); it != vertexHandles.end(); ++it, i++) + _bi.set_color(*it, colors[i]); } } diff --git a/src/Unittests/unittests_loading.hh b/src/Unittests/unittests_loading.hh index 967deadd..70c80bc1 100644 --- a/src/Unittests/unittests_loading.hh +++ b/src/Unittests/unittests_loading.hh @@ -149,9 +149,12 @@ TEST_F(OpenMeshLoader, LoadSimpleOBJCheckHalfEdgeAndVertexNormals) { mesh_.request_halfedge_normals(); mesh_.request_vertex_normals(); + OpenMesh::IO::Options options; + options += OpenMesh::IO::Options::VertexNormal; + std::string file_name = "cube-minimal.obj"; - bool ok = OpenMesh::IO::read_mesh(mesh_, file_name); + bool ok = OpenMesh::IO::read_mesh(mesh_, file_name,options); EXPECT_TRUE(ok) << file_name; @@ -209,6 +212,32 @@ TEST_F(OpenMeshLoader, LoadSimpleOBJCheckHalfEdgeAndVertexNormals) { } +/* + * Just load a obj file and set vertex color option before loading + */ +TEST_F(OpenMeshLoader, LoadSimpleOBJForceVertexColorsAlthoughNotAvailable) { + + mesh_.clear(); + + mesh_.request_vertex_colors(); + + std::string file_name = "cube-minimal.obj"; + + OpenMesh::IO::Options options; + options += OpenMesh::IO::Options::VertexColor; + + bool ok = OpenMesh::IO::read_mesh(mesh_, file_name,options); + + EXPECT_TRUE(ok) << file_name; + + EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!"; + EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!"; + EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!"; + EXPECT_EQ(36u , mesh_.n_halfedges()) << "The number of loaded halfedges is not correct!"; + +} + + /* * Just load a obj file of a cube and checks the halfedge texCoords */ @@ -218,9 +247,12 @@ TEST_F(OpenMeshLoader, LoadSimpleOBJCheckTexCoords) { mesh_.request_halfedge_texcoords2D(); + OpenMesh::IO::Options options; + options += OpenMesh::IO::Options::FaceTexCoord; + std::string file_name = "cube-minimal-texCoords.obj"; - bool ok = OpenMesh::IO::read_mesh(mesh_, file_name); + bool ok = OpenMesh::IO::read_mesh(mesh_, file_name,options); EXPECT_TRUE(ok) << file_name; @@ -255,13 +287,16 @@ TEST_F(OpenMeshLoader, LoadSimpleOBJWithVertexColorsAfterVertices) { mesh_.request_vertex_colors(); - bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-vertex-colors-after-vertex-definition.obj"); + OpenMesh::IO::Options options; + options += OpenMesh::IO::Options::VertexColor; + + bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-vertex-colors-after-vertex-definition.obj",options); EXPECT_TRUE(ok) << "Unable to load cube-minimal-vertex-colors-after-vertex-definition.obj"; EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!"; - EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!"; - EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!"; + EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!"; + EXPECT_EQ(12u , 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"; @@ -291,7 +326,10 @@ TEST_F(OpenMeshLoader, LoadSimpleOBJWithVertexColorsAsVCLines) { mesh_.request_vertex_colors(); - bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-vertex-colors-as-vc-lines.obj"); + OpenMesh::IO::Options options; + options += OpenMesh::IO::Options::VertexColor; + + bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-vertex-colors-as-vc-lines.obj",options); EXPECT_TRUE(ok) << "Unable to load cube-minimal-vertex-colors-as-vc-lines.obj";