65
65
* Local function prototypes (not defined in trackball.h)
67
67
static float tb_project_to_sphere(float, float, float);
68
static void normalize_quat(float [4]);
68
static void normalize_quat(float[4]);
79
vset(float *v, float x, float y, float z)
77
void vset(float *v, float x, float y, float z)
87
vsub(const float *src1, const float *src2, float *dst)
84
void vsub(const float *src1, const float *src2, float *dst)
89
86
dst[0] = src1[0] - src2[0];
90
87
dst[1] = src1[1] - src2[1];
91
88
dst[2] = src1[2] - src2[2];
95
vcopy(const float *v1, float *v2)
91
void vcopy(const float *v1, float *v2)
98
for (i = 0 ; i < 3 ; i++)
94
for (i = 0; i < 3; i++)
103
vcross(const float *v1, const float *v2, float *cross)
98
void vcross(const float *v1, const float *v2, float *cross)
110
105
vcopy(temp, cross);
114
vlength(const float *v)
108
float vlength(const float *v)
116
110
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
120
vscale(float *v, float div)
113
void vscale(float *v, float div)
130
vscale(v,1.0/vlength(v));
134
vdot(const float *v1, const float *v2)
136
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
140
vadd(const float *src1, const float *src2, float *dst)
120
void vnormal(float *v)
122
vscale(v, 1.0 / vlength(v));
125
float vdot(const float *v1, const float *v2)
127
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
130
void vadd(const float *src1, const float *src2, float *dst)
142
132
dst[0] = src1[0] + src2[0];
143
133
dst[1] = src1[1] + src2[1];
156
146
* It is assumed that the arguments to this routine are in the range
160
trackball(float q[4], float p1x, float p1y, float p2x, float p2y)
149
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y)
162
float a[3]; /* Axis of rotation */
163
float phi; /* how much to rotate about axis */
151
float a[3]; /* Axis of rotation */
152
float phi; /* how much to rotate about axis */
164
153
float p1[3], p2[3], d[3];
167
156
if (p1x == p2x && p1y == p2y) {
175
164
* First, figure out z-coordinates for projection of P1 and P2 to
176
165
* deformed sphere
178
vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y));
179
vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y));
167
vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y));
168
vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y));
182
171
* Now, we want the cross product of P1 and P2
187
176
* Figure out how much to rotate around that axis.
190
t = vlength(d) / (2.0*TRACKBALLSIZE);
179
t = vlength(d) / (2.0 * TRACKBALLSIZE);
193
182
* Avoid problems with out-of-control values...
195
if (t > 1.0) t = 1.0;
196
if (t < -1.0) t = -1.0;
197
188
phi = 2.0 * asin(t);
199
axis_to_quat(a,phi,q);
190
axis_to_quat(a, phi, q);
203
194
* Given an axis and angle, compute quaternion.
206
axis_to_quat(float a[3], float phi, float q[4])
196
void axis_to_quat(float a[3], float phi, float q[4])
210
vscale(q,sin(phi/2.0));
200
vscale(q, sin(phi / 2.0));
201
q[3] = cos(phi / 2.0);
215
205
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
216
206
* if we are away from the center of the sphere.
219
tb_project_to_sphere(float r, float x, float y)
208
static float tb_project_to_sphere(float r, float x, float y)
224
if (d < r * 0.70710678118654752440) { /* Inside sphere */
226
} else { /* On hyperbola */
227
t = r / 1.41421356237309504880;
212
d = sqrt(x * x + y * y);
213
if (d < r * 0.70710678118654752440) { /* Inside sphere */
214
z = sqrt(r * r - d * d);
215
} else { /* On hyperbola */
216
t = r / 1.41421356237309504880;
244
233
#define RENORMCOUNT 97
247
add_quats(float q1[4], float q2[4], float dest[4])
235
void add_quats(float q1[4], float q2[4], float dest[4])
237
static int count = 0;
250
238
float t1[4], t2[4], t3[4];
262
tf[3] = q1[3] * q2[3] - vdot(q1,q2);
250
tf[3] = q1[3] * q2[3] - vdot(q1, q2);
284
272
* - Pletinckx, D., Quaternion calculus as a basic tool in computer
285
273
* graphics, The Visual Computer 5, 2-13, 1989.
288
normalize_quat(float q[4])
275
static void normalize_quat(float q[4])
293
mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
294
for (i = 0; i < 4; i++) q[i] /= mag;
280
mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
281
for (i = 0; i < 4; i++)
298
286
* Build a rotation matrix, given a quaternion rotation.
302
build_rotmatrix(float m[4][4], float q[4])
289
void build_rotmatrix(float m[4][4], float q[4])
304
291
m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]);
305
292
m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);