diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.cc b/src/OpenMesh/Core/Mesh/PolyMeshT.cc index 9f59518d..5c323505 100644 --- a/src/OpenMesh/Core/Mesh/PolyMeshT.cc +++ b/src/OpenMesh/Core/Mesh/PolyMeshT.cc @@ -95,15 +95,37 @@ calc_face_normal(FaceHandle _fh) const { assert(halfedge_handle(_fh).is_valid()); ConstFaceVertexIter fv_it(cfv_iter(_fh)); + + Point p0 = point(fv_it); + Point p0i = p0; //save point of vertex 0 + ++fv_it; + Point p1 = point(fv_it); + Point p1i = p1; //save point of vertex 1 + ++fv_it; + Point p2; + + //calculate area-weighted average normal of polygon's ears + Normal n(0,0,0); + for(; fv_it; ++fv_it) + { + p2 = point(fv_it); + n += vector_cast((p2-p1)%(p0-p1)); + p0 = p1; + p1 = p2; + } + + //two additional steps since we started at vertex 2, not 0 + n += vector_cast((p0i-p1)%(p0-p1)); + n += vector_cast((p1i-p0i)%(p1-p0i)); - const Point& p0(point(fv_it)); ++fv_it; - const Point& p1(point(fv_it)); ++fv_it; - const Point& p2(point(fv_it)); - - return calc_face_normal(p0, p1, p2); + typename Normal::value_type norm = n.length(); + + // The expression ((n *= (1.0/norm)),n) is used because the OpenSG + // vector class does not return self after component-wise + // self-multiplication with a scalar!!! + return (norm != typename Normal::value_type(0)) ? ((n *= (typename Normal::value_type(1)/norm)),n) : Normal(0,0,0); } - //----------------------------------------------------------------------------- diff --git a/src/OpenMesh/Core/Mesh/PolyMeshT.hh b/src/OpenMesh/Core/Mesh/PolyMeshT.hh index b17672fe..d40e8f62 100644 --- a/src/OpenMesh/Core/Mesh/PolyMeshT.hh +++ b/src/OpenMesh/Core/Mesh/PolyMeshT.hh @@ -218,7 +218,7 @@ public: void update_face_normals(); /** Calculate normal vector for face _fh. */ - Normal calc_face_normal(FaceHandle _fh) const; + virtual Normal calc_face_normal(FaceHandle _fh) const; /** Calculate normal vector for face (_p0, _p1, _p2). */ Normal calc_face_normal(const Point& _p0, const Point& _p1, diff --git a/src/OpenMesh/Core/Mesh/TriMeshT.cc b/src/OpenMesh/Core/Mesh/TriMeshT.cc index d1cfcd99..644b9907 100644 --- a/src/OpenMesh/Core/Mesh/TriMeshT.cc +++ b/src/OpenMesh/Core/Mesh/TriMeshT.cc @@ -66,6 +66,21 @@ namespace OpenMesh { //== IMPLEMENTATION ========================================================== +template +typename TriMeshT::Normal +TriMeshT:: +calc_face_normal(FaceHandle _fh) const +{ + assert(halfedge_handle(_fh).is_valid()); + ConstFaceVertexIter fv_it(cfv_iter(_fh)); + + const Point& p0(point(fv_it)); ++fv_it; + const Point& p1(point(fv_it)); ++fv_it; + const Point& p2(point(fv_it)); + + return PolyMesh::calc_face_normal(p0, p1, p2); +} + //============================================================================= } // namespace OpenMesh //============================================================================= diff --git a/src/OpenMesh/Core/Mesh/TriMeshT.hh b/src/OpenMesh/Core/Mesh/TriMeshT.hh index 9cf1003e..30d2189a 100644 --- a/src/OpenMesh/Core/Mesh/TriMeshT.hh +++ b/src/OpenMesh/Core/Mesh/TriMeshT.hh @@ -183,14 +183,21 @@ public: inline void split(EdgeHandle _eh, VertexHandle _vh) { PolyMesh::split(_eh, _vh); } - /// Face split (= 1-to-3 split, calls corresponding PolyMeshT function). - /// Face split (= 1-to-3 split, calls corresponding PolyMeshT function). inline void split(FaceHandle _fh, const Point& _p) { PolyMesh::split(_fh, _p); } inline void split(FaceHandle _fh, VertexHandle _vh) { PolyMesh::split(_fh, _vh); } + + /** \name Normal vector computation + */ + //@{ + + /** Calculate normal vector for face _fh (specialized for TriMesh). */ + Normal calc_face_normal(FaceHandle _fh) const; + + //@} };