From 222e55b9e933fda6c35c224ca9b89b6ebff58f00 Mon Sep 17 00:00:00 2001 From: David Bommes Date: Thu, 19 Jan 2012 19:12:39 +0000 Subject: [PATCH] added support for halfedge normals (normals per face/vertex to allow for smooth shading with feature edges) git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@512 fdac6126-5c0c-442c-9429-916003d36597 --- src/OpenMesh/Core/Mesh/AttribKernelT.hh | 34 ++++++++ src/OpenMesh/Core/Mesh/PolyMeshT.cc | 101 +++++++++++++++++++++++- src/OpenMesh/Core/Mesh/PolyMeshT.hh | 18 +++++ 3 files changed, 151 insertions(+), 2 deletions(-) diff --git a/src/OpenMesh/Core/Mesh/AttribKernelT.hh b/src/OpenMesh/Core/Mesh/AttribKernelT.hh index ad24209a..548e9327 100644 --- a/src/OpenMesh/Core/Mesh/AttribKernelT.hh +++ b/src/OpenMesh/Core/Mesh/AttribKernelT.hh @@ -119,6 +119,7 @@ public: refcount_htexcoords1D_(0), refcount_htexcoords2D_(0), refcount_htexcoords3D_(0), + refcount_henormals_(0), refcount_hecolors_(0), refcount_ecolors_(0), refcount_fnormals_(0), @@ -160,6 +161,9 @@ public: if (HAttribs & Attributes::Status) Connectivity::request_halfedge_status(); + if (HAttribs & Attributes::Normal) + request_halfedge_normals(); + if (EAttribs & Attributes::Status) Connectivity::request_edge_status(); @@ -399,6 +403,15 @@ public: { property(edge_colors_, _eh) = _c; } + //------------------------------------------------------------- halfedge normals + + const Normal& normal(HalfedgeHandle _heh) const + { return property(halfedge_normals_, _heh); } + + void set_normal(HalfedgeHandle _heh, const Normal& _n) + { property(halfedge_normals_, _heh) = _n; } + + //------------------------------------------------------------- halfedge colors const Color* halfedge_colors() const @@ -490,6 +503,12 @@ public: add_property( edge_colors_, "e:colors" ); } + void request_halfedge_normals() + { + if (!refcount_henormals_++) + add_property( halfedge_normals_, "h:normals" ); + } + void request_halfedge_colors() { if (!refcount_hecolors_++) @@ -564,6 +583,12 @@ public: remove_property(edge_colors_); } + void release_halfedge_normals() + { + if ((refcount_henormals_ > 0) && (! --refcount_henormals_)) + remove_property(halfedge_normals_); + } + void release_halfedge_colors() { if ((refcount_hecolors_ > 0) && (! --refcount_hecolors_)) @@ -599,6 +624,7 @@ public: bool has_halfedge_texcoords2D() const { return halfedge_texcoords2D_.is_valid();} bool has_halfedge_texcoords3D() const { return halfedge_texcoords3D_.is_valid();} bool has_edge_colors() const { return edge_colors_.is_valid(); } + bool has_halfedge_normals() const { return halfedge_normals_.is_valid(); } bool has_halfedge_colors() const { return halfedge_colors_.is_valid(); } bool has_face_normals() const { return face_normals_.is_valid(); } bool has_face_colors() const { return face_colors_.is_valid(); } @@ -616,6 +642,7 @@ public: typedef HPropHandleT HalfedgeTexCoords2DPropertyHandle; typedef HPropHandleT HalfedgeTexCoords3DPropertyHandle; typedef EPropHandleT EdgeColorsPropertyHandle; + typedef HPropHandleT HalfedgeNormalsPropertyHandle; typedef HPropHandleT HalfedgeColorsPropertyHandle; typedef FPropHandleT FaceNormalsPropertyHandle; typedef FPropHandleT FaceColorsPropertyHandle; @@ -651,6 +678,11 @@ public: HalfedgeTexCoords3DPropertyHandle halfedge_texcoords3D_pph() const { return halfedge_texcoords3D_; } + // standard edge properties + HalfedgeNormalsPropertyHandle halfedge_normals_pph() const + { return halfedge_normals_; } + + // standard edge properties HalfedgeColorsPropertyHandle halfedge_colors_pph() const { return halfedge_colors_; } @@ -705,6 +737,7 @@ private: HalfedgeTexCoords1DPropertyHandle halfedge_texcoords1D_; HalfedgeTexCoords2DPropertyHandle halfedge_texcoords2D_; HalfedgeTexCoords3DPropertyHandle halfedge_texcoords3D_; + HalfedgeNormalsPropertyHandle halfedge_normals_; HalfedgeColorsPropertyHandle halfedge_colors_; // standard edge properties EdgeColorsPropertyHandle edge_colors_; @@ -726,6 +759,7 @@ private: unsigned int refcount_htexcoords1D_; unsigned int refcount_htexcoords2D_; unsigned int refcount_htexcoords3D_; + unsigned int refcount_henormals_; unsigned int refcount_hecolors_; unsigned int refcount_ecolors_; unsigned int refcount_fnormals_; diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.cc b/src/OpenMesh/Core/Mesh/PolyMeshT.cc index 0e5bd3fb..46d7389a 100644 --- a/src/OpenMesh/Core/Mesh/PolyMeshT.cc +++ b/src/OpenMesh/Core/Mesh/PolyMeshT.cc @@ -184,8 +184,9 @@ void PolyMeshT:: update_normals() { - if (Kernel::has_face_normals()) update_face_normals(); - if (Kernel::has_vertex_normals()) update_vertex_normals(); + if (Kernel::has_face_normals()) update_face_normals(); + if (Kernel::has_vertex_normals()) update_vertex_normals(); + if (Kernel::has_halfedge_normals()) update_halfedge_normals(); } @@ -207,6 +208,102 @@ update_face_normals() //----------------------------------------------------------------------------- +template +void +PolyMeshT:: +update_halfedge_normals(const double _feature_angle) +{ + HalfedgeIter h_it(Kernel::halfedges_begin()), h_end(Kernel::halfedges_end()); + + for (; h_it != h_end; ++h_it) + set_normal(h_it.handle(), calc_halfedge_normal(h_it.handle(), _feature_angle)); +} + + +//----------------------------------------------------------------------------- + + +template +typename PolyMeshT::Normal +PolyMeshT:: +calc_halfedge_normal(HalfedgeHandle _heh, const double _feature_angle) const +{ + if(Kernel::is_boundary(_heh)) + return Normal(0,0,0); + else + { + std::vector fhs; fhs.reserve(10); + + HalfedgeHandle heh = _heh; + + // collect CW face-handles + do + { + fhs.push_back(Kernel::face_handle(heh)); + + heh = Kernel::next_halfedge_handle(heh); + heh = Kernel::opposite_halfedge_handle(heh); + } + while(heh != _heh && !Kernel::is_boundary(heh) && !is_estimated_feature_edge(heh, _feature_angle)); + + // collect CCW face-handles + if(heh != _heh && !is_estimated_feature_edge(_heh, _feature_angle)) + { + heh = Kernel::opposite_halfedge_handle(_heh); + + do + { + fhs.push_back(Kernel::face_handle(heh)); + + heh = Kernel::prev_halfedge_handle(heh); + heh = Kernel::opposite_halfedge_handle(heh); + } + while(!Kernel::is_boundary(heh) && !is_estimated_feature_edge(heh, _feature_angle)); + } + + Normal n(0,0,0); + for(unsigned int i=0; i +bool +PolyMeshT:: +is_estimated_feature_edge(HalfedgeHandle _heh, const double _feature_angle) const +{ + EdgeHandle eh = Kernel::edge_handle(_heh); + + if(Kernel::has_edge_status()) + { + if(Kernel::status(eh).feature()) + return true; + } + + if(Kernel::is_boundary(eh)) + return false; + + // compute angle between faces + FaceHandle fh0 = Kernel::face_handle(_heh); + FaceHandle fh1 = Kernel::face_handle(Kernel::opposite_halfedge_handle(_heh)); + + Normal fn0 = Kernel::normal(fh0); + Normal fn1 = Kernel::normal(fh1); + + // dihedral angle above angle threshold + return ( (fn0|fn1) < cos(_feature_angle) ); +} + + +//----------------------------------------------------------------------------- + + template typename PolyMeshT::Normal PolyMeshT:: diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.hh b/src/OpenMesh/Core/Mesh/PolyMeshT.hh index 6c1a253c..343a7129 100644 --- a/src/OpenMesh/Core/Mesh/PolyMeshT.hh +++ b/src/OpenMesh/Core/Mesh/PolyMeshT.hh @@ -225,6 +225,24 @@ public: const Point& _p2) const; // calculates the average of the vertices defining _fh void calc_face_centroid(FaceHandle _fh, Point& _pt) const; + + /// Update normal for halfedge _heh + void update_normal(HalfedgeHandle _heh, const double _feature_angle = 0.8) + { set_normal(_heh, calc_halfedge_normal(_heh)); } + + /** Update normal vectors for all halfedges. + \attention Needs the Attributes::Normal attribute for faces. */ + void update_halfedge_normals(const double _feature_angle = 0.8); + + /** Calculate normal vector for halfedge _heh. */ + /** requires valid face normals!!! */ + virtual Normal calc_halfedge_normal(HalfedgeHandle _fh, const double _feature_angle = 0.8) const; + + + /** identifies feature edges w.r.t. the minimal dihedral angle for feautre edges (in radians) */ + /** and the status feature tag */ + bool is_estimated_feature_edge(HalfedgeHandle _heh, const double _feature_angle) const; + /// Update normal for vertex _vh void update_normal(VertexHandle _vh) { set_normal(_vh, calc_vertex_normal(_vh)); }