2 * This program is under the GNU GPL.
3 * Use at your own risk.
5 * written by David Bucciarelli (tech.hmw@plus.it)
8 * based on a Mikael SkiZoWalker's (MoDEL) / France (Skizo@Hol.Fr) demo
24 static int fullscreen
= 1;
28 #define M_PI 3.14159265
47 static GLfloat terrain
[256 * 256];
48 static GLfloat terraincolor
[256 * 256][3];
53 static int bfcull
= 1;
54 static int usetex
= 1;
55 static int poutline
= 0;
57 static int joyavailable
= 0;
58 static int joyactive
= 0;
60 static long GlobalMnt
= 0;
62 static int scrwidth
= WIDTH
;
63 static int scrheight
= HEIGHT
;
65 #define OBSSTARTX 992.0
66 #define OBSSTARTY 103.0
68 static float obs
[3] = { OBSSTARTX
, heightMnt
* 1.3, OBSSTARTY
};
69 static float dir
[3], v1
[2], v2
[2];
70 static float v
= 15.0;
71 static float alpha
= 75.0;
72 static float beta
= 90.0;
77 static clock_t told
= 0;
86 return (ris
/ (float) CLOCKS_PER_SEC
);
94 dir
[0] = sin(alpha
* M_PI
/ 180.0);
95 dir
[2] = cos(alpha
* M_PI
/ 180.0) * sin(beta
* M_PI
/ 180.0);
96 dir
[1] = cos(beta
* M_PI
/ 180.0);
98 alpha1
= alpha
+ FOV
/ 2.0;
99 v1
[0] = sin(alpha1
* M_PI
/ 180.0);
100 v1
[1] = cos(alpha1
* M_PI
/ 180.0);
102 alpha2
= alpha
- FOV
/ 2.0;
103 v2
[0] = sin(alpha2
* M_PI
/ 180.0);
104 v2
[1] = cos(alpha2
* M_PI
/ 180.0);
106 obs
[0] += v
* dir
[0];
107 obs
[1] += v
* dir
[1];
108 obs
[2] += v
* dir
[2];
115 reshape(int width
, int height
)
119 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
120 glMatrixMode(GL_PROJECTION
);
122 gluPerspective(50.0, ((GLfloat
) width
/ (GLfloat
) height
),
123 lenghtXmnt
* stepYmnt
* 0.01, lenghtXmnt
* stepYmnt
* 0.7);
124 glMatrixMode(GL_MODELVIEW
);
129 clipstrip(float y
, float *start
, float *end
)
131 float x1
, x2
, t1
, t2
, tmp
;
151 if (((x1
< -(lenghtXmnt
* stepXmnt
) / 2) && (t2
<= 0.0)) ||
152 ((t1
<= 0.0) && (x2
> (lenghtXmnt
* stepXmnt
) / 2)) ||
153 ((t1
< 0.0) && (t2
< 0.0)))
156 if ((t1
== 0.0) && (t2
== 0.0)) {
157 if ((v1
[0] < 0.0) && (v1
[1] > 0.0) && (v2
[0] < 0.0) && (v2
[1] < 0.0)) {
158 *start
= -(lenghtXmnt
* stepXmnt
) / 2;
163 if ((v1
[0] > 0.0) && (v1
[1] < 0.0) && (v2
[0] > 0.0) && (v2
[1] > 0.0)) {
165 *end
= (lenghtXmnt
* stepXmnt
) / 2;
175 x2
= -(lenghtXmnt
* stepXmnt
) / 2;
177 x2
= (lenghtXmnt
* stepXmnt
) / 2;
182 x1
= -(lenghtXmnt
* stepXmnt
) / 2;
184 x1
= (lenghtXmnt
* stepXmnt
) / 2;
195 if (x1
< -(lenghtXmnt
* stepXmnt
) / 2)
196 x1
= -(lenghtXmnt
* stepXmnt
) / 2;
199 if (x2
> (lenghtXmnt
* stepXmnt
) / 2)
200 x2
= (lenghtXmnt
* stepXmnt
) / 2;
202 *start
= ((int) (x1
/ stepXmnt
)) * stepXmnt
;
203 *end
= ((int) (x2
/ stepXmnt
)) * stepXmnt
;
209 printstring(void *font
, char *string
)
213 len
= (int) strlen(string
);
214 for (i
= 0; i
< len
; i
++)
215 glutBitmapCharacter(font
, string
[i
]);
222 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
223 glColor4f(0.0, 0.0, 0.0, 0.5);
224 glRecti(40, 40, 600, 440);
227 glColor3f(1.0, 0.0, 0.0);
228 glRasterPos2i(300, 420);
229 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Help");
231 glRasterPos2i(60, 390);
232 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "h - Togle Help");
233 glRasterPos2i(60, 360);
234 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "t - Togle Textures");
235 glRasterPos2i(60, 330);
236 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "f - Togle Fog");
237 glRasterPos2i(60, 300);
238 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "p - Wire frame");
239 glRasterPos2i(60, 270);
240 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "b - Togle Back face culling");
241 glRasterPos2i(60, 240);
242 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Arrow Keys - Rotate");
243 glRasterPos2i(60, 210);
244 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "a - Increase velocity");
245 glRasterPos2i(60, 180);
246 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "z - Decrease velocity");
248 glRasterPos2i(60, 150);
250 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
251 "j - Togle jostick control (Joystick control available)");
253 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
254 "(No Joystick control available)");
260 int h
, i
, idx
, ox
, oy
;
261 float j
, k
, start
, end
;
263 ox
= (int) (obs
[0] / stepXmnt
);
264 oy
= (int) (obs
[2] / stepYmnt
);
265 GlobalMnt
= ((ox
* TSCALE
) & 255) + ((oy
* TSCALE
) & 255) * 256;
268 glTranslatef((float) ox
* stepXmnt
, 0, (float) oy
* stepYmnt
);
270 for (h
= 0, k
= -(lenghtYmnt
* stepYmnt
) / 2; h
< lenghtYmnt
;
271 k
+= stepYmnt
, h
++) {
272 if (!clipstrip(k
, &start
, &end
))
275 glBegin(GL_TRIANGLE_STRIP
); /* I hope that the optimizer will be able to improve this code */
276 for (i
= (int) (lenghtXmnt
/ 2 + start
/ stepXmnt
), j
= start
; j
<= end
;
277 j
+= stepXmnt
, i
++) {
278 idx
= (i
* TSCALE
+ h
* 256 * TSCALE
+ GlobalMnt
) & 65535;
279 glColor3fv(terraincolor
[idx
]);
280 glTexCoord2f((ox
+ i
) / 8.0, (oy
+ h
) / 8.0);
281 glVertex3f(j
, terrain
[idx
], k
);
284 (i
* TSCALE
+ h
* 256 * TSCALE
+ 256 * TSCALE
+
286 glColor3fv(terraincolor
[idx
]);
287 glTexCoord2f((ox
+ i
) / 8.0, (oy
+ h
+ 1) / 8.0);
288 glVertex3f(j
, terrain
[idx
], k
+ stepYmnt
);
293 glDisable(GL_CULL_FACE
);
294 glDisable(GL_TEXTURE_2D
);
297 glColor4f(0.1, 0.7, 1.0, 0.4);
298 glVertex3f(-(lenghtXmnt
* stepXmnt
) / 2.0, heightMnt
* 0.6,
299 -(lenghtYmnt
* stepYmnt
) / 2.0);
300 glVertex3f(-(lenghtXmnt
* stepXmnt
) / 2.0, heightMnt
* 0.6,
301 (lenghtYmnt
* stepYmnt
) / 2.0);
302 glVertex3f((lenghtXmnt
* stepXmnt
) / 2.0, heightMnt
* 0.6,
303 (lenghtYmnt
* stepYmnt
) / 2.0);
304 glVertex3f((lenghtXmnt
* stepXmnt
) / 2.0, heightMnt
* 0.6,
305 -(lenghtYmnt
* stepYmnt
) / 2.0);
309 glEnable(GL_CULL_FACE
);
310 glEnable(GL_TEXTURE_2D
);
320 static UINT max
[2] = { 0, 0 };
321 static UINT min
[2] = { 0xffffffff, 0xffffffff }, center
[2];
325 res
= joyGetPos(JOYSTICKID1
, &joy
);
327 if (res
== JOYERR_NOERROR
) {
330 if (max
[0] < joy
.wXpos
)
332 if (min
[0] > joy
.wXpos
)
334 center
[0] = (max
[0] + min
[0]) / 2;
336 if (max
[1] < joy
.wYpos
)
338 if (min
[1] > joy
.wYpos
)
340 center
[1] = (max
[1] + min
[1]) / 2;
343 if (fabs(center
[0] - (float) joy
.wXpos
) > 0.1 * (max
[0] - min
[0]))
345 2.5 * (center
[0] - (float) joy
.wXpos
) / (max
[0] - min
[0]);
346 if (fabs(center
[1] - (float) joy
.wYpos
) > 0.1 * (max
[1] - min
[1]))
347 beta
+= 2.5 * (center
[1] - (float) joy
.wYpos
) / (max
[1] - min
[1]);
349 if (joy
.wButtons
& JOY_BUTTON1
)
351 if (joy
.wButtons
& JOY_BUTTON2
)
363 static int count
= 0;
364 static char frbuf
[80];
369 glShadeModel(GL_SMOOTH
);
370 glEnable(GL_DEPTH_TEST
);
373 glEnable(GL_TEXTURE_2D
);
375 glDisable(GL_TEXTURE_2D
);
382 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
387 gluLookAt(obs
[0], obs
[1], obs
[2],
388 obs
[0] + dir
[0], obs
[1] + dir
[1], obs
[2] + dir
[2],
394 if ((count
% FRAME
) == 0) {
396 sprintf(frbuf
, "Frame rate: %.3f", FRAME
/ fr
);
399 glDisable(GL_TEXTURE_2D
);
400 glDisable(GL_DEPTH_TEST
);
402 glShadeModel(GL_FLAT
);
404 glMatrixMode(GL_PROJECTION
);
406 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
407 glMatrixMode(GL_MODELVIEW
);
410 glColor3f(1.0, 0.0, 0.0);
411 glRasterPos2i(10, 10);
412 printstring(GLUT_BITMAP_HELVETICA_18
, frbuf
);
413 glRasterPos2i(350, 470);
414 printstring(GLUT_BITMAP_HELVETICA_10
,
415 "Terrain V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
416 glRasterPos2i(434, 457);
417 printstring(GLUT_BITMAP_HELVETICA_10
,
418 "Based on a Mickael's demo (Skizo@Hol.Fr)");
423 reshape(scrwidth
, scrheight
);
431 key(unsigned char k
, int x
, int y
)
445 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
449 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
454 joyactive
= (!joyactive
);
467 glDisable(GL_CULL_FACE
);
471 glEnable(GL_CULL_FACE
);
477 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
478 fullscreen
= (!fullscreen
);
485 special(int k
, int x
, int y
)
504 calccolor(GLfloat height
, GLfloat c
[3])
506 GLfloat color
[4][3] = {
514 height
= height
* (1.0 / 255.0);
523 if ((height
< 0.9) && (height
>= 0.7)) {
524 fact
= (height
- 0.7) * 5.0;
525 c
[0] = fact
* color
[0][0] + (1.0 - fact
) * color
[1][0];
526 c
[1] = fact
* color
[0][1] + (1.0 - fact
) * color
[1][1];
527 c
[2] = fact
* color
[0][2] + (1.0 - fact
) * color
[1][2];
531 if ((height
< 0.7) && (height
>= 0.6)) {
532 fact
= (height
- 0.6) * 10.0;
533 c
[0] = fact
* color
[1][0] + (1.0 - fact
) * color
[2][0];
534 c
[1] = fact
* color
[1][1] + (1.0 - fact
) * color
[2][1];
535 c
[2] = fact
* color
[1][2] + (1.0 - fact
) * color
[2][2];
539 if ((height
< 0.6) && (height
>= 0.5)) {
540 fact
= (height
- 0.5) * 10.0;
541 c
[0] = fact
* color
[2][0] + (1.0 - fact
) * color
[3][0];
542 c
[1] = fact
* color
[2][1] + (1.0 - fact
) * color
[3][1];
543 c
[2] = fact
* color
[2][2] + (1.0 - fact
) * color
[3][2];
555 GLubyte bufferter
[256 * 256], terrainpic
[256 * 256];
560 if ((FilePic
= fopen("terrain.dat", "r")) == NULL
) {
561 fprintf(stderr
, "Error loading Mnt.bin\n");
564 fread(bufferter
, 256 * 256, 1, FilePic
);
567 for (i
= 0; i
< (256 * 256); i
++) {
568 terrain
[i
] = (bufferter
[i
] * (heightMnt
/ 255.0f
));
569 calccolor((GLfloat
) bufferter
[i
], terraincolor
[i
]);
570 tmp
= (((int) bufferter
[i
]) + 96);
571 terrainpic
[i
] = (tmp
> 255) ? 255 : tmp
;
574 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
575 if ((gluerr
= gluBuild2DMipmaps(GL_TEXTURE_2D
, 1, 256, 256, GL_LUMINANCE
,
577 (GLvoid
*) (&terrainpic
[0])))) {
578 fprintf(stderr
, "GLULib%s\n", gluErrorString(gluerr
));
582 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
583 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
585 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
586 GL_LINEAR_MIPMAP_LINEAR
);
587 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
589 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
590 glEnable(GL_TEXTURE_2D
);
596 float fogcolor
[4] = { 0.6, 0.7, 0.7, 1.0 };
598 glClearColor(fogcolor
[0], fogcolor
[1], fogcolor
[2], fogcolor
[3]);
600 glDepthFunc(GL_LEQUAL
);
601 glShadeModel(GL_SMOOTH
);
602 glEnable(GL_DEPTH_TEST
);
603 glEnable(GL_CULL_FACE
);
606 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
609 glFogi(GL_FOG_MODE
, GL_EXP2
);
610 glFogfv(GL_FOG_COLOR
, fogcolor
);
611 glFogf(GL_FOG_DENSITY
, 0.0007);
613 glHint(GL_FOG_HINT
, GL_NICEST
);
616 reshape(scrwidth
, scrheight
);
621 main(int ac
, char **av
)
623 glutInitWindowPosition(0, 0);
624 glutInitWindowSize(WIDTH
, HEIGHT
);
627 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
629 if (!(win
= glutCreateWindow("Terrain"))) {
630 fprintf(stderr
, "Error, couldn't open window\n");
640 glDisable(GL_TEXTURE_2D
);
644 glutReshapeFunc(reshape
);
645 glutDisplayFunc(drawscene
);
646 glutKeyboardFunc(key
);
647 glutSpecialFunc(special
);
648 glutIdleFunc(drawscene
);