trackball.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "trackball.h"
  9. #include "EPS.h"
  10. #include "dot.h"
  11. #include "cross.h"
  12. #include "axis_angle_to_quat.h"
  13. #include "quat_mult.h"
  14. #include <cmath>
  15. #include <cstdlib>
  16. #include <cassert>
  17. #include <algorithm>
  18. #include <iostream>
  19. // Utility IGL_INLINE functions
  20. template <typename Q_type>
  21. static IGL_INLINE Q_type _QuatD(double w, double h)
  22. {
  23. using namespace std;
  24. return (Q_type)(std::abs(w) < std::abs(h) ? std::abs(w) : std::abs(h)) - 4;
  25. }
  26. template <typename Q_type>
  27. static IGL_INLINE Q_type _QuatIX(double x, double w, double h)
  28. {
  29. return (2.0f*(Q_type)x - (Q_type)w - 1.0f)/_QuatD<Q_type>(w, h);
  30. }
  31. template <typename Q_type>
  32. static IGL_INLINE Q_type _QuatIY(double y, double w, double h)
  33. {
  34. return (-2.0f*(Q_type)y + (Q_type)h - 1.0f)/_QuatD<Q_type>(w, h);
  35. }
  36. // This is largely the trackball as implemented in AntTweakbar. Much of the
  37. // code is straight from its source in TwMgr.cpp
  38. // http://www.antisphere.com/Wiki/tools:anttweakbar
  39. template <typename Q_type>
  40. IGL_INLINE void igl::trackball(
  41. const double w,
  42. const double h,
  43. const Q_type speed_factor,
  44. const double down_mouse_x,
  45. const double down_mouse_y,
  46. const double mouse_x,
  47. const double mouse_y,
  48. Q_type * quat)
  49. {
  50. assert(speed_factor > 0);
  51. double original_x =
  52. _QuatIX<Q_type>(speed_factor*(down_mouse_x-w/2)+w/2, w, h);
  53. double original_y =
  54. _QuatIY<Q_type>(speed_factor*(down_mouse_y-h/2)+h/2, w, h);
  55. double x = _QuatIX<Q_type>(speed_factor*(mouse_x-w/2)+w/2, w, h);
  56. double y = _QuatIY<Q_type>(speed_factor*(mouse_y-h/2)+h/2, w, h);
  57. double z = 1;
  58. double n0 = sqrt(original_x*original_x + original_y*original_y + z*z);
  59. double n1 = sqrt(x*x + y*y + z*z);
  60. if(n0>igl::DOUBLE_EPS && n1>igl::DOUBLE_EPS)
  61. {
  62. double v0[] = { original_x/n0, original_y/n0, z/n0 };
  63. double v1[] = { x/n1, y/n1, z/n1 };
  64. double axis[3];
  65. cross(v0,v1,axis);
  66. double sa = sqrt(dot(axis, axis));
  67. double ca = dot(v0, v1);
  68. double angle = atan2(sa, ca);
  69. if( x*x+y*y>1.0 )
  70. {
  71. angle *= 1.0 + 0.2f*(sqrt(x*x+y*y)-1.0);
  72. }
  73. double qrot[4];
  74. axis_angle_to_quat(axis,angle,qrot);
  75. quat[0] = qrot[0];
  76. quat[1] = qrot[1];
  77. quat[2] = qrot[2];
  78. quat[3] = qrot[3];
  79. }
  80. }
  81. template <typename Q_type>
  82. IGL_INLINE void igl::trackball(
  83. const double w,
  84. const double h,
  85. const Q_type speed_factor,
  86. const Q_type * down_quat,
  87. const double down_mouse_x,
  88. const double down_mouse_y,
  89. const double mouse_x,
  90. const double mouse_y,
  91. Q_type * quat)
  92. {
  93. double qrot[4], qres[4], qorig[4];
  94. igl::trackball<double>(
  95. w,h,
  96. speed_factor,
  97. down_mouse_x,down_mouse_y,
  98. mouse_x,mouse_y,
  99. qrot);
  100. double nqorig =
  101. sqrt(down_quat[0]*down_quat[0]+
  102. down_quat[1]*down_quat[1]+
  103. down_quat[2]*down_quat[2]+
  104. down_quat[3]*down_quat[3]);
  105. if( fabs(nqorig)>igl::DOUBLE_EPS_SQ )
  106. {
  107. qorig[0] = down_quat[0]/nqorig;
  108. qorig[1] = down_quat[1]/nqorig;
  109. qorig[2] = down_quat[2]/nqorig;
  110. qorig[3] = down_quat[3]/nqorig;
  111. igl::quat_mult<double>(qrot,qorig,qres);
  112. quat[0] = qres[0];
  113. quat[1] = qres[1];
  114. quat[2] = qres[2];
  115. quat[3] = qres[3];
  116. }
  117. else
  118. {
  119. quat[0] = qrot[0];
  120. quat[1] = qrot[1];
  121. quat[2] = qrot[2];
  122. quat[3] = qrot[3];
  123. }
  124. }
  125. template <typename Scalardown_quat, typename Scalarquat>
  126. IGL_INLINE void igl::trackball(
  127. const double w,
  128. const double h,
  129. const double speed_factor,
  130. const Eigen::Quaternion<Scalardown_quat> & down_quat,
  131. const double down_mouse_x,
  132. const double down_mouse_y,
  133. const double mouse_x,
  134. const double mouse_y,
  135. Eigen::Quaternion<Scalarquat> & quat)
  136. {
  137. using namespace std;
  138. return trackball(
  139. w,
  140. h,
  141. (Scalarquat)speed_factor,
  142. down_quat.coeffs().data(),
  143. down_mouse_x,
  144. down_mouse_y,
  145. mouse_x,
  146. mouse_y,
  147. quat.coeffs().data());
  148. }
  149. #ifdef IGL_STATIC_LIBRARY
  150. // Explicit template specialization
  151. // generated by autoexplicit.sh
  152. template void igl::trackball<double>(double, double, double, double const*, double, double, double, double, double*);
  153. // generated by autoexplicit.sh
  154. template void igl::trackball<float>(double, double, float, float const*, double, double, double, double, float*);
  155. template void igl::trackball<float, float>(double, double, double, Eigen::Quaternion<float, 0> const&, double, double, double, double, Eigen::Quaternion<float, 0>&);
  156. template void igl::trackball<double, double>(double, double, double, Eigen::Quaternion<double, 0> const&, double, double, double, double, Eigen::Quaternion<double, 0>&);
  157. #endif