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