diff --git a/src/OpenMesh/Core/IO/importer/ImporterT.hh b/src/OpenMesh/Core/IO/importer/ImporterT.hh index 09713407..1ecef971 100644 --- a/src/OpenMesh/Core/IO/importer/ImporterT.hh +++ b/src/OpenMesh/Core/IO/importer/ImporterT.hh @@ -86,7 +86,7 @@ public: typedef std::vector VHandles; - ImporterT(Mesh& _mesh) : mesh_(_mesh) {} + ImporterT(Mesh& _mesh) : mesh_(_mesh), halfedgeNormals_() {} virtual VertexHandle add_vertex(const Vec3f& _point) @@ -131,8 +131,24 @@ public: failed_faces_.push_back(_indices); return fh; } - } + //write the half edge normals + if (mesh_.has_halfedge_normals()) + { + //iterate over all incoming haldedges of the added face + for (typename Mesh::FaceHalfedgeIter fh_iter = mesh_.fh_begin(fh); + fh_iter != mesh_.fh_end(fh); ++fh_iter) + { + //and write the normals to it + typename Mesh::HalfedgeHandle heh = fh_iter.current_halfedge_handle(); + typename Mesh::VertexHandle vh = mesh_.to_vertex_handle(heh); + typename std::map::iterator it_heNs = halfedgeNormals_.find(vh); + if (it_heNs != halfedgeNormals_.end()) + mesh_.set_normal(heh,it_heNs->second); + } + halfedgeNormals_.clear(); + } + } return fh; } @@ -142,6 +158,11 @@ public: { if (mesh_.has_vertex_normals()) mesh_.set_normal(_vh, vector_cast(_normal)); + + //saves normals for half edges. + //they will be written, when the face is added + if (mesh_.has_halfedge_normals()) + halfedgeNormals_[_vh] = _normal; } virtual void set_color(VertexHandle _vh, const Vec4uc& _color) @@ -309,6 +330,8 @@ private: Mesh& mesh_; std::vector failed_faces_; + // stores normals for halfedges of the next face + std::map halfedgeNormals_; }; diff --git a/src/OpenMesh/Core/IO/reader/OBJReader.cc b/src/OpenMesh/Core/IO/reader/OBJReader.cc index 9ef6ce56..f22d0708 100644 --- a/src/OpenMesh/Core/IO/reader/OBJReader.cc +++ b/src/OpenMesh/Core/IO/reader/OBJReader.cc @@ -424,6 +424,9 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) std::getline(stream,faceLine); std::stringstream lineData( faceLine ); + FaceHandle fh; + BaseImporter::VHandles faceVertices; + // work on the line until nothing left to read while ( !lineData.eof() ) { @@ -487,6 +490,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()) _bi.set_color(vhandles.back(), colors[value-1]); break; @@ -531,11 +535,16 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt) component = 0; nV++; + + fh = _bi.add_face(faceVertices); + + //clear vertices handles, so no face will be added twice + if (fh.is_valid()) + faceVertices.clear(); + } - size_t n_faces = _bi.n_faces(); - FaceHandle fh = _bi.add_face(vhandles); if( !vhandles.empty() && fh.is_valid() ) _bi.add_face_texcoords( fh, vhandles[0], face_texcoords ); diff --git a/src/Unittests/unittests_loading.hh b/src/Unittests/unittests_loading.hh index 79a6d126..38be4552 100644 --- a/src/Unittests/unittests_loading.hh +++ b/src/Unittests/unittests_loading.hh @@ -139,6 +139,112 @@ TEST_F(OpenMeshLoader, LoadSimpleOBJ) { EXPECT_EQ(12, 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 + */ +TEST_F(OpenMeshLoader, LoadSimpleOBJCheckHalfEdgeAndVertexNormals) { + + mesh_.clear(); + + mesh_.request_halfedge_normals(); + mesh_.request_vertex_normals(); + + std::string file_name = "cube-minimal.obj"; + + bool ok = OpenMesh::IO::read_mesh(mesh_, file_name); + + EXPECT_TRUE(ok) << file_name; + + 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(36, mesh_.n_halfedges()) << "The number of loaded halfedges is not correct!"; + + /////////////////////////////////////////////// + //check vertex normals + EXPECT_EQ(0, mesh_.normal(mesh_.vertex_handle(0))[0] ) << "Wrong vertex normal at vertex 0 component 0"; + EXPECT_EQ(-1, mesh_.normal(mesh_.vertex_handle(0))[1] ) << "Wrong vertex normal at vertex 0 component 1"; + EXPECT_EQ(0, mesh_.normal(mesh_.vertex_handle(0))[2] ) << "Wrong vertex normal at vertex 0 component 2"; + + EXPECT_EQ(0, mesh_.normal(mesh_.vertex_handle(3))[0] ) << "Wrong vertex normal at vertex 3 component 0"; + EXPECT_EQ(0, mesh_.normal(mesh_.vertex_handle(3))[1] ) << "Wrong vertex normal at vertex 3 component 1"; + EXPECT_EQ(1, mesh_.normal(mesh_.vertex_handle(3))[2] ) << "Wrong vertex normal at vertex 3 component 2"; + + EXPECT_EQ(0, mesh_.normal(mesh_.vertex_handle(4))[0] ) << "Wrong vertex normal at vertex 4 component 0"; + EXPECT_EQ(-1, mesh_.normal(mesh_.vertex_handle(4))[1] ) << "Wrong vertex normal at vertex 4 component 1"; + EXPECT_EQ(0, mesh_.normal(mesh_.vertex_handle(4))[2] ) << "Wrong vertex normal at vertex 4 component 2"; + + EXPECT_EQ(0, mesh_.normal(mesh_.vertex_handle(7))[0] ) << "Wrong vertex normal at vertex 7 component 0"; + EXPECT_EQ(0, mesh_.normal(mesh_.vertex_handle(7))[1] ) << "Wrong vertex normal at vertex 7 component 1"; + EXPECT_EQ(1, mesh_.normal(mesh_.vertex_handle(7))[2] ) << "Wrong vertex normal at vertex 7 component 2"; + + /////////////////////////////////////////////// + //check halfedge normals + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(0))[0] ) << "Wrong halfedge normal at halfedge 0 component 0"; + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(0))[1] ) << "Wrong halfedge normal at halfedge 0 component 1"; + EXPECT_EQ(-1, mesh_.normal(mesh_.halfedge_handle(0))[2] ) << "Wrong halfedge normal at halfedge 0 component 2"; + + EXPECT_EQ(-1, mesh_.normal(mesh_.halfedge_handle(10))[0] ) << "Wrong halfedge normal at halfedge 10 component 0"; + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(10))[1] ) << "Wrong halfedge normal at halfedge 10 component 1"; + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(10))[2] ) << "Wrong halfedge normal at halfedge 10 component 2"; + + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(19))[0] ) << "Wrong halfedge normal at halfedge 19 component 0"; + EXPECT_EQ(1, mesh_.normal(mesh_.halfedge_handle(19))[1] ) << "Wrong halfedge normal at halfedge 19 component 1"; + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(19))[2] ) << "Wrong halfedge normal at halfedge 19 component 2"; + + EXPECT_EQ(1, mesh_.normal(mesh_.halfedge_handle(24))[0] ) << "Wrong halfedge normal at halfedge 24 component 0"; + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(24))[1] ) << "Wrong halfedge normal at halfedge 24 component 1"; + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(24))[2] ) << "Wrong halfedge normal at halfedge 24 component 2"; + + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(30))[0] ) << "Wrong halfedge normal at halfedge 30 component 0"; + EXPECT_EQ(-1, mesh_.normal(mesh_.halfedge_handle(30))[1] ) << "Wrong halfedge normal at halfedge 30 component 1"; + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(30))[2] ) << "Wrong halfedge normal at halfedge 30 component 2"; + + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(35))[0] ) << "Wrong halfedge normal at halfedge 35 component 0"; + EXPECT_EQ(0, mesh_.normal(mesh_.halfedge_handle(35))[1] ) << "Wrong halfedge normal at halfedge 35 component 1"; + EXPECT_EQ(1, mesh_.normal(mesh_.halfedge_handle(35))[2] ) << "Wrong halfedge normal at halfedge 35 component 2"; + + mesh_.release_vertex_normals(); + mesh_.release_halfedge_normals(); + +} + +/* + * Just load a obj file of a cube and checks the halfedge texCoords + */ +TEST_F(OpenMeshLoader, LoadSimpleOBJCheckTexCoords) { + + mesh_.clear(); + + mesh_.request_halfedge_texcoords2D(); + + std::string file_name = "cube-minimal-texCoords.obj"; + + bool ok = OpenMesh::IO::read_mesh(mesh_, file_name); + + EXPECT_TRUE(ok) << file_name; + + EXPECT_EQ(1, mesh_.texcoord2D(mesh_.halfedge_handle(0))[0] ) << "Wrong texCoord at halfedge 0 component 0"; + EXPECT_EQ(1, mesh_.texcoord2D(mesh_.halfedge_handle(0))[1] ) << "Wrong texCoord at halfedge 0 component 1"; + + EXPECT_EQ(3, mesh_.texcoord2D(mesh_.halfedge_handle(10))[0] ) << "Wrong texCoord at halfedge 1 component 0"; + EXPECT_EQ(3, mesh_.texcoord2D(mesh_.halfedge_handle(10))[1] ) << "Wrong texCoord at halfedge 1 component 1"; + + EXPECT_EQ(6, mesh_.texcoord2D(mesh_.halfedge_handle(19))[0] ) << "Wrong texCoord at halfedge 4 component 0"; + EXPECT_EQ(6, mesh_.texcoord2D(mesh_.halfedge_handle(19))[1] ) << "Wrong texCoord at halfedge 4 component 1"; + + EXPECT_EQ(7, mesh_.texcoord2D(mesh_.halfedge_handle(24))[0] ) << "Wrong texCoord at halfedge 7 component 0"; + EXPECT_EQ(7, mesh_.texcoord2D(mesh_.halfedge_handle(24))[1] ) << "Wrong texCoord at halfedge 7 component 1"; + + EXPECT_EQ(9, mesh_.texcoord2D(mesh_.halfedge_handle(30))[0] ) << "Wrong texCoord at halfedge 9 component 0"; + EXPECT_EQ(9, mesh_.texcoord2D(mesh_.halfedge_handle(30))[1] ) << "Wrong texCoord at halfedge 9 component 1"; + + EXPECT_EQ(12, mesh_.texcoord2D(mesh_.halfedge_handle(35))[0] ) << "Wrong texCoord at halfedge 11 component 0"; + EXPECT_EQ(12, mesh_.texcoord2D(mesh_.halfedge_handle(35))[1] ) << "Wrong texCoord at halfedge 11 component 1"; + + mesh_.release_halfedge_texcoords2D(); +} + /* * Just load a obj file of a cube with vertex colors defined directly after the vertex definitions