2 * This program is under the GNU GPL.
3 * Use at your own risk.
5 * written by David Bucciarelli (tech.hmw@plus.it)
14 #if defined (WIN32)|| defined(_WIN32)
25 static int fullscreen
= 1;
28 static int WIDTH
= 640;
29 static int HEIGHT
= 480;
36 #define TEX_SKY_WIDTH 256
37 #define TEX_SKY_HEIGHT TEX_SKY_WIDTH
40 #define M_PI 3.1415926535
53 static float obs
[3] = { 3.8, 0.0, 0.0 };
56 static float alpha
= -90.0;
57 static float beta
= 90.0;
60 static int bfcull
= 1;
61 static int usetex
= 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
;
70 static unsigned int totpoly
= 0;
72 static GLuint t1id
, t2id
;
73 static GLuint skydlist
, LODdlist
[MAX_LOD
], LODnumpoly
[MAX_LOD
];
78 GLfloat lspec
[4] = { 1.0, 1.0, 1.0, 1.0 };
79 static GLfloat lightpos
[4] = { 30, 15.0, 30.0, 1.0 };
81 glLightfv(GL_LIGHT0
, GL_POSITION
, lightpos
);
82 glLightfv(GL_LIGHT0
, GL_SPECULAR
, lspec
);
84 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 32.0);
85 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, lspec
);
91 static int slicetable
[MAX_LOD
][2] = {
103 int i
, xslices
, yslices
;
105 obj
= gluNewQuadric();
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
);
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);
121 for (i
= 0; i
< MAX_LOD
; i
++) {
122 LODdlist
[i
] = glGenLists(1);
123 glNewList(LODdlist
[i
], GL_COMPILE
);
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);
137 gluDeleteQuadric(obj
);
143 GLubyte tsky
[TEX_SKY_HEIGHT
][TEX_SKY_WIDTH
][3];
150 glGenTextures(1, &t1id
);
151 glBindTexture(GL_TEXTURE_2D
, t1id
);
153 if (!LoadRGBMipmaps("../images/bw.rgb", 3)) {
154 fprintf(stderr
, "Error reading a texture.\n");
158 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
159 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
161 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
162 GL_LINEAR_MIPMAP_LINEAR
);
163 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
167 glGenTextures(1, &t2id
);
168 glBindTexture(GL_TEXTURE_2D
, t2id
);
170 for (y
= 0; y
< TEX_SKY_HEIGHT
; y
++)
171 for (x
= 0; x
< TEX_SKY_WIDTH
; x
++)
172 if (y
< TEX_SKY_HEIGHT
/ 2) {
173 fact
= y
/ (GLfloat
) (TEX_SKY_HEIGHT
/ 2);
175 (GLubyte
) (255.0f
* (0.1f
* fact
+ 0.3f
* (1.0f
- fact
)));
177 (GLubyte
) (255.0f
* (0.2f
* fact
+ 1.0f
* (1.0f
- fact
)));
181 tsky
[y
][x
][0] = tsky
[TEX_SKY_HEIGHT
- y
- 1][x
][0];
182 tsky
[y
][x
][1] = tsky
[TEX_SKY_HEIGHT
- y
- 1][x
][1];
186 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
189 gluBuild2DMipmaps(GL_TEXTURE_2D
, 3, TEX_SKY_WIDTH
, TEX_SKY_HEIGHT
,
190 GL_RGB
, GL_UNSIGNED_BYTE
, (GLvoid
*) (tsky
)))) {
191 fprintf(stderr
, "GLULib%s\n", (char *) gluErrorString(gluerr
));
195 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
196 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
198 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
199 GL_LINEAR_MIPMAP_LINEAR
);
200 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
206 dir
[0] = sin(alpha
* M_PI
/ 180.0);
207 dir
[1] = cos(alpha
* M_PI
/ 180.0) * sin(beta
* M_PI
/ 180.0);
208 dir
[2] = cos(beta
* M_PI
/ 180.0);
210 if (dir
[0] < 1.0e-5 && dir
[0] > -1.0e-5)
212 if (dir
[1] < 1.0e-5 && dir
[1] > -1.0e-5)
214 if (dir
[2] < 1.0e-5 && dir
[2] > -1.0e-5)
217 obs
[0] += v
* dir
[0];
218 obs
[1] += v
* dir
[1];
219 obs
[2] += v
* dir
[2];
223 special(int k
, int x
, int y
)
246 glDeleteTextures(1, &t1id
);
247 glDeleteTextures(1, &t2id
);
249 glDeleteLists(skydlist
, 1);
250 for (i
= 0; i
< MAX_LOD
; i
++) {
251 glDeleteLists(LODdlist
[i
], 1);
252 glDeleteLists(LODnumpoly
[i
], 1);
258 key(unsigned char k
, int x
, int y
)
275 fullscreen
= (!fullscreen
);
276 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
287 joyactive
= (!joyactive
);
299 normext
= (!normext
);
303 glDisable(GL_CULL_FACE
);
307 glEnable(GL_CULL_FACE
);
313 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
318 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
327 reshape(int w
, int h
)
331 glMatrixMode(GL_PROJECTION
);
333 gluPerspective(90.0, w
/ (float) h
, 0.8, 100.0);
334 glMatrixMode(GL_MODELVIEW
);
336 glViewport(0, 0, w
, h
);
340 printstring(void *font
, char *string
)
344 len
= (int) strlen(string
);
345 for (i
= 0; i
< len
; i
++)
346 glutBitmapCharacter(font
, string
[i
]);
353 glColor4f(0.5, 0.5, 0.5, 0.5);
354 glRecti(40, 40, 600, 440);
357 glColor3f(1.0, 0.0, 0.0);
358 glRasterPos2i(300, 420);
359 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Help");
361 glRasterPos2i(60, 390);
362 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "h - Toggle Help");
363 glRasterPos2i(60, 360);
364 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "t - Toggle Textures");
365 glRasterPos2i(60, 330);
366 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "f - Toggle Fog");
367 glRasterPos2i(60, 300);
368 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "b - Toggle Back face culling");
369 glRasterPos2i(60, 270);
370 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Arrow Keys - Rotate");
371 glRasterPos2i(60, 240);
372 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "a - Increase velocity");
373 glRasterPos2i(60, 210);
374 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "z - Decrease velocity");
375 glRasterPos2i(60, 180);
376 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "p - Toggle Wire frame");
377 glRasterPos2i(60, 150);
378 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
379 "n - Toggle GL_EXT_rescale_normal extension");
380 glRasterPos2i(60, 120);
381 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
382 "+/- - Increase/decrease the Object maximum LOD");
384 glRasterPos2i(60, 90);
386 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
387 "j - Toggle jostick control (Joystick control available)");
389 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
390 "(No Joystick control available)");
397 static UINT max
[2] = { 0, 0 };
398 static UINT min
[2] = { 0xffffffff, 0xffffffff }, center
[2];
402 res
= joyGetPos(JOYSTICKID1
, &joy
);
404 if (res
== JOYERR_NOERROR
) {
407 if (max
[0] < joy
.wXpos
)
409 if (min
[0] > joy
.wXpos
)
411 center
[0] = (max
[0] + min
[0]) / 2;
413 if (max
[1] < joy
.wYpos
)
415 if (min
[1] > joy
.wYpos
)
417 center
[1] = (max
[1] + min
[1]) / 2;
420 if (fabs(center
[0] - (float) joy
.wXpos
) > 0.1 * (max
[0] - min
[0]))
422 2.0 * (center
[0] - (float) joy
.wXpos
) / (max
[0] - min
[0]);
423 if (fabs(center
[1] - (float) joy
.wYpos
) > 0.1 * (max
[1] - min
[1]))
424 beta
+= 2.0 * (center
[1] - (float) joy
.wYpos
) / (max
[1] - min
[1]);
426 if (joy
.wButtons
& JOY_BUTTON1
)
428 if (joy
.wButtons
& JOY_BUTTON2
)
438 drawipers(int depth
, int from
)
442 if (depth
== maxdepth
)
445 lod
= depth
+ LODbias
;
453 glCallList(LODdlist
[lod
]);
456 drawipers(depth
, FROM_DOWN
);
457 drawipers(depth
, FROM_UP
);
458 drawipers(depth
, FROM_FRONT
);
459 drawipers(depth
, FROM_BACK
);
460 drawipers(depth
, FROM_LEFT
);
461 drawipers(depth
, FROM_RIGHT
);
465 glTranslatef(0.0f
, -1.5f
, 0.0f
);
466 glScalef(0.5f
, 0.5f
, 0.5f
);
468 glCallList(LODdlist
[lod
]);
471 drawipers(depth
, FROM_DOWN
);
472 drawipers(depth
, FROM_UP
);
473 drawipers(depth
, FROM_FRONT
);
474 drawipers(depth
, FROM_LEFT
);
475 drawipers(depth
, FROM_RIGHT
);
480 glTranslatef(0.0f
, 1.5f
, 0.0f
);
481 glScalef(0.5f
, 0.5f
, 0.5f
);
483 glCallList(LODdlist
[lod
]);
486 drawipers(depth
, FROM_DOWN
);
487 drawipers(depth
, FROM_UP
);
488 drawipers(depth
, FROM_BACK
);
489 drawipers(depth
, FROM_LEFT
);
490 drawipers(depth
, FROM_RIGHT
);
495 glTranslatef(-1.5f
, 0.0f
, 0.0f
);
496 glScalef(0.5f
, 0.5f
, 0.5f
);
498 glCallList(LODdlist
[lod
]);
501 drawipers(depth
, FROM_DOWN
);
502 drawipers(depth
, FROM_UP
);
503 drawipers(depth
, FROM_FRONT
);
504 drawipers(depth
, FROM_BACK
);
505 drawipers(depth
, FROM_LEFT
);
510 glTranslatef(1.5f
, 0.0f
, 0.0f
);
511 glScalef(0.5f
, 0.5f
, 0.5f
);
513 glCallList(LODdlist
[lod
]);
516 drawipers(depth
, FROM_DOWN
);
517 drawipers(depth
, FROM_UP
);
518 drawipers(depth
, FROM_FRONT
);
519 drawipers(depth
, FROM_BACK
);
520 drawipers(depth
, FROM_RIGHT
);
525 glTranslatef(0.0f
, 0.0f
, 1.5f
);
526 glScalef(0.5f
, 0.5f
, 0.5f
);
528 glCallList(LODdlist
[lod
]);
531 drawipers(depth
, FROM_DOWN
);
532 drawipers(depth
, FROM_FRONT
);
533 drawipers(depth
, FROM_BACK
);
534 drawipers(depth
, FROM_LEFT
);
535 drawipers(depth
, FROM_RIGHT
);
540 glTranslatef(0.0f
, 0.0f
, -1.5f
);
541 glScalef(0.5f
, 0.5f
, 0.5f
);
543 glCallList(LODdlist
[lod
]);
546 drawipers(depth
, FROM_UP
);
547 drawipers(depth
, FROM_FRONT
);
548 drawipers(depth
, FROM_BACK
);
549 drawipers(depth
, FROM_LEFT
);
550 drawipers(depth
, FROM_RIGHT
);
555 totpoly
+= LODnumpoly
[lod
];
561 static char frbuf
[80] = "";
562 static GLfloat alpha
= 0.0f
;
563 static GLfloat beta
= 0.0f
;
564 static float fr
= 0.0;
565 static double t0
= -1.;
566 double dt
, t
= glutGet(GLUT_ELAPSED_TIME
) / 1000.0;
574 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
577 glEnable(GL_TEXTURE_2D
);
579 glDisable(GL_TEXTURE_2D
);
588 gluLookAt(obs
[0], obs
[1], obs
[2],
589 obs
[0] + dir
[0], obs
[1] + dir
[1], obs
[2] + dir
[2],
593 glEnable(GL_DEPTH_TEST
);
595 glShadeModel(GL_SMOOTH
);
596 glBindTexture(GL_TEXTURE_2D
, t1id
);
597 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
598 glColor3f(1.0f
, 1.0f
, 1.0f
);
600 glEnable(GL_LIGHTING
);
603 glEnable(GL_RESCALE_NORMAL_EXT
);
605 glEnable(GL_NORMALIZE
);
608 glRotatef(alpha
, 0.0f
, 0.0f
, 1.0f
);
609 glRotatef(beta
, 1.0f
, 0.0f
, 0.0f
);
611 drawipers(0, FROM_NONE
);
617 glDisable(GL_LIGHTING
);
618 glDisable(GL_LIGHT0
);
619 glShadeModel(GL_FLAT
);
622 glDisable(GL_RESCALE_NORMAL_EXT
);
624 glDisable(GL_NORMALIZE
);
626 glCallList(skydlist
);
633 "Frame rate: %0.2f LOD: %d Tot. poly.: %d Poly/sec: %.1f",
634 fr
, LODbias
, totpoly
, totpoly
* fr
);
636 glDisable(GL_TEXTURE_2D
);
638 glShadeModel(GL_FLAT
);
639 glDisable(GL_DEPTH_TEST
);
641 glMatrixMode(GL_PROJECTION
);
644 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
646 glMatrixMode(GL_MODELVIEW
);
649 glColor3f(1.0, 0.0, 0.0);
650 glRasterPos2i(10, 10);
651 printstring(GLUT_BITMAP_HELVETICA_18
, frbuf
);
652 glRasterPos2i(350, 470);
653 printstring(GLUT_BITMAP_HELVETICA_10
,
654 "IperS V1.0 Written by David Bucciarelli (tech.hmw@plus.it)");
659 glMatrixMode(GL_PROJECTION
);
661 glMatrixMode(GL_MODELVIEW
);
667 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
668 if (t
- T0
>= 2000) {
669 GLfloat seconds
= (t
- T0
) / 1000.0;
670 fr
= Frames
/ seconds
;
678 main(int ac
, char **av
)
680 float fogcolor
[4] = { 0.7, 0.7, 0.7, 1.0 };
683 "IperS V1.0\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
685 glutInitWindowPosition(0, 0);
686 glutInitWindowSize(WIDTH
, HEIGHT
);
689 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
691 if (!(win
= glutCreateWindow("IperS"))) {
692 fprintf(stderr
, "Error, couldn't open window\n");
696 reshape(WIDTH
, HEIGHT
);
698 glShadeModel(GL_SMOOTH
);
699 glEnable(GL_DEPTH_TEST
);
700 glEnable(GL_CULL_FACE
);
701 glEnable(GL_TEXTURE_2D
);
703 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
706 glFogi(GL_FOG_MODE
, GL_EXP2
);
707 glFogfv(GL_FOG_COLOR
, fogcolor
);
709 glFogf(GL_FOG_DENSITY
, 0.006);
711 glHint(GL_FOG_HINT
, GL_NICEST
);
717 glClearColor(fogcolor
[0], fogcolor
[1], fogcolor
[2], fogcolor
[3]);
718 glClear(GL_COLOR_BUFFER_BIT
);
722 glutReshapeFunc(reshape
);
723 glutDisplayFunc(draw
);
724 glutKeyboardFunc(key
);
725 glutSpecialFunc(special
);