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);