Add new demo "fbo_firecube".
[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 <string.h>
13
14 #if defined (WIN32)|| defined(_WIN32)
15 #include <windows.h>
16 #include <mmsystem.h>
17 #endif
18
19 #include <GL/glut.h>
20
21 #include "readtex.h"
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", (char *) 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 if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
209 dir[0] = 0;
210 if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
211 dir[1] = 0;
212 if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
213 dir[2] = 0;
214
215 obs[0] += v * dir[0];
216 obs[1] += v * dir[1];
217 obs[2] += v * dir[2];
218 }
219
220 static void
221 special(int k, int x, int y)
222 {
223 switch (k) {
224 case GLUT_KEY_LEFT:
225 alpha -= 2.0;
226 break;
227 case GLUT_KEY_RIGHT:
228 alpha += 2.0;
229 break;
230 case GLUT_KEY_DOWN:
231 beta -= 2.0;
232 break;
233 case GLUT_KEY_UP:
234 beta += 2.0;
235 break;
236 }
237 }
238
239 static void
240 key(unsigned char k, int x, int y)
241 {
242 switch (k) {
243 case 27:
244 exit(0);
245 break;
246
247 case 'a':
248 v += 0.01;
249 break;
250 case 'z':
251 v -= 0.01;
252 break;
253
254 #ifdef XMESA
255 case ' ':
256 fullscreen = (!fullscreen);
257 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
258 break;
259 #endif
260
261 case '+':
262 LODbias--;
263 break;
264 case '-':
265 LODbias++;
266 break;
267 case 'j':
268 joyactive = (!joyactive);
269 break;
270 case 'h':
271 help = (!help);
272 break;
273 case 'f':
274 fog = (!fog);
275 break;
276 case 't':
277 usetex = (!usetex);
278 break;
279 case 'n':
280 normext = (!normext);
281 break;
282 case 'b':
283 if (bfcull) {
284 glDisable(GL_CULL_FACE);
285 bfcull = 0;
286 }
287 else {
288 glEnable(GL_CULL_FACE);
289 bfcull = 1;
290 }
291 break;
292 case 'p':
293 if (poutline) {
294 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
295 poutline = 0;
296 usetex = 1;
297 }
298 else {
299 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
300 poutline = 1;
301 usetex = 0;
302 }
303 break;
304 }
305 }
306
307 static void
308 reshape(int w, int h)
309 {
310 WIDTH = w;
311 HEIGHT = h;
312 glMatrixMode(GL_PROJECTION);
313 glLoadIdentity();
314 gluPerspective(90.0, w / (float) h, 0.8, 100.0);
315 glMatrixMode(GL_MODELVIEW);
316 glLoadIdentity();
317 glViewport(0, 0, w, h);
318 }
319
320 static void
321 printstring(void *font, char *string)
322 {
323 int len, i;
324
325 len = (int) strlen(string);
326 for (i = 0; i < len; i++)
327 glutBitmapCharacter(font, string[i]);
328 }
329
330 static void
331 printhelp(void)
332 {
333 glEnable(GL_BLEND);
334 glColor4f(0.5, 0.5, 0.5, 0.5);
335 glRecti(40, 40, 600, 440);
336 glDisable(GL_BLEND);
337
338 glColor3f(1.0, 0.0, 0.0);
339 glRasterPos2i(300, 420);
340 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
341
342 glRasterPos2i(60, 390);
343 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
344 glRasterPos2i(60, 360);
345 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Toggle Textures");
346 glRasterPos2i(60, 330);
347 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
348 glRasterPos2i(60, 300);
349 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Toggle Back face culling");
350 glRasterPos2i(60, 270);
351 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
352 glRasterPos2i(60, 240);
353 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
354 glRasterPos2i(60, 210);
355 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
356 glRasterPos2i(60, 180);
357 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "p - Toggle Wire frame");
358 glRasterPos2i(60, 150);
359 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
360 "n - Toggle GL_EXT_rescale_normal extension");
361 glRasterPos2i(60, 120);
362 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
363 "+/- - Increase/decrease the Object maximum LOD");
364
365 glRasterPos2i(60, 90);
366 if (joyavailable)
367 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
368 "j - Toggle jostick control (Joystick control available)");
369 else
370 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
371 "(No Joystick control available)");
372 }
373
374 static void
375 dojoy(void)
376 {
377 #ifdef _WIN32
378 static UINT max[2] = { 0, 0 };
379 static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
380 MMRESULT res;
381 JOYINFO joy;
382
383 res = joyGetPos(JOYSTICKID1, &joy);
384
385 if (res == JOYERR_NOERROR) {
386 joyavailable = 1;
387
388 if (max[0] < joy.wXpos)
389 max[0] = joy.wXpos;
390 if (min[0] > joy.wXpos)
391 min[0] = joy.wXpos;
392 center[0] = (max[0] + min[0]) / 2;
393
394 if (max[1] < joy.wYpos)
395 max[1] = joy.wYpos;
396 if (min[1] > joy.wYpos)
397 min[1] = joy.wYpos;
398 center[1] = (max[1] + min[1]) / 2;
399
400 if (joyactive) {
401 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
402 alpha -=
403 2.0 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
404 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
405 beta += 2.0 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
406
407 if (joy.wButtons & JOY_BUTTON1)
408 v += 0.01;
409 if (joy.wButtons & JOY_BUTTON2)
410 v -= 0.01;
411 }
412 }
413 else
414 joyavailable = 0;
415 #endif
416 }
417
418 static void
419 drawipers(int depth, int from)
420 {
421 int lod;
422
423 if (depth == maxdepth)
424 return;
425
426 lod = depth + LODbias;
427 if (lod < 0)
428 lod = 0;
429 if (lod >= MAX_LOD)
430 return;
431
432 switch (from) {
433 case FROM_NONE:
434 glCallList(LODdlist[lod]);
435
436 depth++;
437 drawipers(depth, FROM_DOWN);
438 drawipers(depth, FROM_UP);
439 drawipers(depth, FROM_FRONT);
440 drawipers(depth, FROM_BACK);
441 drawipers(depth, FROM_LEFT);
442 drawipers(depth, FROM_RIGHT);
443 break;
444 case FROM_FRONT:
445 glPushMatrix();
446 glTranslatef(0.0f, -1.5f, 0.0f);
447 glScalef(0.5f, 0.5f, 0.5f);
448
449 glCallList(LODdlist[lod]);
450
451 depth++;
452 drawipers(depth, FROM_DOWN);
453 drawipers(depth, FROM_UP);
454 drawipers(depth, FROM_FRONT);
455 drawipers(depth, FROM_LEFT);
456 drawipers(depth, FROM_RIGHT);
457 glPopMatrix();
458 break;
459 case FROM_BACK:
460 glPushMatrix();
461 glTranslatef(0.0f, 1.5f, 0.0f);
462 glScalef(0.5f, 0.5f, 0.5f);
463
464 glCallList(LODdlist[lod]);
465
466 depth++;
467 drawipers(depth, FROM_DOWN);
468 drawipers(depth, FROM_UP);
469 drawipers(depth, FROM_BACK);
470 drawipers(depth, FROM_LEFT);
471 drawipers(depth, FROM_RIGHT);
472 glPopMatrix();
473 break;
474 case FROM_LEFT:
475 glPushMatrix();
476 glTranslatef(-1.5f, 0.0f, 0.0f);
477 glScalef(0.5f, 0.5f, 0.5f);
478
479 glCallList(LODdlist[lod]);
480
481 depth++;
482 drawipers(depth, FROM_DOWN);
483 drawipers(depth, FROM_UP);
484 drawipers(depth, FROM_FRONT);
485 drawipers(depth, FROM_BACK);
486 drawipers(depth, FROM_LEFT);
487 glPopMatrix();
488 break;
489 case FROM_RIGHT:
490 glPushMatrix();
491 glTranslatef(1.5f, 0.0f, 0.0f);
492 glScalef(0.5f, 0.5f, 0.5f);
493
494 glCallList(LODdlist[lod]);
495
496 depth++;
497 drawipers(depth, FROM_DOWN);
498 drawipers(depth, FROM_UP);
499 drawipers(depth, FROM_FRONT);
500 drawipers(depth, FROM_BACK);
501 drawipers(depth, FROM_RIGHT);
502 glPopMatrix();
503 break;
504 case FROM_DOWN:
505 glPushMatrix();
506 glTranslatef(0.0f, 0.0f, 1.5f);
507 glScalef(0.5f, 0.5f, 0.5f);
508
509 glCallList(LODdlist[lod]);
510
511 depth++;
512 drawipers(depth, FROM_DOWN);
513 drawipers(depth, FROM_FRONT);
514 drawipers(depth, FROM_BACK);
515 drawipers(depth, FROM_LEFT);
516 drawipers(depth, FROM_RIGHT);
517 glPopMatrix();
518 break;
519 case FROM_UP:
520 glPushMatrix();
521 glTranslatef(0.0f, 0.0f, -1.5f);
522 glScalef(0.5f, 0.5f, 0.5f);
523
524 glCallList(LODdlist[lod]);
525
526 depth++;
527 drawipers(depth, FROM_UP);
528 drawipers(depth, FROM_FRONT);
529 drawipers(depth, FROM_BACK);
530 drawipers(depth, FROM_LEFT);
531 drawipers(depth, FROM_RIGHT);
532 glPopMatrix();
533 break;
534 }
535
536 totpoly += LODnumpoly[lod];
537 }
538
539 static void
540 draw(void)
541 {
542 static char frbuf[80] = "";
543 static GLfloat alpha = 0.0f;
544 static GLfloat beta = 0.0f;
545 static float fr = 0.0;
546 static double t0 = -1.;
547 double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
548 if (t0 < 0.0)
549 t0 = t;
550 dt = t - t0;
551 t0 = t;
552
553 dojoy();
554
555 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
556
557 if (usetex)
558 glEnable(GL_TEXTURE_2D);
559 else
560 glDisable(GL_TEXTURE_2D);
561
562 if (fog)
563 glEnable(GL_FOG);
564 else
565 glDisable(GL_FOG);
566
567 glPushMatrix();
568 calcposobs();
569 gluLookAt(obs[0], obs[1], obs[2],
570 obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
571 0.0, 0.0, 1.0);
572
573 /* Scene */
574 glEnable(GL_DEPTH_TEST);
575
576 glShadeModel(GL_SMOOTH);
577 glBindTexture(GL_TEXTURE_2D, t1id);
578 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
579 glColor3f(1.0f, 1.0f, 1.0f);
580 glEnable(GL_LIGHT0);
581 glEnable(GL_LIGHTING);
582
583 if (normext)
584 glEnable(GL_RESCALE_NORMAL_EXT);
585 else
586 glEnable(GL_NORMALIZE);
587
588 glPushMatrix();
589 glRotatef(alpha, 0.0f, 0.0f, 1.0f);
590 glRotatef(beta, 1.0f, 0.0f, 0.0f);
591 totpoly = 0;
592 drawipers(0, FROM_NONE);
593 glPopMatrix();
594
595 alpha += 4.f * dt;
596 beta += 2.4f * dt;
597
598 glDisable(GL_LIGHTING);
599 glDisable(GL_LIGHT0);
600 glShadeModel(GL_FLAT);
601
602 if (normext)
603 glDisable(GL_RESCALE_NORMAL_EXT);
604 else
605 glDisable(GL_NORMALIZE);
606
607 glCallList(skydlist);
608
609 glPopMatrix();
610
611 /* Help Screen */
612
613 sprintf(frbuf,
614 "Frame rate: %0.2f LOD: %d Tot. poly.: %d Poly/sec: %.1f",
615 fr, LODbias, totpoly, totpoly * fr);
616
617 glDisable(GL_TEXTURE_2D);
618 glDisable(GL_FOG);
619 glShadeModel(GL_FLAT);
620 glDisable(GL_DEPTH_TEST);
621
622 glMatrixMode(GL_PROJECTION);
623 glPushMatrix();
624 glLoadIdentity();
625 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
626
627 glMatrixMode(GL_MODELVIEW);
628 glLoadIdentity();
629
630 glColor3f(1.0, 0.0, 0.0);
631 glRasterPos2i(10, 10);
632 printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
633 glRasterPos2i(350, 470);
634 printstring(GLUT_BITMAP_HELVETICA_10,
635 "IperS V1.0 Written by David Bucciarelli (tech.hmw@plus.it)");
636
637 if (help)
638 printhelp();
639
640 glMatrixMode(GL_PROJECTION);
641 glPopMatrix();
642 glMatrixMode(GL_MODELVIEW);
643
644 glutSwapBuffers();
645
646 Frames++;
647 {
648 GLint t = glutGet(GLUT_ELAPSED_TIME);
649 if (t - T0 >= 2000) {
650 GLfloat seconds = (t - T0) / 1000.0;
651 fr = Frames / seconds;
652 T0 = t;
653 Frames = 0;
654 }
655 }
656 }
657
658 int
659 main(int ac, char **av)
660 {
661 float fogcolor[4] = { 0.7, 0.7, 0.7, 1.0 };
662
663 fprintf(stderr,
664 "IperS V1.0\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
665
666 glutInitWindowPosition(0, 0);
667 glutInitWindowSize(WIDTH, HEIGHT);
668 glutInit(&ac, av);
669
670 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
671
672 if (!(win = glutCreateWindow("IperS"))) {
673 fprintf(stderr, "Error, couldn't open window\n");
674 exit(-1);
675 }
676
677 reshape(WIDTH, HEIGHT);
678
679 glShadeModel(GL_SMOOTH);
680 glEnable(GL_DEPTH_TEST);
681 glEnable(GL_CULL_FACE);
682 glEnable(GL_TEXTURE_2D);
683
684 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
685
686 glEnable(GL_FOG);
687 glFogi(GL_FOG_MODE, GL_EXP2);
688 glFogfv(GL_FOG_COLOR, fogcolor);
689
690 glFogf(GL_FOG_DENSITY, 0.006);
691
692 glHint(GL_FOG_HINT, GL_NICEST);
693
694 inittextures();
695 initdlists();
696 initlight();
697
698 glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
699 glClear(GL_COLOR_BUFFER_BIT);
700
701 calcposobs();
702
703 glutReshapeFunc(reshape);
704 glutDisplayFunc(draw);
705 glutKeyboardFunc(key);
706 glutSpecialFunc(special);
707 glutIdleFunc(draw);
708
709 glutMainLoop();
710
711 return 0;
712 }