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
26 static int fullscreen
= 1;
30 #define M_PI 3.14159265
44 static GLint Frames
= 0;
50 static GLfloat terrain
[256 * 256];
51 static GLfloat terraincolor
[256 * 256][3];
56 static int bfcull
= 1;
57 static int usetex
= 1;
58 static int poutline
= 0;
60 static int joyavailable
= 0;
61 static int joyactive
= 0;
63 static long GlobalMnt
= 0;
65 static int scrwidth
= WIDTH
;
66 static int scrheight
= HEIGHT
;
68 #define OBSSTARTX 992.0
69 #define OBSSTARTY 103.0
71 static float obs
[3] = { OBSSTARTX
, heightMnt
* 1.3, OBSSTARTY
};
72 static float dir
[3], v1
[2], v2
[2];
73 static float v
= 900.0;
74 static float alpha
= 75.0;
75 static float beta
= 90.0;
81 static double t0
= -1.;
82 double dt
, t
= glutGet(GLUT_ELAPSED_TIME
) / 1000.0;
88 dir
[0] = sin(alpha
* M_PI
/ 180.0);
89 dir
[2] = cos(alpha
* M_PI
/ 180.0) * sin(beta
* M_PI
/ 180.0);
90 dir
[1] = cos(beta
* M_PI
/ 180.0);
92 if (dir
[0] < 1.0e-5 && dir
[0] > -1.0e-5)
94 if (dir
[1] < 1.0e-5 && dir
[1] > -1.0e-5)
96 if (dir
[2] < 1.0e-5 && dir
[2] > -1.0e-5)
99 alpha1
= alpha
+ FOV
/ 2.0;
100 v1
[0] = sin(alpha1
* M_PI
/ 180.0);
101 v1
[1] = cos(alpha1
* M_PI
/ 180.0);
103 alpha2
= alpha
- FOV
/ 2.0;
104 v2
[0] = sin(alpha2
* M_PI
/ 180.0);
105 v2
[1] = cos(alpha2
* M_PI
/ 180.0);
107 obs
[0] += v
* dir
[0] * dt
;
108 obs
[1] += v
* dir
[1] * dt
;
109 obs
[2] += v
* dir
[2] * dt
;
116 reshape(int width
, int height
)
120 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
121 glMatrixMode(GL_PROJECTION
);
123 gluPerspective(50.0, ((GLfloat
) width
/ (GLfloat
) height
),
124 lenghtXmnt
* stepYmnt
* 0.01, lenghtXmnt
* stepYmnt
* 0.7);
125 glMatrixMode(GL_MODELVIEW
);
130 clipstrip(float y
, float *start
, float *end
)
132 float x1
, x2
, t1
, t2
, tmp
;
152 if (((x1
< -(lenghtXmnt
* stepXmnt
) / 2) && (t2
<= 0.0)) ||
153 ((t1
<= 0.0) && (x2
> (lenghtXmnt
* stepXmnt
) / 2)) ||
154 ((t1
< 0.0) && (t2
< 0.0)))
157 if ((t1
== 0.0) && (t2
== 0.0)) {
158 if ((v1
[0] < 0.0) && (v1
[1] > 0.0) && (v2
[0] < 0.0) && (v2
[1] < 0.0)) {
159 *start
= -(lenghtXmnt
* stepXmnt
) / 2;
164 if ((v1
[0] > 0.0) && (v1
[1] < 0.0) && (v2
[0] > 0.0) && (v2
[1] > 0.0)) {
166 *end
= (lenghtXmnt
* stepXmnt
) / 2;
176 x2
= -(lenghtXmnt
* stepXmnt
) / 2;
178 x2
= (lenghtXmnt
* stepXmnt
) / 2;
183 x1
= -(lenghtXmnt
* stepXmnt
) / 2;
185 x1
= (lenghtXmnt
* stepXmnt
) / 2;
196 if (x1
< -(lenghtXmnt
* stepXmnt
) / 2)
197 x1
= -(lenghtXmnt
* stepXmnt
) / 2;
200 if (x2
> (lenghtXmnt
* stepXmnt
) / 2)
201 x2
= (lenghtXmnt
* stepXmnt
) / 2;
203 *start
= ((int) (x1
/ stepXmnt
)) * stepXmnt
;
204 *end
= ((int) (x2
/ stepXmnt
)) * stepXmnt
;
210 printstring(void *font
, char *string
)
214 len
= (int) strlen(string
);
215 for (i
= 0; i
< len
; i
++)
216 glutBitmapCharacter(font
, string
[i
]);
223 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
224 glColor4f(0.0, 0.0, 0.0, 0.5);
225 glRecti(40, 40, 600, 440);
228 glColor3f(1.0, 0.0, 0.0);
229 glRasterPos2i(300, 420);
230 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Help");
232 glRasterPos2i(60, 390);
233 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "h - Toggle Help");
234 glRasterPos2i(60, 360);
235 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "t - Toggle Textures");
236 glRasterPos2i(60, 330);
237 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "f - Toggle Fog");
238 glRasterPos2i(60, 300);
239 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "p - Wire frame");
240 glRasterPos2i(60, 270);
241 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "b - Toggle Back face culling");
242 glRasterPos2i(60, 240);
243 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Arrow Keys - Rotate");
244 glRasterPos2i(60, 210);
245 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "a - Increase velocity");
246 glRasterPos2i(60, 180);
247 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "z - Decrease velocity");
249 glRasterPos2i(60, 150);
251 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
252 "j - Toggle jostick control (Joystick control available)");
254 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
255 "(No Joystick control available)");
261 int h
, i
, idx
, ox
, oy
;
262 float j
, k
, start
, end
;
264 ox
= (int) (obs
[0] / stepXmnt
);
265 oy
= (int) (obs
[2] / stepYmnt
);
266 GlobalMnt
= ((ox
* TSCALE
) & 255) + ((oy
* TSCALE
) & 255) * 256;
269 glTranslatef((float) ox
* stepXmnt
, 0, (float) oy
* stepYmnt
);
271 for (h
= 0, k
= -(lenghtYmnt
* stepYmnt
) / 2; h
< lenghtYmnt
;
272 k
+= stepYmnt
, h
++) {
273 if (!clipstrip(k
, &start
, &end
))
276 glBegin(GL_TRIANGLE_STRIP
); /* I hope that the optimizer will be able to improve this code */
277 for (i
= (int) (lenghtXmnt
/ 2 + start
/ stepXmnt
), j
= start
; j
<= end
;
278 j
+= stepXmnt
, i
++) {
279 idx
= (i
* TSCALE
+ h
* 256 * TSCALE
+ GlobalMnt
) & 65535;
280 glColor3fv(terraincolor
[idx
]);
281 glTexCoord2f((ox
+ i
) / 8.0, (oy
+ h
) / 8.0);
282 glVertex3f(j
, terrain
[idx
], k
);
285 (i
* TSCALE
+ h
* 256 * TSCALE
+ 256 * TSCALE
+
287 glColor3fv(terraincolor
[idx
]);
288 glTexCoord2f((ox
+ i
) / 8.0, (oy
+ h
+ 1) / 8.0);
289 glVertex3f(j
, terrain
[idx
], k
+ stepYmnt
);
294 glDisable(GL_CULL_FACE
);
295 glDisable(GL_TEXTURE_2D
);
298 glColor4f(0.1, 0.7, 1.0, 0.4);
299 glVertex3f(-(lenghtXmnt
* stepXmnt
) / 2.0, heightMnt
* 0.6,
300 -(lenghtYmnt
* stepYmnt
) / 2.0);
301 glVertex3f(-(lenghtXmnt
* stepXmnt
) / 2.0, heightMnt
* 0.6,
302 (lenghtYmnt
* stepYmnt
) / 2.0);
303 glVertex3f((lenghtXmnt
* stepXmnt
) / 2.0, heightMnt
* 0.6,
304 (lenghtYmnt
* stepYmnt
) / 2.0);
305 glVertex3f((lenghtXmnt
* stepXmnt
) / 2.0, heightMnt
* 0.6,
306 -(lenghtYmnt
* stepYmnt
) / 2.0);
310 glEnable(GL_CULL_FACE
);
311 glEnable(GL_TEXTURE_2D
);
321 static UINT max
[2] = { 0, 0 };
322 static UINT min
[2] = { 0xffffffff, 0xffffffff }, center
[2];
326 res
= joyGetPos(JOYSTICKID1
, &joy
);
328 if (res
== JOYERR_NOERROR
) {
331 if (max
[0] < joy
.wXpos
)
333 if (min
[0] > joy
.wXpos
)
335 center
[0] = (max
[0] + min
[0]) / 2;
337 if (max
[1] < joy
.wYpos
)
339 if (min
[1] > joy
.wYpos
)
341 center
[1] = (max
[1] + min
[1]) / 2;
344 if (fabs(center
[0] - (float) joy
.wXpos
) > 0.1 * (max
[0] - min
[0]))
346 2.5 * (center
[0] - (float) joy
.wXpos
) / (max
[0] - min
[0]);
347 if (fabs(center
[1] - (float) joy
.wYpos
) > 0.1 * (max
[1] - min
[1]))
348 beta
+= 2.5 * (center
[1] - (float) joy
.wYpos
) / (max
[1] - min
[1]);
350 if (joy
.wButtons
& JOY_BUTTON1
)
352 if (joy
.wButtons
& JOY_BUTTON2
)
364 static char frbuf
[80] = "";
368 glShadeModel(GL_SMOOTH
);
369 glEnable(GL_DEPTH_TEST
);
372 glEnable(GL_TEXTURE_2D
);
374 glDisable(GL_TEXTURE_2D
);
381 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
386 gluLookAt(obs
[0], obs
[1], obs
[2],
387 obs
[0] + dir
[0], obs
[1] + dir
[1], obs
[2] + dir
[2],
393 glDisable(GL_TEXTURE_2D
);
394 glDisable(GL_DEPTH_TEST
);
396 glShadeModel(GL_FLAT
);
398 glMatrixMode(GL_PROJECTION
);
400 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
401 glMatrixMode(GL_MODELVIEW
);
404 glColor3f(1.0, 0.0, 0.0);
405 glRasterPos2i(10, 10);
406 printstring(GLUT_BITMAP_HELVETICA_18
, frbuf
);
407 glRasterPos2i(350, 470);
408 printstring(GLUT_BITMAP_HELVETICA_10
,
409 "Terrain V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
410 glRasterPos2i(434, 457);
411 printstring(GLUT_BITMAP_HELVETICA_10
,
412 "Based on a Mickael's demo (Skizo@Hol.Fr)");
417 reshape(scrwidth
, scrheight
);
423 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
424 if (t
- T0
>= 2000) {
425 GLfloat seconds
= (t
- T0
) / 1000.0;
426 GLfloat fps
= Frames
/ seconds
;
427 sprintf(frbuf
, "Frame rate: %f", fps
);
435 key(unsigned char k
, int x
, int y
)
449 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
453 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
458 joyactive
= (!joyactive
);
471 glDisable(GL_CULL_FACE
);
475 glEnable(GL_CULL_FACE
);
481 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
482 fullscreen
= (!fullscreen
);
489 special(int k
, int x
, int y
)
508 calccolor(GLfloat height
, GLfloat c
[3])
510 GLfloat color
[4][3] = {
518 height
= height
* (1.0 / 255.0);
527 if ((height
< 0.9) && (height
>= 0.7)) {
528 fact
= (height
- 0.7) * 5.0;
529 c
[0] = fact
* color
[0][0] + (1.0 - fact
) * color
[1][0];
530 c
[1] = fact
* color
[0][1] + (1.0 - fact
) * color
[1][1];
531 c
[2] = fact
* color
[0][2] + (1.0 - fact
) * color
[1][2];
535 if ((height
< 0.7) && (height
>= 0.6)) {
536 fact
= (height
- 0.6) * 10.0;
537 c
[0] = fact
* color
[1][0] + (1.0 - fact
) * color
[2][0];
538 c
[1] = fact
* color
[1][1] + (1.0 - fact
) * color
[2][1];
539 c
[2] = fact
* color
[1][2] + (1.0 - fact
) * color
[2][2];
543 if ((height
< 0.6) && (height
>= 0.5)) {
544 fact
= (height
- 0.5) * 10.0;
545 c
[0] = fact
* color
[2][0] + (1.0 - fact
) * color
[3][0];
546 c
[1] = fact
* color
[2][1] + (1.0 - fact
) * color
[3][1];
547 c
[2] = fact
* color
[2][2] + (1.0 - fact
) * color
[3][2];
559 GLubyte bufferter
[256 * 256], terrainpic
[256 * 256];
565 if ((FilePic
= fopen("terrain.dat", "r")) == NULL
) {
566 fprintf(stderr
, "Error loading terrain.dat\n");
569 result
= fread(bufferter
, 256 * 256, 1, FilePic
);
573 for (i
= 0; i
< (256 * 256); i
++) {
574 terrain
[i
] = (bufferter
[i
] * (heightMnt
/ 255.0f
));
575 calccolor((GLfloat
) bufferter
[i
], terraincolor
[i
]);
576 tmp
= (((int) bufferter
[i
]) + 96);
577 terrainpic
[i
] = (tmp
> 255) ? 255 : tmp
;
580 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
581 if ((gluerr
= gluBuild2DMipmaps(GL_TEXTURE_2D
, 1, 256, 256, GL_LUMINANCE
,
583 (GLvoid
*) (&terrainpic
[0])))) {
584 fprintf(stderr
, "GLULib%s\n", (char *) gluErrorString(gluerr
));
588 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
589 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
591 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
592 GL_LINEAR_MIPMAP_LINEAR
);
593 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
595 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
596 glEnable(GL_TEXTURE_2D
);
602 float fogcolor
[4] = { 0.6, 0.7, 0.7, 1.0 };
604 glClearColor(fogcolor
[0], fogcolor
[1], fogcolor
[2], fogcolor
[3]);
606 glDepthFunc(GL_LEQUAL
);
607 glShadeModel(GL_SMOOTH
);
608 glEnable(GL_DEPTH_TEST
);
609 glEnable(GL_CULL_FACE
);
612 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
615 glFogi(GL_FOG_MODE
, GL_EXP2
);
616 glFogfv(GL_FOG_COLOR
, fogcolor
);
617 glFogf(GL_FOG_DENSITY
, 0.0007);
619 glHint(GL_FOG_HINT
, GL_NICEST
);
622 reshape(scrwidth
, scrheight
);
627 main(int ac
, char **av
)
629 glutInitWindowSize(WIDTH
, HEIGHT
);
632 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
634 if (!(win
= glutCreateWindow("Terrain"))) {
635 fprintf(stderr
, "Error, couldn't open window\n");
645 glDisable(GL_TEXTURE_2D
);
649 glutReshapeFunc(reshape
);
650 glutDisplayFunc(drawscene
);
651 glutKeyboardFunc(key
);
652 glutSpecialFunc(special
);
653 glutIdleFunc(drawscene
);