Browse Source

normals example

Former-commit-id: de279a738556b4163b920296f44d49a91f3e6bf7
Alec Jacobson 11 years ago
parent
commit
43b01106e9

+ 2 - 0
include/igl/normalize_row_lengths.h

@@ -16,6 +16,8 @@
 
 
 namespace igl
 namespace igl
 {
 {
+  // Obsolete: just use A.rowwise().normalize() or B=A.rowwise().normalized();
+  //
   // Normalize the rows in A so that their lengths are each 1 and place the new
   // Normalize the rows in A so that their lengths are each 1 and place the new
   // entries in B
   // entries in B
   // Inputs:
   // Inputs:

+ 1 - 3
include/igl/per_vertex_normals.cpp

@@ -8,7 +8,6 @@
 #include "per_vertex_normals.h"
 #include "per_vertex_normals.h"
 
 
 #include "per_face_normals.h"
 #include "per_face_normals.h"
-#include "normalize_row_lengths.h"
 
 
 template <typename DerivedV, typename DerivedF>
 template <typename DerivedV, typename DerivedF>
 IGL_INLINE void igl::per_vertex_normals(
 IGL_INLINE void igl::per_vertex_normals(
@@ -48,8 +47,7 @@ IGL_INLINE void igl::per_vertex_normals(
       N.row(F(i,j)) += FN.row(i);
       N.row(F(i,j)) += FN.row(i);
     }
     }
   }
   }
-  // normalize each row
-  igl::normalize_row_lengths(N,N);
+  N.rowwise().normalize();
 }
 }
 
 
 #ifndef IGL_HEADER_ONLY
 #ifndef IGL_HEADER_ONLY

+ 18 - 13
tutorial/201_Normals/main.cpp

@@ -15,15 +15,19 @@ Eigen::MatrixXd N_corners;
 // This function is called every time a keyboard button is pressed
 // This function is called every time a keyboard button is pressed
 bool key_down(igl::Viewer& viewer, unsigned char key, int modifier)
 bool key_down(igl::Viewer& viewer, unsigned char key, int modifier)
 {
 {
-  if (key == '1')
-    viewer.set_normals(N_vertices);
-
-  if (key == '2')
-    viewer.set_normals(N_faces);
-
-  if (key == '3')
-    viewer.set_normals(N_corners);
-
+  switch(key)
+  {
+    case '1':
+      viewer.set_normals(N_faces);
+      return true;
+    case '2':
+      viewer.set_normals(N_vertices);
+      return true;
+    case '3':
+      viewer.set_normals(N_corners);
+      return true;
+    default: break;
+  }
   return false;
   return false;
 }
 }
 
 
@@ -32,18 +36,19 @@ int main(int argc, char *argv[])
   // Load a mesh in OFF format
   // Load a mesh in OFF format
   igl::readOFF("../shared/fandisk.off", V, F);
   igl::readOFF("../shared/fandisk.off", V, F);
 
 
-  // Compute per-vertex normals
-  igl::per_vertex_normals(V,F,N_vertices);
-
   // Compute per-face normals
   // Compute per-face normals
   igl::per_face_normals(V,F,N_faces);
   igl::per_face_normals(V,F,N_faces);
 
 
-  // Compute per-corner normals
+  // Compute per-vertex normals
+  igl::per_vertex_normals(V,F,N_vertices);
+
+  // Compute per-corner normals, |dihedral angle| > 20 degrees --> crease
   igl::per_corner_normals(V,F,20,N_corners);
   igl::per_corner_normals(V,F,20,N_corners);
 
 
   // Plot the mesh
   // Plot the mesh
   igl::Viewer viewer;
   igl::Viewer viewer;
   viewer.callback_key_down = &key_down;
   viewer.callback_key_down = &key_down;
+  viewer.options.show_lines = false;
   viewer.set_mesh(V, F);
   viewer.set_mesh(V, F);
   viewer.set_normals(N_vertices);
   viewer.set_normals(N_vertices);
   viewer.launch();
   viewer.launch();

+ 1 - 0
tutorial/images/fandisk-normals.jpg.REMOVED.git-id

@@ -0,0 +1 @@
+f2cb86a67341a5a5f3978f2c336eed2bb29cdc83

+ 59 - 0
tutorial/readme.md

@@ -33,6 +33,7 @@ applications for each topic.
 * **100_FileIO**: Example of reading/writing mesh files
 * **100_FileIO**: Example of reading/writing mesh files
 * **101_Serialization**: Example of using the XML serialization framework
 * **101_Serialization**: Example of using the XML serialization framework
 * **102_DrawMesh**: Example of plotting a mesh
 * **102_DrawMesh**: Example of plotting a mesh
+* [201 Normals](#norm)
 * [202 Gaussian Curvature](#gaus)
 * [202 Gaussian Curvature](#gaus)
 * [203 Curvature Directions](#curv)
 * [203 Curvature Directions](#curv)
 * [204 Gradient](#grad)
 * [204 Gradient](#grad)
@@ -71,6 +72,64 @@ mesh. This also provides an introduction to basic drawing and coloring routines
 in our example viewer. Finally, we construct popular discrete differential
 in our example viewer. Finally, we construct popular discrete differential
 geometry operators.
 geometry operators.
 
 
+## <a id=norm></a> Normals
+
+### Per-face 
+Well defined normal orthogonal to triangle's plane. Produces piecewise-flat
+rending: not smooth.
+
+### Per-vertex
+Using per-vertex normals, Phong or Gouraud shading will produce smooth(er)
+renderings. Most techniques for computing per-vertex normals take an average of
+incident face normals. The techniques vary with respect to their different
+weighting schemes. Uniform weighting is heavily biased by the discretization
+choice, where as area-based or angle-based weighting is more forgiving.
+
+The typical half-edge style computation of area-based weights might look
+something like this:
+
+```cpp
+N.setZero(V.rows(),3);
+for(int i : vertices)
+{
+  for(face : incident_faces(i))
+  {
+    N.row(i) += face.area * face.normal;
+  }
+}
+N.rowwise().normalize();
+```
+
+Without a half-edge data-structure it may seem at first glance that looping
+over incident faces---and thus constructing the per-vertex normals---would be
+inefficient. However, per-vertex normals may be _throwing_ each face normal to
+running sums on its corner vertices:
+
+```cpp
+N.setZero(V.rows(),3);
+for(int f = 0; f < F.rows();f++)
+{
+  for(int c = 0; c < 3;c++)
+  {
+    N.row(F(f,c)) += area(f) * face_normal.row(f);
+  }
+}
+N.rowwise().normalize();
+```
+
+### Per-corner
+
+Storing normals per-corner is an efficient an convenient way of supporting both
+smooth and sharp (e.g. creases and corners) rendering. This format is common to
+OpenGL and the .obj mesh file format. Often such normals are tuned by the mesh
+designer, but creases and corners can also be computed automatically. Libigl
+implements a simple scheme which computes corner normals as averages of
+normals of faces incident on the corresponding vertex which do not deviate by a
+specified dihedral angle (e.g. 20°).
+
+![The `Normals` example computes per-face (left), per-vertex (middle) and
+per-corner (right) normals](images/fandisk-normals.jpg)
+
 ## <a id=gaus></a> Gaussian Curvature
 ## <a id=gaus></a> Gaussian Curvature
 Gaussian curvature on a continuous surface is defined as the product of the
 Gaussian curvature on a continuous surface is defined as the product of the
 principal curvatures:
 principal curvatures: