Jelajahi Sumber

- added support for per corner normals
- added example in the tutorial for the normals
- viewer: the cache is now properly invalidated when switching between face and vertex mode


Former-commit-id: f25f098b90ccee6c53f0d5ea18f1a91d1d44d3fb

Daniele Panozzo 11 tahun lalu
induk
melakukan
4529821552

+ 2 - 0
.gitignore

@@ -61,3 +61,5 @@ README.html
 tutorial/readme.html
 tutorial/*/build/*
 tutorial/*/Makefile
+external/glew/build
+*buildXcode*

+ 25 - 12
include/igl/viewer/Viewer.cpp

@@ -693,7 +693,7 @@ namespace igl
     scroll_position = 0.0f;
 
     // Per face
-    options.face_based = false;
+    set_face_based(false);
 
     // C-style callbacks
     callback_pre_draw     = 0;
@@ -1332,6 +1332,8 @@ namespace igl
   void Viewer::OpenGL_state::set_data(const Data &data, bool face_based, bool invert_normals)
   {
     bool per_corner_uv = (data.F_uv.rows() == data.F.rows());
+    bool per_corner_normals = (data.F_normals.rows() == 3 * data.F.rows());
+
     dirty |= data.dirty;
 
     if (!face_based)
@@ -1467,7 +1469,10 @@ namespace igl
         V_normals_vbo.resize(3,data.F.rows()*3);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            V_normals_vbo.col (i*3+j) = data.F_normals.row(i).transpose().cast<float>();
+            V_normals_vbo.col (i*3+j) =
+               per_corner_normals ?
+                 data.F_normals.row(i*3+j).transpose().cast<float>() :
+                 data.F_normals.row(i).transpose().cast<float>();
 
         if (invert_normals)
           V_normals_vbo = -V_normals_vbo;
@@ -2051,8 +2056,7 @@ namespace igl
   void TW_CALL Viewer::set_face_based_cb(const void *param, void *clientData)
   {
     Viewer *viewer = static_cast<Viewer *>(clientData);
-    viewer->data.dirty = Viewer::DIRTY_ALL;
-    viewer->options.face_based = *((bool *) param);
+    viewer->set_face_based(*((bool *) param));
   }
 
   void TW_CALL Viewer::get_face_based_cb(void *param, void *clientData)
@@ -2134,6 +2138,15 @@ namespace igl
     #endif
   }
 
+  void Viewer::set_face_based(bool newvalue)
+  {
+    if (options.face_based != newvalue)
+    {
+      options.face_based = newvalue;
+      data.dirty = DIRTY_ALL;
+    }
+  }
+
   // Helpers that draws the most common meshes
   void Viewer::set_mesh(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F)
   {
@@ -2171,16 +2184,16 @@ namespace igl
     using namespace std;
     if (N.rows() == data.V.rows())
     {
-      options.face_based = false;
+      set_face_based(false);
       data.V_normals = N;
     }
-    else if (N.rows() == data.F.rows())
+    else if (N.rows() == data.F.rows() || N.rows() == data.F.rows()*3)
     {
-      options.face_based = true;
+      set_face_based(true);
       data.F_normals = N;
     }
     else
-      cerr << "ERROR (set_normals): Please provide a normal per face or a normal per vertex.";
+      cerr << "ERROR (set_normals): Please provide a normal per face, per corner or per vertex.";
     data.dirty |= DIRTY_NORMAL;
   }
 
@@ -2218,14 +2231,14 @@ namespace igl
     }
     else if (C.rows() == data.V.rows())
     {
-      options.face_based = false;
+      set_face_based(false);
       data.V_material_diffuse = C;
       data.V_material_ambient = ambient(data.V_material_diffuse);
       data.V_material_specular = specular(data.V_material_diffuse);
     }
     else if (C.rows() == data.F.rows())
     {
-      options.face_based = true;
+      set_face_based(true);
       data.F_material_diffuse = C;
       data.F_material_ambient = ambient(data.F_material_diffuse);
       data.F_material_specular = specular(data.F_material_diffuse);
@@ -2241,7 +2254,7 @@ namespace igl
     using namespace std;
     if (UV.rows() == data.V.rows())
     {
-      options.face_based = false;
+      set_face_based(false);
       data.V_uv = UV;
     }
     else
@@ -2251,7 +2264,7 @@ namespace igl
 
   void Viewer::set_UV(const Eigen::MatrixXd& UV_V, const Eigen::MatrixXi& UV_F)
   {
-    options.face_based = true;
+    set_face_based(true);
     data.V_uv = UV_V;
     data.F_uv = UV_F;
     data.dirty |= DIRTY_UV;

+ 4 - 1
include/igl/viewer/Viewer.h

@@ -345,10 +345,13 @@ namespace igl
     void clear_mesh();      // Clear the mesh data
     void alignCameraCenter(); // Adjust the view to see the entire model
 
+    // Change the visualization mode, invalidating the cache if necessary
+    void set_face_based(bool newvalue);
+
     // Helpers that can draw the most common meshes
     void set_mesh(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F);
     void set_normals(const Eigen::MatrixXd& N);
-    // Set the color of the mesh 
+    // Set the color of the mesh
     //
     // Inputs:
     //   C  #V|#F|1 by 3 list of colors

+ 11 - 0
tutorial/201_Normals/CMakeLists.txt

@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.6)
+project(202_Normals)
+
+include("../CMakeLists.shared")
+
+set(SOURCES
+${PROJECT_SOURCE_DIR}/main.cpp
+)
+
+add_executable(${CMAKE_PROJECT_NAME} ${SOURCES} ${SHARED_SOURCES})
+target_link_libraries(${CMAKE_PROJECT_NAME} ${SHARED_LIBRARIES})

+ 50 - 0
tutorial/201_Normals/main.cpp

@@ -0,0 +1,50 @@
+#include <igl/readOFF.h>
+#include <igl/viewer/Viewer.h>
+#include <igl/per_vertex_normals.h>
+#include <igl/per_face_normals.h>
+#include <igl/per_corner_normals.h>
+
+Eigen::MatrixXd V;
+Eigen::MatrixXi F;
+
+Eigen::MatrixXd N_vertices;
+Eigen::MatrixXd N_faces;
+Eigen::MatrixXd N_corners;
+
+
+// This function is called every time a keyboard button is pressed
+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);
+
+  return false;
+}
+
+int main(int argc, char *argv[])
+{
+  // Load a mesh in OFF format
+  igl::readOFF("../shared/fandisk.off", V, F);
+
+  // Compute per-vertex normals
+  igl::per_vertex_normals(V,F,N_vertices);
+
+  // Compute per-face normals
+  igl::per_face_normals(V,F,N_faces);
+
+  // Compute per-corner normals
+  igl::per_corner_normals(V,F,20,N_corners);
+
+  // Plot the mesh
+  igl::Viewer viewer;
+  viewer.callback_key_down = &key_down;
+  viewer.set_mesh(V, F);
+  viewer.set_normals(N_vertices);
+  viewer.launch();
+}

+ 1 - 0
tutorial/shared/fandisk.off.REMOVED.git-id

@@ -0,0 +1 @@
+fbf72534f48e260e2c7d041463dd70bbde7fdf53