fix glxinfo to query current display.
[mesa.git] / progs / demos / ipers.c
1 /*
2 * This program is under the GNU GPL.
3 * Use at your own risk.
4 *
5 * written by David Bucciarelli (tech.hmw@plus.it)
6 * Humanware s.r.l.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <time.h>
13
14 #ifdef WIN32
15 #include <windows.h>
16 #include <mmsystem.h>
17 #endif
18
19 #include <GL/glut.h>
20
21 #include "readtex.c"
22
23 #ifdef XMESA
24 #include "GL/xmesa.h"
25 static int fullscreen = 1;
26 #endif
27
28 static int WIDTH = 640;
29 static int HEIGHT = 480;
30
31 static GLint T0;
32 static GLint Frames;
33
34 #define MAX_LOD 9
35
36 #define TEX_SKY_WIDTH 256
37 #define TEX_SKY_HEIGHT TEX_SKY_WIDTH
38
39 #ifndef M_PI
40 #define M_PI 3.1415926535
41 #endif
42
43 #define FROM_NONE 0
44 #define FROM_DOWN 1
45 #define FROM_UP 2
46 #define FROM_LEFT 3
47 #define FROM_RIGHT 4
48 #define FROM_FRONT 5
49 #define FROM_BACK 6
50
51 static int win = 0;
52
53 static float obs[3] = { 3.8, 0.0, 0.0 };
54 static float dir[3];
55 static float v = 0.0;
56 static float alpha = -90.0;
57 static float beta = 90.0;
58
59 static int fog = 1;
60 static int bfcull = 1;
61 static int usetex = 1;
62 static int help = 1;
63 static int poutline = 0;
64 static int normext = 1;
65 static int joyavailable = 0;
66 static int joyactive = 0;
67 static int LODbias = 3;
68 static int maxdepth = MAX_LOD;
69
70 static unsigned int totpoly = 0;
71
72 static GLuint t1id, t2id;
73 static GLuint skydlist, LODdlist[MAX_LOD], LODnumpoly[MAX_LOD];
74
75 static void
76 initlight(void)
77 {
78 GLfloat lspec[4] = { 1.0, 1.0, 1.0, 1.0 };
79 static GLfloat lightpos[4] = { 30, 15.0, 30.0, 1.0 };
80
81 glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
82 glLightfv(GL_LIGHT0, GL_SPECULAR, lspec);
83
84 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32.0);
85 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, lspec);
86 }
87
88 static void
89 initdlists(void)
90 {
91 static int slicetable[MAX_LOD][2] = {
92 {21, 10},
93 {18, 9},
94 {15, 8},
95 {12, 7},
96 {9, 6},
97 {7, 5},
98 {5, 4},
99 {4, 3},
100 {3, 2}
101 };
102 GLUquadricObj *obj;
103 int i, xslices, yslices;
104
105 obj = gluNewQuadric();
106
107 skydlist = glGenLists(1);
108 glNewList(skydlist, GL_COMPILE);
109 glBindTexture(GL_TEXTURE_2D, t2id);
110 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
111 glColor3f(1.0f, 1.0f, 1.0f);
112
113 gluQuadricDrawStyle(obj, GLU_FILL);
114 gluQuadricNormals(obj, GLU_NONE);
115 gluQuadricTexture(obj, GL_TRUE);
116 gluQuadricOrientation(obj, GLU_INSIDE);
117 gluSphere(obj, 40.0f, 18, 9);
118
119 glEndList();
120
121 for (i = 0; i < MAX_LOD; i++) {
122 LODdlist[i] = glGenLists(1);
123 glNewList(LODdlist[i], GL_COMPILE);
124
125 gluQuadricDrawStyle(obj, GLU_FILL);
126 gluQuadricNormals(obj, GLU_SMOOTH);
127 gluQuadricTexture(obj, GL_TRUE);
128 gluQuadricOrientation(obj, GLU_OUTSIDE);
129 xslices = slicetable[i][0];
130 yslices = slicetable[i][1];
131 gluSphere(obj, 1.0f, xslices, yslices);
132 LODnumpoly[i] = xslices * (yslices - 2) + 2 * (xslices - 1);
133
134 glEndList();
135 }
136 }
137
138 static void
139 inittextures(void)
140 {
141 GLubyte tsky[TEX_SKY_HEIGHT][TEX_SKY_WIDTH][3];
142 GLuint x, y;
143 GLfloat fact;
144 GLenum gluerr;
145
146 /* Brick */
147
148 glGenTextures(1, &t1id);
149 glBindTexture(GL_TEXTURE_2D, t1id);
150
151 if (!LoadRGBMipmaps("../images/bw.rgb", 3)) {
152 fprintf(stderr, "Error reading a texture.\n");
153 exit(-1);
154 }
155
156 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
157 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
158
159 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
160 GL_LINEAR_MIPMAP_LINEAR);
161 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
162
163 /* Sky */
164
165 glGenTextures(1, &t2id);
166 glBindTexture(GL_TEXTURE_2D, t2id);
167
168 for (y = 0; y < TEX_SKY_HEIGHT; y++)
169 for (x = 0; x < TEX_SKY_WIDTH; x++)
170 if (y < TEX_SKY_HEIGHT / 2) {
171 fact = y / (GLfloat) (TEX_SKY_HEIGHT / 2);
172 tsky[y][x][0] =
173 (GLubyte) (255.0f * (0.1f * fact + 0.3f * (1.0f - fact)));
174 tsky[y][x][1] =
175 (GLubyte) (255.0f * (0.2f * fact + 1.0f * (1.0f - fact)));
176 tsky[y][x][2] = 255;
177 }
178 else {
179 tsky[y][x][0] = tsky[TEX_SKY_HEIGHT - y - 1][x][0];
180 tsky[y][x][1] = tsky[TEX_SKY_HEIGHT - y - 1][x][1];
181 tsky[y][x][2] = 255;
182 }
183
184 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
185 if (
186 (gluerr =
187 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TEX_SKY_WIDTH, TEX_SKY_HEIGHT,
188 GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) (tsky)))) {
189 fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
190 exit(-1);
191 }
192
193 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
194 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
195
196 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
197 GL_LINEAR_MIPMAP_LINEAR);
198 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
199 }
200
201 static void
202 calcposobs(void)
203 {
204 dir[0] = sin(alpha * M_PI / 180.0);
205 dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
206 dir[2] = cos(beta * M_PI / 180.0);
207
208 obs[0] += v * dir[0];
209 obs[1] += v * dir[1];
210 obs[2] += v * dir[2];
211 }
212
213 static void
214 special(int k, int x, int y)
215 {
216 switch (k) {
217 case GLUT_KEY_LEFT:
218 alpha -= 2.0;
219 break;
220 case GLUT_KEY_RIGHT:
221 alpha += 2.0;
222 break;
223 case GLUT_KEY_DOWN:
224 beta -= 2.0;
225 break;
226 case GLUT_KEY_UP:
227 beta += 2.0;
228 break;
229 }
230 }
231
232 static void
233 key(unsigned char k, int x, int y)
234 {
235 switch (k) {
236 case 27:
237 exit(0);
238 break;
239
240 case 'a':
241 v += 0.01;
242 break;
243 case 'z':
244 v -= 0.01;
245 break;
246
247 #ifdef XMESA
248 case ' ':
249 fullscreen = (!fullscreen);
250 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
251 break;
252 #endif
253
254 case '+':
255 LODbias--;
256 break;
257 case '-':
258 LODbias++;
259 break;
260 case 'j':
261 joyactive = (!joyactive);
262 break;
263 case 'h':
264 help = (!help);
265 break;
266 case 'f':
267 fog = (!fog);
268 break;
269 case 't':
270 usetex = (!usetex);
271 break;
272 case 'n':
273 normext = (!normext);
274 break;
275 case 'b':
276 if (bfcull) {
277 glDisable(GL_CULL_FACE);
278 bfcull = 0;
279 }
280 else {
281 glEnable(GL_CULL_FACE);
282 bfcull = 1;
283 }
284 break;
285 case 'p':
286 if (poutline) {
287 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
288 poutline = 0;
289 usetex = 1;
290 }
291 else {
292 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
293 poutline = 1;
294 usetex = 0;
295 }
296 break;
297 }
298 }
299
300 static void
301 reshape(int w, int h)
302 {
303 WIDTH = w;
304 HEIGHT = h;
305 glMatrixMode(GL_PROJECTION);
306 glLoadIdentity();
307 gluPerspective(90.0, w / (float) h, 0.8, 100.0);
308 glMatrixMode(GL_MODELVIEW);
309 glLoadIdentity();
310 glViewport(0, 0, w, h);
311 }
312
313 static void
314 printstring(void *font, char *string)
315 {
316 int len, i;
317
318 len = (int) strlen(string);
319 for (i = 0; i < len; i++)
320 glutBitmapCharacter(font, string[i]);
321 }
322
323 static void
324 printhelp(void)
325 {
326 glEnable(GL_BLEND);
327 glColor4f(0.5, 0.5, 0.5, 0.5);
328 glRecti(40, 40, 600, 440);
329 glDisable(GL_BLEND);
330
331 glColor3f(1.0, 0.0, 0.0);
332 glRasterPos2i(300, 420);
333 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
334
335 glRasterPos2i(60, 390);
336 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
337 glRasterPos2i(60, 360);
338 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Toggle Textures");
339 glRasterPos2i(60, 330);
340 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
341 glRasterPos2i(60, 300);
342 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Toggle Back face culling");
343 glRasterPos2i(60, 270);
344 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
345 glRasterPos2i(60, 240);
346 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
347 glRasterPos2i(60, 210);
348 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
349 glRasterPos2i(60, 180);
350 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "p - Toggle Wire frame");
351 glRasterPos2i(60, 150);
352 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
353 "b - Toggle GL_EXT_rescale_normal extension");
354 glRasterPos2i(60, 120);
355 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
356 "+/- - Increase/decrease the Object maximum LOD");
357
358 glRasterPos2i(60, 90);
359 if (joyavailable)
360 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
361 "j - Toggle jostick control (Joystick control available)");
362 else
363 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
364 "(No Joystick control available)");
365 }
366
367 static void
368 dojoy(void)
369 {
370 #ifdef _WIN32
371 static UINT max[2] = { 0, 0 };
372 static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
373 MMRESULT res;
374 JOYINFO joy;
375
376 res = joyGetPos(JOYSTICKID1, &joy);
377
378 if (res == JOYERR_NOERROR) {
379 joyavailable = 1;
380
381 if (max[0] < joy.wXpos)
382 max[0] = joy.wXpos;
383 if (min[0] > joy.wXpos)
384 min[0] = joy.wXpos;
385 center[0] = (max[0] + min[0]) / 2;
386
387 if (max[1] < joy.wYpos)
388 max[1] = joy.wYpos;
389 if (min[1] > joy.wYpos)
390 min[1] = joy.wYpos;
391 center[1] = (max[1] + min[1]) / 2;
392
393 if (joyactive) {
394 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
395 alpha -=
396 2.0 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
397 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
398 beta += 2.0 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
399
400 if (joy.wButtons & JOY_BUTTON1)
401 v += 0.01;
402 if (joy.wButtons & JOY_BUTTON2)
403 v -= 0.01;
404 }
405 }
406 else
407 joyavailable = 0;
408 #endif
409 }
410
411 static void
412 drawipers(int depth, int from)
413 {
414 int lod;
415
416 if (depth == maxdepth)
417 return;
418
419 lod = depth + LODbias;
420 if (lod < 0)
421 lod = 0;
422 if (lod >= MAX_LOD)
423 return;
424
425 switch (from) {
426 case FROM_NONE:
427 glCallList(LODdlist[lod]);
428
429 depth++;
430 drawipers(depth, FROM_DOWN);
431 drawipers(depth, FROM_UP);
432 drawipers(depth, FROM_FRONT);
433 drawipers(depth, FROM_BACK);
434 drawipers(depth, FROM_LEFT);
435 drawipers(depth, FROM_RIGHT);
436 break;
437 case FROM_FRONT:
438 glPushMatrix();
439 glTranslatef(0.0f, -1.5f, 0.0f);
440 glScalef(0.5f, 0.5f, 0.5f);
441
442 glCallList(LODdlist[lod]);
443
444 depth++;
445 drawipers(depth, FROM_DOWN);
446 drawipers(depth, FROM_UP);
447 drawipers(depth, FROM_FRONT);
448 drawipers(depth, FROM_LEFT);
449 drawipers(depth, FROM_RIGHT);
450 glPopMatrix();
451 break;
452 case FROM_BACK:
453 glPushMatrix();
454 glTranslatef(0.0f, 1.5f, 0.0f);
455 glScalef(0.5f, 0.5f, 0.5f);
456
457 glCallList(LODdlist[lod]);
458
459 depth++;
460 drawipers(depth, FROM_DOWN);
461 drawipers(depth, FROM_UP);
462 drawipers(depth, FROM_BACK);
463 drawipers(depth, FROM_LEFT);
464 drawipers(depth, FROM_RIGHT);
465 glPopMatrix();
466 break;
467 case FROM_LEFT:
468 glPushMatrix();
469 glTranslatef(-1.5f, 0.0f, 0.0f);
470 glScalef(0.5f, 0.5f, 0.5f);
471
472 glCallList(LODdlist[lod]);
473
474 depth++;
475 drawipers(depth, FROM_DOWN);
476 drawipers(depth, FROM_UP);
477 drawipers(depth, FROM_FRONT);
478 drawipers(depth, FROM_BACK);
479 drawipers(depth, FROM_LEFT);
480 glPopMatrix();
481 break;
482 case FROM_RIGHT:
483 glPushMatrix();
484 glTranslatef(1.5f, 0.0f, 0.0f);
485 glScalef(0.5f, 0.5f, 0.5f);
486
487 glCallList(LODdlist[lod]);
488
489 depth++;
490 drawipers(depth, FROM_DOWN);
491 drawipers(depth, FROM_UP);
492 drawipers(depth, FROM_FRONT);
493 drawipers(depth, FROM_BACK);
494 drawipers(depth, FROM_RIGHT);
495 glPopMatrix();
496 break;
497 case FROM_DOWN:
498 glPushMatrix();
499 glTranslatef(0.0f, 0.0f, 1.5f);
500 glScalef(0.5f, 0.5f, 0.5f);
501
502 glCallList(LODdlist[lod]);
503
504 depth++;
505 drawipers(depth, FROM_DOWN);
506 drawipers(depth, FROM_FRONT);
507 drawipers(depth, FROM_BACK);
508 drawipers(depth, FROM_LEFT);
509 drawipers(depth, FROM_RIGHT);
510 glPopMatrix();
511 break;
512 case FROM_UP:
513 glPushMatrix();
514 glTranslatef(0.0f, 0.0f, -1.5f);
515 glScalef(0.5f, 0.5f, 0.5f);
516
517 glCallList(LODdlist[lod]);
518
519 depth++;
520 drawipers(depth, FROM_UP);
521 drawipers(depth, FROM_FRONT);
522 drawipers(depth, FROM_BACK);
523 drawipers(depth, FROM_LEFT);
524 drawipers(depth, FROM_RIGHT);
525 glPopMatrix();
526 break;
527 }
528
529 totpoly += LODnumpoly[lod];
530 }
531
532 static void
533 draw(void)
534 {
535 static char frbuf[80] = "";
536 static GLfloat alpha = 0.0f;
537 static GLfloat beta = 0.0f;
538 static float fr = 0.0;
539
540 dojoy();
541
542 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
543
544 if (usetex)
545 glEnable(GL_TEXTURE_2D);
546 else
547 glDisable(GL_TEXTURE_2D);
548
549 if (fog)
550 glEnable(GL_FOG);
551 else
552 glDisable(GL_FOG);
553
554 glPushMatrix();
555 calcposobs();
556 gluLookAt(obs[0], obs[1], obs[2],
557 obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
558 0.0, 0.0, 1.0);
559
560 /* Scene */
561 glEnable(GL_DEPTH_TEST);
562
563 glShadeModel(GL_SMOOTH);
564 glBindTexture(GL_TEXTURE_2D, t1id);
565 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
566 glColor3f(1.0f, 1.0f, 1.0f);
567 glEnable(GL_LIGHT0);
568 glEnable(GL_LIGHTING);
569
570 if (normext)
571 glEnable(GL_RESCALE_NORMAL_EXT);
572 else
573 glEnable(GL_NORMALIZE);
574
575 glPushMatrix();
576 glRotatef(alpha, 0.0f, 0.0f, 1.0f);
577 glRotatef(beta, 1.0f, 0.0f, 0.0f);
578 totpoly = 0;
579 drawipers(0, FROM_NONE);
580 glPopMatrix();
581
582 alpha += 0.5f;
583 beta += 0.3f;
584
585 glDisable(GL_LIGHTING);
586 glDisable(GL_LIGHT0);
587 glShadeModel(GL_FLAT);
588
589 if (normext)
590 glDisable(GL_RESCALE_NORMAL_EXT);
591 else
592 glDisable(GL_NORMALIZE);
593
594 glCallList(skydlist);
595
596 glPopMatrix();
597
598 /* Help Screen */
599
600 sprintf(frbuf,
601 "Frame rate: %0.2f LOD: %d Tot. poly.: %d Poly/sec: %.1f",
602 fr, LODbias, totpoly, totpoly * fr);
603
604 glDisable(GL_TEXTURE_2D);
605 glDisable(GL_FOG);
606 glShadeModel(GL_FLAT);
607 glDisable(GL_DEPTH_TEST);
608
609 glMatrixMode(GL_PROJECTION);
610 glPushMatrix();
611 glLoadIdentity();
612 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
613
614 glMatrixMode(GL_MODELVIEW);
615 glLoadIdentity();
616
617 glColor3f(1.0, 0.0, 0.0);
618 glRasterPos2i(10, 10);
619 printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
620 glRasterPos2i(350, 470);
621 printstring(GLUT_BITMAP_HELVETICA_10,
622 "IperS V1.0 Written by David Bucciarelli (tech.hmw@plus.it)");
623
624 if (help)
625 printhelp();
626
627 glMatrixMode(GL_PROJECTION);
628 glPopMatrix();
629 glMatrixMode(GL_MODELVIEW);
630
631 glutSwapBuffers();
632
633 Frames++;
634 {
635 GLint t = glutGet(GLUT_ELAPSED_TIME);
636 if (t - T0 >= 2000) {
637 GLfloat seconds = (t - T0) / 1000.0;
638 fr = Frames / seconds;
639 T0 = t;
640 Frames = 0;
641 }
642 }
643 }
644
645 int
646 main(int ac, char **av)
647 {
648 float fogcolor[4] = { 0.7, 0.7, 0.7, 1.0 };
649
650 fprintf(stderr,
651 "IperS V1.0\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
652
653 glutInitWindowPosition(0, 0);
654 glutInitWindowSize(WIDTH, HEIGHT);
655 glutInit(&ac, av);
656
657 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
658
659 if (!(win = glutCreateWindow("IperS"))) {
660 fprintf(stderr, "Error, couldn't open window\n");
661 exit(-1);
662 }
663
664 reshape(WIDTH, HEIGHT);
665
666 glShadeModel(GL_SMOOTH);
667 glEnable(GL_DEPTH_TEST);
668 glEnable(GL_CULL_FACE);
669 glEnable(GL_TEXTURE_2D);
670
671 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
672
673 glEnable(GL_FOG);
674 glFogi(GL_FOG_MODE, GL_EXP2);
675 glFogfv(GL_FOG_COLOR, fogcolor);
676
677 glFogf(GL_FOG_DENSITY, 0.006);
678
679 glHint(GL_FOG_HINT, GL_NICEST);
680
681 inittextures();
682 initdlists();
683 initlight();
684
685 glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
686 glClear(GL_COLOR_BUFFER_BIT);
687
688 calcposobs();
689
690 glutReshapeFunc(reshape);
691 glutDisplayFunc(draw);
692 glutKeyboardFunc(key);
693 glutSpecialFunc(special);
694 glutIdleFunc(draw);
695
696 glutMainLoop();
697
698 return 0;
699 }