Selaa lähdekoodia

rotating widget example with dependencies

Former-commit-id: 8cef99fedb9432e990b06cba568399f717e2a470
Alec Jacobson (jalec 11 vuotta sitten
vanhempi
commit
609c7351ec

+ 7 - 4
examples/rotate-widget/RotateWidget.cpp

@@ -122,10 +122,11 @@ bool RotateWidget::down(const int x, const int y)
     auto on_meridian = [&](
       const Vector3d & hit, 
       const Quaterniond & rot, 
-      const Quaterniond m) -> bool
+      const Quaterniond m,
+      Vector3d & pl_hit) -> bool
     {
       // project onto rotate plane
-      Vector3d pl_hit = hit-pos;
+      pl_hit = hit-pos;
       pl_hit = (m.conjugate()*rot.conjugate()*pl_hit).eval();
       pl_hit(2) = 0;
       pl_hit = (rot*m*pl_hit).eval();
@@ -138,8 +139,11 @@ bool RotateWidget::down(const int x, const int y)
     udrag = udown;
     for(int a = 0;a<3;a++)
     {
-      if(on_meridian(hit,rot,Quaterniond(axis_q[a])))
+      Vector3d pl_hit;
+      if(on_meridian(hit,rot,Quaterniond(axis_q[a]),pl_hit))
       {
+        udown = (pl_hit-pos).normalized()/outer_radius_on_screen;
+        udrag = udown;
         down_type = DownType(DOWN_TYPE_X+a);
         selected_type = down_type;
         {
@@ -151,7 +155,6 @@ bool RotateWidget::down(const int x, const int y)
           // flip y because y coordinate is going to be given backwards in
           // drag()
           down_dir(1) *= -1;
-          cout<<"down_dir: "<<down_dir.transpose()<<endl;
         }
         return true;
       }

+ 20 - 2
examples/rotate-widget/example.cpp

@@ -270,7 +270,6 @@ void display()
 
   TwDraw();
   glutSwapBuffers();
-  glutPostRedisplay();
 }
 
 void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y)
@@ -304,6 +303,7 @@ void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y)
     // Dolly zoom:
     camera.dolly_zoom((double)direction*1.0);
   }
+  glutPostRedisplay();
 }
 
 void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
@@ -374,6 +374,7 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
   }
   pop_object();
   pop_scene();
+  glutPostRedisplay();
 }
 
 void mouse_drag(int mouse_x, int mouse_y)
@@ -426,6 +427,7 @@ void mouse_drag(int mouse_x, int mouse_y)
     }
     camera.orbit(q.conjugate());
   }
+  glutPostRedisplay();
 }
 
 void init_relative()
@@ -504,6 +506,7 @@ void key(unsigned char key, int mouse_x, int mouse_y)
       }
   }
   
+  glutPostRedisplay();
 }
 
 int main(int argc, char * argv[])
@@ -610,8 +613,23 @@ int main(int argc, char * argv[])
   glutKeyboardFunc(key);
   glutMouseFunc(mouse);
   glutMotionFunc(mouse_drag);
-  glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
+  glutPassiveMotionFunc(
+    [](int x, int y){
+      TwEventMouseMotionGLUT(x,y);
+      glutPostRedisplay();
+    });
+  static std::function<void(int)> timer_dummy;
+  auto timer = [] (int ms) {
+    timer_dummy(ms);
+  };
+  timer_dummy = [&] (int ms) {
+    glutTimerFunc(ms, timer, ms);
+    glutPostRedisplay();
+  };
+  glutTimerFunc(500, timer, 500);
+
   glutMainLoop();
 
+
   return 0;
 }

+ 57 - 0
include/igl/forward_kinematics.cpp

@@ -0,0 +1,57 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// 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 "forward_kinematics.h"
+#include <functional>
+
+void igl::forward_kinematics(
+  const Eigen::MatrixXd & C,
+  const Eigen::MatrixXi & BE,
+  const Eigen::VectorXi & P,
+  const std::vector<Eigen::Quaterniond> & dQ,
+  std::vector<Eigen::Quaterniond> & vQ,
+  std::vector<Eigen::Vector3d> & vT)
+{
+  using namespace std;
+  using namespace Eigen;
+  const int m = BE.rows(); 
+  assert(m == P.rows());
+  assert(m == (int)dQ.size());
+  vector<bool> computed(m,false);
+  vQ.resize(m);
+  vT.resize(m);
+  function<void (int) > fk_helper = [&] (int b)
+  {
+    if(!computed[b])
+    {
+      if(P(b) < 0)
+      {
+        // base case for roots
+        vQ[b] = dQ[b];
+        const Vector3d r = C.row(BE(b,0)).transpose();
+        vT[b] = r-dQ[b]*r;
+      }else
+      {
+        // Otherwise first compute parent's
+        const int p = P(b);
+        fk_helper(p);
+        vQ[b] = vQ[p] * dQ[b];
+        const Vector3d r = C.row(BE(b,0)).transpose();
+        vT[b] = vT[p] - vQ[b]*r + vQ[p]*r;
+      }
+      computed[b] = true;
+    }
+  };
+  for(int b = 0;b<m;b++)
+  {
+    fk_helper(b);
+  }
+}
+
+#ifndef IGL_HEADER_ONLY
+// Explicit template instanciation
+#endif

+ 39 - 0
include/igl/forward_kinematics.h

@@ -0,0 +1,39 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// 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_FORWARD_KINEMATICS_H
+#define IGL_FORWARD_KINEMATICS_H
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+#include <vector>
+
+namespace igl
+{
+  // Given a skeleton and a set of relative bone rotations compute absolute
+  // rigid transformations for each bone.
+  //
+  // Inputs:
+  //   C  #C by dim list of joint positions
+  //   BE  #BE by 2 list of bone edge indices
+  //   P  #BE list of parent indices into BE
+  //   dQ  #BE list of relative rotations
+  // Outputs:
+  //   vQ  #BE list of absolute rotations
+  //   vT  #BE list of absolute translations
+  void forward_kinematics(
+    const Eigen::MatrixXd & C,
+    const Eigen::MatrixXi & BE,
+    const Eigen::VectorXi & P,
+    const std::vector<Eigen::Quaterniond> & dQ,
+    std::vector<Eigen::Quaterniond> & vQ,
+    std::vector<Eigen::Vector3d> & vT);
+};
+
+#ifdef IGL_HEADER_ONLY
+#  include "forward_kinematics.cpp"
+#endif
+#endif

+ 46 - 0
include/igl/project_to_line_segment.cpp

@@ -0,0 +1,46 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// 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 "project_to_line_segment.h"
+#include "project_to_line.h"
+#include <Eigen/Core>
+
+template <
+  typename DerivedP, 
+  typename DerivedS, 
+  typename DerivedD, 
+  typename Derivedt, 
+  typename DerivedsqrD>
+IGL_INLINE void igl::project_to_line_segment(
+  const Eigen::PlainObjectBase<DerivedP> & P,
+  const Eigen::PlainObjectBase<DerivedS> & S,
+  const Eigen::PlainObjectBase<DerivedD> & D,
+  Eigen::PlainObjectBase<Derivedt> & t,
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD)
+{
+  project_to_line(P,S,D,t,sqrD);
+  const int np = P.rows();
+  // loop over points and fix those that projected beyond endpoints
+#pragma omp parallel for
+  for(int p = 0;p<np;p++)
+  {
+    if(t(p)<0)
+    {
+      sqrD(p) = (P.row(p)-S).squaredNorm();
+      t(p) = 0;
+    }else if(t(p)>1)
+    {
+      sqrD(p) = (P.row(p)-D).squaredNorm();
+      t(p) = 1;
+    }
+  }
+}
+
+#ifndef IGL_HEADER_ONLY
+// Explicit template specialization
+template void igl::project_to_line_segment<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
+#endif

+ 50 - 0
include/igl/project_to_line_segment.h

@@ -0,0 +1,50 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// 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_PROJECT_TO_LINE_SEGMENT_H
+#define IGL_PROJECT_TO_LINE_SEGMENT_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  // PROJECT_TO_LINE_SEGMENT project points onto vectors, that is find the paramter
+  // t for a point p such that proj_p = (y-x).*t, additionally compute the
+  // squared distance from p to the line of the vector, such that 
+  // |p - proj_p|² = sqr_d
+  //
+  // [T,sqrD] = project_to_line_segment(P,S,D)
+  //
+  // Inputs:
+  //   P  #P by dim list of points to be projected
+  //   S  size dim start position of line vector
+  //   D  size dim destination position of line vector
+  // Outputs:
+  //   T  #P by 1 list of parameters
+  //   sqrD  #P by 1 list of squared distances
+  //
+  //
+  template <
+    typename DerivedP, 
+    typename DerivedS, 
+    typename DerivedD, 
+    typename Derivedt, 
+    typename DerivedsqrD>
+  IGL_INLINE void project_to_line_segment(
+    const Eigen::PlainObjectBase<DerivedP> & P,
+    const Eigen::PlainObjectBase<DerivedS> & S,
+    const Eigen::PlainObjectBase<DerivedD> & D,
+    Eigen::PlainObjectBase<Derivedt> & t,
+    Eigen::PlainObjectBase<DerivedsqrD> & sqrD);
+}
+
+#ifdef IGL_HEADER_ONLY
+#  include "project_to_line.cpp"
+#endif
+
+#endif
+

+ 67 - 0
include/igl/ray_sphere_intersect.cpp

@@ -0,0 +1,67 @@
+#include "ray_sphere_intersect.h"
+
+template <
+  typename Derivedo,
+  typename Derivedd,
+  typename Derivedc, 
+  typename r_type, 
+  typename t_type>
+IGL_INLINE int igl::ray_sphere_intersect(
+  const Eigen::PlainObjectBase<Derivedo> & ao,
+  const Eigen::PlainObjectBase<Derivedd> & d,
+  const Eigen::PlainObjectBase<Derivedc> & ac,
+  r_type r, 
+  t_type & t0,
+  t_type & t1)
+{
+  Eigen::Vector3d o = ao-ac;
+  // http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
+  //Compute A, B and C coefficients
+  double a = d.dot(d);
+  double b = 2 * d.dot(o);
+  double c = o.dot(o) - (r * r);
+
+  //Find discriminant
+  double disc = b * b - 4 * a * c;
+    
+  // if discriminant is negative there are no real roots, so return 
+  // false as ray misses sphere
+  if (disc < 0)
+  {
+    return 0;
+  }
+
+  // compute q as described above
+  double distSqrt = sqrt(disc);
+  double q;
+  if (b < 0)
+  {
+    q = (-b - distSqrt)/2.0;
+  } else
+  {
+    q = (-b + distSqrt)/2.0;
+  }
+
+  // compute t0 and t1
+  t0 = q / a;
+  double _t1 = c/q;
+  if(_t1 == t0)
+  {
+    return 1;
+  }
+  t1 = _t1;
+  // make sure t0 is smaller than t1
+  if (t0 > t1)
+  {
+    // if t0 is bigger than t1 swap them around
+    double temp = t0;
+    t0 = t1;
+    t1 = temp;
+  }
+  return 2;
+}
+
+#ifndef IGL_HEADER_ONLY
+// Explicit template instanciation
+template int igl::ray_sphere_intersect<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1>, double, double>(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, double, double&, double&);
+#endif

+ 46 - 0
include/igl/ray_sphere_intersect.h

@@ -0,0 +1,46 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// 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_RAY_SPHERE_INTERSECT_H
+#define IGL_RAY_SPHERE_INTERSECT_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Compute the intersection between a ray from O in direction D and a sphere
+  // centered at C with radius r
+  //
+  // Inputs:
+  //   o  origin of ray
+  //   d  direction of ray
+  //   c  center of sphere
+  //   r  radius of sphere
+  // Outputs:
+  //   t0  parameterization of first hit (set only if exists) so that hit
+  //    position = o + t0*d
+  //   t1  parameterization of second hit (set only if exists)
+  //   
+  // Returns the number of hits
+  template <
+    typename Derivedo,
+    typename Derivedd,
+    typename Derivedc, 
+    typename r_type, 
+    typename t_type>
+  IGL_INLINE int ray_sphere_intersect(
+    const Eigen::PlainObjectBase<Derivedo> & o,
+    const Eigen::PlainObjectBase<Derivedd> & d,
+    const Eigen::PlainObjectBase<Derivedc> & c,
+    r_type r, 
+    t_type & t0,
+    t_type & t1);
+}
+#ifdef IGL_HEADER_ONLY
+#include "ray_sphere_intersect.cpp"
+#endif
+#endif
+