BeachBall.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "BeachBall.h"
  2. #include <igl/opengl2/draw_beach_ball.h>
  3. #include <igl/quat_to_mat.h>
  4. #include <igl/opengl2/unproject_to_zero_plane.h>
  5. #include <igl/opengl2/unproject.h>
  6. #include <igl/opengl2/project.h>
  7. #include <igl/quat_mult.h>
  8. #include <igl/quat_conjugate.h>
  9. #include <igl/trackball.h>
  10. #include <igl/mat_to_quat.h>
  11. #include <OpenGL/GL.h>
  12. #include <iostream>
  13. #include <cmath>
  14. BeachBall::BeachBall():
  15. radius(1),
  16. is_hover(false),
  17. is_down(false),
  18. trackball_on(false),
  19. down_x(-1),
  20. down_y(-1)
  21. {
  22. r[0]=r[1]=r[2]=0;r[3]=1;
  23. t[0]=t[1]=t[2]=0;t[3]=0;
  24. }
  25. void BeachBall::pushmv() const
  26. {
  27. glPushMatrix();
  28. glLoadIdentity();
  29. glMultMatrixd(mv);
  30. }
  31. void BeachBall::popmv() const
  32. {
  33. glPopMatrix();
  34. }
  35. void BeachBall::push() const
  36. {
  37. using namespace igl;
  38. glPushMatrix();
  39. // Translate to relative origin
  40. glTranslated(t[0],t[1],t[2]);
  41. // Rotate to relative orientation
  42. double mat[4*4]; quat_to_mat(r,mat); glMultMatrixd(mat);
  43. }
  44. void BeachBall::pop() const
  45. {
  46. glPopMatrix();
  47. }
  48. void BeachBall::draw()
  49. {
  50. using namespace std;
  51. using namespace igl;
  52. // Keep track of relative identity (modelview) matrix at draw call
  53. glGetDoublev(GL_MODELVIEW_MATRIX,mv);
  54. push();
  55. // Dim if hovered over
  56. float ld[4];
  57. glGetLightfv(GL_LIGHT0,GL_DIFFUSE,ld);
  58. if(is_hover)
  59. {
  60. float ld_hover[4];
  61. ld_hover[0] = 0.5*ld[0];
  62. ld_hover[1] = 0.5*ld[1];
  63. ld_hover[2] = 0.5*ld[2];
  64. ld_hover[3] = 0.5*ld[3];
  65. glLightfv(GL_LIGHT0,GL_DIFFUSE,ld_hover);
  66. }
  67. // Adjust scale only after setting origin
  68. glPushMatrix();
  69. glScaled(radius,radius,radius);
  70. // draw oriented glyph
  71. igl::opengl2::draw_beach_ball();
  72. // Pop scale
  73. glPopMatrix();
  74. // Reset lighting
  75. glLightfv(GL_LIGHT0,GL_DIFFUSE,ld);
  76. // Reset relative identity
  77. pop();
  78. }
  79. bool BeachBall::in(const int x,const int y) const
  80. {
  81. using namespace igl;
  82. using namespace std;
  83. pushmv();
  84. push();
  85. // Now origin is center of object
  86. double obj[3];
  87. // Check if igl::opengl2::unprojected screen point is nearby
  88. igl::opengl2::unproject_to_zero_plane(x,y, &obj[0], &obj[1], &obj[2]);
  89. bool near = (obj[0]*obj[0] + obj[1]*obj[1] + obj[2]*obj[2])<radius*radius;
  90. pop();
  91. popmv();
  92. return near;
  93. }
  94. bool BeachBall::hover(const int x,const int y)
  95. {
  96. return is_hover = in(x,y);
  97. }
  98. bool BeachBall::down(const int x,const int y)
  99. {
  100. using namespace std;
  101. using namespace igl;
  102. is_down = in(x,y);
  103. if(is_down)
  104. {
  105. copy(r,r+4,down_r);
  106. copy(t,t+4,down_t);
  107. down_x = x;
  108. down_y = y;
  109. trackball_on = true;
  110. }
  111. return is_down;
  112. }
  113. bool BeachBall::drag(const int x,const int y)
  114. {
  115. using namespace igl;
  116. using namespace std;
  117. if(!is_down)
  118. {
  119. return false;
  120. }
  121. if(trackball_on)
  122. {
  123. // Pick up origin location
  124. pushmv();
  125. push();
  126. double origin[3];
  127. igl::opengl2::project(0,0,0,&origin[0],&origin[1],&origin[2]);
  128. pop();
  129. popmv();
  130. double rot[4];
  131. int VP[4];
  132. glGetIntegerv(GL_VIEWPORT,VP);
  133. trackball<double>(
  134. VP[2],
  135. VP[3],
  136. 2,
  137. (down_x-origin[0]+VP[2]/2),
  138. VP[3]-(down_y-origin[1]+VP[3]/2),
  139. ( x-origin[0]+VP[2]/2),
  140. VP[3]-( y-origin[1]+VP[3]/2),
  141. rot);
  142. {
  143. // We've computed change in rotation according to this view:
  144. // R = mv * r, R' = rot * (mv * r)
  145. // But we only want new value for r:
  146. // R' = mv * r'
  147. // mv * r' = rot * (mv * r)
  148. // r' = mv* * rot * sr * r
  149. // Convert modelview matrix to quaternion
  150. double sr_conj[4],scene_rot[4],t1[4],t2[4];
  151. mat4_to_quat(mv,scene_rot);
  152. //cout<<"::sr: "<<
  153. // BeachBall::scene_rot[0]<<" "<<
  154. // BeachBall::scene_rot[1]<<" "<<
  155. // BeachBall::scene_rot[2]<<" "<<
  156. // BeachBall::scene_rot[3]<<" "<<
  157. // endl;
  158. //cout<<" sr: "<<
  159. // scene_rot[0]<<" "<<
  160. // scene_rot[1]<<" "<<
  161. // scene_rot[2]<<" "<<
  162. // scene_rot[3]<<" "<<
  163. // endl;
  164. // Normalize to unit quaternion (rotation only)
  165. double len =
  166. sqrt(scene_rot[0]*scene_rot[0]+
  167. scene_rot[1]*scene_rot[1]+
  168. scene_rot[2]*scene_rot[2]+
  169. scene_rot[3]*scene_rot[3]);
  170. for(int j = 0;j<4;j++)
  171. {
  172. scene_rot[j] /= len;
  173. }
  174. // TODO: Just use Eigen::Quaterniond
  175. quat_conjugate(scene_rot,sr_conj);
  176. quat_mult<double>(sr_conj,rot,t1);
  177. quat_mult<double>(t1,scene_rot,t2);
  178. quat_mult<double>(t2,down_r,r);
  179. }
  180. }else
  181. {
  182. // We want that origin follows mouse move. First define plane we
  183. // igl::opengl2::projecteing screen mouse movement to as perpendicular plan passing
  184. // through this origin.
  185. pushmv();
  186. // down_t igl::opengl2::projected to screen to get depth value
  187. double p[3];
  188. igl::opengl2::project(down_t[0],down_t[1],down_t[2],&p[0],&p[1],&p[2]);
  189. // igl::opengl2::unprojected down_x,down_y with down_t depth
  190. double du[3];
  191. igl::opengl2::unproject(down_x,down_y,p[2],&du[0],&du[1],&du[2]);
  192. // igl::opengl2::unprojected x,y with down_t depth
  193. double u[3];
  194. igl::opengl2::unproject(x,y,p[2],&u[0], &u[1], &u[2]);
  195. popmv();
  196. // Then move this origin according to igl::opengl2::project mouse displacment
  197. t[0] = down_t[0] + (u[0]-du[0]);
  198. t[1] = down_t[1] + (u[1]-du[1]);
  199. t[2] = down_t[2] + (u[2]-du[2]);
  200. }
  201. return is_down;
  202. }
  203. bool BeachBall::right_down(const int x,const int y)
  204. {
  205. using namespace std;
  206. using namespace igl;
  207. is_down = in(x,y);
  208. if(is_down)
  209. {
  210. copy(r,r+4,down_r);
  211. copy(t,t+4,down_t);
  212. down_x = x;
  213. down_y = y;
  214. }
  215. return is_down;
  216. }
  217. bool BeachBall::up(const int /*x*/,const int /*y*/)
  218. {
  219. trackball_on = false;
  220. return is_down = false;
  221. }