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
25 static int fullscreen
= 1;
29 #define M_PI 3.14159265
43 static GLint Frames
= 0;
49 static GLfloat terrain
[256 * 256];
50 static GLfloat terraincolor
[256 * 256][3];
55 static int bfcull
= 1;
56 static int usetex
= 1;
57 static int poutline
= 0;
59 static int joyavailable
= 0;
60 static int joyactive
= 0;
62 static long GlobalMnt
= 0;
64 static int scrwidth
= WIDTH
;
65 static int scrheight
= HEIGHT
;
67 #define OBSSTARTX 992.0
68 #define OBSSTARTY 103.0
70 static float obs
[3] = { OBSSTARTX
, heightMnt
* 1.3, OBSSTARTY
};
71 static float dir
[3], v1
[2], v2
[2];
72 static float v
= 900.0;
73 static float alpha
= 75.0;
74 static float beta
= 90.0;
80 static double t0
= -1.;
81 double dt
, t
= glutGet(GLUT_ELAPSED_TIME
) / 1000.0;
87 dir
[0] = sin(alpha
* M_PI
/ 180.0);
88 dir
[2] = cos(alpha
* M_PI
/ 180.0) * sin(beta
* M_PI
/ 180.0);
89 dir
[1] = cos(beta
* M_PI
/ 180.0);
91 if (dir
[0] < 1.0e-5 && dir
[0] > -1.0e-5)
93 if (dir
[1] < 1.0e-5 && dir
[1] > -1.0e-5)
95 if (dir
[2] < 1.0e-5 && dir
[2] > -1.0e-5)
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] * dt
;
107 obs
[1] += v
* dir
[1] * dt
;
108 obs
[2] += v
* dir
[2] * dt
;
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 - Toggle Help");
233 glRasterPos2i(60, 360);
234 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "t - Toggle Textures");
235 glRasterPos2i(60, 330);
236 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "f - Toggle 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 - Toggle 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 - Toggle 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 char frbuf
[80] = "";
367 glShadeModel(GL_SMOOTH
);
368 glEnable(GL_DEPTH_TEST
);
371 glEnable(GL_TEXTURE_2D
);
373 glDisable(GL_TEXTURE_2D
);
380 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
385 gluLookAt(obs
[0], obs
[1], obs
[2],
386 obs
[0] + dir
[0], obs
[1] + dir
[1], obs
[2] + dir
[2],
392 glDisable(GL_TEXTURE_2D
);
393 glDisable(GL_DEPTH_TEST
);
395 glShadeModel(GL_FLAT
);
397 glMatrixMode(GL_PROJECTION
);
399 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
400 glMatrixMode(GL_MODELVIEW
);
403 glColor3f(1.0, 0.0, 0.0);
404 glRasterPos2i(10, 10);
405 printstring(GLUT_BITMAP_HELVETICA_18
, frbuf
);
406 glRasterPos2i(350, 470);
407 printstring(GLUT_BITMAP_HELVETICA_10
,
408 "Terrain V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
409 glRasterPos2i(434, 457);
410 printstring(GLUT_BITMAP_HELVETICA_10
,
411 "Based on a Mickael's demo (Skizo@Hol.Fr)");
416 reshape(scrwidth
, scrheight
);
422 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
423 if (t
- T0
>= 2000) {
424 GLfloat seconds
= (t
- T0
) / 1000.0;
425 GLfloat fps
= Frames
/ seconds
;
426 sprintf(frbuf
, "Frame rate: %f", fps
);
434 key(unsigned char k
, int x
, int y
)
448 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
452 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
457 joyactive
= (!joyactive
);
470 glDisable(GL_CULL_FACE
);
474 glEnable(GL_CULL_FACE
);
480 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
481 fullscreen
= (!fullscreen
);
488 special(int k
, int x
, int y
)
507 calccolor(GLfloat height
, GLfloat c
[3])
509 GLfloat color
[4][3] = {
517 height
= height
* (1.0 / 255.0);
526 if ((height
< 0.9) && (height
>= 0.7)) {
527 fact
= (height
- 0.7) * 5.0;
528 c
[0] = fact
* color
[0][0] + (1.0 - fact
) * color
[1][0];
529 c
[1] = fact
* color
[0][1] + (1.0 - fact
) * color
[1][1];
530 c
[2] = fact
* color
[0][2] + (1.0 - fact
) * color
[1][2];
534 if ((height
< 0.7) && (height
>= 0.6)) {
535 fact
= (height
- 0.6) * 10.0;
536 c
[0] = fact
* color
[1][0] + (1.0 - fact
) * color
[2][0];
537 c
[1] = fact
* color
[1][1] + (1.0 - fact
) * color
[2][1];
538 c
[2] = fact
* color
[1][2] + (1.0 - fact
) * color
[2][2];
542 if ((height
< 0.6) && (height
>= 0.5)) {
543 fact
= (height
- 0.5) * 10.0;
544 c
[0] = fact
* color
[2][0] + (1.0 - fact
) * color
[3][0];
545 c
[1] = fact
* color
[2][1] + (1.0 - fact
) * color
[3][1];
546 c
[2] = fact
* color
[2][2] + (1.0 - fact
) * color
[3][2];
558 GLubyte bufferter
[256 * 256], terrainpic
[256 * 256];
563 if ((FilePic
= fopen("terrain.dat", "r")) == NULL
) {
564 fprintf(stderr
, "Error loading terrain.dat\n");
567 fread(bufferter
, 256 * 256, 1, FilePic
);
570 for (i
= 0; i
< (256 * 256); i
++) {
571 terrain
[i
] = (bufferter
[i
] * (heightMnt
/ 255.0f
));
572 calccolor((GLfloat
) bufferter
[i
], terraincolor
[i
]);
573 tmp
= (((int) bufferter
[i
]) + 96);
574 terrainpic
[i
] = (tmp
> 255) ? 255 : tmp
;
577 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
578 if ((gluerr
= gluBuild2DMipmaps(GL_TEXTURE_2D
, 1, 256, 256, GL_LUMINANCE
,
580 (GLvoid
*) (&terrainpic
[0])))) {
581 fprintf(stderr
, "GLULib%s\n", (char *) gluErrorString(gluerr
));
585 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
586 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
588 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
589 GL_LINEAR_MIPMAP_LINEAR
);
590 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
592 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
593 glEnable(GL_TEXTURE_2D
);
599 float fogcolor
[4] = { 0.6, 0.7, 0.7, 1.0 };
601 glClearColor(fogcolor
[0], fogcolor
[1], fogcolor
[2], fogcolor
[3]);
603 glDepthFunc(GL_LEQUAL
);
604 glShadeModel(GL_SMOOTH
);
605 glEnable(GL_DEPTH_TEST
);
606 glEnable(GL_CULL_FACE
);
609 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
612 glFogi(GL_FOG_MODE
, GL_EXP2
);
613 glFogfv(GL_FOG_COLOR
, fogcolor
);
614 glFogf(GL_FOG_DENSITY
, 0.0007);
616 glHint(GL_FOG_HINT
, GL_NICEST
);
619 reshape(scrwidth
, scrheight
);
624 main(int ac
, char **av
)
626 glutInitWindowPosition(0, 0);
627 glutInitWindowSize(WIDTH
, HEIGHT
);
630 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
632 if (!(win
= glutCreateWindow("Terrain"))) {
633 fprintf(stderr
, "Error, couldn't open window\n");
643 glDisable(GL_TEXTURE_2D
);
647 glutReshapeFunc(reshape
);
648 glutDisplayFunc(drawscene
);
649 glutKeyboardFunc(key
);
650 glutSpecialFunc(special
);
651 glutIdleFunc(drawscene
);