浏览代码

Merge branch 'viewer-refactor' of https://github.com/libigl/libigl into viewer_refactor

# Conflicts:
#	include/igl/opengl/State.cpp
#	include/igl/opengl/glfw/Viewer.cpp
#	shared/cmake/libigl.cmake
#	tutorial/609_Boolean/CMakeLists.txt
#	tutorial/704_SignedDistance/main.cpp


Former-commit-id: 8d2967ebdc3ff1d90026d1e31f839272f6f5aa74
Daniele Panozzo 7 年之前
父节点
当前提交
0a18442c6b
共有 100 个文件被更改,包括 1424 次插入1512 次删除
  1. 45 25
      include/igl/ViewerData.cpp
  2. 21 63
      include/igl/ViewerData.h
  3. 133 94
      include/igl/opengl/State.cpp
  4. 32 26
      include/igl/opengl/State.h
  5. 53 66
      include/igl/opengl/ViewerCore.cpp
  6. 65 89
      include/igl/opengl/ViewerCore.h
  7. 24 0
      include/igl/opengl/bind_vertex_attrib_array.cpp
  8. 32 0
      include/igl/opengl/bind_vertex_attrib_array.h
  9. 6 6
      include/igl/opengl/glfw/TextRenderer.cpp
  10. 6 3
      include/igl/opengl/glfw/TextRenderer.h
  11. 0 0
      include/igl/opengl/glfw/TextRenderer_fonts.cpp.REMOVED.git-id
  12. 2 2
      include/igl/opengl/glfw/TextRenderer_fonts.h
  13. 346 275
      include/igl/opengl/glfw/Viewer.cpp
  14. 79 64
      include/igl/opengl/glfw/Viewer.h
  15. 6 3
      include/igl/opengl/glfw/ViewerPlugin.h
  16. 9 2
      include/igl/opengl/load_shader.cpp
  17. 6 1
      include/igl/opengl/load_shader.h
  18. 57 1
      include/igl/serialize.h
  19. 0 173
      include/igl/viewer/OpenGL_shader.cpp
  20. 0 98
      include/igl/viewer/OpenGL_shader.h
  21. 0 33
      include/igl/viewer/TODOs.txt
  22. 27 43
      shared/cmake/CMakeLists.txt
  23. 0 16
      shared/cmake/libigl.cmake
  24. 1 1
      tutorial/102_DrawMesh/CMakeLists.txt
  25. 3 3
      tutorial/102_DrawMesh/main.cpp
  26. 1 1
      tutorial/103_Events/CMakeLists.txt
  27. 8 8
      tutorial/103_Events/main.cpp
  28. 1 1
      tutorial/104_Colors/CMakeLists.txt
  29. 4 4
      tutorial/104_Colors/main.cpp
  30. 1 1
      tutorial/105_Overlays/CMakeLists.txt
  31. 7 7
      tutorial/105_Overlays/main.cpp
  32. 1 1
      tutorial/106_ViewerMenu/CMakeLists.txt
  33. 4 4
      tutorial/106_ViewerMenu/main.cpp
  34. 5 0
      tutorial/107_MultipleMeshes/CMakeLists.txt
  35. 40 0
      tutorial/107_MultipleMeshes/main.cpp
  36. 1 1
      tutorial/201_Normals/CMakeLists.txt
  37. 9 9
      tutorial/201_Normals/main.cpp
  38. 1 1
      tutorial/202_GaussianCurvature/CMakeLists.txt
  39. 4 4
      tutorial/202_GaussianCurvature/main.cpp
  40. 1 1
      tutorial/203_CurvatureDirections/CMakeLists.txt
  41. 7 7
      tutorial/203_CurvatureDirections/main.cpp
  42. 1 1
      tutorial/204_Gradient/CMakeLists.txt
  43. 6 6
      tutorial/204_Gradient/main.cpp
  44. 1 1
      tutorial/205_Laplacian/CMakeLists.txt
  45. 7 7
      tutorial/205_Laplacian/main.cpp
  46. 1 1
      tutorial/301_Slice/CMakeLists.txt
  47. 4 4
      tutorial/301_Slice/main.cpp
  48. 1 1
      tutorial/302_Sort/CMakeLists.txt
  49. 4 4
      tutorial/302_Sort/main.cpp
  50. 1 1
      tutorial/303_LaplaceEquation/CMakeLists.txt
  51. 5 5
      tutorial/303_LaplaceEquation/main.cpp
  52. 1 1
      tutorial/304_LinearEqualityConstraints/CMakeLists.txt
  53. 7 7
      tutorial/304_LinearEqualityConstraints/main.cpp
  54. 1 1
      tutorial/305_QuadraticProgramming/CMakeLists.txt
  55. 7 7
      tutorial/305_QuadraticProgramming/main.cpp
  56. 1 1
      tutorial/306_EigenDecomposition/CMakeLists.txt
  57. 7 7
      tutorial/306_EigenDecomposition/main.cpp
  58. 1 1
      tutorial/401_BiharmonicDeformation/CMakeLists.txt
  59. 9 9
      tutorial/401_BiharmonicDeformation/main.cpp
  60. 1 1
      tutorial/402_PolyharmonicDeformation/CMakeLists.txt
  61. 9 9
      tutorial/402_PolyharmonicDeformation/main.cpp
  62. 1 1
      tutorial/403_BoundedBiharmonicWeights/CMakeLists.txt
  63. 14 14
      tutorial/403_BoundedBiharmonicWeights/main.cpp
  64. 1 1
      tutorial/404_DualQuaternionSkinning/CMakeLists.txt
  65. 12 12
      tutorial/404_DualQuaternionSkinning/main.cpp
  66. 1 1
      tutorial/405_AsRigidAsPossible/CMakeLists.txt
  67. 8 8
      tutorial/405_AsRigidAsPossible/main.cpp
  68. 1 1
      tutorial/406_FastAutomaticSkinningTransformations/CMakeLists.txt
  69. 10 10
      tutorial/406_FastAutomaticSkinningTransformations/main.cpp
  70. 1 1
      tutorial/407_BiharmonicCoordinates/CMakeLists.txt
  71. 12 11
      tutorial/407_BiharmonicCoordinates/main.cpp
  72. 1 1
      tutorial/501_HarmonicParam/CMakeLists.txt
  73. 10 10
      tutorial/501_HarmonicParam/main.cpp
  74. 1 1
      tutorial/502_LSCMParam/CMakeLists.txt
  75. 10 10
      tutorial/502_LSCMParam/main.cpp
  76. 1 1
      tutorial/503_ARAPParam/CMakeLists.txt
  77. 10 10
      tutorial/503_ARAPParam/main.cpp
  78. 1 1
      tutorial/504_NRosyDesign/CMakeLists.txt
  79. 12 12
      tutorial/504_NRosyDesign/main.cpp
  80. 1 1
      tutorial/505_MIQ/CMakeLists.txt
  81. 37 37
      tutorial/505_MIQ/main.cpp
  82. 1 1
      tutorial/506_FrameField/CMakeLists.txt
  83. 32 32
      tutorial/506_FrameField/main.cpp
  84. 1 1
      tutorial/507_PolyVectorField/CMakeLists.txt
  85. 9 9
      tutorial/507_PolyVectorField/main.cpp
  86. 1 1
      tutorial/508_ConjugateField/CMakeLists.txt
  87. 19 19
      tutorial/508_ConjugateField/main.cpp
  88. 1 1
      tutorial/509_Planarization/CMakeLists.txt
  89. 17 17
      tutorial/509_Planarization/main.cpp
  90. 1 1
      tutorial/510_Integrable/CMakeLists.txt
  91. 45 45
      tutorial/510_Integrable/main.cpp
  92. 1 1
      tutorial/511_PolyVectorFieldGeneral/CMakeLists.txt
  93. 9 9
      tutorial/511_PolyVectorFieldGeneral/main.cpp
  94. 1 1
      tutorial/601_Serialization/CMakeLists.txt
  95. 1 1
      tutorial/602_Matlab/CMakeLists.txt
  96. 6 6
      tutorial/602_Matlab/main.cpp
  97. 1 1
      tutorial/604_Triangle/CMakeLists.txt
  98. 3 3
      tutorial/604_Triangle/main.cpp
  99. 1 1
      tutorial/605_Tetgen/CMakeLists.txt
  100. 6 6
      tutorial/605_Tetgen/main.cpp

+ 45 - 25
include/igl/viewer/ViewerData.cpp → include/igl/ViewerData.cpp

@@ -8,20 +8,33 @@
 
 #include "ViewerData.h"
 
+#include "per_face_normals.h"
+#include "material_colors.h"
+#include "parula.h"
+#include "per_vertex_normals.h"
+
 #include <iostream>
 
-#include <igl/per_face_normals.h>
-#include <igl/material_colors.h>
-#include <igl/parula.h>
-#include <igl/per_vertex_normals.h>
 
-IGL_INLINE igl::viewer::ViewerData::ViewerData()
-: dirty(DIRTY_ALL)
+IGL_INLINE igl::ViewerData::ViewerData()
+: dirty(DIRTY_ALL),
+  show_faces(true),
+  show_lines(true),
+  invert_normals(false),
+  show_overlay(true),
+  show_overlay_depth(true),
+  show_vertid(false),
+  show_faceid(false),
+  show_texture(false),
+  point_size(30),
+  line_width(0.5f),
+  line_color(0,0,0,1),
+  shininess(35.0f)
 {
   clear();
 };
 
-IGL_INLINE void igl::viewer::ViewerData::set_face_based(bool newvalue)
+IGL_INLINE void igl::ViewerData::set_face_based(bool newvalue)
 {
   if (face_based != newvalue)
   {
@@ -31,7 +44,8 @@ IGL_INLINE void igl::viewer::ViewerData::set_face_based(bool newvalue)
 }
 
 // Helpers that draws the most common meshes
-IGL_INLINE void igl::viewer::ViewerData::set_mesh(const Eigen::MatrixXd& _V, const Eigen::MatrixXi& _F)
+IGL_INLINE void igl::ViewerData::set_mesh(
+    const Eigen::MatrixXd& _V, const Eigen::MatrixXi& _F)
 {
   using namespace std;
 
@@ -72,14 +86,14 @@ IGL_INLINE void igl::viewer::ViewerData::set_mesh(const Eigen::MatrixXd& _V, con
   dirty |= DIRTY_FACE | DIRTY_POSITION;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::set_vertices(const Eigen::MatrixXd& _V)
+IGL_INLINE void igl::ViewerData::set_vertices(const Eigen::MatrixXd& _V)
 {
   V = _V;
   assert(F.size() == 0 || F.maxCoeff() < V.rows());
   dirty |= DIRTY_POSITION;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::set_normals(const Eigen::MatrixXd& N)
+IGL_INLINE void igl::ViewerData::set_normals(const Eigen::MatrixXd& N)
 {
   using namespace std;
   if (N.rows() == V.rows())
@@ -97,7 +111,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_normals(const Eigen::MatrixXd& N)
   dirty |= DIRTY_NORMAL;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::set_colors(const Eigen::MatrixXd &C)
+IGL_INLINE void igl::ViewerData::set_colors(const Eigen::MatrixXd &C)
 {
   using namespace std;
   using namespace Eigen;
@@ -165,7 +179,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_colors(const Eigen::MatrixXd &C)
 
 }
 
-IGL_INLINE void igl::viewer::ViewerData::set_uv(const Eigen::MatrixXd& UV)
+IGL_INLINE void igl::ViewerData::set_uv(const Eigen::MatrixXd& UV)
 {
   using namespace std;
   if (UV.rows() == V.rows())
@@ -178,7 +192,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_uv(const Eigen::MatrixXd& UV)
   dirty |= DIRTY_UV;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::set_uv(const Eigen::MatrixXd& UV_V, const Eigen::MatrixXi& UV_F)
+IGL_INLINE void igl::ViewerData::set_uv(const Eigen::MatrixXd& UV_V, const Eigen::MatrixXi& UV_F)
 {
   set_face_based(true);
   V_uv = UV_V.block(0,0,UV_V.rows(),2);
@@ -187,7 +201,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_uv(const Eigen::MatrixXd& UV_V, con
 }
 
 
-IGL_INLINE void igl::viewer::ViewerData::set_texture(
+IGL_INLINE void igl::ViewerData::set_texture(
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B)
@@ -199,7 +213,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_texture(
   dirty |= DIRTY_TEXTURE;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::set_texture(
+IGL_INLINE void igl::ViewerData::set_texture(
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
@@ -212,7 +226,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_texture(
   dirty |= DIRTY_TEXTURE;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::set_points(
+IGL_INLINE void igl::ViewerData::set_points(
   const Eigen::MatrixXd& P,
   const Eigen::MatrixXd& C)
 {
@@ -221,7 +235,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_points(
   add_points(P,C);
 }
 
-IGL_INLINE void igl::viewer::ViewerData::add_points(const Eigen::MatrixXd& P,  const Eigen::MatrixXd& C)
+IGL_INLINE void igl::ViewerData::add_points(const Eigen::MatrixXd& P,  const Eigen::MatrixXd& C)
 {
   Eigen::MatrixXd P_temp;
 
@@ -242,7 +256,7 @@ IGL_INLINE void igl::viewer::ViewerData::add_points(const Eigen::MatrixXd& P,  c
   dirty |= DIRTY_OVERLAY_POINTS;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::set_edges(
+IGL_INLINE void igl::ViewerData::set_edges(
   const Eigen::MatrixXd& P,
   const Eigen::MatrixXi& E,
   const Eigen::MatrixXd& C)
@@ -265,7 +279,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_edges(
   dirty |= DIRTY_OVERLAY_LINES;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::add_edges(const Eigen::MatrixXd& P1, const Eigen::MatrixXd& P2, const Eigen::MatrixXd& C)
+IGL_INLINE void igl::ViewerData::add_edges(const Eigen::MatrixXd& P1, const Eigen::MatrixXd& P2, const Eigen::MatrixXd& C)
 {
   Eigen::MatrixXd P1_temp,P2_temp;
 
@@ -291,7 +305,7 @@ IGL_INLINE void igl::viewer::ViewerData::add_edges(const Eigen::MatrixXd& P1, co
   dirty |= DIRTY_OVERLAY_LINES;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::add_label(const Eigen::VectorXd& P,  const std::string& str)
+IGL_INLINE void igl::ViewerData::add_label(const Eigen::VectorXd& P,  const std::string& str)
 {
   Eigen::RowVectorXd P_temp;
 
@@ -310,7 +324,7 @@ IGL_INLINE void igl::viewer::ViewerData::add_label(const Eigen::VectorXd& P,  co
   labels_strings.push_back(str);
 }
 
-IGL_INLINE void igl::viewer::ViewerData::clear()
+IGL_INLINE void igl::ViewerData::clear()
 {
   V                       = Eigen::MatrixXd (0,3);
   F                       = Eigen::MatrixXi (0,3);
@@ -337,14 +351,17 @@ IGL_INLINE void igl::viewer::ViewerData::clear()
   face_based = false;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::compute_normals()
+IGL_INLINE void igl::ViewerData::compute_normals()
 {
   igl::per_face_normals(V, F, F_normals);
   igl::per_vertex_normals(V, F, F_normals, V_normals);
   dirty |= DIRTY_NORMAL;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::uniform_colors(const Eigen::Vector3d& ambient, const Eigen::Vector3d& diffuse, const Eigen::Vector3d& specular)
+IGL_INLINE void igl::ViewerData::uniform_colors(
+  const Eigen::Vector3d& ambient, 
+  const Eigen::Vector3d& diffuse, 
+  const Eigen::Vector3d& specular)
 {
   Eigen::Vector4d ambient4;
   Eigen::Vector4d diffuse4;
@@ -357,7 +374,10 @@ IGL_INLINE void igl::viewer::ViewerData::uniform_colors(const Eigen::Vector3d& a
   uniform_colors(ambient4,diffuse4,specular4);
 }
 
-IGL_INLINE void igl::viewer::ViewerData::uniform_colors(const Eigen::Vector4d& ambient, const Eigen::Vector4d& diffuse, const Eigen::Vector4d& specular)
+IGL_INLINE void igl::ViewerData::uniform_colors(
+  const Eigen::Vector4d& ambient, 
+  const Eigen::Vector4d& diffuse, 
+  const Eigen::Vector4d& specular)
 {
   V_material_ambient.resize(V.rows(),4);
   V_material_diffuse.resize(V.rows(),4);
@@ -383,7 +403,7 @@ IGL_INLINE void igl::viewer::ViewerData::uniform_colors(const Eigen::Vector4d& a
   dirty |= DIRTY_SPECULAR | DIRTY_DIFFUSE | DIRTY_AMBIENT;
 }
 
-IGL_INLINE void igl::viewer::ViewerData::grid_texture()
+IGL_INLINE void igl::ViewerData::grid_texture()
 {
   // Don't do anything for an empty mesh
   if(V.rows() == 0)

+ 21 - 63
include/igl/viewer/ViewerData.h → include/igl/ViewerData.h

@@ -5,20 +5,19 @@
 // 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/.
-#ifndef IGL_VIEWER_VIEWER_DATA_H
-#define IGL_VIEWER_VIEWER_DATA_H
+#ifndef IGL_VIEWERDATA_H
+#define IGL_VIEWERDATA_H
 
 #include <cstdint>
 #include <vector>
-
 #include <Eigen/Core>
-
 #include <igl/igl_inline.h>
 
+// Alec: This is a mesh class containing a variety of data types (normals,
+// overlays, material colors, etc.)
+//
 namespace igl
 {
-namespace viewer
-{
 
 // TODO: write documentation
 
@@ -186,66 +185,25 @@ public:
 
   // Enable per-face or per-vertex properties
   bool face_based;
-  /*********************************/
-};
 
-}
-}
+  // Visualization options
+  bool show_overlay;
+  bool show_overlay_depth;
+  bool show_texture;
+  bool show_faces;
+  bool show_lines;
+  bool show_vertid;
+  bool show_faceid;
+  bool invert_normals;
+  // Point size / line width
+  float point_size;
+  float line_width;
+  Eigen::Vector4f line_color;
+  // Shape material
+  float shininess;
+};
 
-#ifdef ENABLE_SERIALIZATION
-#include <igl/serialize.h>
-namespace igl {
-	namespace serialization {
-
-		inline void serialization(bool s, igl::viewer::ViewerData& obj, std::vector<char>& buffer)
-		{
-			SERIALIZE_MEMBER(V);
-			SERIALIZE_MEMBER(F);
-
-			SERIALIZE_MEMBER(F_normals);
-			SERIALIZE_MEMBER(F_material_ambient);
-			SERIALIZE_MEMBER(F_material_diffuse);
-			SERIALIZE_MEMBER(F_material_specular);
-
-			SERIALIZE_MEMBER(V_normals);
-			SERIALIZE_MEMBER(V_material_ambient);
-			SERIALIZE_MEMBER(V_material_diffuse);
-			SERIALIZE_MEMBER(V_material_specular);
-
-			SERIALIZE_MEMBER(V_uv);
-			SERIALIZE_MEMBER(F_uv);
-
-			SERIALIZE_MEMBER(texture_R);
-			SERIALIZE_MEMBER(texture_G);
-			SERIALIZE_MEMBER(texture_B);
-      SERIALIZE_MEMBER(texture_A);
-
-			SERIALIZE_MEMBER(lines);
-			SERIALIZE_MEMBER(points);
-
-			SERIALIZE_MEMBER(labels_positions);
-			SERIALIZE_MEMBER(labels_strings);
-
-			SERIALIZE_MEMBER(dirty);
-
-			SERIALIZE_MEMBER(face_based);
-		}
-
-		template<>
-		inline void serialize(const igl::viewer::ViewerData& obj, std::vector<char>& buffer)
-		{
-			serialization(true, const_cast<igl::viewer::ViewerData&>(obj), buffer);
-		}
-
-		template<>
-		inline void deserialize(igl::viewer::ViewerData& obj, const std::vector<char>& buffer)
-		{
-			serialization(false, obj, const_cast<std::vector<char>&>(buffer));
-			obj.dirty = igl::viewer::ViewerData::DIRTY_ALL;
-		}
-	}
 }
-#endif
 
 #ifndef IGL_STATIC_LIBRARY
 #  include "ViewerData.cpp"

+ 133 - 94
include/igl/viewer/OpenGL_state.cpp → include/igl/opengl/State.cpp

@@ -6,10 +6,13 @@
 // 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 "OpenGL_state.h"
-#include "ViewerData.h"
+#include "State.h"
+#include "bind_vertex_attrib_array.h"
+#include "../ViewerData.h"
+#include "create_shader_program.h"
+#include "destroy_shader_program.h"
 
-IGL_INLINE void igl::viewer::OpenGL_state::init_buffers()
+IGL_INLINE void igl::opengl::State::init_buffers()
 {
   // Mesh: Vertex Array Object & Buffer objects
   glGenVertexArrays(1, &vao_mesh);
@@ -40,7 +43,7 @@ IGL_INLINE void igl::viewer::OpenGL_state::init_buffers()
   dirty = ViewerData::DIRTY_ALL;
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::free_buffers()
+IGL_INLINE void igl::opengl::State::free_buffers()
 {
   glDeleteVertexArrays(1, &vao_mesh);
   glDeleteVertexArrays(1, &vao_overlay_lines);
@@ -63,54 +66,82 @@ IGL_INLINE void igl::viewer::OpenGL_state::free_buffers()
   glDeleteTextures(1, &vbo_tex);
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerData &data, bool invert_normals)
+IGL_INLINE void igl::opengl::State::set_data(
+  const igl::ViewerData &data, 
+  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;
 
+  // Input:
+  //   X  #F by dim quantity
+  // Output:
+  //   X_vbo  #F*3 by dim scattering per corner
+  const auto per_face = [&data](
+      const Eigen::MatrixXd & X,
+      RowMatrixXf & X_vbo)
+  {
+    X_vbo.resize(data.F.rows()*3,3);
+    for (unsigned i=0; i<data.F.rows();++i)
+      for (unsigned j=0;j<3;++j)
+        X_vbo.row(i*3+j) = X.row(i).cast<float>().head(3);
+  };
+
+  // Input:
+  //   X  #V by dim quantity
+  // Output:
+  //   X_vbo  #F*3 by dim scattering per corner
+  const auto per_corner = [&data](
+      const Eigen::MatrixXd & X,
+      RowMatrixXf & X_vbo)
+  {
+    X_vbo.resize(data.F.rows()*3,3);
+    for (unsigned i=0; i<data.F.rows();++i)
+      for (unsigned j=0;j<3;++j)
+        X_vbo.row(i*3+j) = X.row(data.F(i,j)).cast<float>();
+  };
+
   if (!data.face_based)
   {
     if (!(per_corner_uv || per_corner_normals))
     {
       // Vertex positions
       if (dirty & ViewerData::DIRTY_POSITION)
-        V_vbo = (data.V.transpose()).cast<float>();
+        V_vbo = data.V.cast<float>();
 
       // Vertex normals
       if (dirty & ViewerData::DIRTY_NORMAL)
       {
-        V_normals_vbo = (data.V_normals.transpose()).cast<float>();
+        V_normals_vbo = data.V_normals.cast<float>();
         if (invert_normals)
           V_normals_vbo = -V_normals_vbo;
       }
 
       // Per-vertex material settings
       if (dirty & ViewerData::DIRTY_AMBIENT)
-        V_ambient_vbo = (data.V_material_ambient.transpose()).cast<float>();
+        V_ambient_vbo = data.V_material_ambient.cast<float>();
       if (dirty & ViewerData::DIRTY_DIFFUSE)
-        V_diffuse_vbo = (data.V_material_diffuse.transpose()).cast<float>();
+        V_diffuse_vbo = data.V_material_diffuse.cast<float>();
       if (dirty & ViewerData::DIRTY_SPECULAR)
-        V_specular_vbo = (data.V_material_specular.transpose()).cast<float>();
+        V_specular_vbo = data.V_material_specular.cast<float>();
 
       // Face indices
       if (dirty & ViewerData::DIRTY_FACE)
-        F_vbo = (data.F.transpose()).cast<unsigned>();
+        F_vbo = data.F.cast<unsigned>();
 
       // Texture coordinates
       if (dirty & ViewerData::DIRTY_UV)
-        V_uv_vbo = (data.V_uv.transpose()).cast<float>();
+        V_uv_vbo = data.V_uv.cast<float>();
     }
     else
     {
+
       // Per vertex properties with per corner UVs
       if (dirty & ViewerData::DIRTY_POSITION)
       {
-        V_vbo.resize(3,data.F.rows()*3);
-        for (unsigned i=0; i<data.F.rows();++i)
-          for (unsigned j=0;j<3;++j)
-            V_vbo.col(i*3+j) = data.V.row(data.F(i,j)).transpose().cast<float>();
+        per_corner(data.V,V_vbo);
       }
 
       if (dirty & ViewerData::DIRTY_AMBIENT)
@@ -120,7 +151,6 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
           for (unsigned j=0;j<3;++j)
             V_ambient_vbo.col (i*3+j) = data.V_material_ambient.row(data.F(i,j)).transpose().cast<float>();
       }
-
       if (dirty & ViewerData::DIRTY_DIFFUSE)
       {
         V_diffuse_vbo.resize(4,data.F.rows()*3);
@@ -128,7 +158,6 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
           for (unsigned j=0;j<3;++j)
             V_diffuse_vbo.col (i*3+j) = data.V_material_diffuse.row(data.F(i,j)).transpose().cast<float>();
       }
-
       if (dirty & ViewerData::DIRTY_SPECULAR)
       {
         V_specular_vbo.resize(4,data.F.rows()*3);
@@ -155,17 +184,19 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
 
       if (dirty & ViewerData::DIRTY_FACE)
       {
-        F_vbo.resize(3,data.F.rows());
+        F_vbo.resize(data.F.rows(),3);
         for (unsigned i=0; i<data.F.rows();++i)
-          F_vbo.col(i) << i*3+0, i*3+1, i*3+2;
+          F_vbo.row(i) << i*3+0, i*3+1, i*3+2;
       }
 
       if (dirty & ViewerData::DIRTY_UV)
       {
-        V_uv_vbo.resize(2,data.F.rows()*3);
+        V_uv_vbo.resize(data.F.rows()*3,2);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            V_uv_vbo.col(i*3+j) = data.V_uv.row(per_corner_uv ? data.F_uv(i,j) : data.F(i,j)).transpose().cast<float>();
+            V_uv_vbo.row(i*3+j) = 
+              data.V_uv.row(per_corner_uv ? 
+                data.F_uv(i,j) : data.F(i,j)).cast<float>();
       }
     }
   }
@@ -173,45 +204,31 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
   {
     if (dirty & ViewerData::DIRTY_POSITION)
     {
-      V_vbo.resize(3,data.F.rows()*3);
-      for (unsigned i=0; i<data.F.rows();++i)
-        for (unsigned j=0;j<3;++j)
-          V_vbo.col(i*3+j) = data.V.row(data.F(i,j)).transpose().cast<float>();
+      per_corner(data.V,V_vbo);
     }
 
     if (dirty & ViewerData::DIRTY_AMBIENT)
     {
-      V_ambient_vbo.resize(4,data.F.rows()*3);
-      for (unsigned i=0; i<data.F.rows();++i)
-        for (unsigned j=0;j<3;++j)
-          V_ambient_vbo.col (i*3+j) = data.F_material_ambient.row(i).transpose().cast<float>();
+      per_face(data.F_material_ambient,V_ambient_vbo);
     }
-
     if (dirty & ViewerData::DIRTY_DIFFUSE)
     {
-      V_diffuse_vbo.resize(4,data.F.rows()*3);
-      for (unsigned i=0; i<data.F.rows();++i)
-        for (unsigned j=0;j<3;++j)
-          V_diffuse_vbo.col (i*3+j) = data.F_material_diffuse.row(i).transpose().cast<float>();
+      per_face(data.F_material_diffuse,V_diffuse_vbo);
     }
-
     if (dirty & ViewerData::DIRTY_SPECULAR)
     {
-      V_specular_vbo.resize(4,data.F.rows()*3);
-      for (unsigned i=0; i<data.F.rows();++i)
-        for (unsigned j=0;j<3;++j)
-          V_specular_vbo.col(i*3+j) = data.F_material_specular.row(i).transpose().cast<float>();
+      per_face(data.F_material_specular,V_specular_vbo);
     }
 
     if (dirty & ViewerData::DIRTY_NORMAL)
     {
-      V_normals_vbo.resize(3,data.F.rows()*3);
+      V_normals_vbo.resize(data.F.rows()*3,3);
       for (unsigned i=0; i<data.F.rows();++i)
         for (unsigned j=0;j<3;++j)
-          V_normals_vbo.col (i*3+j) =
+          V_normals_vbo.row(i*3+j) =
              per_corner_normals ?
-               data.F_normals.row(i*3+j).transpose().cast<float>() :
-               data.F_normals.row(i).transpose().cast<float>();
+               data.F_normals.row(i*3+j).cast<float>() :
+               data.F_normals.row(i).cast<float>();
 
       if (invert_normals)
         V_normals_vbo = -V_normals_vbo;
@@ -219,17 +236,17 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
 
     if (dirty & ViewerData::DIRTY_FACE)
     {
-      F_vbo.resize(3,data.F.rows());
+      F_vbo.resize(data.F.rows(),3);
       for (unsigned i=0; i<data.F.rows();++i)
-        F_vbo.col(i) << i*3+0, i*3+1, i*3+2;
+        F_vbo.row(i) << i*3+0, i*3+1, i*3+2;
     }
 
     if (dirty & ViewerData::DIRTY_UV)
     {
-        V_uv_vbo.resize(2,data.F.rows()*3);
+        V_uv_vbo.resize(data.F.rows()*3,2);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            V_uv_vbo.col(i*3+j) = data.V_uv.row(per_corner_uv ? data.F_uv(i,j) : data.F(i,j)).transpose().cast<float>();
+            V_uv_vbo.row(i*3+j) = data.V_uv.row(per_corner_uv ? data.F_uv(i,j) : data.F(i,j)).cast<float>();
     }
   }
 
@@ -249,15 +266,15 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
 
   if (dirty & ViewerData::DIRTY_OVERLAY_LINES)
   {
-    lines_V_vbo.resize(3, data.lines.rows()*2);
-    lines_V_colors_vbo.resize(3, data.lines.rows()*2);
-    lines_F_vbo.resize(1, data.lines.rows()*2);
+    lines_V_vbo.resize(data.lines.rows()*2,3);
+    lines_V_colors_vbo.resize(data.lines.rows()*2,3);
+    lines_F_vbo.resize(data.lines.rows()*2,1);
     for (unsigned i=0; i<data.lines.rows();++i)
     {
-      lines_V_vbo.col(2*i+0) = data.lines.block<1, 3>(i, 0).transpose().cast<float>();
-      lines_V_vbo.col(2*i+1) = data.lines.block<1, 3>(i, 3).transpose().cast<float>();
-      lines_V_colors_vbo.col(2*i+0) = data.lines.block<1, 3>(i, 6).transpose().cast<float>();
-      lines_V_colors_vbo.col(2*i+1) = data.lines.block<1, 3>(i, 6).transpose().cast<float>();
+      lines_V_vbo.row(2*i+0) = data.lines.block<1, 3>(i, 0).cast<float>();
+      lines_V_vbo.row(2*i+1) = data.lines.block<1, 3>(i, 3).cast<float>();
+      lines_V_colors_vbo.row(2*i+0) = data.lines.block<1, 3>(i, 6).cast<float>();
+      lines_V_colors_vbo.row(2*i+1) = data.lines.block<1, 3>(i, 6).cast<float>();
       lines_F_vbo(2*i+0) = 2*i+0;
       lines_F_vbo(2*i+1) = 2*i+1;
     }
@@ -265,28 +282,28 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
 
   if (dirty & ViewerData::DIRTY_OVERLAY_POINTS)
   {
-    points_V_vbo.resize(3, data.points.rows());
-    points_V_colors_vbo.resize(3, data.points.rows());
-    points_F_vbo.resize(1, data.points.rows());
+    points_V_vbo.resize(data.points.rows(),3);
+    points_V_colors_vbo.resize(data.points.rows(),3);
+    points_F_vbo.resize(data.points.rows(),1);
     for (unsigned i=0; i<data.points.rows();++i)
     {
-      points_V_vbo.col(i) = data.points.block<1, 3>(i, 0).transpose().cast<float>();
-      points_V_colors_vbo.col(i) = data.points.block<1, 3>(i, 3).transpose().cast<float>();
+      points_V_vbo.row(i) = data.points.block<1, 3>(i, 0).cast<float>();
+      points_V_colors_vbo.row(i) = data.points.block<1, 3>(i, 3).cast<float>();
       points_F_vbo(i) = i;
     }
   }
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::bind_mesh()
+IGL_INLINE void igl::opengl::State::bind_mesh()
 {
   glBindVertexArray(vao_mesh);
-  shader_mesh.bind();
-  shader_mesh.bindVertexAttribArray("position", vbo_V, V_vbo, dirty & ViewerData::DIRTY_POSITION);
-  shader_mesh.bindVertexAttribArray("normal", vbo_V_normals, V_normals_vbo, dirty & ViewerData::DIRTY_NORMAL);
-  shader_mesh.bindVertexAttribArray("Ka", vbo_V_ambient, V_ambient_vbo, dirty & ViewerData::DIRTY_AMBIENT);
-  shader_mesh.bindVertexAttribArray("Kd", vbo_V_diffuse, V_diffuse_vbo, dirty & ViewerData::DIRTY_DIFFUSE);
-  shader_mesh.bindVertexAttribArray("Ks", vbo_V_specular, V_specular_vbo, dirty & ViewerData::DIRTY_SPECULAR);
-  shader_mesh.bindVertexAttribArray("texcoord", vbo_V_uv, V_uv_vbo, dirty & ViewerData::DIRTY_UV);
+  glUseProgram(shader_mesh);
+  bind_vertex_attrib_array(shader_mesh,"position", vbo_V, V_vbo, dirty & ViewerData::DIRTY_POSITION);
+  bind_vertex_attrib_array(shader_mesh,"normal", vbo_V_normals, V_normals_vbo, dirty & ViewerData::DIRTY_NORMAL);
+  bind_vertex_attrib_array(shader_mesh,"Ka", vbo_V_ambient, V_ambient_vbo, dirty & ViewerData::DIRTY_AMBIENT);
+  bind_vertex_attrib_array(shader_mesh,"Kd", vbo_V_diffuse, V_diffuse_vbo, dirty & ViewerData::DIRTY_DIFFUSE);
+  bind_vertex_attrib_array(shader_mesh,"Ks", vbo_V_specular, V_specular_vbo, dirty & ViewerData::DIRTY_SPECULAR);
+  bind_vertex_attrib_array(shader_mesh,"texcoord", vbo_V_uv, V_uv_vbo, dirty & ViewerData::DIRTY_UV);
 
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_F);
   if (dirty & ViewerData::DIRTY_FACE)
@@ -303,18 +320,18 @@ IGL_INLINE void igl::viewer::OpenGL_state::bind_mesh()
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_u, tex_v, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.data());
   }
-  glUniform1i(shader_mesh.uniform("tex"), 0);
+  glUniform1i(glGetUniformLocation(shader_mesh,"tex"), 0);
   dirty &= ~ViewerData::DIRTY_MESH;
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::bind_overlay_lines()
+IGL_INLINE void igl::opengl::State::bind_overlay_lines()
 {
   bool is_dirty = dirty & ViewerData::DIRTY_OVERLAY_LINES;
 
   glBindVertexArray(vao_overlay_lines);
-  shader_overlay_lines.bind();
-  shader_overlay_lines.bindVertexAttribArray("position", vbo_lines_V, lines_V_vbo, is_dirty);
-  shader_overlay_lines.bindVertexAttribArray("color", vbo_lines_V_colors, lines_V_colors_vbo, is_dirty);
+  glUseProgram(shader_overlay_lines);
+ bind_vertex_attrib_array(shader_overlay_lines,"position", vbo_lines_V, lines_V_vbo, is_dirty);
+ bind_vertex_attrib_array(shader_overlay_lines,"color", vbo_lines_V_colors, lines_V_colors_vbo, is_dirty);
 
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_lines_F);
   if (is_dirty)
@@ -323,14 +340,14 @@ IGL_INLINE void igl::viewer::OpenGL_state::bind_overlay_lines()
   dirty &= ~ViewerData::DIRTY_OVERLAY_LINES;
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::bind_overlay_points()
+IGL_INLINE void igl::opengl::State::bind_overlay_points()
 {
   bool is_dirty = dirty & ViewerData::DIRTY_OVERLAY_POINTS;
 
   glBindVertexArray(vao_overlay_points);
-  shader_overlay_points.bind();
-  shader_overlay_points.bindVertexAttribArray("position", vbo_points_V, points_V_vbo, is_dirty);
-  shader_overlay_points.bindVertexAttribArray("color", vbo_points_V_colors, points_V_colors_vbo, is_dirty);
+  glUseProgram(shader_overlay_points);
+ bind_vertex_attrib_array(shader_overlay_points,"position", vbo_points_V, points_V_vbo, is_dirty);
+ bind_vertex_attrib_array(shader_overlay_points,"color", vbo_points_V_colors, points_V_colors_vbo, is_dirty);
 
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_points_F);
   if (is_dirty)
@@ -339,7 +356,7 @@ IGL_INLINE void igl::viewer::OpenGL_state::bind_overlay_points()
   dirty &= ~ViewerData::DIRTY_OVERLAY_POINTS;
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::draw_mesh(bool solid)
+IGL_INLINE void igl::opengl::State::draw_mesh(bool solid)
 {
   glPolygonMode(GL_FRONT_AND_BACK, solid ? GL_FILL : GL_LINE);
 
@@ -349,24 +366,29 @@ IGL_INLINE void igl::viewer::OpenGL_state::draw_mesh(bool solid)
     glEnable(GL_POLYGON_OFFSET_FILL);
     glPolygonOffset(1.0, 1.0);
   }
-  glDrawElements(GL_TRIANGLES, 3*F_vbo.cols(), GL_UNSIGNED_INT, 0);
+  glDrawElements(GL_TRIANGLES, 3*F_vbo.rows(), GL_UNSIGNED_INT, 0);
 
   glDisable(GL_POLYGON_OFFSET_FILL);
   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::draw_overlay_lines()
+IGL_INLINE void igl::opengl::State::draw_overlay_lines()
 {
-  glDrawElements(GL_LINES, lines_F_vbo.cols(), GL_UNSIGNED_INT, 0);
+  glDrawElements(GL_LINES, lines_F_vbo.rows(), GL_UNSIGNED_INT, 0);
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::draw_overlay_points()
+IGL_INLINE void igl::opengl::State::draw_overlay_points()
 {
-  glDrawElements(GL_POINTS, points_F_vbo.cols(), GL_UNSIGNED_INT, 0);
+  glDrawElements(GL_POINTS, points_F_vbo.rows(), GL_UNSIGNED_INT, 0);
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::init()
+IGL_INLINE void igl::opengl::State::init()
 {
+  if(is_initialized)
+  {
+    return;
+  }
+  is_initialized = true;
   std::string mesh_vertex_shader_string =
   "#version 150\n"
   "uniform mat4 model;"
@@ -476,18 +498,35 @@ IGL_INLINE void igl::viewer::OpenGL_state::init()
   "}";
 
   init_buffers();
-  shader_mesh.init(mesh_vertex_shader_string,
-      mesh_fragment_shader_string, "outColor");
-  shader_overlay_lines.init(overlay_vertex_shader_string,
-      overlay_fragment_shader_string, "outColor");
-  shader_overlay_points.init(overlay_vertex_shader_string,
-      overlay_point_fragment_shader_string, "outColor");
+  create_shader_program(
+    mesh_vertex_shader_string,
+    mesh_fragment_shader_string,
+    {},
+    shader_mesh);
+  create_shader_program(
+    overlay_vertex_shader_string,
+    overlay_fragment_shader_string,
+    {},
+    shader_overlay_lines);
+  create_shader_program(
+    overlay_vertex_shader_string,
+    overlay_point_fragment_shader_string,
+    {},
+    shader_overlay_points);
 }
 
-IGL_INLINE void igl::viewer::OpenGL_state::free()
+IGL_INLINE void igl::opengl::State::free()
 {
-  shader_mesh.free();
-  shader_overlay_lines.free();
-  shader_overlay_points.free();
+  const auto free = [](GLuint & id)
+  {
+    if(id)
+    {
+      destroy_shader_program(id);
+      id = 0;
+    }
+  };
+  free(shader_mesh);
+  free(shader_overlay_lines);
+  free(shader_overlay_points);
   free_buffers();
 }

+ 32 - 26
include/igl/viewer/OpenGL_state.h → include/igl/opengl/State.h

@@ -5,32 +5,37 @@
 // 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/.
-#ifndef IGL_VIEWER_OPENGL_STATE_H
-#define IGL_VIEWER_OPENGL_STATE_H
+#ifndef IGL_OPENGL_STATE_H
+#define IGL_OPENGL_STATE_H
 
-// Coverts mesh data inside a igl::viewer::ViewerData class in an OpenGL compatible format
-// The class includes a shader and the opengl calls to plot the data
+// Coverts mesh data inside a igl::ViewerData class in an OpenGL
+// compatible format The class includes a shader and the opengl calls to plot
+// the data
+
+// Alec: not sure why this is call "State". It seems this is a drawable mesh
+// equipt with its own shaders and dirty flags. "Mesh" would even be more
+// appropriate.
 
 #include <igl/igl_inline.h>
-#include <igl/viewer/OpenGL_shader.h>
-#include <igl/viewer/ViewerData.h>
+#include "../ViewerData.h"
 
 namespace igl
 {
-namespace viewer
+namespace opengl
 {
 
-class OpenGL_state
+class State
 {
 public:
   typedef unsigned int GLuint;
 
+  bool is_initialized = false;
   GLuint vao_mesh;
   GLuint vao_overlay_lines;
   GLuint vao_overlay_points;
-  OpenGL_shader shader_mesh;
-  OpenGL_shader shader_overlay_lines;
-  OpenGL_shader shader_overlay_points;
+  GLuint shader_mesh;
+  GLuint shader_overlay_lines;
+  GLuint shader_overlay_points;
 
   GLuint vbo_V; // Vertices of the current mesh (#V x 3)
   GLuint vbo_V_uv; // UV coordinates for the current mesh (#V x 2)
@@ -50,24 +55,25 @@ public:
   GLuint vbo_points_V_colors; // Color values of the point overlay
 
   // Temporary copy of the content of each VBO
-  Eigen::MatrixXf V_vbo;
-  Eigen::MatrixXf V_normals_vbo;
-  Eigen::MatrixXf V_ambient_vbo;
-  Eigen::MatrixXf V_diffuse_vbo;
-  Eigen::MatrixXf V_specular_vbo;
-  Eigen::MatrixXf V_uv_vbo;
-  Eigen::MatrixXf lines_V_vbo;
-  Eigen::MatrixXf lines_V_colors_vbo;
-  Eigen::MatrixXf points_V_vbo;
-  Eigen::MatrixXf points_V_colors_vbo;
+  typedef Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> RowMatrixXf;
+  RowMatrixXf V_vbo;
+  RowMatrixXf V_normals_vbo;
+  RowMatrixXf V_ambient_vbo;
+  RowMatrixXf V_diffuse_vbo;
+  RowMatrixXf V_specular_vbo;
+  RowMatrixXf V_uv_vbo;
+  RowMatrixXf lines_V_vbo;
+  RowMatrixXf lines_V_colors_vbo;
+  RowMatrixXf points_V_vbo;
+  RowMatrixXf points_V_colors_vbo;
 
   int tex_u;
   int tex_v;
   Eigen::Matrix<char,Eigen::Dynamic,1> tex;
 
-  Eigen::Matrix<unsigned, Eigen::Dynamic, Eigen::Dynamic> F_vbo;
-  Eigen::Matrix<unsigned, Eigen::Dynamic, Eigen::Dynamic> lines_F_vbo;
-  Eigen::Matrix<unsigned, Eigen::Dynamic, Eigen::Dynamic> points_F_vbo;
+  Eigen::Matrix<unsigned, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> F_vbo;
+  Eigen::Matrix<unsigned, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> lines_F_vbo;
+  Eigen::Matrix<unsigned, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> points_F_vbo;
 
   // Marks dirty buffers that need to be uploaded to OpenGL
   uint32_t dirty;
@@ -82,7 +88,7 @@ public:
   IGL_INLINE void init_buffers();
 
   // Update contents from a 'Data' instance
-  IGL_INLINE void set_data(const igl::viewer::ViewerData &data, bool invert_normals);
+  IGL_INLINE void set_data(const igl::ViewerData &data, bool invert_normals);
 
   // Bind the underlying OpenGL buffer objects for subsequent mesh draw calls
   IGL_INLINE void bind_mesh();
@@ -111,7 +117,7 @@ public:
 }
 
 #ifndef IGL_STATIC_LIBRARY
-#  include "OpenGL_state.cpp"
+#  include "State.cpp"
 #endif
 
 #endif

+ 53 - 66
include/igl/viewer/ViewerCore.cpp → include/igl/opengl/ViewerCore.cpp

@@ -7,18 +7,19 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 
 #include "ViewerCore.h"
-#include <igl/quat_to_mat.h>
-#include <igl/snap_to_fixed_up.h>
-#include <igl/look_at.h>
-#include <igl/frustum.h>
-#include <igl/ortho.h>
-#include <igl/massmatrix.h>
-#include <igl/barycenter.h>
-#include <igl/PI.h>
+#include "gl.h"
+#include "../quat_to_mat.h"
+#include "../snap_to_fixed_up.h"
+#include "../look_at.h"
+#include "../frustum.h"
+#include "../ortho.h"
+#include "../massmatrix.h"
+#include "../barycenter.h"
+#include "../PI.h"
 #include <Eigen/Geometry>
 #include <iostream>
 
-IGL_INLINE void igl::viewer::ViewerCore::align_camera_center(
+IGL_INLINE void igl::opengl::ViewerCore::align_camera_center(
   const Eigen::MatrixXd& V,
   const Eigen::MatrixXi& F)
 {
@@ -33,7 +34,7 @@ IGL_INLINE void igl::viewer::ViewerCore::align_camera_center(
   }
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::get_scale_and_shift_to_fit_mesh(
+IGL_INLINE void igl::opengl::ViewerCore::get_scale_and_shift_to_fit_mesh(
   const Eigen::MatrixXd& V,
   const Eigen::MatrixXi& F,
   float& zoom,
@@ -53,7 +54,7 @@ IGL_INLINE void igl::viewer::ViewerCore::get_scale_and_shift_to_fit_mesh(
   return get_scale_and_shift_to_fit_mesh(BC,zoom,shift);
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::align_camera_center(
+IGL_INLINE void igl::opengl::ViewerCore::align_camera_center(
   const Eigen::MatrixXd& V)
 {
   if(V.rows() == 0)
@@ -67,7 +68,7 @@ IGL_INLINE void igl::viewer::ViewerCore::align_camera_center(
   }
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::get_scale_and_shift_to_fit_mesh(
+IGL_INLINE void igl::opengl::ViewerCore::get_scale_and_shift_to_fit_mesh(
   const Eigen::MatrixXd& V,
   float& zoom,
   Eigen::Vector3f& shift)
@@ -84,7 +85,7 @@ IGL_INLINE void igl::viewer::ViewerCore::get_scale_and_shift_to_fit_mesh(
 }
 
 
-IGL_INLINE void igl::viewer::ViewerCore::clear_framebuffers()
+IGL_INLINE void igl::opengl::ViewerCore::clear_framebuffers()
 {
   glClearColor(background_color[0],
                background_color[1],
@@ -93,9 +94,9 @@ IGL_INLINE void igl::viewer::ViewerCore::clear_framebuffers()
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::draw(
+IGL_INLINE void igl::opengl::ViewerCore::draw(
   ViewerData& data,
-  OpenGL_state& opengl,
+  State& opengl,
   bool update_matrices)
 {
   using namespace std;
@@ -112,7 +113,7 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
   /* Bind and potentially refresh mesh/line/point data */
   if (data.dirty)
   {
-    opengl.set_data(data, invert_normals);
+    opengl.set_data(data, data.invert_normals);
     data.dirty = ViewerData::DIRTY_NONE;
   }
   opengl.bind_mesh();
@@ -162,21 +163,21 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
   }
 
   // Send transformations to the GPU
-  GLint modeli = opengl.shader_mesh.uniform("model");
-  GLint viewi  = opengl.shader_mesh.uniform("view");
-  GLint proji  = opengl.shader_mesh.uniform("proj");
+  GLint modeli = glGetUniformLocation(opengl.shader_mesh,"model");
+  GLint viewi  = glGetUniformLocation(opengl.shader_mesh,"view");
+  GLint proji  = glGetUniformLocation(opengl.shader_mesh,"proj");
   glUniformMatrix4fv(modeli, 1, GL_FALSE, model.data());
   glUniformMatrix4fv(viewi, 1, GL_FALSE, view.data());
   glUniformMatrix4fv(proji, 1, GL_FALSE, proj.data());
 
   // Light parameters
-  GLint specular_exponenti    = opengl.shader_mesh.uniform("specular_exponent");
-  GLint light_position_worldi = opengl.shader_mesh.uniform("light_position_world");
-  GLint lighting_factori      = opengl.shader_mesh.uniform("lighting_factor");
-  GLint fixed_colori          = opengl.shader_mesh.uniform("fixed_color");
-  GLint texture_factori       = opengl.shader_mesh.uniform("texture_factor");
+  GLint specular_exponenti    = glGetUniformLocation(opengl.shader_mesh,"specular_exponent");
+  GLint light_position_worldi = glGetUniformLocation(opengl.shader_mesh,"light_position_world");
+  GLint lighting_factori      = glGetUniformLocation(opengl.shader_mesh,"lighting_factor");
+  GLint fixed_colori          = glGetUniformLocation(opengl.shader_mesh,"fixed_color");
+  GLint texture_factori       = glGetUniformLocation(opengl.shader_mesh,"texture_factor");
 
-  glUniform1f(specular_exponenti, shininess);
+  glUniform1f(specular_exponenti, data.shininess);
   Vector3f rev_light = -1.*light_position;
   glUniform3fv(light_position_worldi, 1, rev_light.data());
   glUniform1f(lighting_factori, lighting_factor); // enables lighting
@@ -185,26 +186,28 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
   if (data.V.rows()>0)
   {
     // Render fill
-    if (show_faces)
+    if (data.show_faces)
     {
       // Texture
-      glUniform1f(texture_factori, show_texture ? 1.0f : 0.0f);
+      glUniform1f(texture_factori, data.show_texture ? 1.0f : 0.0f);
       opengl.draw_mesh(true);
       glUniform1f(texture_factori, 0.0f);
     }
 
     // Render wireframe
-    if (show_lines)
+    if (data.show_lines)
     {
-      glLineWidth(line_width);
-      glUniform4f(fixed_colori, line_color[0], line_color[1],
-        line_color[2], 1.0f);
+      glLineWidth(data.line_width);
+      glUniform4f(fixed_colori, 
+        data.line_color[0], 
+        data.line_color[1],
+        data.line_color[2], 1.0f);
       opengl.draw_mesh(false);
       glUniform4f(fixed_colori, 0.0f, 0.0f, 0.0f, 0.0f);
     }
 
 #ifdef IGL_VIEWER_WITH_NANOGUI
-    if (show_vertid)
+    if (data.show_vertid)
     {
       textrenderer.BeginDraw(view*model, proj, viewport, object_scale);
       for (int i=0; i<data.V.rows(); ++i)
@@ -212,7 +215,7 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
       textrenderer.EndDraw();
     }
 
-    if (show_faceid)
+    if (data.show_faceid)
     {
       textrenderer.BeginDraw(view*model, proj, viewport, object_scale);
 
@@ -230,9 +233,9 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
 #endif
   }
 
-  if (show_overlay)
+  if (data.show_overlay)
   {
-    if (show_overlay_depth)
+    if (data.show_overlay_depth)
       glEnable(GL_DEPTH_TEST);
     else
       glDisable(GL_DEPTH_TEST);
@@ -240,16 +243,16 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
     if (data.lines.rows() > 0)
     {
       opengl.bind_overlay_lines();
-      modeli = opengl.shader_overlay_lines.uniform("model");
-      viewi  = opengl.shader_overlay_lines.uniform("view");
-      proji  = opengl.shader_overlay_lines.uniform("proj");
+      modeli = glGetUniformLocation(opengl.shader_overlay_lines,"model");
+      viewi  = glGetUniformLocation(opengl.shader_overlay_lines,"view");
+      proji  = glGetUniformLocation(opengl.shader_overlay_lines,"proj");
 
       glUniformMatrix4fv(modeli, 1, GL_FALSE, model.data());
       glUniformMatrix4fv(viewi, 1, GL_FALSE, view.data());
       glUniformMatrix4fv(proji, 1, GL_FALSE, proj.data());
       // This must be enabled, otherwise glLineWidth has no effect
       glEnable(GL_LINE_SMOOTH);
-      glLineWidth(line_width);
+      glLineWidth(data.line_width);
 
       opengl.draw_overlay_lines();
     }
@@ -257,14 +260,14 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
     if (data.points.rows() > 0)
     {
       opengl.bind_overlay_points();
-      modeli = opengl.shader_overlay_points.uniform("model");
-      viewi  = opengl.shader_overlay_points.uniform("view");
-      proji  = opengl.shader_overlay_points.uniform("proj");
+      modeli = glGetUniformLocation(opengl.shader_overlay_points,"model");
+      viewi  = glGetUniformLocation(opengl.shader_overlay_points,"view");
+      proji  = glGetUniformLocation(opengl.shader_overlay_points,"proj");
 
       glUniformMatrix4fv(modeli, 1, GL_FALSE, model.data());
       glUniformMatrix4fv(viewi, 1, GL_FALSE, view.data());
       glUniformMatrix4fv(proji, 1, GL_FALSE, proj.data());
-      glPointSize(point_size);
+      glPointSize(data.point_size);
 
       opengl.draw_overlay_points();
     }
@@ -285,8 +288,8 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
 
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::draw_buffer(ViewerData& data,
-  OpenGL_state& opengl,
+IGL_INLINE void igl::opengl::ViewerCore::draw_buffer(ViewerData& data,
+  State& opengl,
   bool update_matrices,
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
@@ -371,8 +374,8 @@ IGL_INLINE void igl::viewer::ViewerCore::draw_buffer(ViewerData& data,
   glDeleteFramebuffers(1, &frameBuffer);
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::set_rotation_type(
-  const igl::viewer::ViewerCore::RotationType & value)
+IGL_INLINE void igl::opengl::ViewerCore::set_rotation_type(
+  const igl::opengl::ViewerCore::RotationType & value)
 {
   using namespace Eigen;
   using namespace std;
@@ -386,14 +389,10 @@ IGL_INLINE void igl::viewer::ViewerCore::set_rotation_type(
 }
 
 
-IGL_INLINE igl::viewer::ViewerCore::ViewerCore()
+IGL_INLINE igl::opengl::ViewerCore::ViewerCore()
 {
-  // Default shininess
-  shininess = 35.0f;
-
   // Default colors
   background_color << 0.3f, 0.3f, 0.5f, 1.0f;
-  line_color << 0.0f, 0.0f, 0.0f, 1.0f;
 
   // Default lights settings
   light_position << 0.0f, -0.30f, -5.0f;
@@ -417,34 +416,22 @@ IGL_INLINE igl::viewer::ViewerCore::ViewerCore()
   camera_center << 0, 0, 0;
   camera_up << 0, 1, 0;
 
-  // Default visualization options
-  show_faces = true;
-  show_lines = true;
-  invert_normals = false;
-  show_overlay = true;
-  show_overlay_depth = true;
-  show_vertid = false;
-  show_faceid = false;
-  show_texture = false;
   depth_test = true;
 
-  // Default point size / line width
-  point_size = 30;
-  line_width = 0.5f;
   is_animating = false;
   animation_max_fps = 30.;
 
   viewport.setZero();
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::init()
+IGL_INLINE void igl::opengl::ViewerCore::init()
 {
 #ifdef IGL_VIEWER_WITH_NANOGUI
   textrenderer.Init();
 #endif
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::shut()
+IGL_INLINE void igl::opengl::ViewerCore::shut()
 {
 #ifdef IGL_VIEWER_WITH_NANOGUI
   textrenderer.Shut();

+ 65 - 89
include/igl/viewer/ViewerCore.h → include/igl/opengl/ViewerCore.h

@@ -5,14 +5,15 @@
 // 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/.
-#ifndef IGL_VIEWER_VIEWER_CORE_H
-#define IGL_VIEWER_VIEWER_CORE_H
+#ifndef IGL_OPENGL_VIEWERCORE_H
+#define IGL_OPENGL_VIEWERCORE_H
 
-#include <igl/viewer/OpenGL_state.h>
+#include <igl/opengl/State.h>
 #ifdef IGL_VIEWER_WITH_NANOGUI
-#include <igl/viewer/TextRenderer.h>
+#include <igl/opengl/glfw/TextRenderer.h>
 #endif
-#include <igl/viewer/ViewerData.h>
+#include <igl/ViewerData.h>
+#include <igl/opengl/State.h>
 
 #include <igl/igl_inline.h>
 #include <Eigen/Geometry>
@@ -20,7 +21,7 @@
 
 namespace igl
 {
-namespace viewer
+namespace opengl
 {
 
 // Basic class of the 3D mesh viewer
@@ -73,10 +74,12 @@ public:
   IGL_INLINE void clear_framebuffers();
 
   // Draw everything
-  IGL_INLINE void draw(ViewerData& data, OpenGL_state& opengl, bool update_matrices = true);
+  //
+  // data cannot be const because it is being set to "clean"
+  IGL_INLINE void draw(ViewerData& data, State& opengl, bool update_matrices = true);
   IGL_INLINE void draw_buffer(
     ViewerData& data,
-    OpenGL_state& opengl,
+    State& opengl,
     bool update_matrices,
     Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
     Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
@@ -100,12 +103,9 @@ public:
   TextRenderer textrenderer;
 #endif
 
-  // Shape material
-  float shininess;
 
   // Colors
   Eigen::Vector4f background_color;
-  Eigen::Vector4f line_color;
 
   // Lighting
   Eigen::Vector3f light_position;
@@ -133,21 +133,8 @@ public:
   float camera_dnear;
   float camera_dfar;
 
-  // Visualization options
-  bool show_overlay;
-  bool show_overlay_depth;
-  bool show_texture;
-  bool show_faces;
-  bool show_lines;
-  bool show_vertid;
-  bool show_faceid;
-  bool invert_normals;
   bool depth_test;
 
-  // Point size / line width
-  float point_size;
-  float line_width;
-
   // Animation
   bool is_animating;
   double animation_max_fps;
@@ -158,7 +145,8 @@ public:
   // Viewport size
   Eigen::Vector4f viewport;
 
-  // Save the OpenGL transformation matrices used for the previous rendering pass
+  // Save the OpenGL transformation matrices used for the previous rendering
+  // pass
   Eigen::Matrix4f view;
   Eigen::Matrix4f model;
   Eigen::Matrix4f proj;
@@ -169,73 +157,61 @@ public:
 }
 }
 
+// Alec: Is this the best place for this?
 #ifdef ENABLE_SERIALIZATION
 #include <igl/serialize.h>
 namespace igl {
-	namespace serialization {
-
-		inline void serialization(bool s, igl::viewer::ViewerCore& obj, std::vector<char>& buffer)
-		{
-			SERIALIZE_MEMBER(shininess);
-
-			SERIALIZE_MEMBER(background_color);
-			SERIALIZE_MEMBER(line_color);
-
-			SERIALIZE_MEMBER(light_position);
-			SERIALIZE_MEMBER(lighting_factor);
-
-			SERIALIZE_MEMBER(trackball_angle);
-			SERIALIZE_MEMBER(rotation_type);
-
-			SERIALIZE_MEMBER(model_zoom);
-			SERIALIZE_MEMBER(model_translation);
-
-			SERIALIZE_MEMBER(model_zoom_uv);
-			SERIALIZE_MEMBER(model_translation_uv);
-
-			SERIALIZE_MEMBER(camera_zoom);
-			SERIALIZE_MEMBER(orthographic);
-			SERIALIZE_MEMBER(camera_view_angle);
-			SERIALIZE_MEMBER(camera_dnear);
-			SERIALIZE_MEMBER(camera_dfar);
-			SERIALIZE_MEMBER(camera_eye);
-			SERIALIZE_MEMBER(camera_center);
-			SERIALIZE_MEMBER(camera_up);
-
-			SERIALIZE_MEMBER(show_faces);
-			SERIALIZE_MEMBER(show_lines);
-			SERIALIZE_MEMBER(invert_normals);
-			SERIALIZE_MEMBER(show_overlay);
-			SERIALIZE_MEMBER(show_overlay_depth);
-			SERIALIZE_MEMBER(show_vertid);
-			SERIALIZE_MEMBER(show_faceid);
-			SERIALIZE_MEMBER(show_texture);
-			SERIALIZE_MEMBER(depth_test);
-
-			SERIALIZE_MEMBER(point_size);
-			SERIALIZE_MEMBER(line_width);
-			SERIALIZE_MEMBER(is_animating);
-			SERIALIZE_MEMBER(animation_max_fps);
-
-			SERIALIZE_MEMBER(object_scale);
-
-			SERIALIZE_MEMBER(viewport);
-			SERIALIZE_MEMBER(view);
-			SERIALIZE_MEMBER(model);
-			SERIALIZE_MEMBER(proj);
-		}
-
-		template<>
-		inline void serialize(const igl::viewer::ViewerCore& obj, std::vector<char>& buffer)
-		{
-			serialization(true, const_cast<igl::viewer::ViewerCore&>(obj), buffer);
-		}
-
-		template<>
-		inline void deserialize(igl::viewer::ViewerCore& obj, const std::vector<char>& buffer)
-		{
-			serialization(false, obj, const_cast<std::vector<char>&>(buffer));
-		}
+  namespace serialization {
+
+    inline void serialization(bool s, igl::opengl::ViewerCore& obj, std::vector<char>& buffer)
+    {
+
+      SERIALIZE_MEMBER(background_color);
+
+      SERIALIZE_MEMBER(light_position);
+      SERIALIZE_MEMBER(lighting_factor);
+
+      SERIALIZE_MEMBER(trackball_angle);
+      SERIALIZE_MEMBER(rotation_type);
+
+      SERIALIZE_MEMBER(model_zoom);
+      SERIALIZE_MEMBER(model_translation);
+
+      SERIALIZE_MEMBER(model_zoom_uv);
+      SERIALIZE_MEMBER(model_translation_uv);
+
+      SERIALIZE_MEMBER(camera_zoom);
+      SERIALIZE_MEMBER(orthographic);
+      SERIALIZE_MEMBER(camera_view_angle);
+      SERIALIZE_MEMBER(camera_dnear);
+      SERIALIZE_MEMBER(camera_dfar);
+      SERIALIZE_MEMBER(camera_eye);
+      SERIALIZE_MEMBER(camera_center);
+      SERIALIZE_MEMBER(camera_up);
+
+      SERIALIZE_MEMBER(depth_test);
+      SERIALIZE_MEMBER(is_animating);
+      SERIALIZE_MEMBER(animation_max_fps);
+
+      SERIALIZE_MEMBER(object_scale);
+
+      SERIALIZE_MEMBER(viewport);
+      SERIALIZE_MEMBER(view);
+      SERIALIZE_MEMBER(model);
+      SERIALIZE_MEMBER(proj);
+    }
+
+    template<>
+    inline void serialize(const igl::opengl::ViewerCore& obj, std::vector<char>& buffer)
+    {
+      serialization(true, const_cast<igl::opengl::ViewerCore&>(obj), buffer);
+    }
+
+    template<>
+    inline void deserialize(igl::opengl::ViewerCore& obj, const std::vector<char>& buffer)
+    {
+      serialization(false, obj, const_cast<std::vector<char>&>(buffer));
+    }
   }
 }
 #endif

+ 24 - 0
include/igl/opengl/bind_vertex_attrib_array.cpp

@@ -0,0 +1,24 @@
+#include "bind_vertex_attrib_array.h"
+
+IGL_INLINE GLint igl::opengl::bind_vertex_attrib_array(
+  const GLuint program_shader,
+  const std::string &name, 
+  GLuint bufferID, 
+  const Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> &M, 
+  bool refresh)
+{
+  GLint id = glGetAttribLocation(program_shader, name.c_str());
+  if (id < 0)
+    return id;
+  if (M.size() == 0)
+  {
+    glDisableVertexAttribArray(id);
+    return id;
+  }
+  glBindBuffer(GL_ARRAY_BUFFER, bufferID);
+  if (refresh)
+    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*M.size(), M.data(), GL_DYNAMIC_DRAW);
+  glVertexAttribPointer(id, M.cols(), GL_FLOAT, GL_FALSE, 0, 0);
+  glEnableVertexAttribArray(id);
+  return id;
+}

+ 32 - 0
include/igl/opengl/bind_vertex_attrib_array.h

@@ -0,0 +1,32 @@
+#ifndef IGL_OPENGL_BIND_VERTEX_ATTRIB_ARRAY_H
+#define IGL_OPENGL_BIND_VERTEX_ATTRIB_ARRAY_H
+#include "gl.h"
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+namespace igl
+{
+  namespace opengl
+  {
+    // Bind a per-vertex array attribute and refresh its contents from an Eigen
+    // matrix
+    //
+    // Inputs:
+    //   program_shader  id of shader program
+    //   name  name of attribute in vertex shader
+    //   bufferID  id of buffer to bind to
+    //   M  #V by dim matrix of per-vertex data
+    //   refresh  whether to actually call glBufferData or just bind the buffer
+    // Returns id of named attribute in shader
+    IGL_INLINE GLint bind_vertex_attrib_array(
+      const GLuint program_shader,
+      const std::string &name, 
+      GLuint bufferID, 
+      const Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> &M, 
+      bool refresh);
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#include "bind_vertex_attrib_array.cpp"
+#endif
+#endif

+ 6 - 6
include/igl/viewer/TextRenderer.cpp → include/igl/opengl/glfw/TextRenderer.cpp

@@ -19,9 +19,9 @@
 #include <nanovg_gl.h>
 
 
-IGL_INLINE igl::viewer::TextRenderer::TextRenderer(): ctx(nullptr) {}
+IGL_INLINE igl::opengl::glfw::TextRenderer::TextRenderer(): ctx(nullptr) {}
 
-IGL_INLINE int igl::viewer::TextRenderer::Init()
+IGL_INLINE int igl::opengl::glfw::TextRenderer::Init()
 {
   using namespace std;
   #ifdef NDEBUG
@@ -36,7 +36,7 @@ IGL_INLINE int igl::viewer::TextRenderer::Init()
   return 0;
 }
 
-IGL_INLINE int igl::viewer::TextRenderer::Shut()
+IGL_INLINE int igl::opengl::glfw::TextRenderer::Shut()
 {
   using namespace std;
   if(ctx)
@@ -44,7 +44,7 @@ IGL_INLINE int igl::viewer::TextRenderer::Shut()
   return 0;
 }
 
-IGL_INLINE void igl::viewer::TextRenderer::BeginDraw(
+IGL_INLINE void igl::opengl::glfw::TextRenderer::BeginDraw(
   const Eigen::Matrix4f &view,
   const Eigen::Matrix4f &proj,
   const Eigen::Vector4f &_viewport,
@@ -71,13 +71,13 @@ IGL_INLINE void igl::viewer::TextRenderer::BeginDraw(
   nvgBeginFrame(ctx,mSize[0],mSize[1],mPixelRatio);
 }
 
-IGL_INLINE void igl::viewer::TextRenderer::EndDraw()
+IGL_INLINE void igl::opengl::glfw::TextRenderer::EndDraw()
 {
   using namespace std;
   nvgEndFrame(ctx);
 }
 
-IGL_INLINE void igl::viewer::TextRenderer::DrawText(
+IGL_INLINE void igl::opengl::glfw::TextRenderer::DrawText(
   Eigen::Vector3d pos, Eigen::Vector3d normal, const std::string &text)
 {
   using namespace std;

+ 6 - 3
include/igl/viewer/TextRenderer.h → include/igl/opengl/glfw/TextRenderer.h

@@ -5,8 +5,8 @@
 // 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/.
-#ifndef IGL_VIEWER_TEXT_RENDERER_H
-#define IGL_VIEWER_TEXT_RENDERER_H
+#ifndef IGL_OPENGL_GLFW_TEXT_RENDERER_H
+#define IGL_OPENGL_GLFW_TEXT_RENDERER_H
 #ifdef IGL_VIEWER_WITH_NANOGUI
 
 #include <Eigen/Dense>
@@ -18,7 +18,9 @@ struct NVGcontext;
 
 namespace igl
 {
-namespace viewer
+namespace opengl
+{
+namespace glfw
 {
 
   class TextRenderer
@@ -47,6 +49,7 @@ namespace viewer
 
 }
 }
+}
 
 #ifndef IGL_STATIC_LIBRARY
 #  include "TextRenderer.cpp"

+ 0 - 0
include/igl/viewer/TextRenderer_fonts.cpp.REMOVED.git-id → include/igl/opengl/glfw/TextRenderer_fonts.cpp.REMOVED.git-id


+ 2 - 2
include/igl/viewer/TextRenderer_fonts.h → include/igl/opengl/glfw/TextRenderer_fonts.h

@@ -6,8 +6,8 @@
 // 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/.
 
-#ifndef IGL_TEXT_RENDERER_FONTS_H
-#define IGL_TEXT_RENDERER_FONTS_H
+#ifndef IGL_OPENGL_GLFW_TEXT_RENDERER_FONTS_H
+#define IGL_OPENGL_GLFW_TEXT_RENDERER_FONTS_H
 
 #include <stdint.h>
 

+ 346 - 275
include/igl/viewer/Viewer.cpp → include/igl/opengl/glfw/Viewer.cpp

@@ -73,13 +73,12 @@
 #include <igl/two_axis_valuator_fixed_up.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/unproject.h>
-
 #ifdef ENABLE_SERIALIZATION
 #include <igl/serialize.h>
 #endif
 
 // Internal global variables used for glfw event handling
-static igl::viewer::Viewer * __viewer;
+static igl::opengl::glfw::Viewer * __viewer;
 static double highdpi = 1;
 static double scroll_x = 0;
 static double scroll_y = 0;
@@ -93,14 +92,14 @@ static void glfw_mouse_press(GLFWwindow* window, int button, int action, int mod
     false;
 #endif
 
-  igl::viewer::Viewer::MouseButton mb;
+  igl::opengl::glfw::Viewer::MouseButton mb;
 
   if (button == GLFW_MOUSE_BUTTON_1)
-    mb = igl::viewer::Viewer::MouseButton::Left;
+    mb = igl::opengl::glfw::Viewer::MouseButton::Left;
   else if (button == GLFW_MOUSE_BUTTON_2)
-    mb = igl::viewer::Viewer::MouseButton::Right;
+    mb = igl::opengl::glfw::Viewer::MouseButton::Right;
   else //if (button == GLFW_MOUSE_BUTTON_3)
-    mb = igl::viewer::Viewer::MouseButton::Middle;
+    mb = igl::opengl::glfw::Viewer::MouseButton::Middle;
 
   if (action == GLFW_PRESS)
   {
@@ -195,8 +194,155 @@ static void glfw_drop_callback(GLFWwindow *window,int count,const char **filenam
 
 namespace igl
 {
-namespace viewer
+namespace opengl
+{
+namespace glfw
 {
+
+  IGL_INLINE int Viewer::launch(bool resizable,bool fullscreen)
+  {
+    // TODO return values are being ignored...
+    launch_init(resizable,fullscreen);
+    launch_rendering(true);
+    launch_shut();
+    return EXIT_SUCCESS;
+  }
+
+  IGL_INLINE int  Viewer::launch_init(bool resizable,bool fullscreen)
+  {
+    glfwSetErrorCallback(glfw_error_callback);
+    if (!glfwInit())
+    {
+      return EXIT_FAILURE;
+    }
+    glfwWindowHint(GLFW_SAMPLES, 8);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+    #ifdef __APPLE__
+      glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+    #endif
+    if(fullscreen)
+    {
+      GLFWmonitor *monitor = glfwGetPrimaryMonitor();
+      const GLFWvidmode *mode = glfwGetVideoMode(monitor);
+      window = glfwCreateWindow(mode->width,mode->height,"libigl viewer",monitor,nullptr);
+    }
+    else
+    {
+      if (core.viewport.tail<2>().any()) {
+        window = glfwCreateWindow(core.viewport(2),core.viewport(3),"libigl viewer",nullptr,nullptr);
+      } else {
+        window = glfwCreateWindow(1280,800,"libigl viewer",nullptr,nullptr);
+      }
+    }
+    if (!window)
+    {
+      glfwTerminate();
+      return EXIT_FAILURE;
+    }
+    glfwMakeContextCurrent(window);
+    #ifndef __APPLE__
+      glewExperimental = true;
+      GLenum err = glewInit();
+      if(GLEW_OK != err)
+      {
+        /* Problem: glewInit failed, something is seriously wrong. */
+       fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
+      }
+      glGetError(); // pull and savely ignonre unhandled errors like GL_INVALID_ENUM
+      fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
+    #endif
+    #if defined(DEBUG) || defined(_DEBUG)
+      int major, minor, rev;
+      major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
+      minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
+      rev = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
+      printf("OpenGL version recieved: %d.%d.%d\n", major, minor, rev);
+      printf("Supported OpenGL is %s\n", (const char*)glGetString(GL_VERSION));
+      printf("Supported GLSL is %s\n", (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
+    #endif
+    glfwSetInputMode(window,GLFW_CURSOR,GLFW_CURSOR_NORMAL);
+    // Initialize FormScreen
+#ifdef IGL_VIEWER_WITH_NANOGUI
+    screen = new nanogui::Screen();
+    screen->initialize(window, false);
+    ngui = new nanogui::FormHelper(screen);
+#endif
+    __viewer = this;
+    // Register callbacks
+    glfwSetKeyCallback(window, glfw_key_callback);
+    glfwSetCursorPosCallback(window,glfw_mouse_move);
+    glfwSetWindowSizeCallback(window,glfw_window_size);
+    glfwSetMouseButtonCallback(window,glfw_mouse_press);
+    glfwSetScrollCallback(window,glfw_mouse_scroll);
+    glfwSetCharModsCallback(window,glfw_char_mods_callback);
+    glfwSetDropCallback(window,glfw_drop_callback);
+    // Handle retina displays (windows and mac)
+    int width, height;
+    glfwGetFramebufferSize(window, &width, &height);
+    int width_window, height_window;
+    glfwGetWindowSize(window, &width_window, &height_window);
+    highdpi = width/width_window;
+    glfw_window_size(window,width_window,height_window);
+    //opengl.init();
+    core.align_camera_center(selected_data().V,selected_data().F);
+    // Initialize IGL viewer
+    init();
+    return EXIT_SUCCESS;
+  }
+
+
+
+  IGL_INLINE bool Viewer::launch_rendering(bool loop)
+  {
+    // glfwMakeContextCurrent(window);
+    // Rendering loop
+    while (!glfwWindowShouldClose(window))
+    {
+      double tic = get_seconds();
+      draw();
+      glfwSwapBuffers(window);
+      if(core.is_animating)
+      {
+        glfwPollEvents();
+        // In microseconds
+        double duration = 1000000.*(get_seconds()-tic);
+        const double min_duration = 1000000./core.animation_max_fps;
+        if(duration<min_duration)
+        {
+          std::this_thread::sleep_for(std::chrono::microseconds((int)(min_duration-duration)));
+        }
+      }
+      else
+      {
+        glfwWaitEvents();
+      }
+      if (!loop)
+        return !glfwWindowShouldClose(window);
+    }
+    return EXIT_SUCCESS;
+  }
+
+  IGL_INLINE void Viewer::launch_shut()
+  {
+    for(auto & opengl : opengl_state_list)
+    {
+      opengl.free();
+    }
+    core.shut();
+    shutdown_plugins();
+#ifdef IGL_VIEWER_WITH_NANOGUI
+    delete ngui;
+    //delete screen;
+    screen = nullptr;
+    ngui = nullptr;
+#endif
+    glfwDestroyWindow(window);
+    glfwTerminate();
+    return;
+  }
+
   IGL_INLINE void Viewer::init()
   {
 #ifdef IGL_VIEWER_WITH_NANOGUI
@@ -222,7 +368,8 @@ namespace viewer
   #endif
 
     ngui->addGroup("Viewing Options");
-    ngui->addButton("Center object",[&](){this->core.align_camera_center(this->data.V,this->data.F);});
+    ngui->addButton("Center object",[&](){this->core.align_camera_center(
+      this->selected_data().V,this->selected_data().F);});
     ngui->addButton("Snap canonical view",[&]()
     {
       this->snap_to_canonical_quaternion();
@@ -234,34 +381,36 @@ namespace viewer
 
     ngui->addVariable<bool>("Face-based", [&](bool checked)
     {
-      this->data.set_face_based(checked);
+      this->selected_data().set_face_based(checked);
     },[&]()
     {
-      return this->data.face_based;
+      return this->selected_data().face_based;
     });
 
-    ngui->addVariable("Show texture",core.show_texture);
+    ngui->addVariable("Show texture",this->selected_data().show_texture);
 
     ngui->addVariable<bool>("Invert normals",[&](bool checked)
     {
-      this->data.dirty |= ViewerData::DIRTY_NORMAL;
-      this->core.invert_normals = checked;
+      this->selected_data().dirty |= ViewerData::DIRTY_NORMAL;
+      this->selected_data().invert_normals = checked;
     },[&]()
     {
-      return this->core.invert_normals;
+      return this->selected_data().invert_normals;
     });
 
-    ngui->addVariable("Show overlay", core.show_overlay);
-    ngui->addVariable("Show overlay depth", core.show_overlay_depth);
+    // Alec: This will probably just attach to the selected_data() at the time
+    // that addVariable is called. We probably need to use a callback here.
+    ngui->addVariable("Show overlay", selected_data().show_overlay);
+    ngui->addVariable("Show overlay depth", selected_data().show_overlay_depth);
+    ngui->addVariable("Line color", (nanogui::Color &) selected_data().line_color);
     ngui->addVariable("Background", (nanogui::Color &) core.background_color);
-    ngui->addVariable("Line color", (nanogui::Color &) core.line_color);
-    ngui->addVariable("Shininess", core.shininess);
+    ngui->addVariable("Shininess", selected_data().shininess);
 
     ngui->addGroup("Overlays");
-    ngui->addVariable("Wireframe", core.show_lines);
-    ngui->addVariable("Fill", core.show_faces);
-    ngui->addVariable("Show vertex labels", core.show_vertid);
-    ngui->addVariable("Show faces labels", core.show_faceid);
+    ngui->addVariable("Wireframe", selected_data().show_lines);
+    ngui->addVariable("Fill", selected_data().show_faces);
+    ngui->addVariable("Show vertex labels", selected_data().show_vertid);
+    ngui->addVariable("Show faces labels", selected_data().show_faceid);
 
     screen->setVisible(true);
     screen->performLayout();
@@ -276,7 +425,27 @@ namespace viewer
     init_plugins();
   }
 
-  IGL_INLINE Viewer::Viewer()
+  IGL_INLINE void Viewer::init_plugins()
+  {
+    // Init all plugins
+    for (unsigned int i = 0; i<plugins.size(); ++i)
+    {
+      plugins[i]->init(this);
+    }
+  }
+
+  IGL_INLINE void Viewer::shutdown_plugins()
+  {
+    for (unsigned int i = 0; i<plugins.size(); ++i)
+    {
+      plugins[i]->shutdown();
+    }
+  }
+
+  IGL_INLINE Viewer::Viewer():
+    data_list(1),
+    opengl_state_list(1),
+    selected_data_index(0)
   {
     window = nullptr;
 
@@ -291,7 +460,7 @@ namespace viewer
     scroll_position = 0.0f;
 
     // Per face
-    data.set_face_based(false);
+    selected_data().set_face_based(false);
 
     // C-style callbacks
     callback_init         = nullptr;
@@ -315,7 +484,7 @@ namespace viewer
     callback_key_up_data        = nullptr;
 
 #ifndef IGL_VIEWER_VIEWER_QUIET
-    const std::string usage(R"(igl::viewer::Viewer usage:
+    const std::string usage(R"(igl::opengl::glfw::Viewer usage:
   [drag]  Rotate scene
   A,a     Toggle animation (tight draw loop)
   F,f     Toggle face based
@@ -325,7 +494,8 @@ namespace viewer
   T,t     Toggle filled faces
   Z       Snap to canonical view
   [,]     Toggle between rotation control types (trackball, two-axis
-          valuator with fixed up, 2D mode with no rotation))"
+          valuator with fixed up, 2D mode with no rotation)
+  <,>     Toggle between models.)"
 #ifdef IGL_VIEWER_WITH_NANOGUI
 		R"(
   ;       Toggle vertex labels
@@ -336,30 +506,13 @@ namespace viewer
 #endif
   }
 
-  IGL_INLINE void Viewer::init_plugins()
-  {
-    // Init all plugins
-    for (unsigned int i = 0; i<plugins.size(); ++i)
-    {
-      plugins[i]->init(this);
-    }
-  }
-
   IGL_INLINE Viewer::~Viewer()
   {
   }
 
-  IGL_INLINE void Viewer::shutdown_plugins()
+  IGL_INLINE bool Viewer::load_mesh_from_file(
+      const std::string & mesh_file_name_string)
   {
-    for (unsigned int i = 0; i<plugins.size(); ++i)
-    {
-      plugins[i]->shutdown();
-    }
-  }
-
-  IGL_INLINE bool Viewer::load_mesh_from_file(const char* mesh_file_name)
-  {
-    std::string mesh_file_name_string = std::string(mesh_file_name);
 
     // first try to load it with a plugin
     for (unsigned int i = 0; i<plugins.size(); ++i)
@@ -370,12 +523,18 @@ namespace viewer
       }
     }
 
-    data.clear();
+    // Create new data slot and set to selected
+    if(!(selected_data().F.rows() == 0  && selected_data().V.rows() == 0))
+    {
+      append_mesh();
+    }
+    selected_data().clear();
 
     size_t last_dot = mesh_file_name_string.rfind('.');
     if (last_dot == std::string::npos)
     {
-      printf("Error: No file extension found in %s\n",mesh_file_name);
+      std::cerr<<"Error: No file extension found in "<<
+        mesh_file_name_string<<std::endl;
       return false;
     }
 
@@ -387,7 +546,7 @@ namespace viewer
       Eigen::MatrixXi F;
       if (!igl::readOFF(mesh_file_name_string, V, F))
         return false;
-      data.set_mesh(V,F);
+      selected_data().set_mesh(V,F);
     }
     else if (extension == "obj" || extension =="OBJ")
     {
@@ -407,8 +566,8 @@ namespace viewer
         return false;
       }
 
-      data.set_mesh(V,F);
-      data.set_uv(UV_V,UV_F);
+      selected_data().set_mesh(V,F);
+      selected_data().set_uv(UV_V,UV_F);
 
     }
     else
@@ -418,16 +577,16 @@ namespace viewer
       return false;
     }
 
-    data.compute_normals();
-    data.uniform_colors(Eigen::Vector3d(51.0/255.0,43.0/255.0,33.3/255.0),
+    selected_data().compute_normals();
+    selected_data().uniform_colors(Eigen::Vector3d(51.0/255.0,43.0/255.0,33.3/255.0),
                    Eigen::Vector3d(255.0/255.0,228.0/255.0,58.0/255.0),
                    Eigen::Vector3d(255.0/255.0,235.0/255.0,80.0/255.0));
-    if (data.V_uv.rows() == 0)
+    if (selected_data().V_uv.rows() == 0)
     {
-      data.grid_texture();
+      selected_data().grid_texture();
     }
 
-    core.align_camera_center(data.V,data.F);
+    core.align_camera_center(selected_data().V,selected_data().F);
 
     for (unsigned int i = 0; i<plugins.size(); ++i)
       if (plugins[i]->post_load())
@@ -436,10 +595,9 @@ namespace viewer
     return true;
   }
 
-  IGL_INLINE bool Viewer::save_mesh_to_file(const char* mesh_file_name)
+  IGL_INLINE bool Viewer::save_mesh_to_file(
+      const std::string & mesh_file_name_string)
   {
-    std::string mesh_file_name_string(mesh_file_name);
-
     // first try to load it with a plugin
     for (unsigned int i = 0; i<plugins.size(); ++i)
       if (plugins[i]->save(mesh_file_name_string))
@@ -449,13 +607,15 @@ namespace viewer
     if (last_dot == std::string::npos)
     {
       // No file type determined
-      printf("Error: No file extension found in %s\n",mesh_file_name);
+      std::cerr<<"Error: No file extension found in "<<
+        mesh_file_name_string<<std::endl;
       return false;
     }
     std::string extension = mesh_file_name_string.substr(last_dot+1);
     if (extension == "off" || extension =="OFF")
     {
-      return igl::writeOFF(mesh_file_name_string,data.V,data.F);
+      return igl::writeOFF(
+        mesh_file_name_string,selected_data().V,selected_data().F);
     }
     else if (extension == "obj" || extension =="OBJ")
     {
@@ -465,8 +625,10 @@ namespace viewer
       Eigen::MatrixXd UV_V;
       Eigen::MatrixXi UV_F;
 
-      return igl::writeOBJ(mesh_file_name_string, data.V,
-          data.F, corner_normals, fNormIndices, UV_V, UV_F);
+      return igl::writeOBJ(mesh_file_name_string, 
+          selected_data().V,
+          selected_data().F, 
+          corner_normals, fNormIndices, UV_V, UV_F);
     }
     else
     {
@@ -502,20 +664,20 @@ namespace viewer
       case 'F':
       case 'f':
       {
-        data.set_face_based(!data.face_based);
+        selected_data().set_face_based(!selected_data().face_based);
         return true;
       }
       case 'I':
       case 'i':
       {
-        data.dirty |= ViewerData::DIRTY_NORMAL;
-        core.invert_normals = !core.invert_normals;
+        selected_data().dirty |= ViewerData::DIRTY_NORMAL;
+        selected_data().invert_normals = !selected_data().invert_normals;
         return true;
       }
       case 'L':
       case 'l':
       {
-        core.show_lines = !core.show_lines;
+        selected_data().show_lines = !selected_data().show_lines;
         return true;
       }
       case 'O':
@@ -527,7 +689,7 @@ namespace viewer
       case 'T':
       case 't':
       {
-        core.show_faces = !core.show_faces;
+        selected_data().show_faces = !selected_data().show_faces;
         return true;
       }
       case 'Z':
@@ -545,12 +707,19 @@ namespace viewer
 
         return true;
       }
+      case '<':
+      case '>':
+      {
+        selected_data_index = 
+          (selected_data_index + data_list.size() + (unicode_key=='>'?1:-1))%data_list.size();
+        return true;
+      }
 #ifdef IGL_VIEWER_WITH_NANOGUI
       case ';':
-        core.show_vertid = !core.show_vertid;
+        selected_data().show_vertid = !selected_data().show_vertid;
         return true;
       case ':':
-        core.show_faceid = !core.show_faceid;
+        selected_data().show_faceid = !selected_data().show_faceid;
         return true;
 #endif
       default: break;//do nothing
@@ -603,12 +772,12 @@ namespace viewer
 
     // Initialization code for the trackball
     Eigen::RowVector3d center;
-    if (data.V.rows() == 0)
+    if (selected_data().V.rows() == 0)
     {
       center << 0,0,0;
     }else
     {
-      center = data.V.colwise().sum()/data.V.rows();
+      center = selected_data().V.colwise().sum()/selected_data().V.rows();
     }
 
     Eigen::Vector3f coord =
@@ -767,6 +936,52 @@ namespace viewer
     return true;
   }
 
+  IGL_INLINE bool Viewer::load_scene()
+  {
+    std::string fname = igl::file_dialog_open();
+    if(fname.length() == 0)
+    {
+      return false;
+    }
+    return load_scene(fname);
+  }
+
+  IGL_INLINE bool Viewer::load_scene(std::string fname)
+  {
+#ifdef ENABLE_SERIALIZATION
+    igl::deserialize(core,"Core",fname.c_str());
+#ifndef ENABLE_SERIALIZATION_CORE_ONLY
+    igl::deserialize(selected_data(),"Data",fname.c_str());
+    for(unsigned int i = 0; i <plugins.size(); ++i)
+    {
+      igl::deserialize(*plugins[i],plugins[i]->plugin_name,fname.c_str());
+    }
+#endif
+#endif
+    return true;
+  }
+
+  IGL_INLINE bool Viewer::save_scene()
+  {
+    std::string fname = igl::file_dialog_save();
+    if (fname.length() == 0)
+      return false;
+
+#ifdef ENABLE_SERIALIZATION
+
+    igl::serialize(core,"Core",fname.c_str(),true);
+
+#ifndef ENABLE_SERIALIZATION_CORE_ONLY
+    igl::serialize(selected_data(),"Data",fname.c_str());
+    for(unsigned int i = 0; i <plugins.size(); ++i)
+      igl::serialize(*plugins[i],plugins[i]->plugin_name,fname.c_str());
+#endif
+
+#endif
+
+    return true;
+  }
+
   IGL_INLINE void Viewer::draw()
   {
     using namespace std;
@@ -787,79 +1002,46 @@ namespace viewer
     }
 
     core.clear_framebuffers();
-
     if (callback_pre_draw)
+    {
       if (callback_pre_draw(*this))
+      {
         return;
-
+      }
+    }
     for (unsigned int i = 0; i<plugins.size(); ++i)
+    {
       if (plugins[i]->pre_draw())
+      {
         return;
-
-    core.draw(data,opengl);
-
+      }
+    }
+    assert(data_list.size() == opengl_state_list.size());
+    for(int i = 0;i<data_list.size();i++)
+    {
+      opengl_state_list[i].init();
+      core.draw(data_list[i],opengl_state_list[i]);
+    }
     if (callback_post_draw)
+    {
       if (callback_post_draw(*this))
+      {
         return;
-
+      }
+    }
     for (unsigned int i = 0; i<plugins.size(); ++i)
+    {
       if (plugins[i]->post_draw())
+      {
         break;
-
+      }
+    }
 #ifdef IGL_VIEWER_WITH_NANOGUI
-	ngui->refresh();
 	screen->drawContents();
 	screen->drawWidgets();
 #endif
   }
 
-  IGL_INLINE bool Viewer::save_scene()
-  {
-    std::string fname = igl::file_dialog_save();
-    if (fname.length() == 0)
-      return false;
-
-#ifdef ENABLE_SERIALIZATION
-
-    igl::serialize(core,"Core",fname.c_str(),true);
-
-#ifndef ENABLE_SERIALIZATION_CORE_ONLY
-    igl::serialize(data,"Data",fname.c_str());
-    for(unsigned int i = 0; i <plugins.size(); ++i)
-      igl::serialize(*plugins[i],plugins[i]->plugin_name,fname.c_str());
-#endif
-
-#endif
-
-    return true;
-  }
-
-  IGL_INLINE bool Viewer::load_scene()
-  {
-    std::string fname = igl::file_dialog_open();
-    if(fname.length() == 0)
-      return false;
-
-    return load_scene(fname);
-  }
-
-  IGL_INLINE bool Viewer::load_scene(std::string fname)
-  {
-#ifdef ENABLE_SERIALIZATION
-
-    igl::deserialize(core,"Core",fname.c_str());
-
-#ifndef ENABLE_SERIALIZATION_CORE_ONLY
-    igl::deserialize(data,"Data",fname.c_str());
-    for(unsigned int i = 0; i <plugins.size(); ++i)
-      igl::deserialize(*plugins[i],plugins[i]->plugin_name,fname.c_str());
-#endif
-
-#endif
-
-    return true;
-  }
-
   IGL_INLINE void Viewer::resize(int w,int h)
   {
     if (window) {
@@ -903,165 +1085,54 @@ namespace viewer
     this->save_mesh_to_file(fname.c_str());
   }
 
-
-  IGL_INLINE int  Viewer::launch_init(bool resizable,bool fullscreen)
+  IGL_INLINE ViewerData& Viewer::selected_data()
   {
-    glfwSetErrorCallback(glfw_error_callback);
-    if (!glfwInit())
-      return EXIT_FAILURE;
-
-    glfwWindowHint(GLFW_SAMPLES, 8);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-
-    #ifdef __APPLE__
-      glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-      glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
-    #endif
-
-    if(fullscreen)
-    {
-      GLFWmonitor *monitor = glfwGetPrimaryMonitor();
-      const GLFWvidmode *mode = glfwGetVideoMode(monitor);
-      window = glfwCreateWindow(mode->width,mode->height,"libigl viewer",monitor,nullptr);
-    }
-    else
-    {
-      if (core.viewport.tail<2>().any()) {
-        window = glfwCreateWindow(core.viewport(2),core.viewport(3),"libigl viewer",nullptr,nullptr);
-      } else {
-        window = glfwCreateWindow(1280,800,"libigl viewer",nullptr,nullptr);
-      }
-    }
-
-    if (!window)
-    {
-      glfwTerminate();
-      return EXIT_FAILURE;
-    }
-
-    glfwMakeContextCurrent(window);
-
-    #ifndef __APPLE__
-      glewExperimental = true;
-      GLenum err = glewInit();
-      if(GLEW_OK != err)
-      {
-        /* Problem: glewInit failed, something is seriously wrong. */
-       fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
-      }
-      glGetError(); // pull and safely ignore unhandled errors like GL_INVALID_ENUM
-      fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
-    #endif
-
-    #if defined(DEBUG) || defined(_DEBUG)
-      int major, minor, rev;
-      major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
-      minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
-      rev = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
-      printf("OpenGL version received: %d.%d.%d\n", major, minor, rev);
-      printf("Supported OpenGL is %s\n", (const char*)glGetString(GL_VERSION));
-      printf("Supported GLSL is %s\n", (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
-    #endif
-
-    glfwSetInputMode(window,GLFW_CURSOR,GLFW_CURSOR_NORMAL);
-
-    // Initialize FormScreen
-#ifdef IGL_VIEWER_WITH_NANOGUI
-    screen = new nanogui::Screen();
-    screen->initialize(window, false);
-    ngui = new nanogui::FormHelper(screen);
-#endif
-
-    __viewer = this;
-
-    // Register callbacks
-    glfwSetKeyCallback(window, glfw_key_callback);
-    glfwSetCursorPosCallback(window,glfw_mouse_move);
-    glfwSetWindowSizeCallback(window,glfw_window_size);
-    glfwSetMouseButtonCallback(window,glfw_mouse_press);
-    glfwSetScrollCallback(window,glfw_mouse_scroll);
-    glfwSetCharModsCallback(window,glfw_char_mods_callback);
-    glfwSetDropCallback(window,glfw_drop_callback);
-
-    // Handle retina displays (windows and mac)
-    int width, height;
-    glfwGetFramebufferSize(window, &width, &height);
-
-    int width_window, height_window;
-    glfwGetWindowSize(window, &width_window, &height_window);
-
-    highdpi = width/width_window;
-
-    glfw_window_size(window,width_window,height_window);
-
-    opengl.init();
-
-    core.align_camera_center(data.V,data.F);
-
-    // Initialize IGL viewer
-    init();
-    return EXIT_SUCCESS;
+    assert(!data_list.empty() && "data_list should never be empty");
+    assert(
+      (selected_data_index >= 0 && selected_data_index < data_list.size()) && 
+      "selected_data_index should be in bounds");
+    return data_list[selected_data_index];
   }
 
-  IGL_INLINE bool Viewer::launch_rendering(bool loop)
+  IGL_INLINE void Viewer::append_mesh()
   {
-    // glfwMakeContextCurrent(window);
+    assert(data_list.size() == opengl_state_list.size());
+    assert(data_list.size() >= 1);
 
-    // Rendering loop
-    while (!glfwWindowShouldClose(window))
-    {
-      double tic = get_seconds();
-      draw();
-
-      glfwSwapBuffers(window);
-      if(core.is_animating)
-      {
-        glfwPollEvents();
-        // In microseconds
-        double duration = 1000000.*(get_seconds()-tic);
-        const double min_duration = 1000000./core.animation_max_fps;
-        if(duration<min_duration)
-        {
-          std::this_thread::sleep_for(std::chrono::microseconds((int)(min_duration-duration)));
-        }
-      }
-      else
-      {
-        glfwWaitEvents();
-      }
-
-      if (!loop)
-        return !glfwWindowShouldClose(window);
-    }
-    return EXIT_SUCCESS;
+    data_list.emplace_back();
+    opengl_state_list.emplace_back();
+    selected_data_index = data_list.size()-1;
   }
-
-  IGL_INLINE void Viewer::launch_shut()
+  IGL_INLINE bool Viewer::erase_mesh(const size_t index)
   {
-    opengl.free();
-    core.shut();
-
-    shutdown_plugins();
-#ifdef IGL_VIEWER_WITH_NANOGUI
-    delete ngui;
-    //delete screen;
-    screen = nullptr;
-    ngui = nullptr;
-#endif
-
-    glfwDestroyWindow(window);
-    glfwTerminate();
-    return;
+    assert(data_list.size() == opengl_state_list.size());
+    assert(data_list.size() >= 1);
+    if(data_list.size() == 1)
+    {
+      // Cannot remove last mesh
+      return false;
+    }
+    data_list.erase(data_list.begin()                 + index);
+    opengl_state_list.erase(opengl_state_list.begin() + index);
+    if(selected_data_index >= index && selected_data_index>0)
+    {
+      selected_data_index--;
+    }
+    std::cout<<"data: "<<data_list.size()<<std::endl;
+    std::cout<<"opengl_state: "<<opengl_state_list.size()<<std::endl;
+    std::cout<<"selected_data_index: "<<selected_data_index<<std::endl;
+    return true;
   }
 
-  IGL_INLINE int Viewer::launch(bool resizable,bool fullscreen)
+  IGL_INLINE State& Viewer::selected_opengl_state()
   {
-    // TODO return values are being ignored...
-    launch_init(resizable,fullscreen);
-    launch_rendering(true);
-    launch_shut();
-    return EXIT_SUCCESS;
+    assert(!opengl_state_list.empty() && "opengl_state_list should never be empty");
+    assert(opengl_state_list.size() == data_list.size());
+    assert(
+      (selected_data_index >= 0 && selected_data_index < opengl_state_list.size()) && 
+      "selected_data_index should be in bounds");
+    return opengl_state_list[selected_data_index];
   }
 } // end namespace
+} // end namespace
 }

+ 79 - 64
include/igl/viewer/Viewer.h → include/igl/opengl/glfw/Viewer.h

@@ -5,27 +5,26 @@
 // 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/.
-#ifndef IGL_VIEWER_VIEWER_H
-#define IGL_VIEWER_VIEWER_H
+#ifndef IGL_OPENGL_GLFW_VIEWER_H
+#define IGL_OPENGL_GLFW_VIEWER_H
 
 #ifndef IGL_OPENGL_4
 #define IGL_OPENGL_4
 #endif
 
-#include <vector>
-#include <string>
-#include <cstdint>
+
+#include "../../igl_inline.h"
+#include "../State.h"
+#include "../ViewerCore.h"
+#include "../../ViewerData.h"
+#include "ViewerPlugin.h"
 
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 
-#include <igl/igl_inline.h>
-
-#include "OpenGL_shader.h"
-#include "OpenGL_state.h"
-#include "ViewerCore.h"
-#include "ViewerData.h"
-#include "ViewerPlugin.h"
+#include <vector>
+#include <string>
+#include <cstdint>
 
 #define IGL_MOD_SHIFT           0x0001
 #define IGL_MOD_CONTROL         0x0002
@@ -40,93 +39,109 @@ struct GLFWwindow;
 
 namespace igl
 {
-namespace viewer
+namespace opengl
+{
+namespace glfw
 {
   // GLFW-based mesh viewer
   class Viewer
   {
   public:
-    GLFWwindow* window;
-
+    // UI Enumerations
+    enum class MouseButton {Left, Middle, Right};
+    enum class MouseMode { None, Rotation, Zoom, Pan, Translation} mouse_mode;
     IGL_INLINE int launch(bool resizable = true,bool fullscreen = false);
     IGL_INLINE int launch_init(bool resizable = true,bool fullscreen = false);
     IGL_INLINE bool launch_rendering(bool loop = true);
     IGL_INLINE void launch_shut();
-
     IGL_INLINE void init();
-
-    // Stores all the viewing options
-    ViewerCore core;
-
-    // Stores all the data that should be visualized
-    ViewerData data;
-
-    // Stores the vbos indices and opengl related settings
-    OpenGL_state opengl;
-
-    // List of registered plugins
-    std::vector<ViewerPlugin*> plugins;
     IGL_INLINE void init_plugins();
     IGL_INLINE void shutdown_plugins();
-
-    // Temporary data stored when the mouse button is pressed
-    Eigen::Quaternionf down_rotation;
-    int current_mouse_x;
-    int current_mouse_y;
-    int down_mouse_x;
-    int down_mouse_y;
-    float down_mouse_z;
-    Eigen::Vector3f down_translation;
-    bool down;
-    bool hack_never_moved;
-
-#ifdef IGL_VIEWER_WITH_NANOGUI
-    nanogui::FormHelper* ngui;
-    nanogui::Screen* screen;
-#endif
-
-    // Keep track of the global position of the scrollwheel
-    float scroll_position;
-
-    // UI Enumerations
-    enum class MouseButton {Left, Middle, Right};
-    enum class MouseMode { None, Rotation, Zoom, Pan, Translation} mouse_mode;
-
     Viewer();
     ~Viewer();
-
     // Mesh IO
-    IGL_INLINE bool load_mesh_from_file(const char* mesh_file_name);
-    IGL_INLINE bool save_mesh_to_file(const char* mesh_file_name);
-
+    IGL_INLINE bool load_mesh_from_file(const std::string & mesh_file_name);
+    IGL_INLINE bool   save_mesh_to_file(const std::string & mesh_file_name);
     // Callbacks
     IGL_INLINE bool key_pressed(unsigned int unicode_key,int modifier);
     IGL_INLINE bool key_down(int key,int modifier);
     IGL_INLINE bool key_up(int key,int modifier);
-
     IGL_INLINE bool mouse_down(MouseButton button,int modifier);
     IGL_INLINE bool mouse_up(MouseButton button,int modifier);
-
     IGL_INLINE bool mouse_move(int mouse_x,int mouse_y);
     IGL_INLINE bool mouse_scroll(float delta_y);
-
     // Scene IO
     IGL_INLINE bool load_scene();
     IGL_INLINE bool load_scene(std::string fname);
     IGL_INLINE bool save_scene();
-
     // Draw everything
     IGL_INLINE void draw();
-
     // OpenGL context resize
     IGL_INLINE void resize(int w,int h); // explicitly set window size
     IGL_INLINE void post_resize(int w,int h); // external resize due to user interaction
-
     // Helper functions
     IGL_INLINE void snap_to_canonical_quaternion();
     IGL_INLINE void open_dialog_load_mesh();
     IGL_INLINE void open_dialog_save_mesh();
-
+    IGL_INLINE ViewerData& selected_data();
+    //IGL_INLINE const ViewerData& const_selected_data() const;
+    IGL_INLINE State& selected_opengl_state();
+    // Append a new "slot" for a mesh (i.e., create empty entires at the end of
+    // the data_list and opengl_state_list.
+    //
+    // Returns number of meshes (always >= 1)
+    // 
+    // Side Effects:
+    //   selected_data_index is set this newly created, last entry (i.e.,
+    //   #meshes-1)
+    IGL_INLINE void append_mesh();
+    // Erase a mesh (i.e., its corresponding data and state entires in data_list
+    // and opengl_state_list)
+    //
+    // Inputs:
+    //   index  index of mesh to erase
+    // Returns whether erasure was successful <=> cannot erase last mesh
+    // 
+    // Side Effects:
+    //   If selected_data_index is greater than or equal to index then it is
+    //   decremented
+    // Example:
+    //   // Erase all mesh slots except first and clear remaining mesh
+    //   viewer.selected_data_index = viewer.data_list.size()-1;
+    //   while(viewer.erase_mesh(viewer.selected_data_index)){};
+    //   viewer.selected_data().clear();
+    //
+    IGL_INLINE bool erase_mesh(const size_t index);
+  private:
+    // Alec: I call this data_list instead of just data to avoid confusion with
+    // old "data" variable.
+    // Stores all the data that should be visualized
+    std::vector<ViewerData> data_list;
+    // Stores the vbos indices and opengl related settings
+    std::vector<State> opengl_state_list;
+  public:
+    size_t selected_data_index;
+    GLFWwindow* window;
+    // Stores all the viewing options
+    ViewerCore core;
+    // List of registered plugins
+    std::vector<ViewerPlugin*> plugins;
+    // Temporary data stored when the mouse button is pressed
+    Eigen::Quaternionf down_rotation;
+    int current_mouse_x;
+    int current_mouse_y;
+    int down_mouse_x;
+    int down_mouse_y;
+    float down_mouse_z;
+    Eigen::Vector3f down_translation;
+    bool down;
+    bool hack_never_moved;
+#ifdef IGL_VIEWER_WITH_NANOGUI
+    nanogui::FormHelper* ngui;
+    nanogui::Screen* screen;
+#endif
+    // Keep track of the global position of the scrollwheel
+    float scroll_position;
     // C++-style functions
     //
     // Returns **true** if action should be cancelled.
@@ -141,7 +156,6 @@ namespace viewer
     // THESE SHOULD BE DEPRECATED:
     std::function<bool(Viewer& viewer, unsigned char key, int modifiers)> callback_key_down;
     std::function<bool(Viewer& viewer, unsigned char key, int modifiers)> callback_key_up;
-
     // Pointers to per-callback data
     void* callback_init_data;
     void* callback_pre_draw_data;
@@ -160,6 +174,7 @@ namespace viewer
 
 } // end namespace
 } // end namespace
+} // end namespace
 
 #ifndef IGL_STATIC_LIBRARY
 #  include "Viewer.cpp"

+ 6 - 3
include/igl/viewer/ViewerPlugin.h → include/igl/opengl/glfw/ViewerPlugin.h

@@ -5,8 +5,8 @@
 // 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/.
-#ifndef IGL_VIEWER_VIEWER_PLUGIN_H
-#define IGL_VIEWER_VIEWER_PLUGIN_H
+#ifndef IGL_OPENGL_GLFW_VIEWERPLUGIN_H
+#define IGL_OPENGL_GLFW_VIEWERPLUGIN_H
 
 // TODO:
 // * create plugins/skeleton.h
@@ -19,7 +19,9 @@
 
 namespace igl
 {
-namespace viewer
+namespace opengl
+{
+namespace glfw
 {
 
 // Abstract class for plugins
@@ -175,6 +177,7 @@ namespace serialization
 }
 #endif
 
+}
 }
 }
 

+ 9 - 2
include/igl/opengl/load_shader.cpp

@@ -10,8 +10,14 @@
 // Copyright Denis Kovacs 4/10/08
 #include "print_shader_info_log.h"
 #include <cstdio>
-IGL_INLINE GLuint igl::opengl::load_shader(const char *src,const GLenum type)
+IGL_INLINE GLuint igl::opengl::load_shader(
+  const std::string & src,const GLenum type)
 {
+  if(src.empty())
+  {
+    return (GLuint) 0;
+  }
+
   GLuint s = glCreateShader(type);
   if(s == 0)
   {
@@ -19,7 +25,8 @@ IGL_INLINE GLuint igl::opengl::load_shader(const char *src,const GLenum type)
     return 0;
   }
   // Pass shader source string
-  glShaderSource(s, 1, &src, NULL);
+  const char *c = src.c_str();
+  glShaderSource(s, 1, &c, NULL);
   glCompileShader(s);
   // Print info log (if any)
   igl::opengl::print_shader_info_log(s);

+ 6 - 1
include/igl/opengl/load_shader.h

@@ -9,12 +9,14 @@
 #define IGL_OPENGL_LOAD_SHADER_H
 #include "../igl_inline.h" 
 #include "gl.h"
+#include <string>
 
 namespace igl
 {
   namespace opengl
   {
     // Creates and compiles a shader from a given string
+    //
     // Inputs:
     //   src  string containing GLSL shader code
     //   type  GLSL type of shader, one of:
@@ -22,7 +24,10 @@ namespace igl
     //     GL_FRAGMENT_SHADER
     //     GL_GEOMETRY_SHADER
     // Returns  index id of the newly created shader, 0 on error
-    IGL_INLINE GLuint load_shader(const char *src,const GLenum type);
+    // 
+    // Will immediately return 0 if src is empty.
+    IGL_INLINE GLuint load_shader(
+      const std::string & src,const GLenum type);
   }
 }
 

+ 57 - 1
include/igl/serialize.h

@@ -1254,5 +1254,61 @@ namespace igl
     }
   }
 }
- 
+
+#include "ViewerData.h"
+namespace igl 
+{
+  namespace serialization
+  {
+    inline void serialization(bool s, igl::ViewerData& obj, std::vector<char>& buffer)
+    {
+      SERIALIZE_MEMBER(V);
+      SERIALIZE_MEMBER(F);
+      SERIALIZE_MEMBER(F_normals);
+      SERIALIZE_MEMBER(F_material_ambient);
+      SERIALIZE_MEMBER(F_material_diffuse);
+      SERIALIZE_MEMBER(F_material_specular);
+      SERIALIZE_MEMBER(V_normals);
+      SERIALIZE_MEMBER(V_material_ambient);
+      SERIALIZE_MEMBER(V_material_diffuse);
+      SERIALIZE_MEMBER(V_material_specular);
+      SERIALIZE_MEMBER(V_uv);
+      SERIALIZE_MEMBER(F_uv);
+      SERIALIZE_MEMBER(texture_R);
+      SERIALIZE_MEMBER(texture_G);
+      SERIALIZE_MEMBER(texture_B);
+      SERIALIZE_MEMBER(texture_A);
+      SERIALIZE_MEMBER(lines);
+      SERIALIZE_MEMBER(points);
+      SERIALIZE_MEMBER(labels_positions);
+      SERIALIZE_MEMBER(labels_strings);
+      SERIALIZE_MEMBER(dirty);
+      SERIALIZE_MEMBER(face_based);
+      SERIALIZE_MEMBER(show_faces);
+      SERIALIZE_MEMBER(show_lines);
+      SERIALIZE_MEMBER(invert_normals);
+      SERIALIZE_MEMBER(show_overlay);
+      SERIALIZE_MEMBER(show_overlay_depth);
+      SERIALIZE_MEMBER(show_vertid);
+      SERIALIZE_MEMBER(show_faceid);
+      SERIALIZE_MEMBER(show_texture);
+      SERIALIZE_MEMBER(point_size);
+      SERIALIZE_MEMBER(line_width);
+      SERIALIZE_MEMBER(line_color);
+      SERIALIZE_MEMBER(shininess);
+    }
+    template<>
+    inline void serialize(const igl::ViewerData& obj, std::vector<char>& buffer)
+    {
+      serialization(true, const_cast<igl::ViewerData&>(obj), buffer);
+    }
+    template<>
+    inline void deserialize(igl::ViewerData& obj, const std::vector<char>& buffer)
+    {
+      serialization(false, obj, const_cast<std::vector<char>&>(buffer));
+      obj.dirty = igl::ViewerData::DIRTY_ALL;
+    }
+  }
+}
+
 #endif

+ 0 - 173
include/igl/viewer/OpenGL_shader.cpp

@@ -1,173 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Wenzel Jacob <wenzel@inf.ethz.ch>
-//
-// 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 "OpenGL_shader.h"
-
-#include <iostream>
-#include <fstream>
-
-IGL_INLINE bool igl::viewer::OpenGL_shader::init_from_files(
-  const std::string &vertex_shader_filename,
-  const std::string &fragment_shader_filename,
-  const std::string &fragment_data_name,
-  const std::string &geometry_shader_filename,
-  int geometry_shader_max_vertices)
-{
-  auto file_to_string = [](const std::string &filename)->std::string
-  {
-    std::ifstream t(filename);
-    return std::string((std::istreambuf_iterator<char>(t)),
-                        std::istreambuf_iterator<char>());
-  };
-
-  return init(
-    file_to_string(vertex_shader_filename),
-    file_to_string(fragment_shader_filename),
-    fragment_data_name,
-    file_to_string(geometry_shader_filename),
-    geometry_shader_max_vertices
- );
-}
-
-IGL_INLINE bool igl::viewer::OpenGL_shader::init(
-  const std::string &vertex_shader_string,
-  const std::string &fragment_shader_string,
-  const std::string &fragment_data_name,
-  const std::string &geometry_shader_string,
-  int geometry_shader_max_vertices)
-{
-  using namespace std;
-  vertex_shader = create_shader_helper(GL_VERTEX_SHADER, vertex_shader_string);
-  geometry_shader = create_shader_helper(GL_GEOMETRY_SHADER, geometry_shader_string);
-  fragment_shader = create_shader_helper(GL_FRAGMENT_SHADER, fragment_shader_string);
-
-  if (!vertex_shader || !fragment_shader)
-    return false;
-
-  program_shader = glCreateProgram();
-
-  glAttachShader(program_shader, vertex_shader);
-  glAttachShader(program_shader, fragment_shader);
-
-  if (geometry_shader)
-  {
-    glAttachShader(program_shader, geometry_shader);
-
-    /* This covers only basic cases and may need to be modified */
-    glProgramParameteri(program_shader, GL_GEOMETRY_INPUT_TYPE, GL_TRIANGLES);
-    glProgramParameteri(program_shader, GL_GEOMETRY_OUTPUT_TYPE, GL_TRIANGLES);
-    glProgramParameteri(program_shader, GL_GEOMETRY_VERTICES_OUT, geometry_shader_max_vertices);
-  }
-
-  glBindFragDataLocation(program_shader, 0, fragment_data_name.c_str());
-  glLinkProgram(program_shader);
-
-  GLint status;
-  glGetProgramiv(program_shader, GL_LINK_STATUS, &status);
-
-  if (status != GL_TRUE)
-  {
-    char buffer[512];
-    glGetProgramInfoLog(program_shader, 512, NULL, buffer);
-    cerr << "Linker error: " << endl << buffer << endl;
-    program_shader = 0;
-    return false;
-  }
-
-  return true;
-}
-
-IGL_INLINE void igl::viewer::OpenGL_shader::bind()
-{
-  glUseProgram(program_shader);
-}
-
-IGL_INLINE GLint igl::viewer::OpenGL_shader::attrib(const std::string &name) const
-{
-  return glGetAttribLocation(program_shader, name.c_str());
-}
-
-IGL_INLINE GLint igl::viewer::OpenGL_shader::uniform(const std::string &name) const
-{
-  return glGetUniformLocation(program_shader, name.c_str());
-}
-
-IGL_INLINE GLint igl::viewer::OpenGL_shader::bindVertexAttribArray(
-  const std::string &name, GLuint bufferID, const Eigen::MatrixXf &M, bool refresh) const
-{
-  GLint id = attrib(name);
-  if (id < 0)
-    return id;
-  if (M.size() == 0)
-  {
-    glDisableVertexAttribArray(id);
-    return id;
-  }
-  glBindBuffer(GL_ARRAY_BUFFER, bufferID);
-  if (refresh)
-    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*M.size(), M.data(), GL_DYNAMIC_DRAW);
-  glVertexAttribPointer(id, M.rows(), GL_FLOAT, GL_FALSE, 0, 0);
-  glEnableVertexAttribArray(id);
-  return id;
-}
-
-IGL_INLINE void igl::viewer::OpenGL_shader::free()
-{
-  if (program_shader)
-  {
-    glDeleteProgram(program_shader);
-    program_shader = 0;
-  }
-  if (vertex_shader)
-  {
-    glDeleteShader(vertex_shader);
-    vertex_shader = 0;
-  }
-  if (fragment_shader)
-  {
-    glDeleteShader(fragment_shader);
-    fragment_shader = 0;
-  }
-  if (geometry_shader)
-  {
-    glDeleteShader(geometry_shader);
-    geometry_shader = 0;
-  }
-}
-
-IGL_INLINE GLuint igl::viewer::OpenGL_shader::create_shader_helper(GLint type, const std::string &shader_string)
-{
-  using namespace std;
-  if (shader_string.empty())
-    return (GLuint) 0;
-
-  GLuint id = glCreateShader(type);
-  const char *shader_string_const = shader_string.c_str();
-  glShaderSource(id, 1, &shader_string_const, NULL);
-  glCompileShader(id);
-
-  GLint status;
-  glGetShaderiv(id, GL_COMPILE_STATUS, &status);
-
-  if (status != GL_TRUE)
-  {
-    char buffer[512];
-    if (type == GL_VERTEX_SHADER)
-      cerr << "Vertex shader:" << endl;
-    else if (type == GL_FRAGMENT_SHADER)
-      cerr << "Fragment shader:" << endl;
-    else if (type == GL_GEOMETRY_SHADER)
-      cerr << "Geometry shader:" << endl;
-    cerr << shader_string << endl << endl;
-    glGetShaderInfoLog(id, 512, NULL, buffer);
-    cerr << "Error: " << endl << buffer << endl;
-    return (GLuint) 0;
-  }
-
-  return id;
-}

+ 0 - 98
include/igl/viewer/OpenGL_shader.h

@@ -1,98 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Wenzel Jacob <wenzel@inf.ethz.ch>
-//
-// 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/.
-
-#ifndef IGL_VIEWER_OPENGL_SHADER_H
-#define IGL_VIEWER_OPENGL_SHADER_H
-
-#include <igl/igl_inline.h>
-#include <string>
-#include <Eigen/Core>
-
-#ifdef _WIN32
-#  include <windows.h>
-#  undef max
-#  undef min
-#  undef DrawText
-#endif
-
-#ifndef __APPLE__
-#  define GLEW_STATIC
-#  include <GL/glew.h>
-#endif
-
-#ifdef __APPLE__
-#   include <OpenGL/gl3.h>
-#   define __gl_h_ /* Prevent inclusion of the old gl.h */
-#else
-#   include <GL/gl.h>
-#endif
-
-namespace igl
-{
-namespace viewer
-{
-
-// This class wraps an OpenGL program composed of three shaders
-// TODO: write documentation
-
-class OpenGL_shader
-{
-public:
-  typedef unsigned int GLuint;
-  typedef int GLint;
-
-  GLuint vertex_shader;
-  GLuint fragment_shader;
-  GLuint geometry_shader;
-  GLuint program_shader;
-
-  IGL_INLINE OpenGL_shader() : vertex_shader(0), fragment_shader(0),
-    geometry_shader(0), program_shader(0) { }
-
-  // Create a new shader from the specified source strings
-  IGL_INLINE bool init(const std::string &vertex_shader_string,
-    const std::string &fragment_shader_string,
-    const std::string &fragment_data_name,
-    const std::string &geometry_shader_string = "",
-    int geometry_shader_max_vertices = 3);
-
-  // Create a new shader from the specified files on disk
-  IGL_INLINE bool init_from_files(const std::string &vertex_shader_filename,
-    const std::string &fragment_shader_filename,
-    const std::string &fragment_data_name,
-    const std::string &geometry_shader_filename = "",
-    int geometry_shader_max_vertices = 3);
-
-  // Select this shader for subsequent draw calls
-  IGL_INLINE void bind();
-
-  // Release all OpenGL objects
-  IGL_INLINE void free();
-
-  // Return the OpenGL handle of a named shader attribute (-1 if it does not exist)
-  IGL_INLINE GLint attrib(const std::string &name) const;
-
-  // Return the OpenGL handle of a uniform attribute (-1 if it does not exist)
-  IGL_INLINE GLint uniform(const std::string &name) const;
-
-  // Bind a per-vertex array attribute and refresh its contents from an Eigen amtrix
-  IGL_INLINE GLint bindVertexAttribArray(const std::string &name, GLuint bufferID,
-    const Eigen::MatrixXf &M, bool refresh) const;
-
-  IGL_INLINE GLuint create_shader_helper(GLint type, const std::string &shader_string);
-
-};
-
-}
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "OpenGL_shader.cpp"
-#endif
-
-#endif

+ 0 - 33
include/igl/viewer/TODOs.txt

@@ -1,33 +0,0 @@
-- `align_and_center_object` continues to zoom out on repeated calls
-- trackball_angle should be a quaternion
-- data.lines, data.points should not concatenate colors with coordinates
-- snap to canonical recenters origin but trackball does not
-- rewrite in libigl style
-- separate various class into their own .h/.cpp pairs
-- remove use of double underscores (http://stackoverflow.com/a/224420/148668)
-- document inputs and outputs to all functions
-- document all member fields
-- document all classes
-- light direction is backwards
-- remove global variables (not threadsafe)
-- encapsulate (in igl namespace) and move static/global functions, use lambdas?
-- preface macros with "IGL_"
-- trackball mouseup captured by tweakbar
-- zoom with pan rather than scaling
-- refresh draw while resizing
-- use constructor initializer list rather than complicated constructor
-- support per-element alpha values
-+ snap to canonical view key shortcut is not working
-+ resize TwBar with window
-+ trackball should be able to drag over TwBar
-+ don't zoom on horizontal scale
-+ remove global `using namespace std`
-+ remove `#define IGL_HEADER_ONLY`
-+ guard `#undef max`
-+ fix all -Wsign-compare
-+ missing `#include <iostream>`
-+ missing `#include <fstream>`
-+ fix all -Wunused-but-set-variable
-+ makefile for libiglviewer.a
-+ Viewer.h should include Viewer.cpp
-+ depth test for overlays cannot be disabled

+ 27 - 43
shared/cmake/CMakeLists.txt

@@ -19,14 +19,9 @@ option(LIBIGL_WITH_OPENGL_GLFW      "Use GLFW"           OFF)
 option(LIBIGL_WITH_PNG              "Use PNG"            OFF)
 option(LIBIGL_WITH_TETGEN           "Use Tetgen"         OFF)
 option(LIBIGL_WITH_TRIANGLE         "Use Triangle"       OFF)
-option(LIBIGL_WITH_VIEWER           "Use OpenGL viewer"  OFF)
 option(LIBIGL_WITH_XML              "Use XML"            OFF)
 option(LIBIGL_WITH_PYTHON           "Use Python"         OFF)
 
-if(LIBIGL_WITH_VIEWER AND (NOT LIBIGL_WITH_OPENGL_GLFW OR NOT LIBIGL_WITH_OPENGL) )
-  message(FATAL_ERROR "LIBIGL_WITH_VIEWER=ON requires LIBIGL_WITH_OPENGL_GLFW=ON and LIBIGL_WITH_OPENGL=ON")
-endif()
-
 ### Compilation configuration ###
 if(MSVC)
   ### Enable parallel compilation for Visual Studio
@@ -376,12 +371,36 @@ if(LIBIGL_WITH_OPENGL)
     # Note: if add_subdirectory("${NANOGUI_DIR}" "nanogui") runs below it will
     # add GLFW as a side-effect; in this case, CMake will complain about
     # duplicates if we add them here.
-    if (NOT (LIBIGL_WITH_VIEWER AND LIBIGL_WITH_NANOGUI))
-        add_subdirectory("${NANOGUI_DIR}/ext/glfw" "glfw")
-    endif()
     set(LIBIGL_OPENGL_GLFW_EXTRA_LIBRARIES "glfw" ${GLFW_LIBRARIES})
+
+    ### Compile the viewer with NANOGUI support ###
+    if(LIBIGL_WITH_NANOGUI)
+      list(APPEND LIBIGL_DEFINITIONS "-DIGL_VIEWER_WITH_NANOGUI")
+      if (LIBIGL_WITH_PYTHON)
+        set(NANOGUI_BUILD_PYTHON ON CACHE BOOL " " FORCE)
+      else()
+        set(NANOGUI_BUILD_PYTHON OFF CACHE BOOL " " FORCE)
+      endif()
+      set(NANOGUI_BUILD_EXAMPLE OFF CACHE BOOL " " FORCE)
+      set(NANOGUI_BUILD_SHARED  OFF CACHE BOOL " " FORCE)
+      add_subdirectory("${NANOGUI_DIR}" "nanogui")
+      set(NANOGUI_INCLUDE_DIRS
+        "${NANOGUI_DIR}/include"
+        "${NANOGUI_DIR}/ext/nanovg/src")
+      list(APPEND GLFW_INCLUDE_DIRS "${NANOGUI_INCLUDE_DIRS}")
+      list(APPEND LIBIGL_OPENGL_GLFW_EXTRA_LIBRARIES "nanogui" ${NANOGUI_EXTRA_LIBS})
+    else()
+      add_subdirectory("${NANOGUI_DIR}/ext/glfw" "glfw")
+    endif()
+    list(APPEND VIEWER_INCLUDE_DIRS ${GLFW_INCLUDE_DIRS})
+    list(APPEND LIBIGL_INCLUDE_DIRS ${VIEWER_INCLUDE_DIRS})
+    list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_VIEWER_EXTRA_LIBRARIES})
+
     if(LIBIGL_USE_STATIC_LIBRARY)
       CompileIGL_Module("opengl/glfw" "")
+      if(LIBIGL_WITH_NANOGUI)
+        target_compile_definitions(igl_opengl_glfw PRIVATE -DIGL_VIEWER_WITH_NANOGUI)
+      endif()
       target_include_directories(igl_opengl_glfw PRIVATE ${GLFW_INCLUDE_DIRS})
       target_include_directories(igl_opengl_glfw PRIVATE ${OPENGL_INCLUDE_DIR})
       if(NOT APPLE)
@@ -390,40 +409,6 @@ if(LIBIGL_WITH_OPENGL)
     endif()
     list(APPEND LIBIGL_INCLUDE_DIRS ${GLFW_INCLUDE_DIRS})
     list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_OPENGL_GLFW_EXTRA_LIBRARIES})
-
-    ### Compile the viewer ###
-    if(LIBIGL_WITH_VIEWER)
-      if(LIBIGL_WITH_NANOGUI)
-        list(APPEND LIBIGL_DEFINITIONS "-DIGL_VIEWER_WITH_NANOGUI")
-        if (LIBIGL_WITH_PYTHON)
-          set(NANOGUI_BUILD_PYTHON ON CACHE BOOL " " FORCE)
-        else()
-          set(NANOGUI_BUILD_PYTHON OFF CACHE BOOL " " FORCE)
-        endif()
-        set(NANOGUI_BUILD_EXAMPLE OFF CACHE BOOL " " FORCE)
-        set(NANOGUI_BUILD_SHARED  OFF CACHE BOOL " " FORCE)
-        add_subdirectory("${NANOGUI_DIR}" "nanogui")
-        set(VIEWER_INCLUDE_DIRS
-          "${NANOGUI_DIR}/include"
-          "${NANOGUI_DIR}/ext/nanovg/src")
-        set(LIBIGL_VIEWER_EXTRA_LIBRARIES "nanogui" ${NANOGUI_EXTRA_LIBS})
-      else()
-        set(VIEWER_INCLUDE_DIRS "${NANOGUI_DIR}/ext/glfw/include")
-      endif()
-      list(APPEND VIEWER_INCLUDE_DIRS ${GLFW_INCLUDE_DIRS})
-      list(APPEND LIBIGL_INCLUDE_DIRS ${VIEWER_INCLUDE_DIRS})
-      list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_VIEWER_EXTRA_LIBRARIES})
-      if(LIBIGL_USE_STATIC_LIBRARY)
-        CompileIGL_Module("viewer" "")
-        if(LIBIGL_WITH_NANOGUI)
-          target_compile_definitions(igl_viewer PRIVATE -DIGL_VIEWER_WITH_NANOGUI)
-        endif()
-        target_include_directories(igl_viewer PRIVATE ${VIEWER_INCLUDE_DIRS})
-        if(NOT APPLE)
-          target_include_directories(igl_viewer PRIVATE "${NANOGUI_DIR}/ext/glew/include")
-        endif()
-      endif()
-    endif()
   endif()
 
 endif()
@@ -521,7 +506,6 @@ if(NOT ${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
   set(LIBIGL_PNG_EXTRA_LIBRARIES         ${LIBIGL_PNG_EXTRA_LIBRARIES}         PARENT_SCOPE)
   set(LIBIGL_TETGEN_EXTRA_LIBRARIES      ${LIBIGL_TETGEN_EXTRA_LIBRARIES}      PARENT_SCOPE)
   set(LIBIGL_TRIANGLE_EXTRA_LIBRARIES    ${LIBIGL_TRIANGLE_EXTRA_LIBRARIES}    PARENT_SCOPE)
-  set(LIBIGL_VIEWER_EXTRA_LIBRARIES      ${LIBIGL_VIEWER_EXTRA_LIBRARIES}      PARENT_SCOPE)
   set(LIBIGL_XML_EXTRA_LIBRARIES         ${LIBIGL_XML_EXTRA_LIBRARIES}         PARENT_SCOPE)
   set(LIBIGL_EXTRA_LIBRARIES ${LIBIGL_EXTRA_LIBRARIES} PARENT_SCOPE)
   set(LIBIGL_DEFINITIONS ${LIBIGL_DEFINITIONS} PARENT_SCOPE)

+ 0 - 16
shared/cmake/libigl.cmake

@@ -16,14 +16,9 @@ option(LIBIGL_WITH_OPENGL_GLFW      "Use GLFW"           ON)
 option(LIBIGL_WITH_PNG              "Use PNG"            ON)
 option(LIBIGL_WITH_TETGEN           "Use Tetgen"         ON)
 option(LIBIGL_WITH_TRIANGLE         "Use Triangle"       ON)
-option(LIBIGL_WITH_VIEWER           "Use OpenGL viewer"  ON)
 option(LIBIGL_WITH_XML              "Use XML"            ON)
 option(LIBIGL_WITH_PYTHON           "Use Python"         OFF)
 
-if(LIBIGL_WITH_VIEWER AND (NOT LIBIGL_WITH_OPENGL_GLFW OR NOT LIBIGL_WITH_OPENGL) )
-  message(FATAL_ERROR "LIBIGL_WITH_VIEWER=ON requires LIBIGL_WITH_OPENGL_GLFW=ON and LIBIGL_WITH_OPENGL=ON")
-endif()
-
 ################################################################################
 
 ### Configuration
@@ -324,17 +319,6 @@ if(LIBIGL_WITH_OPENGL)
     target_link_libraries(igl_opengl_glfw ${IGL_SCOPE} igl_opengl glfw)
   endif()
 
-  # Viewer module
-  if(LIBIGL_WITH_VIEWER)
-    compile_igl_module("viewer")
-    target_link_libraries(igl_viewer ${IGL_SCOPE} glfw glew ${OPENGL_gl_LIBRARY})
-    target_include_directories(igl_viewer SYSTEM ${IGL_SCOPE} ${OPENGL_INCLUDE_DIR})
-    if(TARGET nanogui)
-      target_link_libraries(igl_viewer ${IGL_SCOPE} nanogui)
-      target_compile_definitions(igl_viewer ${IGL_SCOPE} -DIGL_VIEWER_WITH_NANOGUI)
-    endif()
-  endif()
-
 endif()
 
 ################################################################################

+ 1 - 1
tutorial/102_DrawMesh/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(102_DrawMesh)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 3 - 3
tutorial/102_DrawMesh/main.cpp

@@ -1,5 +1,5 @@
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include "tutorial_shared_path.h"
 
 Eigen::MatrixXd V;
@@ -11,7 +11,7 @@ int main(int argc, char *argv[])
   igl::readOFF(TUTORIAL_SHARED_PATH "/bunny.off", V, F);
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
   viewer.launch();
 }

+ 1 - 1
tutorial/103_Events/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(103_Events)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 8 - 8
tutorial/103_Events/main.cpp

@@ -1,5 +1,5 @@
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <iostream>
 #include "tutorial_shared_path.h"
 
@@ -7,23 +7,23 @@ Eigen::MatrixXd V1,V2;
 Eigen::MatrixXi F1,F2;
 
 // This function is called every time a keyboard button is pressed
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   std::cout<<"Key: "<<key<<" "<<(unsigned int)key<<std::endl;
   if (key == '1')
   {
     // Clear should be called before drawing the mesh
-    viewer.data.clear();
+    viewer.selected_data().clear();
     // Draw_mesh creates or updates the vertices and faces of the displayed mesh.
     // If a mesh is already displayed, draw_mesh returns an error if the given V and
     // F have size different than the current ones
-    viewer.data.set_mesh(V1, F1);
+    viewer.selected_data().set_mesh(V1, F1);
     viewer.core.align_camera_center(V1,F1);
   }
   else if (key == '2')
   {
-    viewer.data.clear();
-    viewer.data.set_mesh(V2, F2);
+    viewer.selected_data().clear();
+    viewer.selected_data().set_mesh(V2, F2);
     viewer.core.align_camera_center(V2,F2);
   }
 
@@ -41,10 +41,10 @@ int main(int argc, char *argv[])
 2 Switch to fertility mesh
     )";
 
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
   // Register a keyboard callback that allows to switch between
   // the two loaded meshes
   viewer.callback_key_down = &key_down;
-  viewer.data.set_mesh(V1, F1);
+  viewer.selected_data().set_mesh(V1, F1);
   viewer.launch();
 }

+ 1 - 1
tutorial/104_Colors/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(104_Colors)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 4 - 4
tutorial/104_Colors/main.cpp

@@ -1,5 +1,5 @@
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/jet.h>
 #include "tutorial_shared_path.h"
 
@@ -13,8 +13,8 @@ int main(int argc, char *argv[])
   igl::readOFF(TUTORIAL_SHARED_PATH "/screwdriver.off", V, F);
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
 
   // Use the z coordinate as a scalar field over the surface
   Eigen::VectorXd Z = V.col(2);
@@ -23,7 +23,7 @@ int main(int argc, char *argv[])
   igl::jet(Z,true,C);
 
   // Add per-vertex colors
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 
   // Launch the viewer
   viewer.launch();

+ 1 - 1
tutorial/105_Overlays/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(105_Overlays)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 7 - 7
tutorial/105_Overlays/main.cpp

@@ -1,5 +1,5 @@
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <sstream>
 #include "tutorial_shared_path.h"
 
@@ -44,15 +44,15 @@ int main(int argc, char *argv[])
   7 ,3;
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
 
   // Plot the corners of the bounding box as points
-  viewer.data.add_points(V_box,Eigen::RowVector3d(1,0,0));
+  viewer.selected_data().add_points(V_box,Eigen::RowVector3d(1,0,0));
 
   // Plot the edges of the bounding box
   for (unsigned i=0;i<E_box.rows(); ++i)
-    viewer.data.add_edges
+    viewer.selected_data().add_edges
     (
       V_box.row(E_box(i,0)),
       V_box.row(E_box(i,1)),
@@ -62,10 +62,10 @@ int main(int argc, char *argv[])
   // Plot labels with the coordinates of bounding box vertices
   std::stringstream l1;
   l1 << m(0) << ", " << m(1) << ", " << m(2);
-  viewer.data.add_label(m,l1.str());
+  viewer.selected_data().add_label(m,l1.str());
   std::stringstream l2;
   l2 << M(0) << ", " << M(1) << ", " << M(2);
-  viewer.data.add_label(M,l2.str());
+  viewer.selected_data().add_label(M,l2.str());
 
   // Launch the viewer
   viewer.launch();

+ 1 - 1
tutorial/106_ViewerMenu/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(106_ViewerMenu)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 4 - 4
tutorial/106_ViewerMenu/main.cpp

@@ -9,7 +9,7 @@ int main()
 #else
 
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <nanogui/formhelper.h>
 #include <nanogui/screen.h>
 #include <iostream>
@@ -28,10 +28,10 @@ int main(int argc, char *argv[])
   igl::readOFF(TUTORIAL_SHARED_PATH "/bunny.off", V, F);
 
   // Init the viewer
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
 
   // Extend viewer menu
-  viewer.callback_init = [&](igl::viewer::Viewer& viewer)
+  viewer.callback_init = [&](igl::opengl::glfw::Viewer& viewer)
   {
     // Add new group
     viewer.ngui->addGroup("New Group");
@@ -65,7 +65,7 @@ int main(int argc, char *argv[])
   };
 
   // Plot the mesh
-  viewer.data.set_mesh(V, F);
+  viewer.selected_data().set_mesh(V, F);
   viewer.launch();
 }
 #endif

+ 5 - 0
tutorial/107_MultipleMeshes/CMakeLists.txt

@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(107_MultipleMeshes)
+
+add_executable(${PROJECT_NAME}_bin main.cpp)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 40 - 0
tutorial/107_MultipleMeshes/main.cpp

@@ -0,0 +1,40 @@
+#include "tutorial_shared_path.h"
+#include <igl/opengl/glfw/Viewer.h>
+#include <string>
+#include <iostream>
+
+int main(int argc, char * argv[])
+{
+  igl::opengl::glfw::Viewer viewer;
+  const auto names = 
+    {"cube.obj","sphere.obj","xcylinder.obj","ycylinder.obj","zcylinder.obj"};
+  for(const auto & name : names)
+  {
+    viewer.load_mesh_from_file(std::string(TUTORIAL_SHARED_PATH) + "/" + name);
+  }
+
+  // Set colors of each mesh by selecting its index first
+  viewer.selected_data_index = 0;
+  viewer.selected_data().set_colors(Eigen::RowVector3d(0.8,0.47,0.22));
+  viewer.selected_data_index = 1;
+  viewer.selected_data().set_colors(Eigen::RowVector3d(0.6,0.01,0.11));
+  viewer.selected_data_index = 2;
+  viewer.selected_data().set_colors(Eigen::RowVector3d(0.37,0.06,0.25));
+  viewer.selected_data_index = 3;
+  viewer.selected_data().set_colors(Eigen::RowVector3d(1,1,1));
+
+  viewer.callback_key_down = 
+    [&](igl::opengl::glfw::Viewer &, unsigned int key, int mod)
+  {
+    // Delete
+    if(key == 3)
+    {
+      viewer.erase_mesh(viewer.selected_data_index);
+      return true;
+    }
+    return false;
+  };
+
+  viewer.launch();
+  return EXIT_SUCCESS;
+}

+ 1 - 1
tutorial/201_Normals/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(201_Normals)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 9 - 9
tutorial/201_Normals/main.cpp

@@ -1,5 +1,5 @@
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/per_vertex_normals.h>
 #include <igl/per_face_normals.h>
 #include <igl/per_corner_normals.h>
@@ -15,18 +15,18 @@ Eigen::MatrixXd N_corners;
 
 
 // This function is called every time a keyboard button is pressed
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   switch(key)
   {
     case '1':
-      viewer.data.set_normals(N_faces);
+      viewer.selected_data().set_normals(N_faces);
       return true;
     case '2':
-      viewer.data.set_normals(N_vertices);
+      viewer.selected_data().set_normals(N_vertices);
       return true;
     case '3':
-      viewer.data.set_normals(N_corners);
+      viewer.selected_data().set_normals(N_corners);
       return true;
     default: break;
   }
@@ -48,11 +48,11 @@ int main(int argc, char *argv[])
   igl::per_corner_normals(V,F,20,N_corners);
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
   viewer.callback_key_down = &key_down;
-  viewer.core.show_lines = false;
-  viewer.data.set_mesh(V, F);
-  viewer.data.set_normals(N_faces);
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().set_normals(N_faces);
   std::cout<<
     "Press '1' for per-face normals."<<std::endl<<
     "Press '2' for per-vertex normals."<<std::endl<<

+ 1 - 1
tutorial/202_GaussianCurvature/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(202_GaussianCurvature)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 4 - 4
tutorial/202_GaussianCurvature/main.cpp

@@ -2,7 +2,7 @@
 #include <igl/massmatrix.h>
 #include <igl/invert_diag.h>
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/jet.h>
 #include "tutorial_shared_path.h"
 
@@ -29,8 +29,8 @@ int main(int argc, char *argv[])
   igl::jet(K,true,C);
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.data.set_colors(C);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().set_colors(C);
   viewer.launch();
 }

+ 1 - 1
tutorial/203_CurvatureDirections/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(203_CurvatureDirections)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 7 - 7
tutorial/203_CurvatureDirections/main.cpp

@@ -8,7 +8,7 @@
 #include <igl/per_vertex_normals.h>
 #include <igl/principal_curvature.h>
 #include <igl/read_triangle_mesh.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include "tutorial_shared_path.h"
 
 Eigen::MatrixXd V;
@@ -43,27 +43,27 @@ int main(int argc, char *argv[])
   // mean curvature
   H = 0.5*(PV1+PV2);
 
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
 
 
   // Compute pseudocolor
   MatrixXd C;
   igl::parula(H,true,C);
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 
   // Average edge length for sizing
   const double avg = igl::avg_edge_length(V,F);
 
   // Draw a blue segment parallel to the minimal curvature direction
   const RowVector3d red(0.8,0.2,0.2),blue(0.2,0.2,0.8);
-  viewer.data.add_edges(V + PD1*avg, V - PD1*avg, blue);
+  viewer.selected_data().add_edges(V + PD1*avg, V - PD1*avg, blue);
 
   // Draw a red segment parallel to the maximal curvature direction
-  viewer.data.add_edges(V + PD2*avg, V - PD2*avg, red);
+  viewer.selected_data().add_edges(V + PD2*avg, V - PD2*avg, red);
 
   // Hide wireframe
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
 
   viewer.launch();
 }

+ 1 - 1
tutorial/204_Gradient/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(204_Gradient)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 6 - 6
tutorial/204_Gradient/main.cpp

@@ -4,7 +4,7 @@
 #include <igl/jet.h>
 #include <igl/readDMAT.h>
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include <iostream>
 #include "tutorial_shared_path.h"
@@ -32,15 +32,15 @@ int main(int argc, char *argv[])
   // Compute gradient magnitude
   const VectorXd GU_mag = GU.rowwise().norm();
 
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
 
   // Compute pseudocolor for original function
   MatrixXd C;
   igl::jet(U,true,C);
   // // Or for gradient magnitude
   //igl::jet(GU_mag,true,C);
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 
   // Average edge length divided by average gradient (for scaling)
   const double max_size = igl::avg_edge_length(V,F) / GU_mag.mean();
@@ -48,10 +48,10 @@ int main(int argc, char *argv[])
   MatrixXd BC;
   igl::barycenter(V,F,BC);
   const RowVector3d black(0,0,0);
-  viewer.data.add_edges(BC,BC+max_size*GU, black);
+  viewer.selected_data().add_edges(BC,BC+max_size*GU, black);
 
   // Hide wireframe
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
 
   viewer.launch();
 }

+ 1 - 1
tutorial/205_Laplacian/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(205_Laplacian)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 7 - 7
tutorial/205_Laplacian/main.cpp

@@ -8,7 +8,7 @@
 #include <igl/readDMAT.h>
 #include <igl/readOFF.h>
 #include <igl/repdiag.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include <iostream>
 #include "tutorial_shared_path.h"
@@ -16,7 +16,7 @@
 Eigen::MatrixXd V,U;
 Eigen::MatrixXi F;
 Eigen::SparseMatrix<double> L;
-igl::viewer::Viewer viewer;
+igl::opengl::glfw::Viewer viewer;
 
 int main(int argc, char *argv[])
 {
@@ -43,7 +43,7 @@ int main(int argc, char *argv[])
   K = -G.transpose() * T * G;
   cout<<"|K-L|: "<<(K-L).norm()<<endl;
 
-  const auto &key_down = [](igl::viewer::Viewer &viewer,unsigned char key,int mod)->bool
+  const auto &key_down = [](igl::opengl::glfw::Viewer &viewer,unsigned char key,int mod)->bool
   {
     switch(key)
     {
@@ -81,8 +81,8 @@ int main(int argc, char *argv[])
         return false;
     }
     // Send new positions, update normals, recenter
-    viewer.data.set_vertices(U);
-    viewer.data.compute_normals();
+    viewer.selected_data().set_vertices(U);
+    viewer.selected_data().compute_normals();
     viewer.core.align_camera_center(U,F);
     return true;
   };
@@ -95,8 +95,8 @@ int main(int argc, char *argv[])
 
   // Initialize smoothing with base mesh
   U = V;
-  viewer.data.set_mesh(U, F);
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_mesh(U, F);
+  viewer.selected_data().set_colors(C);
   viewer.callback_key_down = key_down;
 
   cout<<"Press [space] to smooth."<<endl;;

+ 1 - 1
tutorial/301_Slice/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(301_Slice)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 4 - 4
tutorial/301_Slice/main.cpp

@@ -2,7 +2,7 @@
 #include <igl/readOFF.h>
 #include <igl/slice.h>
 #include <igl/slice_into.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <iostream>
 #include "tutorial_shared_path.h"
 
@@ -34,8 +34,8 @@ int main(int argc, char *argv[])
   igl::slice_into(R,K,1,C);
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.data.set_colors(C);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().set_colors(C);
   viewer.launch();
 }

+ 1 - 1
tutorial/302_Sort/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(302_Sort)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 4 - 4
tutorial/302_Sort/main.cpp

@@ -4,7 +4,7 @@
 #include <igl/readOFF.h>
 #include <igl/slice_into.h>
 #include <igl/sortrows.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <iostream>
 #include "tutorial_shared_path.h"
 
@@ -32,8 +32,8 @@ int main(int argc, char *argv[])
   igl::jet(J,true,C);
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.data.set_colors(C);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().set_colors(C);
   viewer.launch();
 }

+ 1 - 1
tutorial/303_LaplaceEquation/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(303_LaplaceEquation)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 5 - 5
tutorial/303_LaplaceEquation/main.cpp

@@ -8,7 +8,7 @@
 #include <igl/slice.h>
 #include <igl/slice_into.h>
 #include <igl/unique.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <Eigen/Sparse>
 #include <iostream>
 #include "tutorial_shared_path.h"
@@ -65,9 +65,9 @@ int main(int argc, char *argv[])
   igl::jet(Z,true,C);
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.core.show_lines = false;
-  viewer.data.set_colors(C);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().set_colors(C);
   viewer.launch();
 }

+ 1 - 1
tutorial/304_LinearEqualityConstraints/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(304_LinearEqualityConstraints)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 7 - 7
tutorial/304_LinearEqualityConstraints/main.cpp

@@ -5,7 +5,7 @@
 #include <igl/massmatrix.h>
 #include <igl/min_quad_with_fixed.h>
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <Eigen/Sparse>
 #include <iostream>
 #include "tutorial_shared_path.h"
@@ -72,19 +72,19 @@ int main(int argc, char *argv[])
   igl::jet(Z_const,min_z,max_z,data.C_const);
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.core.show_lines = false;
-  viewer.data.set_colors(data.C);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().set_colors(data.C);
 
   viewer.callback_key_down = 
-    [](igl::viewer::Viewer& viewer,unsigned char key,int mod)->bool
+    [](igl::opengl::glfw::Viewer& viewer,unsigned char key,int mod)->bool
     {
       if(key == ' ')
       {
         Data & data = *static_cast<Data*>(viewer.callback_key_down_data);
         static bool toggle = true;
-        viewer.data.set_colors(toggle?data.C_const:data.C);
+        viewer.selected_data().set_colors(toggle?data.C_const:data.C);
         toggle = !toggle;
         return true;
       }else

+ 1 - 1
tutorial/305_QuadraticProgramming/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(305_QuadraticProgramming)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 7 - 7
tutorial/305_QuadraticProgramming/main.cpp

@@ -5,7 +5,7 @@
 #include <igl/jet.h>
 #include <igl/massmatrix.h>
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <Eigen/Sparse>
 #include <iostream>
 #include "tutorial_shared_path.h"
@@ -14,7 +14,7 @@ Eigen::VectorXi b;
 Eigen::VectorXd B,bc,lx,ux,Beq,Bieq,Z;
 Eigen::SparseMatrix<double> Q,Aeq,Aieq;
 
-void solve(igl::viewer::Viewer &viewer)
+void solve(igl::opengl::glfw::Viewer &viewer)
 {
   using namespace std;
   igl::active_set_params as;
@@ -23,10 +23,10 @@ void solve(igl::viewer::Viewer &viewer)
   // Pseudo-color based on solution
   Eigen::MatrixXd C;
   igl::jet(Z,0,1,C);
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 }
 
-bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mod)
+bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mod)
 {
   switch(key)
   {
@@ -56,9 +56,9 @@ int main(int argc, char *argv[])
   igl::readOFF(TUTORIAL_SHARED_PATH "/cheburashka.off",V,F);
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.core.show_lines = false;
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().show_lines = false;
   viewer.callback_key_down = &key_down;
 
   // One fixed point

+ 1 - 1
tutorial/306_EigenDecomposition/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(306_EigenDecomposition)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 7 - 7
tutorial/306_EigenDecomposition/main.cpp

@@ -1,7 +1,7 @@
 #include <igl/eigs.h>
 #include <igl/cotmatrix.h>
 #include <igl/massmatrix.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/parula.h>
 #include <igl/read_triangle_mesh.h>
 #include <Eigen/Sparse>
@@ -38,8 +38,8 @@ int main(int argc, char * argv[])
   }
   U = ((U.array()-U.minCoeff())/(U.maxCoeff()-U.minCoeff())).eval();
 
-  igl::viewer::Viewer viewer;
-  viewer.callback_key_down = [&](igl::viewer::Viewer & viewer,unsigned char key,int)->bool
+  igl::opengl::glfw::Viewer viewer;
+  viewer.callback_key_down = [&](igl::opengl::glfw::Viewer & viewer,unsigned char key,int)->bool
   {
     switch(key)
     {
@@ -58,14 +58,14 @@ int main(int argc, char * argv[])
         {
           V.col(2) = Z;
         }
-        viewer.data.set_mesh(V,F);
-        viewer.data.compute_normals();
-        viewer.data.set_colors(C);
+        viewer.selected_data().set_mesh(V,F);
+        viewer.selected_data().compute_normals();
+        viewer.selected_data().set_colors(C);
         return true;
       }
     }
   };
   viewer.callback_key_down(viewer,' ',0);
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
   viewer.launch();
 }

+ 1 - 1
tutorial/401_BiharmonicDeformation/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(401_BiharmonicDeformation)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 9 - 9
tutorial/401_BiharmonicDeformation/main.cpp

@@ -2,7 +2,7 @@
 #include <igl/harmonic.h>
 #include <igl/readOBJ.h>
 #include <igl/readDMAT.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <algorithm>
 #include <iostream>
 #include "tutorial_shared_path.h"
@@ -15,7 +15,7 @@ Eigen::VectorXd Z;
 Eigen::MatrixXi F;
 Eigen::VectorXi b;
 
-bool pre_draw(igl::viewer::Viewer & viewer)
+bool pre_draw(igl::opengl::glfw::Viewer & viewer)
 {
   using namespace Eigen;
   // Determine boundary conditions
@@ -36,12 +36,12 @@ bool pre_draw(igl::viewer::Viewer & viewer)
   {
     igl::harmonic(V,F,b,U_bc_anim,2.,U);
   }
-  viewer.data.set_vertices(U);
-  viewer.data.compute_normals();
+  viewer.selected_data().set_vertices(U);
+  viewer.selected_data().compute_normals();
   return false;
 }
 
-bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
+bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods)
 {
   switch(key)
   {
@@ -109,10 +109,10 @@ int main(int argc, char *argv[])
   }
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(U, F);
-  viewer.core.show_lines = false;
-  viewer.data.set_colors(C);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(U, F);
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().set_colors(C);
   viewer.core.trackball_angle = Eigen::Quaternionf(sqrt(2.0),0,sqrt(2.0),0);
   viewer.core.trackball_angle.normalize();
   viewer.callback_pre_draw = &pre_draw;

+ 1 - 1
tutorial/402_PolyharmonicDeformation/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(402_PolyharmonicDeformation)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 9 - 9
tutorial/402_PolyharmonicDeformation/main.cpp

@@ -1,7 +1,7 @@
 #include <igl/colon.h>
 #include <igl/harmonic.h>
 #include <igl/readOBJ.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <algorithm>
 #include <iostream>
 #include "tutorial_shared_path.h"
@@ -16,7 +16,7 @@ Eigen::MatrixXi F;
 Eigen::VectorXi b;
 Eigen::VectorXd bc;
 
-bool pre_draw(igl::viewer::Viewer & viewer)
+bool pre_draw(igl::opengl::glfw::Viewer & viewer)
 {
   using namespace Eigen;
   if(resolve)
@@ -25,8 +25,8 @@ bool pre_draw(igl::viewer::Viewer & viewer)
     resolve = false;
   }
   U.col(2) = z_max*Z;
-  viewer.data.set_vertices(U);
-  viewer.data.compute_normals();
+  viewer.selected_data().set_vertices(U);
+  viewer.selected_data().compute_normals();
   if(viewer.core.is_animating)
   {
     z_max += z_dir;
@@ -35,7 +35,7 @@ bool pre_draw(igl::viewer::Viewer & viewer)
   return false;
 }
 
-bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
+bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods)
 {
   switch(key)
   {
@@ -93,10 +93,10 @@ int main(int argc, char *argv[])
   }
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(U, F);
-  viewer.core.show_lines = false;
-  viewer.data.set_colors(C);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(U, F);
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().set_colors(C);
   viewer.core.trackball_angle = Eigen::Quaternionf(0.81,-0.58,-0.03,-0.03);
   viewer.core.trackball_angle.normalize();
   viewer.callback_pre_draw = &pre_draw;

+ 1 - 1
tutorial/403_BoundedBiharmonicWeights/CMakeLists.txt

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12)
 project(403_BoundedBiharmonicWeights)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)
 if(TARGET igl::mosek)
   target_link_libraries(${PROJECT_NAME}_bin igl::mosek)
 endif()

+ 14 - 14
tutorial/403_BoundedBiharmonicWeights/main.cpp

@@ -17,7 +17,7 @@
 #include <igl/readDMAT.h>
 #include <igl/readMESH.h>
 #include <igl/readTGF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/bbw.h>
 //#include <igl/embree/bone_heat.h>
 
@@ -42,7 +42,7 @@ RotationList pose;
 double anim_t = 1.0;
 double anim_t_dir = -0.03;
 
-bool pre_draw(igl::viewer::Viewer & viewer)
+bool pre_draw(igl::opengl::glfw::Viewer & viewer)
 {
   using namespace Eigen;
   using namespace std;
@@ -76,23 +76,23 @@ bool pre_draw(igl::viewer::Viewer & viewer)
     MatrixXi BET;
     igl::deform_skeleton(C,BE,T,CT,BET);
 
-    viewer.data.set_vertices(U);
-    viewer.data.set_edges(CT,BET,sea_green);
-    viewer.data.compute_normals();
+    viewer.selected_data().set_vertices(U);
+    viewer.selected_data().set_edges(CT,BET,sea_green);
+    viewer.selected_data().compute_normals();
     anim_t += anim_t_dir;
     anim_t_dir *= (anim_t>=1.0 || anim_t<=0.0?-1.0:1.0);
   }
   return false;
 }
 
-void set_color(igl::viewer::Viewer &viewer)
+void set_color(igl::opengl::glfw::Viewer &viewer)
 {
   Eigen::MatrixXd C;
   igl::jet(W.col(selected).eval(),true,C);
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 }
 
-bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
+bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods)
 {
   switch(key)
   {
@@ -160,13 +160,13 @@ int main(int argc, char *argv[])
   igl::lbs_matrix(V,W,M);
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(U, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(U, F);
   set_color(viewer);
-  viewer.data.set_edges(C,BE,sea_green);
-  viewer.core.show_lines = false;
-  viewer.core.show_overlay_depth = false;
-  viewer.core.line_width = 1;
+  viewer.selected_data().set_edges(C,BE,sea_green);
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().show_overlay_depth = false;
+  viewer.selected_data().line_width = 1;
   viewer.callback_pre_draw = &pre_draw;
   viewer.callback_key_down = &key_down;
   viewer.core.is_animating = false;

+ 1 - 1
tutorial/404_DualQuaternionSkinning/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(404_DualQuaternionSkinning)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 12 - 12
tutorial/404_DualQuaternionSkinning/main.cpp

@@ -8,7 +8,7 @@
 #include <igl/readDMAT.h>
 #include <igl/readOBJ.h>
 #include <igl/readTGF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include <Eigen/Geometry>
 #include <Eigen/StdVector>
@@ -32,7 +32,7 @@ double anim_t_dir = 0.015;
 bool use_dqs = false;
 bool recompute = true;
 
-bool pre_draw(igl::viewer::Viewer & viewer)
+bool pre_draw(igl::opengl::glfw::Viewer & viewer)
 {
   using namespace Eigen;
   using namespace std;
@@ -77,9 +77,9 @@ bool pre_draw(igl::viewer::Viewer & viewer)
     MatrixXi BET;
     igl::deform_skeleton(C,BE,T,CT,BET);
     
-    viewer.data.set_vertices(U);
-    viewer.data.set_edges(CT,BET,sea_green);
-    viewer.data.compute_normals();
+    viewer.selected_data().set_vertices(U);
+    viewer.selected_data().set_edges(CT,BET,sea_green);
+    viewer.selected_data().compute_normals();
     if(viewer.core.is_animating)
     {
       anim_t += anim_t_dir;
@@ -92,7 +92,7 @@ bool pre_draw(igl::viewer::Viewer & viewer)
   return false;
 }
 
-bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
+bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods)
 {
   recompute = true;
   switch(key)
@@ -130,12 +130,12 @@ int main(int argc, char *argv[])
   igl::lbs_matrix(V,W,M);
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(U, F);
-  viewer.data.set_edges(C,BE,sea_green);
-  viewer.core.show_lines = false;
-  viewer.core.show_overlay_depth = false;
-  viewer.core.line_width = 1;
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(U, F);
+  viewer.selected_data().set_edges(C,BE,sea_green);
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().show_overlay_depth = false;
+  viewer.selected_data().line_width = 1;
   viewer.core.trackball_angle.normalize();
   viewer.callback_pre_draw = &pre_draw;
   viewer.callback_key_down = &key_down;

+ 1 - 1
tutorial/405_AsRigidAsPossible/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(405_AsRigidAsPossible)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 8 - 8
tutorial/405_AsRigidAsPossible/main.cpp

@@ -9,7 +9,7 @@
 #include <igl/readDMAT.h>
 #include <igl/readOFF.h>
 #include <igl/arap.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include <Eigen/Geometry>
 #include <Eigen/StdVector>
@@ -32,7 +32,7 @@ double anim_t = 0.0;
 double anim_t_dir = 0.03;
 igl::ARAPData arap_data;
 
-bool pre_draw(igl::viewer::Viewer & viewer)
+bool pre_draw(igl::opengl::glfw::Viewer & viewer)
 {
   using namespace Eigen;
   using namespace std;
@@ -68,8 +68,8 @@ bool pre_draw(igl::viewer::Viewer & viewer)
       }
     }
     igl::arap_solve(bc,arap_data,U);
-    viewer.data.set_vertices(U);
-    viewer.data.compute_normals();
+    viewer.selected_data().set_vertices(U);
+    viewer.selected_data().compute_normals();
   if(viewer.core.is_animating)
   {
     anim_t += anim_t_dir;
@@ -77,7 +77,7 @@ bool pre_draw(igl::viewer::Viewer & viewer)
   return false;
 }
 
-bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
+bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods)
 {
   switch(key)
   {
@@ -122,9 +122,9 @@ int main(int argc, char *argv[])
   }
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(U, F);
-  viewer.data.set_colors(C);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(U, F);
+  viewer.selected_data().set_colors(C);
   viewer.callback_pre_draw = &pre_draw;
   viewer.callback_key_down = &key_down;
   viewer.core.is_animating = false;

+ 1 - 1
tutorial/406_FastAutomaticSkinningTransformations/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(406_FastAutomaticSkinningTransformations)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 10 - 10
tutorial/406_FastAutomaticSkinningTransformations/main.cpp

@@ -15,7 +15,7 @@
 #include <igl/readOBJ.h>
 #include <igl/arap.h>
 #include <igl/arap_dof.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include <Eigen/Geometry>
 #include <Eigen/StdVector>
@@ -51,7 +51,7 @@ enum ModeType
   NUM_MODE_TYPES = 4
 } mode = MODE_TYPE_ARAP;
 
-bool pre_draw(igl::viewer::Viewer & viewer)
+bool pre_draw(igl::opengl::glfw::Viewer & viewer)
 {
   using namespace Eigen;
   using namespace std;
@@ -101,9 +101,9 @@ bool pre_draw(igl::viewer::Viewer & viewer)
         break;
       }
     }
-    viewer.data.set_vertices(U);
-    viewer.data.set_points(bc,sea_green);
-    viewer.data.compute_normals();
+    viewer.selected_data().set_vertices(U);
+    viewer.selected_data().set_points(bc,sea_green);
+    viewer.selected_data().compute_normals();
     if(viewer.core.is_animating)
     {
       anim_t += anim_t_dir;
@@ -115,7 +115,7 @@ bool pre_draw(igl::viewer::Viewer & viewer)
   return false;
 }
 
-bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
+bool key_down(igl::opengl::glfw::Viewer &viewer, unsigned char key, int mods)
 {
   switch(key)
   {
@@ -206,10 +206,10 @@ int main(int argc, char *argv[])
   bbd = (V.colwise().maxCoeff()- V.colwise().minCoeff()).norm();
 
   // Plot the mesh with pseudocolors
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(U, F);
-  viewer.data.add_points(igl::slice(V,b,1),sea_green);
-  viewer.core.show_lines = false;
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(U, F);
+  viewer.selected_data().add_points(igl::slice(V,b,1),sea_green);
+  viewer.selected_data().show_lines = false;
   viewer.callback_pre_draw = &pre_draw;
   viewer.callback_key_down = &key_down;
   viewer.core.is_animating = false;

+ 1 - 1
tutorial/407_BiharmonicCoordinates/CMakeLists.txt

@@ -2,5 +2,5 @@ cmake_minimum_required(VERSION 2.8.12)
 project(407_BiharmonicCoordinates)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)
 

+ 12 - 11
tutorial/407_BiharmonicCoordinates/main.cpp

@@ -1,3 +1,4 @@
+#include <igl/opengl/gl.h>
 #include <igl/arap.h>
 #include <igl/biharmonic_coordinates.h>
 #include <igl/cat.h>
@@ -11,7 +12,7 @@
 #include <igl/remove_unreferenced.h>
 #include <igl/slice.h>
 #include <igl/writeDMAT.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <Eigen/Sparse>
 #include <iostream>
 #include <queue>
@@ -100,20 +101,20 @@ int main(int argc, char * argv[])
   // Random initial velocities to wiggle things
   arap_data.vel = MatrixXd::Random(n,3);
   
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
   // Create one huge mesh containing both meshes
   igl::cat(1,low.U,high.U,scene.U);
   igl::cat(1,low.F,MatrixXi(high.F.array()+low.V.rows()),scene.F);
   // Color each mesh
-  viewer.data.set_mesh(scene.U,scene.F);
+  viewer.selected_data().set_mesh(scene.U,scene.F);
   MatrixXd C(scene.F.rows(),3);
   C<<
     RowVector3d(0.8,0.5,0.2).replicate(low.F.rows(),1),
     RowVector3d(0.3,0.4,1.0).replicate(high.F.rows(),1);
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 
   viewer.callback_key_pressed = 
-    [&](igl::viewer::Viewer & viewer,unsigned int key,int mods)->bool
+    [&](igl::opengl::glfw::Viewer & viewer,unsigned int key,int mods)->bool
   {
     switch(key)
     {
@@ -127,7 +128,7 @@ int main(int argc, char * argv[])
         return true;
     }
   };
-  viewer.callback_pre_draw = [&](igl::viewer::Viewer & viewer)->bool
+  viewer.callback_pre_draw = [&](igl::opengl::glfw::Viewer & viewer)->bool
   {
     glEnable(GL_CULL_FACE);
     if(viewer.core.is_animating)
@@ -150,20 +151,20 @@ int main(int argc, char * argv[])
       high.U = W * (low.U.rowwise() + RowVector3d(1,0,0));
       scene.U.block(low.U.rows(),0,high.U.rows(),high.U.cols()) = high.U;
 
-      viewer.data.set_vertices(scene.U);
-      viewer.data.compute_normals();
+      viewer.selected_data().set_vertices(scene.U);
+      viewer.selected_data().compute_normals();
     }
     return false;
   };
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
   viewer.core.is_animating = true;
   viewer.core.animation_max_fps = 30.;
-  viewer.data.set_face_based(true);
+  viewer.selected_data().set_face_based(true);
   cout<<R"(
 [space] to toggle animation
 'r'     to reset positions 
       )";
   viewer.core.rotation_type = 
-    igl::viewer::ViewerCore::ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP;
+    igl::opengl::ViewerCore::ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP;
   viewer.launch();
 }

+ 1 - 1
tutorial/501_HarmonicParam/CMakeLists.txt

@@ -2,5 +2,5 @@ cmake_minimum_required(VERSION 2.8.12)
 project(501_HarmonicParam)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)
 

+ 10 - 10
tutorial/501_HarmonicParam/main.cpp

@@ -2,7 +2,7 @@
 #include <igl/harmonic.h>
 #include <igl/map_vertices_to_circle.h>
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include "tutorial_shared_path.h"
 
@@ -10,22 +10,22 @@ Eigen::MatrixXd V;
 Eigen::MatrixXi F;
 Eigen::MatrixXd V_uv;
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   if (key == '1')
   {
     // Plot the 3D mesh
-    viewer.data.set_mesh(V,F);
+    viewer.selected_data().set_mesh(V,F);
     viewer.core.align_camera_center(V,F);
   }
   else if (key == '2')
   {
     // Plot the mesh in 2D using the UV coordinates as vertex coordinates
-    viewer.data.set_mesh(V_uv,F);
+    viewer.selected_data().set_mesh(V_uv,F);
     viewer.core.align_camera_center(V_uv,F);
   }
 
-  viewer.data.compute_normals();
+  viewer.selected_data().compute_normals();
 
   return false;
 }
@@ -50,16 +50,16 @@ int main(int argc, char *argv[])
   V_uv *= 5;
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.data.set_uv(V_uv);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().set_uv(V_uv);
   viewer.callback_key_down = &key_down;
 
   // Disable wireframe
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
 
   // Draw checkerboard texture
-  viewer.core.show_texture = true;
+  viewer.selected_data().show_texture = true;
 
   // Launch the viewer
   viewer.launch();

+ 1 - 1
tutorial/502_LSCMParam/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(502_LSCMParam)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 10 - 10
tutorial/502_LSCMParam/main.cpp

@@ -1,6 +1,6 @@
 #include <igl/boundary_loop.h>
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include <igl/lscm.h>
 
@@ -10,23 +10,23 @@ Eigen::MatrixXd V;
 Eigen::MatrixXi F;
 Eigen::MatrixXd V_uv;
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
 
   if (key == '1')
   {
     // Plot the 3D mesh
-    viewer.data.set_mesh(V,F);
+    viewer.selected_data().set_mesh(V,F);
     viewer.core.align_camera_center(V,F);
   }
   else if (key == '2')
   {
     // Plot the mesh in 2D using the UV coordinates as vertex coordinates
-    viewer.data.set_mesh(V_uv,F);
+    viewer.selected_data().set_mesh(V_uv,F);
     viewer.core.align_camera_center(V_uv,F);
   }
 
-  viewer.data.compute_normals();
+  viewer.selected_data().compute_normals();
 
   return false;
 }
@@ -54,16 +54,16 @@ int main(int argc, char *argv[])
   V_uv *= 5;
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.data.set_uv(V_uv);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().set_uv(V_uv);
   viewer.callback_key_down = &key_down;
 
   // Disable wireframe
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
 
   // Draw checkerboard texture
-  viewer.core.show_texture = true;
+  viewer.selected_data().show_texture = true;
 
   // Launch the viewer
   viewer.launch();

+ 1 - 1
tutorial/503_ARAPParam/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(503_ARAPParam)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 10 - 10
tutorial/503_ARAPParam/main.cpp

@@ -3,7 +3,7 @@
 #include <igl/harmonic.h>
 #include <igl/map_vertices_to_circle.h>
 #include <igl/readOFF.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include "tutorial_shared_path.h"
 
@@ -14,7 +14,7 @@ Eigen::MatrixXd initial_guess;
 
 bool show_uv = false;
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   if (key == '1')
     show_uv = false;
@@ -26,16 +26,16 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
 
   if (show_uv)
   {
-    viewer.data.set_mesh(V_uv,F);
+    viewer.selected_data().set_mesh(V_uv,F);
     viewer.core.align_camera_center(V_uv,F);
   }
   else
   {
-    viewer.data.set_mesh(V,F);
+    viewer.selected_data().set_mesh(V,F);
     viewer.core.align_camera_center(V,F);
   }
 
-  viewer.data.compute_normals();
+  viewer.selected_data().compute_normals();
 
   return false;
 }
@@ -76,16 +76,16 @@ int main(int argc, char *argv[])
   V_uv *= 20;
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.data.set_uv(V_uv);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
+  viewer.selected_data().set_uv(V_uv);
   viewer.callback_key_down = &key_down;
 
   // Disable wireframe
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
 
   // Draw checkerboard texture
-  viewer.core.show_texture = true;
+  viewer.selected_data().show_texture = true;
 
   // Launch the viewer
   viewer.launch();

+ 1 - 1
tutorial/504_NRosyDesign/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(504_NRosyDesign)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer igl::comiso tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::comiso tutorials)

+ 12 - 12
tutorial/504_NRosyDesign/main.cpp

@@ -3,7 +3,7 @@
 #include <igl/local_basis.h>
 #include <igl/readOFF.h>
 #include <igl/copyleft/comiso/nrosy.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include "tutorial_shared_path.h"
 
@@ -55,7 +55,7 @@ void representative_to_nrosy(
 // Plots the mesh with an N-RoSy field and its singularities on top
 // The constrained faces (b) are colored in red.
 void plot_mesh_nrosy(
-  igl::viewer::Viewer& viewer,
+  igl::opengl::glfw::Viewer& viewer,
   Eigen::MatrixXd& V,
   Eigen::MatrixXi& F,
   int N,
@@ -66,8 +66,8 @@ void plot_mesh_nrosy(
   using namespace Eigen;
   using namespace std;
   // Clear the mesh
-  viewer.data.clear();
-  viewer.data.set_mesh(V,F);
+  viewer.selected_data().clear();
+  viewer.selected_data().set_mesh(V,F);
 
   // Expand the representative vectors in the full vector set and plot them as lines
   double avg = igl::avg_edge_length(V, F);
@@ -82,26 +82,26 @@ void plot_mesh_nrosy(
     for(unsigned j=0; j<N; ++j)
       Be.row(i*N+j) = B.row(i);
 
-  viewer.data.add_edges(Be,Be+Y*(avg/2),RowVector3d(0,0,1));
+  viewer.selected_data().add_edges(Be,Be+Y*(avg/2),RowVector3d(0,0,1));
 
   // Plot the singularities as colored dots (red for negative, blue for positive)
   for (unsigned i=0; i<S.size();++i)
   {
     if (S(i) < -0.001)
-      viewer.data.add_points(V.row(i),RowVector3d(1,0,0));
+      viewer.selected_data().add_points(V.row(i),RowVector3d(1,0,0));
     else if (S(i) > 0.001)
-      viewer.data.add_points(V.row(i),RowVector3d(0,1,0));
+      viewer.selected_data().add_points(V.row(i),RowVector3d(0,1,0));
   }
 
   // Highlight in red the constrained faces
   MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
   for (unsigned i=0; i<b.size();++i)
     C.row(b(i)) << 1, 0, 0;
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 }
 
   // It allows to change the degree of the field when a number is pressed
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   using namespace Eigen;
   using namespace std;
@@ -131,17 +131,17 @@ int main(int argc, char *argv[])
   bc.resize(1,3);
   bc << 1,1,1;
 
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
 
   // Interpolate the field and plot
   key_down(viewer, '4', 0);
 
   // Plot the mesh
-  viewer.data.set_mesh(V, F);
+  viewer.selected_data().set_mesh(V, F);
   viewer.callback_key_down = &key_down;
 
   // Disable wireframe
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
 
   // Launch the viewer
   viewer.launch();

+ 1 - 1
tutorial/505_MIQ/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(505_MIQ)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer igl::comiso tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::comiso tutorials)

+ 37 - 37
tutorial/505_MIQ/main.cpp

@@ -11,7 +11,7 @@
 #include <igl/rotate_vectors.h>
 #include <igl/copyleft/comiso/miq.h>
 #include <igl/copyleft/comiso/nrosy.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <sstream>
 
 #include "tutorial_shared_path.h"
@@ -80,7 +80,7 @@ void line_texture(Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> &te
     texture_B = texture_R;
   }
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   if (key == 'E')
   {
@@ -90,38 +90,38 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   if (key <'1' || key >'8')
     return false;
 
-  viewer.data.clear();
-  viewer.core.show_lines = false;
-  viewer.core.show_texture = false;
+  viewer.selected_data().clear();
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().show_texture = false;
 
   if (key == '1')
   {
     // Cross field
-    viewer.data.set_mesh(V, F);
-    viewer.data.add_edges(extend_arrows ? B - global_scale*X1 : B, B + global_scale*X1 ,Eigen::RowVector3d(1,0,0));
-    viewer.data.add_edges(extend_arrows ? B - global_scale*X2 : B, B + global_scale*X2 ,Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().set_mesh(V, F);
+    viewer.selected_data().add_edges(extend_arrows ? B - global_scale*X1 : B, B + global_scale*X1 ,Eigen::RowVector3d(1,0,0));
+    viewer.selected_data().add_edges(extend_arrows ? B - global_scale*X2 : B, B + global_scale*X2 ,Eigen::RowVector3d(0,0,1));
   }
 
   if (key == '2')
   {
     // Bisector field
-    viewer.data.set_mesh(V, F);
-    viewer.data.add_edges(extend_arrows ? B - global_scale*BIS1 : B, B + global_scale*BIS1 ,Eigen::RowVector3d(1,0,0));
-    viewer.data.add_edges(extend_arrows ? B - global_scale*BIS2 : B, B + global_scale*BIS2 ,Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().set_mesh(V, F);
+    viewer.selected_data().add_edges(extend_arrows ? B - global_scale*BIS1 : B, B + global_scale*BIS1 ,Eigen::RowVector3d(1,0,0));
+    viewer.selected_data().add_edges(extend_arrows ? B - global_scale*BIS2 : B, B + global_scale*BIS2 ,Eigen::RowVector3d(0,0,1));
   }
 
   if (key == '3')
   {
     // Bisector field combed
-    viewer.data.set_mesh(V, F);
-    viewer.data.add_edges(extend_arrows ? B - global_scale*BIS1_combed : B, B + global_scale*BIS1_combed ,Eigen::RowVector3d(1,0,0));
-    viewer.data.add_edges(extend_arrows ? B - global_scale*BIS2_combed : B, B + global_scale*BIS2_combed ,Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().set_mesh(V, F);
+    viewer.selected_data().add_edges(extend_arrows ? B - global_scale*BIS1_combed : B, B + global_scale*BIS1_combed ,Eigen::RowVector3d(1,0,0));
+    viewer.selected_data().add_edges(extend_arrows ? B - global_scale*BIS2_combed : B, B + global_scale*BIS2_combed ,Eigen::RowVector3d(0,0,1));
   }
 
   if (key == '4')
   {
     // Singularities and cuts
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
 
     // Plot cuts
     int l_count = Seams.sum();
@@ -141,15 +141,15 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
       }
     }
 
-    viewer.data.add_edges(P1, P2, Eigen::RowVector3d(1, 0, 0));
+    viewer.selected_data().add_edges(P1, P2, Eigen::RowVector3d(1, 0, 0));
 
     // Plot the singularities as colored dots (red for negative, blue for positive)
     for (unsigned i=0; i<singularityIndex.size();++i)
     {
       if (singularityIndex(i) < 2 && singularityIndex(i) > 0)
-        viewer.data.add_points(V.row(i),Eigen::RowVector3d(1,0,0));
+        viewer.selected_data().add_points(V.row(i),Eigen::RowVector3d(1,0,0));
       else if (singularityIndex(i) > 2)
-        viewer.data.add_points(V.row(i),Eigen::RowVector3d(0,1,0));
+        viewer.selected_data().add_points(V.row(i),Eigen::RowVector3d(0,1,0));
     }
 
   }
@@ -158,9 +158,9 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   {
     // Singularities and cuts, original field
     // Singularities and cuts
-    viewer.data.set_mesh(V, F);
-    viewer.data.add_edges(extend_arrows ? B - global_scale*X1_combed : B, B + global_scale*X1_combed ,Eigen::RowVector3d(1,0,0));
-    viewer.data.add_edges(extend_arrows ? B - global_scale*X2_combed : B, B + global_scale*X2_combed ,Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().set_mesh(V, F);
+    viewer.selected_data().add_edges(extend_arrows ? B - global_scale*X1_combed : B, B + global_scale*X1_combed ,Eigen::RowVector3d(1,0,0));
+    viewer.selected_data().add_edges(extend_arrows ? B - global_scale*X2_combed : B, B + global_scale*X2_combed ,Eigen::RowVector3d(0,0,1));
 
     // Plot cuts
     int l_count = Seams.sum();
@@ -180,50 +180,50 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
       }
     }
 
-    viewer.data.add_edges(P1, P2, Eigen::RowVector3d(1, 0, 0));
+    viewer.selected_data().add_edges(P1, P2, Eigen::RowVector3d(1, 0, 0));
 
     // Plot the singularities as colored dots (red for negative, blue for positive)
     for (unsigned i=0; i<singularityIndex.size();++i)
     {
       if (singularityIndex(i) < 2 && singularityIndex(i) > 0)
-        viewer.data.add_points(V.row(i),Eigen::RowVector3d(1,0,0));
+        viewer.selected_data().add_points(V.row(i),Eigen::RowVector3d(1,0,0));
       else if (singularityIndex(i) > 2)
-        viewer.data.add_points(V.row(i),Eigen::RowVector3d(0,1,0));
+        viewer.selected_data().add_points(V.row(i),Eigen::RowVector3d(0,1,0));
     }
   }
 
   if (key == '6')
   {
     // Global parametrization UV
-    viewer.data.set_mesh(UV, FUV);
-    viewer.data.set_uv(UV);
-    viewer.core.show_lines = true;
+    viewer.selected_data().set_mesh(UV, FUV);
+    viewer.selected_data().set_uv(UV);
+    viewer.selected_data().show_lines = true;
   }
 
   if (key == '7')
   {
     // Global parametrization in 3D
-    viewer.data.set_mesh(V, F);
-    viewer.data.set_uv(UV,FUV);
-    viewer.core.show_texture = true;
+    viewer.selected_data().set_mesh(V, F);
+    viewer.selected_data().set_uv(UV,FUV);
+    viewer.selected_data().show_texture = true;
   }
 
   if (key == '8')
   {
     // Global parametrization in 3D with seams
-    viewer.data.set_mesh(V, F);
-    viewer.data.set_uv(UV_seams,FUV_seams);
-    viewer.core.show_texture = true;
+    viewer.selected_data().set_mesh(V, F);
+    viewer.selected_data().set_uv(UV_seams,FUV_seams);
+    viewer.selected_data().show_texture = true;
   }
 
-  viewer.data.set_colors(Eigen::RowVector3d(1,1,1));
+  viewer.selected_data().set_colors(Eigen::RowVector3d(1,1,1));
 
   // Replace the standard texture with an integer shift invariant texture
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> texture_R, texture_G, texture_B;
   line_texture(texture_R, texture_G, texture_B);
-  viewer.data.set_texture(texture_R, texture_B, texture_G);
+  viewer.selected_data().set_texture(texture_R, texture_B, texture_G);
 
-  viewer.core.align_camera_center(viewer.data.V,viewer.data.F);
+  viewer.core.align_camera_center(viewer.selected_data().V,viewer.selected_data().F);
 
   return false;
 }
@@ -315,7 +315,7 @@ igl::copyleft::comiso::miq(V,
          false);
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
 
   // Plot the original mesh with a texture parametrization
   key_down(viewer,'7',0);

+ 1 - 1
tutorial/506_FrameField/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(506_FrameField)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer igl::comiso tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::comiso tutorials)

+ 32 - 32
tutorial/506_FrameField/main.cpp

@@ -10,7 +10,7 @@
 #include <igl/copyleft/comiso/nrosy.h>
 #include <igl/copyleft/comiso/miq.h>
 #include <igl/copyleft/comiso/frame_field.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 
 #include "tutorial_shared_path.h"
 
@@ -68,7 +68,7 @@ void line_texture(Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> &te
   texture_B = texture_R;
 }
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   using namespace std;
   using namespace Eigen;
@@ -76,14 +76,14 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   if (key <'1' || key >'6')
     return false;
 
-  viewer.data.clear();
-  viewer.core.show_lines = false;
-  viewer.core.show_texture = false;
+  viewer.selected_data().clear();
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().show_texture = false;
 
   if (key == '1')
   {
     // Frame field constraints
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
 
     MatrixXd F1_t = MatrixXd::Zero(FF1.rows(),FF1.cols());
     MatrixXd F2_t = MatrixXd::Zero(FF2.rows(),FF2.cols());
@@ -96,7 +96,7 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
       F2_t.row(b(i)) = bc2.row(i);
     }
 
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     MatrixXd C1,C2;
     VectorXd K1 = F1_t.rowwise().norm();
@@ -104,72 +104,72 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
     igl::jet(K1,true,C1);
     igl::jet(K2,true,C2);
 
-    viewer.data.add_edges(B - global_scale*F1_t, B + global_scale*F1_t ,C1);
-    viewer.data.add_edges(B - global_scale*F2_t, B + global_scale*F2_t ,C2);
+    viewer.selected_data().add_edges(B - global_scale*F1_t, B + global_scale*F1_t ,C1);
+    viewer.selected_data().add_edges(B - global_scale*F2_t, B + global_scale*F2_t ,C2);
   }
 
   if (key == '2')
   {
     // Frame field
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
     MatrixXd C1,C2;
     VectorXd K1 = FF1.rowwise().norm();
     VectorXd K2 = FF2.rowwise().norm();
     igl::jet(K1,true,C1);
     igl::jet(K2,true,C2);
 
-    viewer.data.add_edges(B - global_scale*FF1, B + global_scale*FF1 ,C1);
-    viewer.data.add_edges(B - global_scale*FF2, B + global_scale*FF2 ,C2);
+    viewer.selected_data().add_edges(B - global_scale*FF1, B + global_scale*FF1 ,C1);
+    viewer.selected_data().add_edges(B - global_scale*FF2, B + global_scale*FF2 ,C2);
 
     // Highlight in red the constrained faces
     MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
     for (unsigned i=0; i<b.size();++i)
       C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
   }
 
   if (key == '3')
   {
     // Deformed with frame field
-    viewer.data.set_mesh(V_deformed, F);
-    viewer.data.add_edges(B_deformed - global_scale*FF1_deformed, B_deformed + global_scale*FF1_deformed ,Eigen::RowVector3d(1,0,0));
-    viewer.data.add_edges(B_deformed - global_scale*FF2_deformed, B_deformed + global_scale*FF2_deformed ,Eigen::RowVector3d(0,0,1));
-    viewer.data.set_colors(RowVector3d(1,1,1));
+    viewer.selected_data().set_mesh(V_deformed, F);
+    viewer.selected_data().add_edges(B_deformed - global_scale*FF1_deformed, B_deformed + global_scale*FF1_deformed ,Eigen::RowVector3d(1,0,0));
+    viewer.selected_data().add_edges(B_deformed - global_scale*FF2_deformed, B_deformed + global_scale*FF2_deformed ,Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().set_colors(RowVector3d(1,1,1));
   }
 
   if (key == '4')
   {
     // Deformed with cross field
-    viewer.data.set_mesh(V_deformed, F);
-    viewer.data.add_edges(B_deformed - global_scale*X1_deformed, B_deformed + global_scale*X1_deformed ,Eigen::RowVector3d(0,0,1));
-    viewer.data.add_edges(B_deformed - global_scale*X2_deformed, B_deformed + global_scale*X2_deformed ,Eigen::RowVector3d(0,0,1));
-    viewer.data.set_colors(RowVector3d(1,1,1));
+    viewer.selected_data().set_mesh(V_deformed, F);
+    viewer.selected_data().add_edges(B_deformed - global_scale*X1_deformed, B_deformed + global_scale*X1_deformed ,Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().add_edges(B_deformed - global_scale*X2_deformed, B_deformed + global_scale*X2_deformed ,Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().set_colors(RowVector3d(1,1,1));
   }
 
   if (key == '5')
   {
     // Deformed with quad texture
-    viewer.data.set_mesh(V_deformed, F);
-    viewer.data.set_uv(V_uv,F_uv);
-    viewer.data.set_colors(RowVector3d(1,1,1));
-    viewer.core.show_texture = true;
+    viewer.selected_data().set_mesh(V_deformed, F);
+    viewer.selected_data().set_uv(V_uv,F_uv);
+    viewer.selected_data().set_colors(RowVector3d(1,1,1));
+    viewer.selected_data().show_texture = true;
   }
 
   if (key == '6')
   {
     // Deformed with quad texture
-    viewer.data.set_mesh(V, F);
-    viewer.data.set_uv(V_uv,F_uv);
-    viewer.data.set_colors(RowVector3d(1,1,1));
-    viewer.core.show_texture = true;
+    viewer.selected_data().set_mesh(V, F);
+    viewer.selected_data().set_uv(V_uv,F_uv);
+    viewer.selected_data().set_colors(RowVector3d(1,1,1));
+    viewer.selected_data().show_texture = true;
   }
 
   // Replace the standard texture with an integer shift invariant texture
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> texture_R, texture_G, texture_B;
   line_texture(texture_R, texture_G, texture_B);
-  viewer.data.set_texture(texture_R, texture_B, texture_G);
-  viewer.core.align_camera_center(viewer.data.V,viewer.data.F);
+  viewer.selected_data().set_texture(texture_R, texture_B, texture_G);
+  viewer.core.align_camera_center(viewer.selected_data().V,viewer.selected_data().F);
 
   return false;
 }
@@ -245,7 +245,7 @@ int main(int argc, char *argv[])
            false,
            2);
 
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
   // Plot the original mesh with a texture parametrization
   key_down(viewer,'6',0);
 

+ 1 - 1
tutorial/507_PolyVectorField/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(507_PolyVectorField)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 9 - 9
tutorial/507_PolyVectorField/main.cpp

@@ -5,7 +5,7 @@
 #include <igl/n_polyvector.h>
 #include <igl/readDMAT.h>
 #include <igl/readOBJ.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <cstdlib>
 #include <iostream>
 #include <vector>
@@ -70,7 +70,7 @@ Eigen::VectorXd random_constraints(const
   return r;
 }
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   using namespace std;
   using namespace Eigen;
@@ -78,7 +78,7 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   if (key <'1' || key >'8')
     return false;
 
-  viewer.data.lines.resize(0,9);
+  viewer.selected_data().lines.resize(0,9);
 
   int num = key  - '0';
 
@@ -103,7 +103,7 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
   for (unsigned i=0; i<b.size();++i)
     C.row(b(i)) << 1, 0, 0;
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 
   for (int n=0; n<num; ++n)
   {
@@ -118,7 +118,7 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
     VectorXd c = VF.rowwise().norm();
     MatrixXd C2;
     igl::jet(c,1,1+rand_factor,C2);
-    viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , C2);
+    viewer.selected_data().add_edges(B - global_scale*VF, B + global_scale*VF , C2);
   }
 
   return false;
@@ -144,11 +144,11 @@ int main(int argc, char *argv[])
   // Make the example deterministic
   srand(0);
 
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
   viewer.callback_key_down = &key_down;
-  viewer.core.show_lines = false;
-  viewer.core.line_width = 10000;// this does not work, why?
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().line_width = 10000;// this does not work, why?
   key_down(viewer,'2',0);
 
 

+ 1 - 1
tutorial/508_ConjugateField/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(508_ConjugateField)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 19 - 19
tutorial/508_ConjugateField/main.cpp

@@ -8,7 +8,7 @@
 #include <igl/n_polyvector.h>
 #include <igl/readDMAT.h>
 #include <igl/readOBJ.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <vector>
 #include <cstdlib>
 
@@ -34,7 +34,7 @@ Eigen::VectorXd conjugacy_s;
 Eigen::VectorXd conjugacy_c;
 
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   using namespace std;
   using namespace Eigen;
@@ -42,7 +42,7 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   if (key <'1' || key >'5')
     return false;
 
-  viewer.data.lines.resize(0,9);
+  viewer.selected_data().lines.resize(0,9);
   // Highlight in red the constrained faces
   MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
   for (unsigned i=0; i<b.size();++i)
@@ -73,44 +73,44 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
       F2_t.row(b(i)) = bc.block(i,3,1,3);
     }
 
-    viewer.data.add_edges(B - global_scale*F1_t, B + global_scale*F1_t , Eigen::RowVector3d(0,0,1));
-    viewer.data.add_edges(B - global_scale*F2_t, B + global_scale*F2_t , Eigen::RowVector3d(0,0,1));
-    viewer.data.set_colors(C);
+    viewer.selected_data().add_edges(B - global_scale*F1_t, B + global_scale*F1_t , Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().add_edges(B - global_scale*F2_t, B + global_scale*F2_t , Eigen::RowVector3d(0,0,1));
+    viewer.selected_data().set_colors(C);
   }
 
   if (key == '2')
   {
     // Interpolated result
-    viewer.data.add_edges(B - global_scale*smooth_pvf.block(0,0,F.rows(),3),
+    viewer.selected_data().add_edges(B - global_scale*smooth_pvf.block(0,0,F.rows(),3),
                       B + global_scale*smooth_pvf.block(0,0,F.rows(),3),
                       Eigen::RowVector3d(0,0,1));
-    viewer.data.add_edges(B - global_scale*smooth_pvf.block(0,3,F.rows(),3),
+    viewer.selected_data().add_edges(B - global_scale*smooth_pvf.block(0,3,F.rows(),3),
                       B + global_scale*smooth_pvf.block(0,3,F.rows(),3),
                       Eigen::RowVector3d(0,0,1));
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
   }
 
   if (key == '3')
   {
     // Interpolated result
-    viewer.data.set_colors(CS);
+    viewer.selected_data().set_colors(CS);
   }
 
   if (key == '4')
   {
     // Conjugate field
-    viewer.data.add_edges(B - global_scale*conjugate_pvf.block(0,0,F.rows(),3),
+    viewer.selected_data().add_edges(B - global_scale*conjugate_pvf.block(0,0,F.rows(),3),
                       B + global_scale*conjugate_pvf.block(0,0,F.rows(),3),
                       Eigen::RowVector3d(0,0,1));
-    viewer.data.add_edges(B - global_scale*conjugate_pvf.block(0,3,F.rows(),3),
+    viewer.selected_data().add_edges(B - global_scale*conjugate_pvf.block(0,3,F.rows(),3),
                       B + global_scale*conjugate_pvf.block(0,3,F.rows(),3),
                       Eigen::RowVector3d(0,0,1));
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
   }
   if (key == '5')
   {
     // Conjugate field
-    viewer.data.set_colors(CC);
+    viewer.selected_data().set_colors(CC);
   }
 
   return false;
@@ -173,11 +173,11 @@ int main(int argc, char *argv[])
   pvV << igl::dot_row(Vc,B1), igl::dot_row(Vc,B2);
   csdata.evaluateConjugacy(pvU, pvV, conjugacy_c);
   // Launch the viewer
-  igl::viewer::Viewer viewer;
-  viewer.core.invert_normals = true;
-  viewer.core.show_lines = false;
-  viewer.core.show_texture = false;
-  viewer.data.set_mesh(V, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().invert_normals = true;
+  viewer.selected_data().show_lines = false;
+  viewer.selected_data().show_texture = false;
+  viewer.selected_data().set_mesh(V, F);
   viewer.callback_key_down = &key_down;
   key_down(viewer,'1',0);
   viewer.launch();

+ 1 - 1
tutorial/509_Planarization/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(509_Planarization)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 17 - 17
tutorial/509_Planarization/main.cpp

@@ -6,7 +6,7 @@
 #include <igl/readDMAT.h>
 #include <igl/readOFF.h>
 #include <igl/slice.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <vector>
 #include <cstdlib>
 
@@ -28,7 +28,7 @@ Eigen::MatrixXd PQC0plan, PQC1plan, PQC2plan, PQC3plan;
 double global_scale; //TODO: not used
 
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   using namespace std;
   using namespace Eigen;
@@ -37,7 +37,7 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   if (key == '1')
   {
     // Draw the triangulated quad mesh
-    viewer.data.set_mesh(VQC, FQCtri);
+    viewer.selected_data().set_mesh(VQC, FQCtri);
 
     // Assign a color to each quad that corresponds to its planarity
     VectorXd planarity;
@@ -46,20 +46,20 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
     igl::jet(planarity, 0, 0.01, Ct);
     MatrixXd C(FQCtri.rows(),3);
     C << Ct, Ct;
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     // Plot a line for each edge of the quad mesh
-    viewer.data.add_edges(PQC0, PQC1, Eigen::RowVector3d(0,0,0));
-    viewer.data.add_edges(PQC1, PQC2, Eigen::RowVector3d(0,0,0));
-    viewer.data.add_edges(PQC2, PQC3, Eigen::RowVector3d(0,0,0));
-    viewer.data.add_edges(PQC3, PQC0, Eigen::RowVector3d(0,0,0));
+    viewer.selected_data().add_edges(PQC0, PQC1, Eigen::RowVector3d(0,0,0));
+    viewer.selected_data().add_edges(PQC1, PQC2, Eigen::RowVector3d(0,0,0));
+    viewer.selected_data().add_edges(PQC2, PQC3, Eigen::RowVector3d(0,0,0));
+    viewer.selected_data().add_edges(PQC3, PQC0, Eigen::RowVector3d(0,0,0));
   }
 
   // Plot the planarized quad mesh
   if (key == '2')
   {
     // Draw the triangulated quad mesh
-    viewer.data.set_mesh(VQCplan, FQCtri);
+    viewer.selected_data().set_mesh(VQCplan, FQCtri);
 
     // Assign a color to each quad that corresponds to its planarity
     VectorXd planarity;
@@ -68,13 +68,13 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
     igl::jet(planarity, 0, 0.01, Ct);
     MatrixXd C(FQCtri.rows(),3);
     C << Ct, Ct;
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     // Plot a line for each edge of the quad mesh
-    viewer.data.add_edges(PQC0plan, PQC1plan, Eigen::RowVector3d(0,0,0));
-    viewer.data.add_edges(PQC1plan, PQC2plan, Eigen::RowVector3d(0,0,0));
-    viewer.data.add_edges(PQC2plan, PQC3plan, Eigen::RowVector3d(0,0,0));
-    viewer.data.add_edges(PQC3plan, PQC0plan, Eigen::RowVector3d(0,0,0));
+    viewer.selected_data().add_edges(PQC0plan, PQC1plan, Eigen::RowVector3d(0,0,0));
+    viewer.selected_data().add_edges(PQC1plan, PQC2plan, Eigen::RowVector3d(0,0,0));
+    viewer.selected_data().add_edges(PQC2plan, PQC3plan, Eigen::RowVector3d(0,0,0));
+    viewer.selected_data().add_edges(PQC3plan, PQC0plan, Eigen::RowVector3d(0,0,0));
   }
 
   return false;
@@ -107,10 +107,10 @@ int main(int argc, char *argv[])
   igl::slice( VQCplan, FQC.col(3).eval(), 1, PQC3plan);
 
   // Launch the viewer
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
   key_down(viewer,'2',0);
-  viewer.core.invert_normals = true;
-  viewer.core.show_lines = false;
+  viewer.selected_data().invert_normals = true;
+  viewer.selected_data().show_lines = false;
   viewer.callback_key_down = &key_down;
   viewer.launch();
 }

+ 1 - 1
tutorial/510_Integrable/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(510_Integrable)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 45 - 45
tutorial/510_Integrable/main.cpp

@@ -2,7 +2,7 @@
 #include <igl/readOBJ.h>
 #include <igl/n_polyvector.h>
 #include <igl/integrable_polyvector_fields.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/local_basis.h>
 #include <igl/avg_edge_length.h>
 #include <igl/is_border_vertex.h>
@@ -222,7 +222,7 @@ bc<<
 
 }
 
-void drawCuts(igl::viewer::Viewer& viewer,
+void drawCuts(igl::opengl::glfw::Viewer& viewer,
               const Eigen::MatrixXi &cuts)
 {
   int maxCutNum = cuts.sum();
@@ -237,10 +237,10 @@ void drawCuts(igl::viewer::Viewer& viewer,
         end.row(ind) = V.row(F(i,(j+1)%3));
         ind++;
       }
-  viewer.data.add_edges(start, end , Eigen::RowVector3d(1.,0,1.));
+  viewer.selected_data().add_edges(start, end , Eigen::RowVector3d(1.,0,1.));
 }
 
-void drawField(igl::viewer::Viewer &viewer,
+void drawField(igl::opengl::glfw::Viewer &viewer,
                const Eigen::MatrixXd &field,
                const Eigen::RowVector3d &color)
 {
@@ -248,11 +248,11 @@ void drawField(igl::viewer::Viewer &viewer,
   {
     Eigen::MatrixXd VF = field.block(0,n*3,F.rows(),3);
     Eigen::VectorXd c = VF.rowwise().norm();
-    viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , color);
+    viewer.selected_data().add_edges(B - global_scale*VF, B + global_scale*VF , color);
   }
 }
 
-void drawConstraints(igl::viewer::Viewer &viewer)
+void drawConstraints(igl::opengl::glfw::Viewer &viewer)
 {
   for (int n=0; n<2; ++n)
   {
@@ -264,7 +264,7 @@ void drawConstraints(igl::viewer::Viewer &viewer)
       if (blevel[i] ==1 && n>0)
         color.row(i)<<0.7,0.7,0.7;
     // Eigen::RowVector3d color; color<<0.5,0.5,0.5;
-    viewer.data.add_edges(Bc - global_scale*bc.block(0,n*3,bc.rows(),3), Bc + global_scale*bc.block(0,n*3,bc.rows(),3) , color);
+    viewer.selected_data().add_edges(Bc - global_scale*bc.block(0,n*3,bc.rows(),3), Bc + global_scale*bc.block(0,n*3,bc.rows(),3) , color);
   }
 
 }
@@ -311,27 +311,27 @@ void colorEdgeMeshFaces(const Eigen::VectorXd &values,
 
 }
 
-void update_display(igl::viewer::Viewer& viewer)
+void update_display(igl::opengl::glfw::Viewer& viewer)
 {
   using namespace std;
   using namespace Eigen;
 
-  viewer.data.clear();
-  viewer.data.lines.resize(0,9);
-  viewer.data.points.resize(0,6);
-  viewer.core.show_texture = false;
+  viewer.selected_data().clear();
+  viewer.selected_data().lines.resize(0,9);
+  viewer.selected_data().points.resize(0,6);
+  viewer.selected_data().show_texture = false;
 
   if (display_mode == 1)
   {
     cerr<< "Displaying original field, its singularities and its cuts"  <<endl;
 
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
 
     // Highlight in red the constrained faces
     MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
     for (unsigned i=0; i<b.size();++i)
       C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     //Draw constraints
     drawConstraints(viewer);
@@ -345,7 +345,7 @@ void update_display(igl::viewer::Viewer& viewer)
 
     //Draw Singularities
     Eigen::MatrixXd singular_points = igl::slice(V, singularities_ori, 1);
-    viewer.data.add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
+    viewer.selected_data().add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
 
   }
 
@@ -353,13 +353,13 @@ void update_display(igl::viewer::Viewer& viewer)
   {
     cerr<< "Displaying current field, its singularities and its cuts"  <<endl;
 
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
 
     // Highlight in red the constrained faces
     MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
     for (unsigned i=0; i<b.size();++i)
       C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     //Draw constraints
     drawConstraints(viewer);
@@ -373,17 +373,17 @@ void update_display(igl::viewer::Viewer& viewer)
 
     //Draw Singularities
     Eigen::MatrixXd singular_points = igl::slice(V, singularities, 1);
-    viewer.data.add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
+    viewer.selected_data().add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
   }
 
   if (display_mode == 3)
   {
     cerr<< "Displaying original field and its curl"  <<endl;
 
-    viewer.data.set_mesh(Vbs, Fbs);
+    viewer.selected_data().set_mesh(Vbs, Fbs);
     Eigen::MatrixXd C;
     colorEdgeMeshFaces(curl_ori, 0, 0.2, C);
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     // Draw Field
     Eigen::RowVector3d color; color<<1,1,1;
@@ -395,10 +395,10 @@ void update_display(igl::viewer::Viewer& viewer)
   {
     cerr<< "Displaying current field and its curl"  <<endl;
 
-    viewer.data.set_mesh(Vbs, Fbs);
+    viewer.selected_data().set_mesh(Vbs, Fbs);
     Eigen::MatrixXd C;
     colorEdgeMeshFaces(curl, 0, 0.2, C);
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     // Draw Field
     Eigen::RowVector3d color; color<<1,1,1;
@@ -409,10 +409,10 @@ void update_display(igl::viewer::Viewer& viewer)
   {
     cerr<< "Displaying original poisson-integrated field and original poisson error"  <<endl;
 
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
     Eigen::MatrixXd C;
     igl::jet(poisson_error_ori, 0, 0.5, C);
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     // Draw Field
     Eigen::RowVector3d color; color<<1,1,1;
@@ -423,10 +423,10 @@ void update_display(igl::viewer::Viewer& viewer)
   {
     cerr<< "Displaying current poisson-integrated field and current poisson error"  <<endl;
 
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
     Eigen::MatrixXd C;
     igl::jet(poisson_error, 0, 0.5, C);
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     // Draw Field
     Eigen::RowVector3d color; color<<1,1,1;
@@ -437,38 +437,38 @@ void update_display(igl::viewer::Viewer& viewer)
   {
     cerr<< "Displaying original texture with cuts and singularities"  <<endl;
 
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
     MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-    viewer.data.set_colors(C);
-    viewer.data.set_uv(uv_scale*scalars_ori, Fcut_ori);
-    viewer.data.set_texture(texture_R, texture_B, texture_G);
-    viewer.core.show_texture = true;
+    viewer.selected_data().set_colors(C);
+    viewer.selected_data().set_uv(uv_scale*scalars_ori, Fcut_ori);
+    viewer.selected_data().set_texture(texture_R, texture_B, texture_G);
+    viewer.selected_data().show_texture = true;
 
     // Draw Cuts
     drawCuts(viewer,cuts_ori);
 
     //Draw Singularities
     Eigen::MatrixXd singular_points = igl::slice(V, singularities_ori, 1);
-    viewer.data.add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
+    viewer.selected_data().add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
 
   }
   if (display_mode == 8)
   {
     cerr<< "Displaying current texture with cuts and singularities"  <<endl;
 
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
     MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-    viewer.data.set_colors(C);
-    viewer.data.set_uv(uv_scale*scalars, Fcut);
-    viewer.data.set_texture(texture_R, texture_B, texture_G);
-    viewer.core.show_texture = true;
+    viewer.selected_data().set_colors(C);
+    viewer.selected_data().set_uv(uv_scale*scalars, Fcut);
+    viewer.selected_data().set_texture(texture_R, texture_B, texture_G);
+    viewer.selected_data().show_texture = true;
 
     // Draw Cuts
     drawCuts(viewer,cuts);
 
     //Draw Singularities
     Eigen::MatrixXd singular_points = igl::slice(V, singularities, 1);
-    viewer.data.add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
+    viewer.selected_data().add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
 
   }
 
@@ -476,13 +476,13 @@ void update_display(igl::viewer::Viewer& viewer)
   {
     cerr<< "Displaying original field overlaid onto the current integrated field"  <<endl;
 
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
 
     // Highlight in red the constrained faces
     MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
     for (unsigned i=0; i<b.size();++i)
       C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     // Draw Field
     Eigen::RowVector3d color; color<<0,0,1;
@@ -498,13 +498,13 @@ void update_display(igl::viewer::Viewer& viewer)
   {
     cerr<< "Displaying current field overlaid onto the current integrated field"  <<endl;
 
-    viewer.data.set_mesh(V, F);
+    viewer.selected_data().set_mesh(V, F);
 
     // Highlight in red the constrained faces
     MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
     for (unsigned i=0; i<b.size();++i)
       C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
+    viewer.selected_data().set_colors(C);
 
     // Draw Field
     Eigen::RowVector3d color; color<<0,0,1;
@@ -517,7 +517,7 @@ void update_display(igl::viewer::Viewer& viewer)
 
 }
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
 
   if (key == '1')
@@ -707,9 +707,9 @@ int main(int argc, char *argv[])
 
   cerr<<"Done. Press keys 1-0 for various visualizations, 'A' to improve integrability." <<endl;
 
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
   viewer.callback_key_down = &key_down;
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
   key_down(viewer,'2',0);
 
   // Replace the standard texture with an integer shift invariant texture

+ 1 - 1
tutorial/511_PolyVectorFieldGeneral/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(511_PolyVectorFieldGeneral)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 9 - 9
tutorial/511_PolyVectorFieldGeneral/main.cpp

@@ -1,6 +1,6 @@
 #include <igl/readOBJ.h>
 #include <igl/readDMAT.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/barycenter.h>
 #include <igl/avg_edge_length.h>
 #include <vector>
@@ -71,7 +71,7 @@ Eigen::VectorXd random_constraints(const
   return r;
 }
 
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   using namespace std;
   using namespace Eigen;
@@ -79,7 +79,7 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   if (key <'1' || key >'9')
     return false;
 
-  viewer.data.lines.resize(0,9);
+  viewer.selected_data().lines.resize(0,9);
 
   int num = key  - '0';
 
@@ -129,7 +129,7 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
   MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
   for (unsigned i=0; i<b.size();++i)
     C.row(b(i)) << 1, 0, 0;
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 
   for (int n=0; n<num; ++n)
   {
@@ -144,8 +144,8 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
     VectorXd c = VF.rowwise().norm();
     MatrixXd C2;
     igl::jet(c,1,1+rand_factor,C2);
-    // viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , C2);
-    viewer.data.add_edges(B, B + global_scale*VF , C2);
+    // viewer.selected_data().add_edges(B - global_scale*VF, B + global_scale*VF , C2);
+    viewer.selected_data().add_edges(B, B + global_scale*VF , C2);
   }
 
 
@@ -172,10 +172,10 @@ int main(int argc, char *argv[])
   // Make the example deterministic
   srand(0);
 
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V, F);
   viewer.callback_key_down = &key_down;
-  viewer.core.show_lines = false;
+  viewer.selected_data().show_lines = false;
   key_down(viewer,'3',0);
   std::cerr << " *** Press keys 1-9 to select number of vectors per point. ***" << std::endl;
   

+ 1 - 1
tutorial/601_Serialization/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(601_Serialization)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer igl::xml tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::xml tutorials)

+ 1 - 1
tutorial/602_Matlab/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(602_Matlab)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer igl::matlab tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::matlab tutorials)

+ 6 - 6
tutorial/602_Matlab/main.cpp

@@ -2,7 +2,7 @@
 #include <igl/readOFF.h>
 #include <igl/cotmatrix.h>
 #include <igl/matlab/matlabinterface.h>
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <iostream>
 
 #include "tutorial_shared_path.h"
@@ -17,7 +17,7 @@ Engine* engine;
 // Eigenvectors of the laplacian
 Eigen::MatrixXd EV;
 
-void plotEV(igl::viewer::Viewer& viewer, int id)
+void plotEV(igl::opengl::glfw::Viewer& viewer, int id)
 {
   Eigen::VectorXd v = EV.col(id);
   v = v.array() - v.minCoeff();
@@ -32,11 +32,11 @@ void plotEV(igl::viewer::Viewer& viewer, int id)
     C.row(i) << r,g,b;
   }
 
-  viewer.data.set_colors(C);
+  viewer.selected_data().set_colors(C);
 }
 
 // This function is called every time a keyboard button is pressed
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   if (key >= '1' && key <= '9')
     plotEV(viewer,(key - '1') + 1);
@@ -72,9 +72,9 @@ int main(int argc, char *argv[])
   igl::matlab::mlgetmatrix(&engine,"EV",EV);
 
   // Plot the mesh
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
   viewer.callback_key_down = &key_down;
-  viewer.data.set_mesh(V, F);
+  viewer.selected_data().set_mesh(V, F);
 
   // Plot the first non-trivial eigenvector
   plotEV(viewer,1);

+ 1 - 1
tutorial/604_Triangle/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(604_Triangle)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer igl::triangle tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::triangle tutorials)

+ 3 - 3
tutorial/604_Triangle/main.cpp

@@ -1,4 +1,4 @@
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/triangle/triangulate.h>
 // Input polygon
 Eigen::MatrixXd V;
@@ -31,7 +31,7 @@ int main(int argc, char *argv[])
   igl::triangle::triangulate(V,E,H,"a0.005q",V2,F2);
 
   // Plot the generated mesh
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V2,F2);
+  igl::opengl::glfw::Viewer viewer;
+  viewer.selected_data().set_mesh(V2,F2);
   viewer.launch();
 }

+ 1 - 1
tutorial/605_Tetgen/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(605_Tetgen)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer igl::tetgen tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::tetgen tutorials)

+ 6 - 6
tutorial/605_Tetgen/main.cpp

@@ -1,4 +1,4 @@
-#include <igl/viewer/Viewer.h>
+#include <igl/opengl/glfw/Viewer.h>
 #include <igl/copyleft/tetgen/tetrahedralize.h>
 #include <igl/readOFF.h>
 #include <igl/barycenter.h>
@@ -16,7 +16,7 @@ Eigen::MatrixXi TT;
 Eigen::MatrixXi TF;
 
 // This function is called every time a keyboard button is pressed
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 {
   using namespace std;
   using namespace Eigen;
@@ -49,9 +49,9 @@ bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
       F_temp.row(i*4+3) << (i*4)+1, (i*4)+2, (i*4)+3;
     }
 
-    viewer.data.clear();
-    viewer.data.set_mesh(V_temp,F_temp);
-    viewer.data.set_face_based(true);
+    viewer.selected_data().clear();
+    viewer.selected_data().set_mesh(V_temp,F_temp);
+    viewer.selected_data().set_face_based(true);
   }
 
 
@@ -73,7 +73,7 @@ int main(int argc, char *argv[])
   igl::barycenter(TV,TT,B);
 
   // Plot the generated mesh
-  igl::viewer::Viewer viewer;
+  igl::opengl::glfw::Viewer viewer;
   viewer.callback_key_down = &key_down;
   key_down(viewer,'5',0);
   viewer.launch();

部分文件因为文件数量过多而无法显示