per_corner_normals.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #ifndef IGL_PER_CORNER_NORMALS_H
  2. #define IGL_PER_CORNER_NORMALS_H
  3. #include <Eigen/Core>
  4. #endif
  5. namespace igl
  6. {
  7. // Compute vertex normals via vertex position list, face list
  8. // Inputs:
  9. // V #V by 3 eigen Matrix of mesh vertex 3D positions
  10. // F #F by 3 eigne Matrix of face (triangle) indices
  11. // corner_threshold threshold in degrees on sharp angles
  12. // Output:
  13. // CN #F*3 by 3 eigen Matrix of mesh vertex 3D normals, where the normal
  14. // for corner F(i,j) is at CN(i*3+j,:)
  15. inline void per_corner_normals(
  16. const Eigen::MatrixXd & V,
  17. const Eigen::MatrixXi & F,
  18. const double corner_threshold,
  19. Eigen::MatrixXd & CN);
  20. // Other Inputs:
  21. // FN #F by 3 eigen Matrix of face normals
  22. // VF map from vertices to list of incident faces
  23. inline void per_corner_normals(
  24. const Eigen::MatrixXd & V,
  25. const Eigen::MatrixXi & F,
  26. const Eigen::MatrixXd & FN,
  27. const std::vector<std::vector<int> >& VF,
  28. const double corner_threshold,
  29. Eigen::MatrixXd & CN);
  30. }
  31. // Implementation
  32. #include "vf.h"
  33. #include "per_face_normals.h"
  34. #include "PI.h"
  35. inline void igl::per_corner_normals(
  36. const Eigen::MatrixXd & V,
  37. const Eigen::MatrixXi & F,
  38. const double corner_threshold,
  39. Eigen::MatrixXd & CN)
  40. {
  41. using namespace igl;
  42. using namespace Eigen;
  43. using namespace std;
  44. MatrixXd FN;
  45. per_face_normals(V,F,FN);
  46. vector<vector<int> > VF,VFi;
  47. vf(V,F,VF,VFi);
  48. return per_corner_normals(V,F,FN,VF,corner_threshold,CN);
  49. }
  50. inline void igl::per_corner_normals(
  51. const Eigen::MatrixXd & V,
  52. const Eigen::MatrixXi & F,
  53. const Eigen::MatrixXd & FN,
  54. const std::vector<std::vector<int> >& VF,
  55. const double corner_threshold,
  56. Eigen::MatrixXd & CN)
  57. {
  58. using namespace igl;
  59. using namespace Eigen;
  60. using namespace std;
  61. // number of faces
  62. const int m = F.rows();
  63. // initialize output to zero
  64. CN = MatrixXd::Constant(m*3,3,0);
  65. // loop over faces
  66. for(size_t i = 0;i<m;i++)
  67. {
  68. // Normal of this face
  69. Vector3d fn = FN.row(i);
  70. // loop over corners
  71. for(size_t j = 0;j<3;j++)
  72. {
  73. std::vector<int> incident_faces = VF[F(i,j)];
  74. // loop over faces sharing vertex of this corner
  75. for(int k = 0;k<(int)incident_faces.size();k++)
  76. {
  77. Vector3d ifn = FN.row(incident_faces[k]);
  78. // dot product between face's normal and other face's normal
  79. double dp = fn.dot(ifn);
  80. // if difference in normal is slight then add to average
  81. if(dp > cos(corner_threshold*PI/180))
  82. {
  83. // add to running sum
  84. CN.row(i*3+j) += ifn;
  85. // else ignore
  86. }else
  87. {
  88. }
  89. }
  90. // normalize to take average
  91. double length = CN.row(i*3+j).norm();
  92. CN.row(i*3+j) /= length;
  93. }
  94. }
  95. }