trackball.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #ifndef IGL_TRACKBALL_H
  2. #define IGL_TRACKBALL_H
  3. namespace igl
  4. {
  5. // Applies a trackball drag to a given rotation
  6. // Inputs:
  7. // w width of the trackball context
  8. // h height of the trackball context
  9. // speed_factor controls how fast the trackball feels, 1 is normal
  10. // down_quat rotation at mouse down, i.e. the rotation we're applying the
  11. // trackball motion to (as quaternion)
  12. // down_mouse_x x position of mouse down
  13. // down_mouse_y y position of mouse down
  14. // mouse_x current x position of mouse
  15. // mouse_y current y position of mouse
  16. // Outputs:
  17. // quat the resulting rotation (as quaternion)
  18. template <typename Q_type>
  19. inline void trackball(
  20. const int w,
  21. const int h,
  22. const Q_type speed_factor,
  23. const Q_type * down_quat,
  24. const int down_mouse_x,
  25. const int down_mouse_y,
  26. const int mouse_x,
  27. const int mouse_y,
  28. Q_type * quat);
  29. }
  30. // Implementation
  31. #include "EPS.h"
  32. #include "dot.h"
  33. #include "cross.h"
  34. #include "axis_angle_to_quat.h"
  35. #include "quat_mult.h"
  36. #include <cmath>
  37. #include <cstdlib>
  38. #include <algorithm>
  39. // Utility inline functions
  40. template <typename Q_type>
  41. static inline Q_type _QuatD(int w, int h)
  42. {
  43. return (Q_type)(abs(w) < abs(h) ? abs(w) : abs(h)) - 4;
  44. }
  45. template <typename Q_type>
  46. static inline Q_type _QuatIX(int x, int w, int h)
  47. {
  48. return (2.0f*(Q_type)x - (Q_type)w - 1.0f)/_QuatD<Q_type>(w, h);
  49. }
  50. template <typename Q_type>
  51. static inline Q_type _QuatIY(int y, int w, int h)
  52. {
  53. return (-2.0f*(Q_type)y + (Q_type)h - 1.0f)/_QuatD<Q_type>(w, h);
  54. }
  55. // This is largely the trackball as implemented in AntTweakbar. Much of the
  56. // code is straight from its source in TwMgr.cpp
  57. // http://www.antisphere.com/Wiki/tools:anttweakbar
  58. template <typename Q_type>
  59. inline void igl::trackball(
  60. const int w,
  61. const int h,
  62. const Q_type speed_factor,
  63. const Q_type * down_quat,
  64. const int down_mouse_x,
  65. const int down_mouse_y,
  66. const int mouse_x,
  67. const int mouse_y,
  68. Q_type * quat)
  69. {
  70. assert(speed_factor > 0);
  71. double original_x =
  72. _QuatIX<Q_type>(speed_factor*(down_mouse_x-w/2)+w/2, w, h);
  73. double original_y =
  74. _QuatIY<Q_type>(speed_factor*(down_mouse_y-h/2)+h/2, w, h);
  75. double x = _QuatIX<Q_type>(speed_factor*(mouse_x-w/2)+w/2, w, h);
  76. double y = _QuatIY<Q_type>(speed_factor*(mouse_y-h/2)+h/2, w, h);
  77. double z = 1;
  78. double n0 = sqrt(original_x*original_x + original_y*original_y + z*z);
  79. double n1 = sqrt(x*x + y*y + z*z);
  80. if(n0>igl::DOUBLE_EPS && n1>igl::DOUBLE_EPS)
  81. {
  82. double v0[] = { original_x/n0, original_y/n0, z/n0 };
  83. double v1[] = { x/n1, y/n1, z/n1 };
  84. double axis[3];
  85. cross(v0,v1,axis);
  86. double sa = sqrt(dot(axis, axis));
  87. double ca = dot(v0, v1);
  88. double angle = atan2(sa, ca);
  89. if( x*x+y*y>1.0 )
  90. {
  91. angle *= 1.0 + 0.2f*(sqrt(x*x+y*y)-1.0);
  92. }
  93. double qrot[4], qres[4], qorig[4];
  94. axis_angle_to_quat(axis,angle,qrot);
  95. double nqorig =
  96. sqrt(down_quat[0]*down_quat[0]+
  97. down_quat[1]*down_quat[1]+
  98. down_quat[2]*down_quat[2]+
  99. down_quat[3]*down_quat[3]);
  100. if( fabs(nqorig)>igl::DOUBLE_EPS_SQ )
  101. {
  102. qorig[0] = down_quat[0]/nqorig;
  103. qorig[1] = down_quat[1]/nqorig;
  104. qorig[2] = down_quat[2]/nqorig;
  105. qorig[3] = down_quat[3]/nqorig;
  106. igl::quat_mult<double>(qrot,qorig,qres);
  107. quat[0] = qres[0];
  108. quat[1] = qres[1];
  109. quat[2] = qres[2];
  110. quat[3] = qres[3];
  111. }
  112. else
  113. {
  114. quat[0] = qrot[0];
  115. quat[1] = qrot[1];
  116. quat[2] = qrot[2];
  117. quat[3] = qrot[3];
  118. }
  119. }
  120. }
  121. #endif