From 53371f63e1b9f49a7b697c098f8b6ac98618a2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20M=C3=B6ller?= Date: Mon, 9 Mar 2015 09:56:41 +0000 Subject: [PATCH] - fix crash, if obj file contains degenerated faces - added unittest for this case closes #2382 git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@1236 fdac6126-5c0c-442c-9429-916003d36597 --- src/OpenMesh/Core/IO/reader/OBJReader.cc | 32 ++++++++++++++++++- .../TestFiles/cube-minimal-degenerated.obj | 29 +++++++++++++++++ src/Unittests/unittests_read_write_OBJ.cc | 16 ++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/Unittests/TestFiles/cube-minimal-degenerated.obj diff --git a/src/OpenMesh/Core/IO/reader/OBJReader.cc b/src/OpenMesh/Core/IO/reader/OBJReader.cc index d3a55d98..7f8f0f9d 100644 --- a/src/OpenMesh/Core/IO/reader/OBJReader.cc +++ b/src/OpenMesh/Core/IO/reader/OBJReader.cc @@ -64,6 +64,10 @@ using std::isspace; #include #endif +#include +#include +#include + //=== NAMESPACES ============================================================== @@ -94,6 +98,28 @@ void trimString( std::string& _string) { _string = _string.substr( start, end-start+1 ); } +//----------------------------------------------------------------------------- +template +class HasSeen : public std::unary_function +{ +public: + HasSeen () : seen_ () { } + + bool operator ()(const Handle& i) const + { + return (!seen_.insert(i.idx()).second); + } + +private: + mutable std::set seen_; +}; + +// remove duplicated indices from one face +void remove_duplicated_vertices(BaseImporter::VHandles& _indices) +{ + _indices.erase(std::remove_if(_indices.begin(),_indices.end(),HasSeen()),_indices.end()); +} + //----------------------------------------------------------------------------- _OBJReader_:: @@ -575,7 +601,11 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) // note that add_face can possibly triangulate the faces, which is why we have to // store the current number of faces first size_t n_faces = _bi.n_faces(); - fh = _bi.add_face(faceVertices); + remove_duplicated_vertices(faceVertices); + + //A minimum of three vertices are required. + if (faceVertices.size() > 2) + fh = _bi.add_face(faceVertices); if (!vhandles.empty() && fh.is_valid() ) _bi.add_face_texcoords(fh, vhandles[0], face_texcoords); diff --git a/src/Unittests/TestFiles/cube-minimal-degenerated.obj b/src/Unittests/TestFiles/cube-minimal-degenerated.obj new file mode 100644 index 00000000..00222801 --- /dev/null +++ b/src/Unittests/TestFiles/cube-minimal-degenerated.obj @@ -0,0 +1,29 @@ +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 8//1 2//1 +f 2//1 8//1 4//1 +f 2//1 2//1 2//1 +f 2//1 8//1 2//1 diff --git a/src/Unittests/unittests_read_write_OBJ.cc b/src/Unittests/unittests_read_write_OBJ.cc index ec6cbe3c..938f259d 100644 --- a/src/Unittests/unittests_read_write_OBJ.cc +++ b/src/Unittests/unittests_read_write_OBJ.cc @@ -47,6 +47,22 @@ TEST_F(OpenMeshReadWriteOBJ, LoadSimpleOBJ) { EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!"; } +/* + * Just load a obj file of a cube with degenerated faces + */ +TEST_F(OpenMeshReadWriteOBJ, LoadDegeneratedOBJ) { + + mesh_.clear(); + + bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal.obj"); + + EXPECT_TRUE(ok) << "Unable to load cube-minimal.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!"; +} + /* * Just load a obj file of a cube and checks the halfedge and vertex normals */