makefile rules to build as static library and install/uninstall
[miniglut] / test.c
1 #include <math.h>
2 #include "miniglut.h"
3
4 void idle(void);
5 void display(void);
6 void reshape(int x, int y);
7 void keypress(unsigned char key, int x, int y);
8 void mouse(int bn, int st, int x, int y);
9 void motion(int x, int y);
10 void sball_motion(int x, int y, int z);
11 void sball_rotate(int rx, int ry, int rz);
12 void sball_button(int bn, int state);
13
14 static void vcross(float *res, const float *a, const float *b);
15 static void qmul(float *a, const float *b);
16 static void qrotation(float *q, float angle, float x, float y, float z);
17 static void qrotate(float *q, float angle, float x, float y, float z);
18 static void mrotation_quat(float *m, const float *q);
19
20
21 float cam_theta, cam_phi = 25, cam_dist = 8;
22 int mouse_x, mouse_y;
23 int bnstate[8];
24 int anim;
25 float torus_pos[3], torus_rot[4] = {0, 0, 0, 1};
26
27
28 int main(int argc, char **argv)
29 {
30         glutInit(&argc, argv);
31         glutInitWindowSize(1024, 768);
32         glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
33         glutCreateWindow("miniglut test");
34
35         glutDisplayFunc(display);
36         glutReshapeFunc(reshape);
37         glutKeyboardFunc(keypress);
38         glutMouseFunc(mouse);
39         glutMotionFunc(motion);
40         glutSpaceballMotionFunc(sball_motion);
41         glutSpaceballRotateFunc(sball_rotate);
42         glutSpaceballButtonFunc(sball_button);
43
44         glEnable(GL_DEPTH_TEST);
45         glEnable(GL_CULL_FACE);
46         glEnable(GL_LIGHTING);
47         glEnable(GL_LIGHT0);
48
49         glutMainLoop();
50         return 0;
51 }
52
53 void idle(void)
54 {
55         glutPostRedisplay();
56 }
57
58 void display(void)
59 {
60         long tm;
61         float lpos[] = {-1, 2, 3, 0};
62         float sbrot_xform[16];
63
64         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
65
66         glMatrixMode(GL_MODELVIEW);
67         glLoadIdentity();
68         glTranslatef(0, 0, -cam_dist);
69         glRotatef(cam_phi, 1, 0, 0);
70         glRotatef(cam_theta, 0, 1, 0);
71
72         glLightfv(GL_LIGHT0, GL_POSITION, lpos);
73
74         glPushMatrix();
75         if(anim) {
76                 tm = glutGet(GLUT_ELAPSED_TIME);
77                 glRotatef(tm / 10.0f, 1, 0, 0);
78                 glRotatef(tm / 10.0f, 0, 1, 0);
79         }
80         glutSolidTorus(0.3, 1, 16, 24);
81         glPopMatrix();
82
83         glutSolidSphere(0.4, 16, 8);
84
85         glPushMatrix();
86         glTranslatef(torus_pos[0] - 2.5, torus_pos[1], torus_pos[2]);
87         mrotation_quat(sbrot_xform, torus_rot);
88         glMultMatrixf(sbrot_xform);
89         glutSolidCube(1.5);
90         glPopMatrix();
91
92         glPushMatrix();
93         glTranslatef(2.5, -1, 0);
94         glRotatef(-90, 1, 0, 0);
95         glutSolidCone(1.1, 2, 16, 2);
96         glPopMatrix();
97
98         glBegin(GL_QUADS);
99         glNormal3f(0, 1, 0);
100         glVertex3f(-5, -1.3, 5);
101         glVertex3f(5, -1.3, 5);
102         glVertex3f(5, -1.3, -5);
103         glVertex3f(-5, -1.3, -5);
104         glEnd();
105
106         glutSwapBuffers();
107 }
108
109 #define ZNEAR   0.5f
110 void reshape(int x, int y)
111 {
112         float vsz, aspect = (float)x / (float)y;
113         glViewport(0, 0, x, y);
114         glMatrixMode(GL_PROJECTION);
115         glLoadIdentity();
116         vsz = 0.4663f * ZNEAR;
117         glFrustum(-aspect * vsz, aspect * vsz, -vsz, vsz, 0.5, 500.0);
118 }
119
120 void keypress(unsigned char key, int x, int y)
121 {
122         static int fullscr;
123         static int prev_xsz, prev_ysz;
124
125         switch(key) {
126         case 27:
127         case 'q':
128                 glutExit();
129                 break;
130
131         case ' ':
132                 anim ^= 1;
133                 glutIdleFunc(anim ? idle : 0);
134                 glutPostRedisplay();
135                 break;
136
137         case '\n':
138         case '\r':
139                 if(!(glutGetModifiers() & GLUT_ACTIVE_ALT)) {
140                         break;
141                 }
142         case 'f':
143                 fullscr ^= 1;
144                 if(fullscr) {
145                         prev_xsz = glutGet(GLUT_WINDOW_WIDTH);
146                         prev_ysz = glutGet(GLUT_WINDOW_HEIGHT);
147                         glutFullScreen();
148                 } else {
149                         glutReshapeWindow(prev_xsz, prev_ysz);
150                 }
151                 break;
152         }
153 }
154
155 void mouse(int bn, int st, int x, int y)
156 {
157         int bidx = bn - GLUT_LEFT_BUTTON;
158         bnstate[bidx] = st == GLUT_DOWN;
159         mouse_x = x;
160         mouse_y = y;
161 }
162
163 void motion(int x, int y)
164 {
165         int dx = x - mouse_x;
166         int dy = y - mouse_y;
167         mouse_x = x;
168         mouse_y = y;
169
170         if(!(dx | dy)) return;
171
172         if(bnstate[0]) {
173                 cam_theta += dx * 0.5;
174                 cam_phi += dy * 0.5;
175                 if(cam_phi < -90) cam_phi = -90;
176                 if(cam_phi > 90) cam_phi = 90;
177                 glutPostRedisplay();
178         }
179         if(bnstate[2]) {
180                 cam_dist += dy * 0.1;
181                 if(cam_dist < 0) cam_dist = 0;
182                 glutPostRedisplay();
183         }
184 }
185
186 void sball_motion(int x, int y, int z)
187 {
188         torus_pos[0] += x * 0.001f;
189         torus_pos[1] += y * 0.001f;
190         torus_pos[2] -= z * 0.001f;
191         glutPostRedisplay();
192 }
193
194 static float rsqrt(float number)
195 {
196         int i;
197         float x2, y;
198         static const float threehalfs = 1.5f;
199
200         x2 = number * 0.5f;
201         y = number;
202         i = *(int*)&y;
203         i = 0x5f3759df - (i >> 1);
204         y = *(float*)&i;
205         y *= threehalfs - (x2 * y * y);
206         y *= threehalfs - (x2 * y * y);
207         return y;
208 }
209
210 void sball_rotate(int rx, int ry, int rz)
211 {
212         if(rx | ry | rz) {
213                 float s = (float)rsqrt(rx * rx + ry * ry + rz * rz);
214                 qrotate(torus_rot, 0.001f / s, rx * s, ry * s, -rz * s);
215                 glutPostRedisplay();
216         }
217 }
218
219 void sball_button(int bn, int state)
220 {
221         if(state == GLUT_DOWN) {
222                 torus_pos[0] = torus_pos[1] = torus_pos[2] = 0;
223                 torus_rot[0] = torus_rot[1] = torus_rot[2] = 0;
224                 torus_rot[3] = 1;
225                 glutPostRedisplay();
226         }
227 }
228
229
230 static void vcross(float *res, const float *a, const float *b)
231 {
232         res[0] = a[1] * b[2] - a[2] * b[1];
233         res[1] = a[2] * b[0] - a[0] * b[2];
234         res[2] = a[0] * b[1] - a[1] * b[0];
235 }
236
237 static void qmul(float *a, const float *b)
238 {
239         float x, y, z, dot;
240         float cross[3];
241
242         dot = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
243         vcross(cross, a, b);
244
245         x = a[3] * b[0] + b[3] * a[0] + cross[0];
246         y = a[3] * b[1] + b[3] * a[1] + cross[1];
247         z = a[3] * b[2] + b[3] * a[2] + cross[2];
248         a[3] = a[3] * b[3] - dot;
249         a[0] = x;
250         a[1] = y;
251         a[2] = z;
252 }
253
254 void mglut_sincos(float angle, float *sptr, float *cptr);
255 float mglut_tan(float x);
256
257 static void qrotation(float *q, float angle, float x, float y, float z)
258 {
259         float sa, ca;
260         mglut_sincos(angle * 0.5f, &sa, &ca);
261         q[3] = ca;
262         q[0] = x * sa;
263         q[1] = y * sa;
264         q[2] = z * sa;
265 }
266
267 static void qrotate(float *q, float angle, float x, float y, float z)
268 {
269         float qrot[4];
270         qrotation(qrot, angle, x, y, z);
271         qmul(qrot, q);
272         q[0] = qrot[0];
273         q[1] = qrot[1];
274         q[2] = qrot[2];
275         q[3] = qrot[3];
276 }
277
278 static void mrotation_quat(float *m, const float *q)
279 {
280         float xsq2 = 2.0f * q[0] * q[0];
281         float ysq2 = 2.0f * q[1] * q[1];
282         float zsq2 = 2.0f * q[2] * q[2];
283         float sx = 1.0f - ysq2 - zsq2;
284         float sy = 1.0f - xsq2 - zsq2;
285         float sz = 1.0f - xsq2 - ysq2;
286
287         m[3] = m[7] = m[11] = m[12] = m[13] = m[14] = 0.0f;
288         m[15] = 1.0f;
289
290         m[0] = sx;
291         m[1] = 2.0f * q[0] * q[1] + 2.0f * q[3] * q[2];
292         m[2] = 2.0f * q[2] * q[0] - 2.0f * q[3] * q[1];
293         m[4] = 2.0f * q[0] * q[1] - 2.0f * q[3] * q[2];
294         m[5] = sy;
295         m[6] = 2.0f * q[1] * q[2] + 2.0f * q[3] * q[0];
296         m[8] = 2.0f * q[2] * q[0] + 2.0f * q[3] * q[1];
297         m[9] = 2.0f * q[1] * q[2] - 2.0f * q[3] * q[0];
298         m[10] = sz;
299 }