Эх сурвалжийг харах

Merge branch 'master' of github.com:libigl/libigl

Former-commit-id: 62cb8eabeab9616b7330a16be38ca92f69f7fcc3
Alec Jacobson 10 жил өмнө
parent
commit
27c9d052c6

+ 0 - 1
include/igl/AABB.h

@@ -1037,7 +1037,6 @@ inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
   }
   const auto & point_point_squared_distance = [&](const RowVectorDIMS & s)
   {
-    cout<<"pp"<<endl;
     const Scalar sqr_d_s = (p-s).squaredNorm();
     set_min(p,sqr_d_s,m_primitive,s,sqr_d,i,c);
   };

+ 1 - 1
include/igl/ARAPEnergyType.h

@@ -22,7 +22,7 @@ namespace igl
   //       deformation" by [Chao et al.  2010], rotations defined at elements
   //       (triangles or tets) 
   //     ARAP_ENERGY_TYPE_DEFAULT  Choose one automatically: spokes and rims
-  //       for surfaces, elements for planar meshes and test (not fully
+  //       for surfaces, elements for planar meshes and tets (not fully
   //       supported)
   enum ARAPEnergyType
   {

+ 4 - 2
include/igl/arap.cpp

@@ -153,7 +153,8 @@ IGL_INLINE bool igl::arap_precomputation(
     assert(h != 0);
     SparseMatrix<double> M;
     massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,data.M);
-    SparseMatrix<double> DQ = 1./(h*h)*data.M;
+    const double dw = (1./data.ym)*(h*h);
+    SparseMatrix<double> DQ = dw * 1./(h*h)*data.M;
     Q += DQ;
     // Dummy external forces
     data.f_ext = MatrixXd::Zero(n,data.dim);
@@ -268,7 +269,8 @@ IGL_INLINE bool igl::arap_solve(
       // h*data.vel = (V0-Vm1)
       // -h*data.vel = -V0+Vm1)
       // -V0-h*data.vel = -2V0+Vm1
-      Dl = 1./(h*h)*data.M*(-U0 - h*data.vel) - data.f_ext;
+      const double dw = (1./data.ym)*(h*h);
+      Dl = dw * (1./(h*h)*data.M*(-U0 - h*data.vel) - data.f_ext);
     }
 
     VectorXd Rcol;

+ 3 - 0
include/igl/arap.h

@@ -26,6 +26,7 @@ namespace igl
     // f_ext  #V by dim list of external forces
     // vel  #V by dim list of velocities
     // h  dynamics time step
+    // ym  ~Young's modulus smaller is softer, larger is more rigid/stiff
     // max_iter  maximum inner iterations
     // K  rhs pre-multiplier
     // M  mass matrix
@@ -38,6 +39,7 @@ namespace igl
     bool with_dynamics;
     Eigen::MatrixXd f_ext,vel;
     double h;
+    double ym;
     int max_iter;
     Eigen::SparseMatrix<double> K,M;
     Eigen::SparseMatrix<double> CSM;
@@ -51,6 +53,7 @@ namespace igl
         with_dynamics(false),
         f_ext(),
         h(1),
+        ym(1),
         max_iter(10),
         K(),
         CSM(),

+ 1 - 3
include/igl/boolean/mesh_boolean.cpp

@@ -11,9 +11,8 @@
 #include <igl/cgal/remesh_self_intersections.h>
 #include <igl/remove_unreferenced.h>
 #include <igl/unique_simplices.h>
-#include <iostream>
-
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <iostream>
 
 //#define IGL_MESH_BOOLEAN_DEBUG
 
@@ -312,7 +311,6 @@ IGL_INLINE void igl::boolean::mesh_boolean(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-
 // This is a hack to discuss
 #include <igl/remove_unreferenced.cpp>
 

+ 3 - 0
include/igl/fit_rotations.h

@@ -12,6 +12,9 @@
 
 namespace igl
 {
+  // Known issues: This seems to be implemented in Eigen/Geometry:
+  // Eigen::umeyama
+  //
   // FIT_ROTATIONS Given an input mesh and new positions find rotations for
   // every covariance matrix in a stack of covariance matrices
   // 

+ 43 - 18
include/igl/remove_unreferenced.cpp

@@ -20,24 +20,61 @@ IGL_INLINE void igl::remove_unreferenced(
   Eigen::PlainObjectBase<DerivedNF> &NF,
   Eigen::PlainObjectBase<DerivedI> &I)
 {
+  Eigen::Matrix<typename DerivedI::Scalar,Eigen::Dynamic,1> J;
+  remove_unreferenced(V,F,NV,NF,I,J);
+}
 
-  // Mark referenced vertices
-  Eigen::MatrixXi mark = Eigen::MatrixXi::Zero(V.rows(),1);
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedNV,
+  typename DerivedNF,
+  typename DerivedI,
+  typename DerivedJ>
+IGL_INLINE void igl::remove_unreferenced(
+  const Eigen::PlainObjectBase<DerivedV> &V,
+  const Eigen::PlainObjectBase<DerivedF> &F,
+  Eigen::PlainObjectBase<DerivedNV> &NV,
+  Eigen::PlainObjectBase<DerivedNF> &NF,
+  Eigen::PlainObjectBase<DerivedI> &I,
+  Eigen::PlainObjectBase<DerivedJ> &J)
+{
+  const size_t n = V.rows();
+  remove_unreferenced(n,F,I,J);
+  NF = F;
+  for_each(NF.data(),NF.data()+NF.size(),[&I](int & a){a=I(a);});
+  slice(V,J,1,NV);
+}
 
+template <
+  typename DerivedF,
+  typename DerivedI,
+  typename DerivedJ>
+IGL_INLINE void igl::remove_unreferenced(
+  const size_t n,
+  const Eigen::PlainObjectBase<DerivedF> &F,
+  Eigen::PlainObjectBase<DerivedI> &I,
+  Eigen::PlainObjectBase<DerivedJ> &J)
+{
+  // Mark referenced vertices
+  typedef Eigen::Matrix<bool,Eigen::Dynamic,1> MatrixXb;
+  MatrixXb mark = MatrixXb::Zero(n,1);
   for(int i=0; i<F.rows(); ++i)
   {
     for(int j=0; j<F.cols(); ++j)
     {
       if (F(i,j) != -1)
+      {
         mark(F(i,j)) = 1;
+      }
     }
   }
 
   // Sum the occupied cells
-  int newsize = mark.sum();
+  int newsize = mark.count();
 
-  NV.resize(newsize,V.cols());
-  I.resize(V.rows(),1);
+  I.resize(n,1);
+  J.resize(newsize,1);
 
   // Do a pass on the marked vector and remove the unreferenced vertices
   int count = 0;
@@ -45,8 +82,8 @@ IGL_INLINE void igl::remove_unreferenced(
   {
     if (mark(i) == 1)
     {
-      NV.row(count) = V.row(i);
       I(i) = count;
+      J(count) = i;
       count++;
     }
     else
@@ -54,18 +91,6 @@ IGL_INLINE void igl::remove_unreferenced(
       I(i) = -1;
     }
   }
-
-  NF.resize(F.rows(),F.cols());
-
-  // Apply I on F
-  for (int i=0; i<F.rows(); ++i)
-  {
-    Eigen::RowVectorXi t(F.cols());
-    for (int j=0; j<F.cols(); ++j)
-      t(j) = I(F(i,j));
-
-    NF.row(i) = t;
-  }
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 39 - 5
include/igl/remove_unreferenced.h

@@ -18,14 +18,16 @@
 #include <Eigen/Core>
 namespace igl 
 {
-  // [ NV, NF ] = remove_unreferenced( V,F)
   // Remove unreferenced vertices from V, updating F accordingly
   //
   // Input:
-  // V,F: mesh description
-  //
-  // Output:
-  // NV, NF: new mesh without unreferenced vertices
+  //   V  #V by dim list of mesh vertex positions
+  //   F  #F by ss list of simplices (Values of -1 are quitely skipped)
+  // Outputs:
+  //   NV  #NV by dim list of mesh vertex positions
+  //   NF  #NF by ss list of simplices
+  //   IM  #V by 1 list of indices such that: NF = IM(F) and NT = IM(T)
+  //      and V(find(IM<=size(NV,1)),:) = NV
   //
   template <
     typename DerivedV,
@@ -39,6 +41,38 @@ namespace igl
     Eigen::PlainObjectBase<DerivedNV> &NV,
     Eigen::PlainObjectBase<DerivedNF> &NF,
     Eigen::PlainObjectBase<DerivedI> &I);
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedNV,
+    typename DerivedNF,
+    typename DerivedI,
+    typename DerivedJ>
+  IGL_INLINE void remove_unreferenced(
+    const Eigen::PlainObjectBase<DerivedV> &V,
+    const Eigen::PlainObjectBase<DerivedF> &F,
+    Eigen::PlainObjectBase<DerivedNV> &NV,
+    Eigen::PlainObjectBase<DerivedNF> &NF,
+    Eigen::PlainObjectBase<DerivedI> &I,
+    Eigen::PlainObjectBase<DerivedJ> &J);
+  // Inputs:
+  //   n  number of vertices (possibly greater than F.maxCoeff()+1)
+  //   F  #F by ss list of simplices
+  // Outputs:
+  //   IM  #V by 1 list of indices such that: NF = IM(F) and NT = IM(T)
+  //      and V(find(IM<=size(NV,1)),:) = NV
+  //   J  #RV by 1 list, such that RV = V(J,:)
+  //   
+  template <
+    typename DerivedF,
+    typename DerivedI,
+    typename DerivedJ>
+  IGL_INLINE void remove_unreferenced(
+    const size_t n,
+    const Eigen::PlainObjectBase<DerivedF> &F,
+    Eigen::PlainObjectBase<DerivedI> &I,
+    Eigen::PlainObjectBase<DerivedJ> &J);
+
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 4 - 3
include/igl/snap_to_canonical_view_quat.cpp

@@ -96,12 +96,13 @@ IGL_INLINE bool igl::snap_to_canonical_view_quat(
   return false;
 }
 
+template <typename Scalarq, typename Scalars>
 IGL_INLINE bool igl::snap_to_canonical_view_quat(
-  const Eigen::Quaterniond & q,
+  const Eigen::Quaternion<Scalarq> & q,
   const double threshold,
-  Eigen::Quaterniond & s)
+  Eigen::Quaternion<Scalars> & s)
 {
-  return snap_to_canonical_view_quat<double>( 
+  return snap_to_canonical_view_quat<Scalars>( 
     q.coeffs().data(),threshold,s.coeffs().data());
 }
 

+ 3 - 2
include/igl/snap_to_canonical_view_quat.h

@@ -30,10 +30,11 @@ namespace igl
     const Q_type threshold,
     Q_type* s);
 
+  template <typename Scalarq, typename Scalars>
   IGL_INLINE bool snap_to_canonical_view_quat(
-    const Eigen::Quaterniond & q,
+    const Eigen::Quaternion<Scalarq> & q,
     const double threshold,
-    Eigen::Quaterniond & s);
+    Eigen::Quaternion<Scalars> & s);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 4 - 3
include/igl/trackball.cpp

@@ -132,22 +132,23 @@ IGL_INLINE void igl::trackball(
   }
 }
 
+template <typename Scalardown_quat, typename Scalarquat>
 IGL_INLINE void igl::trackball(
   const double w,
   const double h,
   const double speed_factor,
-  const Eigen::Quaterniond & down_quat,
+  const Eigen::Quaternion<Scalardown_quat> & down_quat,
   const double down_mouse_x,
   const double down_mouse_y,
   const double mouse_x,
   const double mouse_y,
-  Eigen::Quaterniond & quat)
+  Eigen::Quaternion<Scalarquat> & quat)
 {
   using namespace std;
   return trackball(
     w,
     h,
-    speed_factor,
+    (Scalarquat)speed_factor,
     down_quat.coeffs().data(),
     down_mouse_x,
     down_mouse_y,

+ 3 - 2
include/igl/trackball.h

@@ -60,16 +60,17 @@ namespace igl
     const double mouse_y,
     Q_type * quat);
   // Eigen wrapper.
+  template <typename Scalardown_quat, typename Scalarquat>
   IGL_INLINE void trackball(
     const double w,
     const double h,
     const double speed_factor,
-    const Eigen::Quaterniond & down_quat,
+    const Eigen::Quaternion<Scalardown_quat> & down_quat,
     const double down_mouse_x,
     const double down_mouse_y,
     const double mouse_x,
     const double mouse_y,
-    Eigen::Quaterniond & quat);
+    Eigen::Quaternion<Scalarquat> & quat);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 11 - 10
include/igl/two_axis_valuator_fixed_up.cpp

@@ -8,33 +8,34 @@
 #include "two_axis_valuator_fixed_up.h"
 #include "PI.h"
 
+template <typename Scalardown_quat, typename Scalarquat>
 IGL_INLINE void igl::two_axis_valuator_fixed_up(
   const int w,
   const int h,
   const double speed,
-  const Eigen::Quaterniond & down_quat,
+  const Eigen::Quaternion<Scalardown_quat> & down_quat,
   const int down_x,
   const int down_y,
   const int mouse_x,
   const int mouse_y,
-  Eigen::Quaterniond & quat)
+  Eigen::Quaternion<Scalarquat> & quat)
 {
   using namespace Eigen;
-  Vector3d axis(0,1,0);
+  Matrix<Scalarquat,3,1> axis(0,1,0);
   quat = down_quat * 
-    Quaterniond(
-      AngleAxisd(
-        PI*((double)(mouse_x-down_x))/(double)w*speed/2.0,
+    Quaternion<Scalarquat>(
+      AngleAxis<Scalarquat>(
+        PI*((Scalarquat)(mouse_x-down_x))/(Scalarquat)w*speed/2.0,
         axis.normalized()));
   quat.normalize();
   {
-    Vector3d axis(1,0,0);
+    Matrix<Scalarquat,3,1> axis(1,0,0);
     if(axis.norm() != 0)
     {
       quat = 
-        Quaterniond(
-          AngleAxisd(
-            PI*(mouse_y-down_y)/(double)h*speed/2.0,
+        Quaternion<Scalarquat>(
+          AngleAxis<Scalarquat>(
+            PI*(mouse_y-down_y)/(Scalarquat)h*speed/2.0,
             axis.normalized())) * quat;
       quat.normalize();
     }

+ 3 - 2
include/igl/two_axis_valuator_fixed_up.h

@@ -30,16 +30,17 @@ namespace igl
   //   quat  the resulting rotation (as quaternion)
   //
   // See also: snap_to_fixed_up
+  template <typename Scalardown_quat, typename Scalarquat>
   IGL_INLINE void two_axis_valuator_fixed_up(
     const int w,
     const int h,
     const double speed,
-    const Eigen::Quaterniond & down_quat,
+    const Eigen::Quaternion<Scalardown_quat> & down_quat,
     const int down_x,
     const int down_y,
     const int mouse_x,
     const int mouse_y,
-    Eigen::Quaterniond & quat);
+    Eigen::Quaternion<Scalarquat> & quat);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 49 - 22
include/igl/viewer/Viewer.cpp

@@ -62,6 +62,7 @@
 #include <igl/quat_mult.h>
 #include <igl/axis_angle_to_quat.h>
 #include <igl/trackball.h>
+#include <igl/two_axis_valuator_fixed_up.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/unproject.h>
 
@@ -108,6 +109,16 @@ static void glfw_error_callback(int error, const char* description)
   fputs(description, stderr);
 }
 
+static void glfw_char_mods_callback(GLFWwindow* window, unsigned int codepoint, int modifier)
+{
+  // TODO: pass to nanogui (although it's also using physical key down/up
+  // rather than character codes...
+  if(! __viewer->ngui->charEvent(window,codepoint) )
+  {
+    __viewer->key_pressed(codepoint, modifier);
+  }
+}
+
 static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int modifier)
 {
   if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
@@ -150,11 +161,6 @@ static void glfw_mouse_scroll(GLFWwindow* window, double x, double y)
     __viewer->mouse_scroll(y);
 }
 
-static void glfw_char_callback(GLFWwindow* window, unsigned int c)
-{
-  __viewer->ngui->charEvent(window,c);
-}
-
 static void glfw_drop_callback(GLFWwindow *window,int count,const char **filenames)
 {
   __viewer->ngui->dropEvent(window,count,filenames);
@@ -410,18 +416,26 @@ namespace viewer
     return true;
   }
 
+  IGL_INLINE bool Viewer::key_pressed(unsigned int unicode_key,int modifiers)
+  {
+    if (callback_key_pressed)
+      if (callback_key_pressed(*this,unicode_key,modifiers))
+        return true;
+
+    for (unsigned int i = 0; i<plugins.size(); ++i)
+      if (plugins[i]->key_pressed(unicode_key, modifiers))
+        return true;
+    return false;
+  }
+
   IGL_INLINE bool Viewer::key_down(int key,int modifiers)
   {
     if (callback_key_down)
       if (callback_key_down(*this,key,modifiers))
         return true;
-
     for (unsigned int i = 0; i<plugins.size(); ++i)
       if (plugins[i]->key_down(key, modifiers))
         return true;
-
-    char k = key;
-
     return false;
   }
 
@@ -526,17 +540,30 @@ namespace viewer
     {
       switch (mouse_mode)
       {
-        case MouseMode::Rotation :
+        case MouseMode::Rotation:
         {
-          igl::trackball(core.viewport(2),
-                         core.viewport(3),
-                         2.0f,
-                         down_rotation.data(),
-                         down_mouse_x,
-                         down_mouse_y,
-                         mouse_x,
-                         mouse_y,
-                         core.trackball_angle.data());
+          switch(core.rotation_type)
+          {
+            case ViewerCore::ROTATION_TYPE_TRACKBALL:
+              igl::trackball(core.viewport(2),
+                             core.viewport(3),
+                             2.0f,
+                             down_rotation,
+                             down_mouse_x,
+                             down_mouse_y,
+                             mouse_x,
+                             mouse_y,
+                             core.trackball_angle);
+              break;
+            case ViewerCore::ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP:
+              igl::two_axis_valuator_fixed_up(
+                  core.viewport(2),core.viewport(3),
+                  2.0,
+                  down_rotation,
+                  down_mouse_x, down_mouse_y, mouse_x, mouse_y,
+                  core.trackball_angle);
+              break;
+          }
           //Eigen::Vector4f snapq = core.trackball_angle;
 
           break;
@@ -673,8 +700,8 @@ namespace viewer
 
   IGL_INLINE void Viewer::snap_to_canonical_quaternion()
   {
-    Eigen::Vector4f snapq = this->core.trackball_angle;
-    igl::snap_to_canonical_view_quat(snapq.data(),1.0f,this->core.trackball_angle.data());
+    Eigen::Quaternionf snapq = this->core.trackball_angle;
+    igl::snap_to_canonical_view_quat(snapq,1.0f,this->core.trackball_angle);
   }
 
   IGL_INLINE void Viewer::open_dialog_load_mesh()
@@ -769,7 +796,7 @@ namespace viewer
     glfwSetWindowSizeCallback(window,glfw_window_size);
     glfwSetMouseButtonCallback(window,glfw_mouse_press);
     glfwSetScrollCallback(window,glfw_mouse_scroll);
-    glfwSetCharCallback(window,glfw_char_callback);
+    glfwSetCharModsCallback(window,glfw_char_mods_callback);
     glfwSetDropCallback(window,glfw_drop_callback);
 
     // Handle retina displays (windows and mac)

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

@@ -61,7 +61,7 @@ namespace viewer
     IGL_INLINE void shutdown_plugins();
 
     // Temporary data stored when the mouse button is pressed
-    Eigen::Vector4f down_rotation;
+    Eigen::Quaternionf down_rotation;
     int current_mouse_x;
     int current_mouse_y;
     int down_mouse_x;
@@ -88,6 +88,7 @@ namespace viewer
     IGL_INLINE bool save_mesh_to_file(const char* 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);
 
@@ -121,6 +122,8 @@ namespace viewer
     std::function<bool(Viewer& viewer, int button, int modifier)> callback_mouse_up;
     std::function<bool(Viewer& viewer, int mouse_x, int mouse_y)> callback_mouse_move;
     std::function<bool(Viewer& viewer, float delta_y)> callback_mouse_scroll;
+    std::function<bool(Viewer& viewer, unsigned int key, int modifiers)> callback_key_pressed;
+    // 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;
 
@@ -132,6 +135,7 @@ namespace viewer
     void* callback_mouse_up_data;
     void* callback_mouse_move_data;
     void* callback_mouse_scroll_data;
+    void* callback_key_pressed_data;
     void* callback_key_down_data;
     void* callback_key_up_data;
 

+ 2 - 2
include/igl/viewer/ViewerCore.cpp

@@ -184,7 +184,7 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(ViewerData& data, OpenGL_state& op
 
     // Set model transformation
     float mat[16];
-    igl::quat_to_mat(trackball_angle.data(), mat);
+    igl::quat_to_mat(trackball_angle.coeffs().data(), mat);
 
     for (unsigned i=0;i<4;++i)
       for (unsigned j=0;j<4;++j)
@@ -417,7 +417,7 @@ IGL_INLINE igl::viewer::ViewerCore::ViewerCore()
   lighting_factor = 1.0f; //on
 
   // Default trackball
-  trackball_angle << 0.0f, 0.0f, 0.0f, 1.0f;
+  trackball_angle = Eigen::Quaternionf::Identity();
 
   // Defalut model viewing parameters
   model_zoom = 1.0f;

+ 7 - 1
include/igl/viewer/ViewerCore.h

@@ -84,7 +84,13 @@ public:
   float lighting_factor;
 
   // Trackball angle (quaternion)
-  Eigen::Vector4f trackball_angle;
+  enum RotationType
+  {
+    ROTATION_TYPE_TRACKBALL = 0,
+    ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP = 1,
+    NUM_ROTATION_TYPES = 2
+  } rotation_type;
+  Eigen::Quaternionf trackball_angle;
 
   // Model viewing parameters
   float model_zoom;

+ 10 - 1
include/igl/viewer/ViewerPlugin.h

@@ -126,7 +126,16 @@ public:
     return false;
   }
 
-  // This function is called when a keyboard key is pressed
+  // This function is called when a keyboard key is pressed. Unlike key_down
+  // this will reveal the actual character being sent (not just the physical
+  // key)
+  // - modifiers is a bitfield that might one or more of the following bits Preview3D::NO_KEY, Preview3D::SHIFT, Preview3D::CTRL, Preview3D::ALT;
+  IGL_INLINE virtual bool key_pressed(unsigned int key, int modifiers)
+  {
+    return false;
+  }
+
+  // This function is called when a keyboard key is down
   // - modifiers is a bitfield that might one or more of the following bits Preview3D::NO_KEY, Preview3D::SHIFT, Preview3D::CTRL, Preview3D::ALT;
   IGL_INLINE virtual bool key_down(int key, int modifiers)
   {