trackball.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:4k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*
  2.  *  Simple trackball-like motion adapted (ripped off) from projtex.c
  3.  *  (written by David Yu and David Blythe).  See the SIGGRAPH '96
  4.  *  Advanced OpenGL course notes.
  5.  */
  6. /* includes */
  7. #include <math.h>
  8. #include <assert.h>
  9. #include <GL/glut.h>
  10. #include "trackball.h"
  11. /* globals */
  12. static GLuint    tb_lasttime;
  13. static GLfloat   tb_lastposition[3];
  14. static GLfloat   tb_angle = 0.0;
  15. static GLfloat   tb_axis[3];
  16. static GLfloat   tb_transform[4][4];
  17. static GLuint    tb_width;
  18. static GLuint    tb_height;
  19. static GLint     tb_button = -1;
  20. static GLboolean tb_tracking = GL_FALSE;
  21. static GLboolean tb_animate = GL_TRUE;
  22. /* functions */
  23. static void
  24. _tbPointToVector(int x, int y, int width, int height, float v[3])
  25. {
  26.   float d, a;
  27.   /* project x, y onto a hemi-sphere centered within width, height. */
  28.   v[0] = (2.0 * x - width) / width;
  29.   v[1] = (height - 2.0 * y) / height;
  30.   d = sqrt(v[0] * v[0] + v[1] * v[1]);
  31.   v[2] = cos((3.14159265 / 2.0) * ((d < 1.0) ? d : 1.0));
  32.   a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  33.   v[0] *= a;
  34.   v[1] *= a;
  35.   v[2] *= a;
  36. }
  37. static void
  38. _tbAnimate(void)
  39. {
  40.   glutPostRedisplay();
  41. }
  42. void
  43. _tbStartMotion(int x, int y, int button, int time)
  44. {
  45.   assert(tb_button != -1);
  46.   tb_tracking = GL_TRUE;
  47.   tb_lasttime = time;
  48.   _tbPointToVector(x, y, tb_width, tb_height, tb_lastposition);
  49. }
  50. void
  51. _tbStopMotion(int button, unsigned time)
  52. {
  53.   assert(tb_button != -1);
  54.   tb_tracking = GL_FALSE;
  55.   if (time == tb_lasttime && tb_animate) {
  56.     glutIdleFunc(_tbAnimate);
  57.   } else {
  58.     tb_angle = 0.0;
  59.     if (tb_animate)
  60.       glutIdleFunc(0);
  61.   }
  62. }
  63. void
  64. tbAnimate(GLboolean animate)
  65. {
  66.   tb_animate = animate;
  67. }
  68. void
  69. tbInit(GLuint button)
  70. {
  71.   tb_button = button;
  72.   tb_angle = 0.0;
  73.   /* put the identity in the trackball transform */
  74.   glPushMatrix();
  75.   glLoadIdentity();
  76.   glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)tb_transform);
  77.   glPopMatrix();
  78. }
  79. void
  80. tbMatrix()
  81. {
  82.   assert(tb_button != -1);
  83.   glPushMatrix();
  84.   glLoadIdentity();
  85.   glRotatef(tb_angle, tb_axis[0], tb_axis[1], tb_axis[2]);
  86.   glMultMatrixf((GLfloat *)tb_transform);
  87.   glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)tb_transform);
  88.   glPopMatrix();
  89.   glMultMatrixf((GLfloat *)tb_transform);
  90. }
  91. void
  92. tbReshape(int width, int height)
  93. {
  94.   assert(tb_button != -1);
  95.   tb_width  = width;
  96.   tb_height = height;
  97. }
  98. void
  99. tbMouse(int button, int state, int x, int y)
  100. {
  101.   assert(tb_button != -1);
  102.   if (state == GLUT_DOWN && button == tb_button)
  103.     _tbStartMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME));
  104.   else if (state == GLUT_UP && button == tb_button)
  105.     _tbStopMotion(button, glutGet(GLUT_ELAPSED_TIME));
  106. }
  107. void
  108. tbMotion(int x, int y)
  109. {
  110.   GLfloat current_position[3], dx, dy, dz;
  111.   assert(tb_button != -1);
  112.   if (tb_tracking == GL_FALSE)
  113.     return;
  114.   _tbPointToVector(x, y, tb_width, tb_height, current_position);
  115.   /* calculate the angle to rotate by (directly proportional to the
  116.      length of the mouse movement */
  117.   dx = current_position[0] - tb_lastposition[0];
  118.   dy = current_position[1] - tb_lastposition[1];
  119.   dz = current_position[2] - tb_lastposition[2];
  120.   tb_angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
  121.   /* calculate the axis of rotation (cross product) */
  122.   tb_axis[0] = tb_lastposition[1] * current_position[2] - 
  123.                tb_lastposition[2] * current_position[1];
  124.   tb_axis[1] = tb_lastposition[2] * current_position[0] - 
  125.                tb_lastposition[0] * current_position[2];
  126.   tb_axis[2] = tb_lastposition[0] * current_position[1] - 
  127.                tb_lastposition[1] * current_position[0];
  128.   /* reset for next time */
  129.   tb_lasttime = glutGet(GLUT_ELAPSED_TIME);
  130.   tb_lastposition[0] = current_position[0];
  131.   tb_lastposition[1] = current_position[1];
  132.   tb_lastposition[2] = current_position[2];
  133.   /* remember to draw new position */
  134.   glutPostRedisplay();
  135. }