// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2013 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "per_vertex_normals.h" #include "get_seconds.h" #include "per_face_normals.h" #include "doublearea.h" #include "internal_angles.h" template IGL_INLINE void igl::per_vertex_normals( const Eigen::PlainObjectBase& V, const Eigen::PlainObjectBase& F, const igl::PerVertexNormalsWeightingType weighting, Eigen::PlainObjectBase & N) { Eigen::Matrix PFN; igl::per_face_normals(V,F,PFN); return per_vertex_normals(V,F,weighting,PFN,N); } template IGL_INLINE void igl::per_vertex_normals( const Eigen::PlainObjectBase& V, const Eigen::PlainObjectBase& F, Eigen::PlainObjectBase & N) { return per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT,N); } template IGL_INLINE void igl::per_vertex_normals( const Eigen::PlainObjectBase& V, const Eigen::PlainObjectBase& F, const igl::PerVertexNormalsWeightingType weighting, const Eigen::PlainObjectBase& FN, Eigen::PlainObjectBase & N) { using namespace std; // Resize for output N.setZero(V.rows(),3); Eigen::Matrix W(F.rows(),3); switch(weighting) { case PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM: W.setConstant(1.); break; default: assert(false && "Unknown weighting type"); case PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT: case PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA: { Eigen::Matrix A; doublearea(V,F,A); W = A.replicate(1,3); break; } case PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE: internal_angles(V,F,W); break; } // loop over faces const int Frows = F.rows(); //// Minimum number of iterms per openmp thread //#ifndef IGL_OMP_MIN_VALUE //# define IGL_OMP_MIN_VALUE 1000 //#endif //#pragma omp parallel for if (Frows>IGL_OMP_MIN_VALUE) for(int i = 0; i < Frows;i++) { // throw normal at each corner for(int j = 0; j < 3;j++) { // Q: Does this need to be critical? // A: Yes. Different (i,j)'s could produce the same F(i,j) //#pragma omp critical N.row(F(i,j)) += W(i,j)*FN.row(i); } } // take average via normalization N.rowwise().normalize(); } template IGL_INLINE void igl::per_vertex_normals( const Eigen::PlainObjectBase& V, const Eigen::PlainObjectBase& F, const Eigen::PlainObjectBase& FN, Eigen::PlainObjectBase & N) { return per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT,FN,N); } #ifdef IGL_STATIC_LIBRARY // Explicit template specialization template void igl::per_vertex_normals, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); template void igl::per_vertex_normals, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); template void igl::per_vertex_normals, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, igl::PerVertexNormalsWeightingType, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); template void igl::per_vertex_normals, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); template void igl::per_vertex_normals, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); template void igl::per_vertex_normals, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); #endif