~ubuntu-branches/ubuntu/jaunty/mesa/jaunty

« back to all changes in this revision

Viewing changes to progs/demos/trackball.c

  • Committer: Bazaar Package Importer
  • Author(s): Timo Aaltonen
  • Date: 2009-01-23 10:20:24 UTC
  • mfrom: (1.2.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20090123102024-1f3kmb3aea7wzk67
Tags: 7.3~rc3-1ubuntu1
* Merge with Debian experimental.
* Drop 102_dont_vblank.patch, since the new drm code in the kernel
  fixes the bugs that it worked around.
* Bump the build-dependency of libdrm to 2.4.4. It's the first version
  with necessary changes to build this.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdio.h>
 
2
/*
 
3
 * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
 
4
 * ALL RIGHTS RESERVED
 
5
 * Permission to use, copy, modify, and distribute this software for
 
6
 * any purpose and without fee is hereby granted, provided that the above
 
7
 * copyright notice appear in all copies and that both the copyright notice
 
8
 * and this permission notice appear in supporting documentation, and that
 
9
 * the name of Silicon Graphics, Inc. not be used in advertising
 
10
 * or publicity pertaining to distribution of the software without specific,
 
11
 * written prior permission.
 
12
 *
 
13
 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
 
14
 * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
 
15
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
 
16
 * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
 
17
 * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
 
18
 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
 
19
 * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
 
20
 * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
 
21
 * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
 
22
 * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
 
23
 * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
 
24
 * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
 
25
 *
 
26
 * US Government Users Restricted Rights
 
27
 * Use, duplication, or disclosure by the Government is subject to
 
28
 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
 
29
 * (c)(1)(ii) of the Rights in Technical Data and Computer Software
 
30
 * clause at DFARS 252.227-7013 and/or in similar or successor
 
31
 * clauses in the FAR or the DOD or NASA FAR Supplement.
 
32
 * Unpublished-- rights reserved under the copyright laws of the
 
33
 * United States.  Contractor/manufacturer is Silicon Graphics,
 
34
 * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
 
35
 *
 
36
 * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
 
37
 */
 
38
/*
 
39
 * Trackball code:
 
40
 *
 
41
 * Implementation of a virtual trackball.
 
42
 * Implemented by Gavin Bell, lots of ideas from Thant Tessman and
 
43
 *   the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129.
 
44
 *
 
45
 * Vector manip code:
 
46
 *
 
47
 * Original code from:
 
48
 * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli
 
49
 *
 
50
 * Much mucking with by:
 
51
 * Gavin Bell
 
52
 */
 
53
#if defined(_WIN32)
 
54
#pragma warning (disable:4244)          /* disable bogus conversion warnings */
 
55
#endif
 
56
#include <math.h>
 
57
#include "trackball.h"
 
58
 
 
59
/*
 
60
 * This size should really be based on the distance from the center of
 
61
 * rotation to the point on the object underneath the mouse.  That
 
62
 * point would then track the mouse as closely as possible.  This is a
 
63
 * simple example, though, so that is left as an Exercise for the
 
64
 * Programmer.
 
65
 */
 
66
#define TRACKBALLSIZE  (0.8f)
 
67
 
 
68
/*
 
69
 * Local function prototypes (not defined in trackball.h)
 
70
 */
 
71
static float tb_project_to_sphere(float, float, float);
 
72
static void normalize_quat(float [4]);
 
73
 
 
74
static void
 
75
vzero(float v[3])
 
76
{
 
77
    v[0] = 0.0;
 
78
    v[1] = 0.0;
 
79
    v[2] = 0.0;
 
80
}
 
81
 
 
82
static void
 
83
vset(float v[3], float x, float y, float z)
 
84
{
 
85
    v[0] = x;
 
86
    v[1] = y;
 
87
    v[2] = z;
 
88
}
 
89
 
 
90
static void
 
91
vsub(const float src1[3], const float src2[3], float dst[3])
 
92
{
 
93
    dst[0] = src1[0] - src2[0];
 
94
    dst[1] = src1[1] - src2[1];
 
95
    dst[2] = src1[2] - src2[2];
 
96
}
 
97
 
 
98
static void
 
99
vcopy(const float v1[3], float v2[3])
 
100
{
 
101
    register int i;
 
102
    for (i = 0 ; i < 3 ; i++)
 
103
        v2[i] = v1[i];
 
104
}
 
105
 
 
106
static void
 
107
vcross(const float v1[3], const float v2[3], float cross[3])
 
108
{
 
109
    float temp[3];
 
110
 
 
111
    temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
 
112
    temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
 
113
    temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
 
114
    vcopy(temp, cross);
 
115
}
 
116
 
 
117
static float
 
118
vlength(const float v[3])
 
119
{
 
120
    return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
 
121
}
 
122
 
 
123
static void
 
124
vscale(float v[3], float div)
 
125
{
 
126
    v[0] *= div;
 
127
    v[1] *= div;
 
128
    v[2] *= div;
 
129
}
 
130
 
 
131
static void
 
132
vnormal(float v[3])
 
133
{
 
134
    vscale(v,1.0/vlength(v));
 
135
}
 
136
 
 
137
static float
 
138
vdot(const float v1[3], const float v2[3])
 
139
{
 
140
    return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
 
141
}
 
142
 
 
143
static void
 
144
vadd(const float src1[3], const float src2[3], float dst[3])
 
145
{
 
146
    dst[0] = src1[0] + src2[0];
 
147
    dst[1] = src1[1] + src2[1];
 
148
    dst[2] = src1[2] + src2[2];
 
149
}
 
150
 
 
151
/*
 
152
 * Ok, simulate a track-ball.  Project the points onto the virtual
 
153
 * trackball, then figure out the axis of rotation, which is the cross
 
154
 * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
 
155
 * Note:  This is a deformed trackball-- is a trackball in the center,
 
156
 * but is deformed into a hyperbolic sheet of rotation away from the
 
157
 * center.  This particular function was chosen after trying out
 
158
 * several variations.
 
159
 *
 
160
 * It is assumed that the arguments to this routine are in the range
 
161
 * (-1.0 ... 1.0)
 
162
 */
 
163
void
 
164
trackball(float q[4], float p1x, float p1y, float p2x, float p2y)
 
165
{
 
166
    float a[3]; /* Axis of rotation */
 
167
    float phi;  /* how much to rotate about axis */
 
168
    float p1[3], p2[3], d[3];
 
169
    float t;
 
170
 
 
171
    if (p1x == p2x && p1y == p2y) {
 
172
        /* Zero rotation */
 
173
        vzero(q);
 
174
        q[3] = 1.0;
 
175
        return;
 
176
    }
 
177
 
 
178
    /*
 
179
     * First, figure out z-coordinates for projection of P1 and P2 to
 
180
     * deformed sphere
 
181
     */
 
182
    vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y));
 
183
    vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y));
 
184
 
 
185
    /*
 
186
     *  Now, we want the cross product of P1 and P2
 
187
     */
 
188
    vcross(p2,p1,a);
 
189
 
 
190
    /*
 
191
     *  Figure out how much to rotate around that axis.
 
192
     */
 
193
    vsub(p1,p2,d);
 
194
    t = vlength(d) / (2.0*TRACKBALLSIZE);
 
195
 
 
196
    /*
 
197
     * Avoid problems with out-of-control values...
 
198
     */
 
199
    if (t > 1.0) t = 1.0;
 
200
    if (t < -1.0) t = -1.0;
 
201
    phi = 2.0 * asin(t);
 
202
 
 
203
    axis_to_quat(a,phi,q);
 
204
}
 
205
 
 
206
/*
 
207
 *  Given an axis and angle, compute quaternion.
 
208
 */
 
209
void
 
210
axis_to_quat(const float a[3], float phi, float q[4])
 
211
{
 
212
    vcopy(a,q);
 
213
    vnormal(q);
 
214
    vscale(q, sin(phi/2.0));
 
215
    q[3] = cos(phi/2.0);
 
216
}
 
217
 
 
218
/*
 
219
 * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
 
220
 * if we are away from the center of the sphere.
 
221
 */
 
222
static float
 
223
tb_project_to_sphere(float r, float x, float y)
 
224
{
 
225
    float d, t, z;
 
226
 
 
227
    d = sqrt(x*x + y*y);
 
228
    if (d < r * 0.70710678118654752440) {    /* Inside sphere */
 
229
        z = sqrt(r*r - d*d);
 
230
    } else {           /* On hyperbola */
 
231
        t = r / 1.41421356237309504880;
 
232
        z = t*t / d;
 
233
    }
 
234
    return z;
 
235
}
 
236
 
 
237
/*
 
238
 * Given two rotations, e1 and e2, expressed as quaternion rotations,
 
239
 * figure out the equivalent single rotation and stuff it into dest.
 
240
 *
 
241
 * This routine also normalizes the result every RENORMCOUNT times it is
 
242
 * called, to keep error from creeping in.
 
243
 *
 
244
 * NOTE: This routine is written so that q1 or q2 may be the same
 
245
 * as dest (or each other).
 
246
 */
 
247
 
 
248
#define RENORMCOUNT 97
 
249
 
 
250
void
 
251
add_quats(const float q1[4], const float q2[4], float dest[4])
 
252
{
 
253
    static int count=0;
 
254
    float t1[4], t2[4], t3[4];
 
255
    float tf[4];
 
256
 
 
257
#if 0
 
258
printf("q1 = %f %f %f %f\n", q1[0], q1[1], q1[2], q1[3]);
 
259
printf("q2 = %f %f %f %f\n", q2[0], q2[1], q2[2], q2[3]);
 
260
#endif
 
261
 
 
262
    vcopy(q1,t1);
 
263
    vscale(t1,q2[3]);
 
264
 
 
265
    vcopy(q2,t2);
 
266
    vscale(t2,q1[3]);
 
267
 
 
268
    vcross(q2,q1,t3);
 
269
    vadd(t1,t2,tf);
 
270
    vadd(t3,tf,tf);
 
271
    tf[3] = q1[3] * q2[3] - vdot(q1,q2);
 
272
 
 
273
#if 0
 
274
printf("tf = %f %f %f %f\n", tf[0], tf[1], tf[2], tf[3]);
 
275
#endif
 
276
 
 
277
    dest[0] = tf[0];
 
278
    dest[1] = tf[1];
 
279
    dest[2] = tf[2];
 
280
    dest[3] = tf[3];
 
281
 
 
282
    if (++count > RENORMCOUNT) {
 
283
        count = 0;
 
284
        normalize_quat(dest);
 
285
    }
 
286
}
 
287
 
 
288
/*
 
289
 * Quaternions always obey:  a^2 + b^2 + c^2 + d^2 = 1.0
 
290
 * If they don't add up to 1.0, dividing by their magnitued will
 
291
 * renormalize them.
 
292
 *
 
293
 * Note: See the following for more information on quaternions:
 
294
 *
 
295
 * - Shoemake, K., Animating rotation with quaternion curves, Computer
 
296
 *   Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985.
 
297
 * - Pletinckx, D., Quaternion calculus as a basic tool in computer
 
298
 *   graphics, The Visual Computer 5, 2-13, 1989.
 
299
 */
 
300
static void
 
301
normalize_quat(float q[4])
 
302
{
 
303
    int i;
 
304
    float mag;
 
305
 
 
306
    mag = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
 
307
    for (i = 0; i < 4; i++)
 
308
        q[i] /= mag;
 
309
}
 
310
 
 
311
/*
 
312
 * Build a rotation matrix, given a quaternion rotation.
 
313
 *
 
314
 */
 
315
void
 
316
build_rotmatrix(float m[4][4], const float q[4])
 
317
{
 
318
    m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]);
 
319
    m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);
 
320
    m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]);
 
321
    m[0][3] = 0.0;
 
322
 
 
323
    m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]);
 
324
    m[1][1]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]);
 
325
    m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
 
326
    m[1][3] = 0.0;
 
327
 
 
328
    m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]);
 
329
    m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]);
 
330
    m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]);
 
331
    m[2][3] = 0.0;
 
332
 
 
333
    m[3][0] = 0.0;
 
334
    m[3][1] = 0.0;
 
335
    m[3][2] = 0.0;
 
336
    m[3][3] = 1.0;
 
337
}
 
338