1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
/*
* Simple trackball-like motion adapted (ripped off) from projtex.c
* (written by David Yu and David Blythe). See the SIGGRAPH '96
* Advanced OpenGL course notes.
*/
/* includes */
#include <math.h>
#include <assert.h>
#include <GL/glut.h>
#include "tb.h"
#include "trackball.h"
/* globals */
static GLuint tb_lasttime;
float curquat[4];
float lastquat[4];
int beginx, beginy;
static GLuint tb_width;
static GLuint tb_height;
static GLint tb_button = -1;
static GLboolean tb_tracking = GL_FALSE;
static GLboolean tb_animate = GL_TRUE;
void
tbStepAnimation(void)
{
add_quats(lastquat, curquat, curquat);
}
void
_tbAnimate(void)
{
tbStepAnimation();
glutPostRedisplay();
}
static void
defaultAnimateFunc(int animate)
{
if (animate) {
glutIdleFunc(_tbAnimate);
} else {
glutIdleFunc(0);
}
}
void (*animateFunc)(int animate) = defaultAnimateFunc;
void
_tbStartMotion(int x, int y, int time)
{
assert(tb_button != -1);
animateFunc(0);
tb_tracking = GL_TRUE;
tb_lasttime = time;
beginx = x;
beginy = y;
}
void
_tbStopMotion(unsigned time)
{
assert(tb_button != -1);
tb_tracking = GL_FALSE;
if (time == tb_lasttime && tb_animate) {
animateFunc(1);
} else {
if (tb_animate) {
animateFunc(0);
}
}
}
void
tbAnimate(GLboolean animate)
{
tb_animate = animate;
}
void
tbInit(GLuint button)
{
tb_button = button;
trackball(curquat, 0.0, 0.0, 0.0, 0.0);
}
void
tbMatrix(void)
{
GLfloat m[4][4];
assert(tb_button != -1);
build_rotmatrix(m, curquat);
glMultMatrixf(&m[0][0]);
}
void
tbReshape(int width, int height)
{
assert(tb_button != -1);
tb_width = width;
tb_height = height;
}
void
tbMouse(int button, int state, int x, int y)
{
assert(tb_button != -1);
if (state == GLUT_DOWN && button == tb_button)
_tbStartMotion(x, y, glutGet(GLUT_ELAPSED_TIME));
else if (state == GLUT_UP && button == tb_button)
_tbStopMotion(glutGet(GLUT_ELAPSED_TIME));
}
void
tbMotion(int x, int y)
{
if (tb_tracking) {
trackball(lastquat,
(2.0 * beginx - tb_width) / tb_width,
(tb_height - 2.0 * beginy) / tb_height,
(2.0 * x - tb_width) / tb_width,
(tb_height - 2.0 * y) / tb_height
);
beginx = x;
beginy = y;
tb_animate = 1;
tb_lasttime = glutGet(GLUT_ELAPSED_TIME);
tbStepAnimation();
}
}
void
tbAnimateFunc(void (*func)(int animate))
{
animateFunc = func;
}
|