132001f49Smrg/*
232001f49Smrg * This program is under the GNU GPL.
332001f49Smrg * Use at your own risk.
432001f49Smrg *
532001f49Smrg * written by David Bucciarelli (tech.hmw@plus.it)
632001f49Smrg *            Humanware s.r.l.
732001f49Smrg *
832001f49Smrg * based on a Mikael SkiZoWalker's (MoDEL) / France (Skizo@Hol.Fr) demo
932001f49Smrg */
1032001f49Smrg
1132001f49Smrg#include <assert.h>
1232001f49Smrg#include <stdio.h>
1332001f49Smrg#include <math.h>
1432001f49Smrg#include <stdlib.h>
1532001f49Smrg#include <string.h>
1632001f49Smrg#include <time.h>
1732001f49Smrg
1832001f49Smrg#ifdef WIN32
1932001f49Smrg#include <windows.h>
2032001f49Smrg#endif
2132001f49Smrg
2232001f49Smrg#include "glut_wrap.h"
2332001f49Smrg
2432001f49Smrg#ifdef XMESA
2532001f49Smrg#include "GL/xmesa.h"
2632001f49Smrgstatic int fullscreen = 1;
2732001f49Smrg#endif
2832001f49Smrg
2932001f49Smrg#ifndef M_PI
3032001f49Smrg#define M_PI 3.14159265
3132001f49Smrg#endif
3232001f49Smrg
3332001f49Smrg#define heightMnt	450
3432001f49Smrg#define	lenghtXmnt	62
3532001f49Smrg#define lenghtYmnt	62
3632001f49Smrg
3732001f49Smrg#define stepXmnt     96.0
3832001f49Smrg#define stepYmnt     96.0
3932001f49Smrg
4032001f49Smrg#define WIDTH 640
4132001f49Smrg#define HEIGHT 480
4232001f49Smrg
4332001f49Smrgstatic GLint T0 = 0;
4432001f49Smrgstatic GLint Frames = 0;
4532001f49Smrg
4632001f49Smrg#define TSCALE 4
4732001f49Smrg
4832001f49Smrg#define FOV 85
4932001f49Smrg
5032001f49Smrgstatic GLfloat terrain[256 * 256];
5132001f49Smrgstatic GLfloat terraincolor[256 * 256][3];
5232001f49Smrg
5332001f49Smrgstatic int win = 0;
5432001f49Smrg
5532001f49Smrgstatic int fog = 1;
5632001f49Smrgstatic int bfcull = 1;
5732001f49Smrgstatic int usetex = 1;
5832001f49Smrgstatic int poutline = 0;
5932001f49Smrgstatic int help = 1;
6032001f49Smrgstatic int joyavailable = 0;
6132001f49Smrgstatic int joyactive = 0;
6232001f49Smrgstatic float ModZMnt;
6332001f49Smrgstatic long GlobalMnt = 0;
6432001f49Smrg
6532001f49Smrgstatic int scrwidth = WIDTH;
6632001f49Smrgstatic int scrheight = HEIGHT;
6732001f49Smrg
6832001f49Smrg#define OBSSTARTX 992.0
6932001f49Smrg#define OBSSTARTY 103.0
7032001f49Smrg
7132001f49Smrgstatic float obs[3] = { OBSSTARTX, heightMnt * 1.3, OBSSTARTY };
7232001f49Smrgstatic float dir[3], v1[2], v2[2];
7332001f49Smrgstatic float v = 900.0;
7432001f49Smrgstatic float alpha = 75.0;
7532001f49Smrgstatic float beta = 90.0;
7632001f49Smrg
7732001f49Smrgstatic void
7832001f49Smrgcalcposobs(void)
7932001f49Smrg{
8032001f49Smrg   float alpha1, alpha2;
8132001f49Smrg   static double t0 = -1.;
8232001f49Smrg   double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
8332001f49Smrg   if (t0 < 0.0)
8432001f49Smrg      t0 = t;
8532001f49Smrg   dt = t - t0;
8632001f49Smrg   t0 = t;
8732001f49Smrg
8832001f49Smrg   dir[0] = sin(alpha * M_PI / 180.0);
8932001f49Smrg   dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
9032001f49Smrg   dir[1] = cos(beta * M_PI / 180.0);
9132001f49Smrg
9232001f49Smrg   if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
9332001f49Smrg      dir[0] = 0;
9432001f49Smrg   if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
9532001f49Smrg      dir[1] = 0;
9632001f49Smrg   if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
9732001f49Smrg      dir[2] = 0;
9832001f49Smrg
9932001f49Smrg   alpha1 = alpha + FOV / 2.0;
10032001f49Smrg   v1[0] = sin(alpha1 * M_PI / 180.0);
10132001f49Smrg   v1[1] = cos(alpha1 * M_PI / 180.0);
10232001f49Smrg
10332001f49Smrg   alpha2 = alpha - FOV / 2.0;
10432001f49Smrg   v2[0] = sin(alpha2 * M_PI / 180.0);
10532001f49Smrg   v2[1] = cos(alpha2 * M_PI / 180.0);
10632001f49Smrg
10732001f49Smrg   obs[0] += v * dir[0] * dt;
10832001f49Smrg   obs[1] += v * dir[1] * dt;
10932001f49Smrg   obs[2] += v * dir[2] * dt;
11032001f49Smrg
11132001f49Smrg   if (obs[1] < 0.0)
11232001f49Smrg      obs[1] = 0.0;
11332001f49Smrg}
11432001f49Smrg
11532001f49Smrgstatic void
11632001f49Smrgreshape(int width, int height)
11732001f49Smrg{
11832001f49Smrg   scrwidth = width;
11932001f49Smrg   scrheight = height;
12032001f49Smrg   glViewport(0, 0, (GLint) width, (GLint) height);
12132001f49Smrg   glMatrixMode(GL_PROJECTION);
12232001f49Smrg   glLoadIdentity();
12332001f49Smrg   gluPerspective(50.0, ((GLfloat) width / (GLfloat) height),
12432001f49Smrg		  lenghtXmnt * stepYmnt * 0.01, lenghtXmnt * stepYmnt * 0.7);
12532001f49Smrg   glMatrixMode(GL_MODELVIEW);
12632001f49Smrg   glLoadIdentity();
12732001f49Smrg}
12832001f49Smrg
12932001f49Smrgstatic int
13032001f49Smrgclipstrip(float y, float *start, float *end)
13132001f49Smrg{
13232001f49Smrg   float x1, x2, t1, t2, tmp;
13332001f49Smrg
13432001f49Smrg   if (v1[1] == 0.0) {
13532001f49Smrg      t1 = 0.0;
13632001f49Smrg      x1 = -HUGE_VAL;
13732001f49Smrg   }
13832001f49Smrg   else {
13932001f49Smrg      t1 = y / v1[1];
14032001f49Smrg      x1 = t1 * v1[0];
14132001f49Smrg   }
14232001f49Smrg
14332001f49Smrg   if (v2[1] == 0.0) {
14432001f49Smrg      t2 = 0.0;
14532001f49Smrg      x2 = HUGE_VAL;
14632001f49Smrg   }
14732001f49Smrg   else {
14832001f49Smrg      t2 = y / v2[1];
14932001f49Smrg      x2 = t2 * v2[0];
15032001f49Smrg   }
15132001f49Smrg
15232001f49Smrg   if (((x1 < -(lenghtXmnt * stepXmnt) / 2) && (t2 <= 0.0)) ||
15332001f49Smrg       ((t1 <= 0.0) && (x2 > (lenghtXmnt * stepXmnt) / 2)) ||
15432001f49Smrg       ((t1 < 0.0) && (t2 < 0.0)))
15532001f49Smrg      return 0;
15632001f49Smrg
15732001f49Smrg   if ((t1 == 0.0) && (t2 == 0.0)) {
15832001f49Smrg      if ((v1[0] < 0.0) && (v1[1] > 0.0) && (v2[0] < 0.0) && (v2[1] < 0.0)) {
15932001f49Smrg	 *start = -(lenghtXmnt * stepXmnt) / 2;
16032001f49Smrg	 *end = stepXmnt;
16132001f49Smrg	 return 1;
16232001f49Smrg      }
16332001f49Smrg      else {
16432001f49Smrg	 if ((v1[0] > 0.0) && (v1[1] < 0.0) && (v2[0] > 0.0) && (v2[1] > 0.0)) {
16532001f49Smrg	    *start = -stepXmnt;
16632001f49Smrg	    *end = (lenghtXmnt * stepXmnt) / 2;
16732001f49Smrg	    return 1;
16832001f49Smrg	 }
16932001f49Smrg	 else
17032001f49Smrg	    return 0;
17132001f49Smrg      }
17232001f49Smrg   }
17332001f49Smrg   else {
17432001f49Smrg      if (t2 < 0.0) {
17532001f49Smrg	 if (x1 < 0.0)
17632001f49Smrg	    x2 = -(lenghtXmnt * stepXmnt) / 2;
17732001f49Smrg	 else
17832001f49Smrg	    x2 = (lenghtXmnt * stepXmnt) / 2;
17932001f49Smrg      }
18032001f49Smrg
18132001f49Smrg      if (t1 < 0.0) {
18232001f49Smrg	 if (x2 < 0.0)
18332001f49Smrg	    x1 = -(lenghtXmnt * stepXmnt) / 2;
18432001f49Smrg	 else
18532001f49Smrg	    x1 = (lenghtXmnt * stepXmnt) / 2;
18632001f49Smrg      }
18732001f49Smrg   }
18832001f49Smrg
18932001f49Smrg   if (x1 > x2) {
19032001f49Smrg      tmp = x1;
19132001f49Smrg      x1 = x2;
19232001f49Smrg      x2 = tmp;
19332001f49Smrg   }
19432001f49Smrg
19532001f49Smrg   x1 -= stepXmnt;
19632001f49Smrg   if (x1 < -(lenghtXmnt * stepXmnt) / 2)
19732001f49Smrg      x1 = -(lenghtXmnt * stepXmnt) / 2;
19832001f49Smrg
19932001f49Smrg   x2 += stepXmnt;
20032001f49Smrg   if (x2 > (lenghtXmnt * stepXmnt) / 2)
20132001f49Smrg      x2 = (lenghtXmnt * stepXmnt) / 2;
20232001f49Smrg
20332001f49Smrg   *start = ((int) (x1 / stepXmnt)) * stepXmnt;
20432001f49Smrg   *end = ((int) (x2 / stepXmnt)) * stepXmnt;
20532001f49Smrg
20632001f49Smrg   return 1;
20732001f49Smrg}
20832001f49Smrg
20932001f49Smrgstatic void
21032001f49Smrgprintstring(void *font, char *string)
21132001f49Smrg{
21232001f49Smrg   int len, i;
21332001f49Smrg
21432001f49Smrg   len = (int) strlen(string);
21532001f49Smrg   for (i = 0; i < len; i++)
21632001f49Smrg      glutBitmapCharacter(font, string[i]);
21732001f49Smrg}
21832001f49Smrg
21932001f49Smrgstatic void
22032001f49Smrgprinthelp(void)
22132001f49Smrg{
22232001f49Smrg   glEnable(GL_BLEND);
22332001f49Smrg   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
22432001f49Smrg   glColor4f(0.0, 0.0, 0.0, 0.5);
22532001f49Smrg   glRecti(40, 40, 600, 440);
22632001f49Smrg   glDisable(GL_BLEND);
22732001f49Smrg
22832001f49Smrg   glColor3f(1.0, 0.0, 0.0);
22932001f49Smrg   glRasterPos2i(300, 420);
23032001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
23132001f49Smrg
23232001f49Smrg   glRasterPos2i(60, 390);
23332001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
23432001f49Smrg   glRasterPos2i(60, 360);
23532001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Toggle Textures");
23632001f49Smrg   glRasterPos2i(60, 330);
23732001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
23832001f49Smrg   glRasterPos2i(60, 300);
23932001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "p - Wire frame");
24032001f49Smrg   glRasterPos2i(60, 270);
24132001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Toggle Back face culling");
24232001f49Smrg   glRasterPos2i(60, 240);
24332001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
24432001f49Smrg   glRasterPos2i(60, 210);
24532001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
24632001f49Smrg   glRasterPos2i(60, 180);
24732001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
24832001f49Smrg
24932001f49Smrg   glRasterPos2i(60, 150);
25032001f49Smrg   if (joyavailable)
25132001f49Smrg      printstring(GLUT_BITMAP_TIMES_ROMAN_24,
25232001f49Smrg		  "j - Toggle jostick control (Joystick control available)");
25332001f49Smrg   else
25432001f49Smrg      printstring(GLUT_BITMAP_TIMES_ROMAN_24,
25532001f49Smrg		  "(No Joystick control available)");
25632001f49Smrg}
25732001f49Smrg
25832001f49Smrgstatic void
25932001f49Smrgdrawterrain(void)
26032001f49Smrg{
26132001f49Smrg   int h, i, idx, ox, oy;
26232001f49Smrg   float j, k, start, end;
26332001f49Smrg
26432001f49Smrg   ox = (int) (obs[0] / stepXmnt);
26532001f49Smrg   oy = (int) (obs[2] / stepYmnt);
26632001f49Smrg   GlobalMnt = ((ox * TSCALE) & 255) + ((oy * TSCALE) & 255) * 256;
26732001f49Smrg
26832001f49Smrg   glPushMatrix();
26932001f49Smrg   glTranslatef((float) ox * stepXmnt, 0, (float) oy * stepYmnt);
27032001f49Smrg
27132001f49Smrg   for (h = 0, k = -(lenghtYmnt * stepYmnt) / 2; h < lenghtYmnt;
27232001f49Smrg	k += stepYmnt, h++) {
27332001f49Smrg      if (!clipstrip(k, &start, &end))
27432001f49Smrg	 continue;
27532001f49Smrg
27632001f49Smrg      glBegin(GL_TRIANGLE_STRIP);	/* I hope that the optimizer will be able to improve this code */
27732001f49Smrg      for (i = (int) (lenghtXmnt / 2 + start / stepXmnt), j = start; j <= end;
27832001f49Smrg	   j += stepXmnt, i++) {
27932001f49Smrg	 idx = (i * TSCALE + h * 256 * TSCALE + GlobalMnt) & 65535;
28032001f49Smrg	 glColor3fv(terraincolor[idx]);
28132001f49Smrg	 glTexCoord2f((ox + i) / 8.0, (oy + h) / 8.0);
28232001f49Smrg	 glVertex3f(j, terrain[idx], k);
28332001f49Smrg
28432001f49Smrg	 idx =
28532001f49Smrg	    (i * TSCALE + h * 256 * TSCALE + 256 * TSCALE +
28632001f49Smrg	     GlobalMnt) & 65535;
28732001f49Smrg	 glColor3fv(terraincolor[idx]);
28832001f49Smrg	 glTexCoord2f((ox + i) / 8.0, (oy + h + 1) / 8.0);
28932001f49Smrg	 glVertex3f(j, terrain[idx], k + stepYmnt);
29032001f49Smrg      }
29132001f49Smrg      glEnd();
29232001f49Smrg   }
29332001f49Smrg
29432001f49Smrg   glDisable(GL_CULL_FACE);
29532001f49Smrg   glDisable(GL_TEXTURE_2D);
29632001f49Smrg   glEnable(GL_BLEND);
29732001f49Smrg   glBegin(GL_QUADS);
29832001f49Smrg   glColor4f(0.1, 0.7, 1.0, 0.4);
29932001f49Smrg   glVertex3f(-(lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
30032001f49Smrg	      -(lenghtYmnt * stepYmnt) / 2.0);
30132001f49Smrg   glVertex3f(-(lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
30232001f49Smrg	      (lenghtYmnt * stepYmnt) / 2.0);
30332001f49Smrg   glVertex3f((lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
30432001f49Smrg	      (lenghtYmnt * stepYmnt) / 2.0);
30532001f49Smrg   glVertex3f((lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
30632001f49Smrg	      -(lenghtYmnt * stepYmnt) / 2.0);
30732001f49Smrg   glEnd();
30832001f49Smrg   glDisable(GL_BLEND);
30932001f49Smrg   if (bfcull)
31032001f49Smrg      glEnable(GL_CULL_FACE);
31132001f49Smrg   glEnable(GL_TEXTURE_2D);
31232001f49Smrg
31332001f49Smrg   glPopMatrix();
31432001f49Smrg
31532001f49Smrg}
31632001f49Smrg
31732001f49Smrgstatic void
31832001f49Smrgdojoy(void)
31932001f49Smrg{
32032001f49Smrg#ifdef WIN32
32132001f49Smrg   static UINT max[2] = { 0, 0 };
32232001f49Smrg   static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
32332001f49Smrg   MMRESULT res;
32432001f49Smrg   JOYINFO joy;
32532001f49Smrg
32632001f49Smrg   res = joyGetPos(JOYSTICKID1, &joy);
32732001f49Smrg
32832001f49Smrg   if (res == JOYERR_NOERROR) {
32932001f49Smrg      joyavailable = 1;
33032001f49Smrg
33132001f49Smrg      if (max[0] < joy.wXpos)
33232001f49Smrg	 max[0] = joy.wXpos;
33332001f49Smrg      if (min[0] > joy.wXpos)
33432001f49Smrg	 min[0] = joy.wXpos;
33532001f49Smrg      center[0] = (max[0] + min[0]) / 2;
33632001f49Smrg
33732001f49Smrg      if (max[1] < joy.wYpos)
33832001f49Smrg	 max[1] = joy.wYpos;
33932001f49Smrg      if (min[1] > joy.wYpos)
34032001f49Smrg	 min[1] = joy.wYpos;
34132001f49Smrg      center[1] = (max[1] + min[1]) / 2;
34232001f49Smrg
34332001f49Smrg      if (joyactive) {
34432001f49Smrg	 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
34532001f49Smrg	    alpha +=
34632001f49Smrg	       2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
34732001f49Smrg	 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
34832001f49Smrg	    beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
34932001f49Smrg
35032001f49Smrg	 if (joy.wButtons & JOY_BUTTON1)
35132001f49Smrg	    v += 0.5;
35232001f49Smrg	 if (joy.wButtons & JOY_BUTTON2)
35332001f49Smrg	    v -= 0.5;
35432001f49Smrg      }
35532001f49Smrg   }
35632001f49Smrg   else
35732001f49Smrg      joyavailable = 0;
35832001f49Smrg#endif
35932001f49Smrg}
36032001f49Smrg
36132001f49Smrgstatic void
36232001f49Smrgdrawscene(void)
36332001f49Smrg{
36432001f49Smrg   static char frbuf[80] = "";
36532001f49Smrg
36632001f49Smrg   dojoy();
36732001f49Smrg
36832001f49Smrg   glShadeModel(GL_SMOOTH);
36932001f49Smrg   glEnable(GL_DEPTH_TEST);
37032001f49Smrg
37132001f49Smrg   if (usetex)
37232001f49Smrg      glEnable(GL_TEXTURE_2D);
37332001f49Smrg   else
37432001f49Smrg      glDisable(GL_TEXTURE_2D);
37532001f49Smrg
37632001f49Smrg   if (fog)
37732001f49Smrg      glEnable(GL_FOG);
37832001f49Smrg   else
37932001f49Smrg      glDisable(GL_FOG);
38032001f49Smrg
38132001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
38232001f49Smrg
38332001f49Smrg   glPushMatrix();
38432001f49Smrg
38532001f49Smrg   calcposobs();
38632001f49Smrg   gluLookAt(obs[0], obs[1], obs[2],
38732001f49Smrg	     obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
38832001f49Smrg	     0.0, 1.0, 0.0);
38932001f49Smrg
39032001f49Smrg   drawterrain();
39132001f49Smrg   glPopMatrix();
39232001f49Smrg
39332001f49Smrg   glDisable(GL_TEXTURE_2D);
39432001f49Smrg   glDisable(GL_DEPTH_TEST);
39532001f49Smrg   glDisable(GL_FOG);
39632001f49Smrg   glShadeModel(GL_FLAT);
39732001f49Smrg
39832001f49Smrg   glMatrixMode(GL_PROJECTION);
39932001f49Smrg   glLoadIdentity();
40032001f49Smrg   glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
40132001f49Smrg   glMatrixMode(GL_MODELVIEW);
40232001f49Smrg   glLoadIdentity();
40332001f49Smrg
40432001f49Smrg   glColor3f(1.0, 0.0, 0.0);
40532001f49Smrg   glRasterPos2i(10, 10);
40632001f49Smrg   printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
40732001f49Smrg   glRasterPos2i(350, 470);
40832001f49Smrg   printstring(GLUT_BITMAP_HELVETICA_10,
40932001f49Smrg	       "Terrain V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
41032001f49Smrg   glRasterPos2i(434, 457);
41132001f49Smrg   printstring(GLUT_BITMAP_HELVETICA_10,
41232001f49Smrg	       "Based on a Mickael's demo (Skizo@Hol.Fr)");
41332001f49Smrg
41432001f49Smrg   if (help)
41532001f49Smrg      printhelp();
41632001f49Smrg
41732001f49Smrg   reshape(scrwidth, scrheight);
41832001f49Smrg
41932001f49Smrg   glutSwapBuffers();
42032001f49Smrg
42132001f49Smrg   Frames++;
42232001f49Smrg   {
42332001f49Smrg      GLint t = glutGet(GLUT_ELAPSED_TIME);
42432001f49Smrg      if (t - T0 >= 2000) {
42532001f49Smrg         GLfloat seconds = (t - T0) / 1000.0;
42632001f49Smrg         GLfloat fps = Frames / seconds;
42732001f49Smrg         sprintf(frbuf, "Frame rate: %f", fps);
42832001f49Smrg         printf("%s\n", frbuf);
4297ec3b29aSmrg         fflush(stdout);
43032001f49Smrg         T0 = t;
43132001f49Smrg         Frames = 0;
43232001f49Smrg      }
43332001f49Smrg   }
43432001f49Smrg}
43532001f49Smrg
43632001f49Smrgstatic void
43732001f49Smrgkey(unsigned char k, int x, int y)
43832001f49Smrg{
43932001f49Smrg   switch (k) {
44032001f49Smrg   case 27:
44132001f49Smrg      exit(0);
44232001f49Smrg      break;
44332001f49Smrg   case 'a':
44432001f49Smrg      v += 50.;
44532001f49Smrg      break;
44632001f49Smrg   case 'z':
44732001f49Smrg      v -= 50.;
44832001f49Smrg      break;
44932001f49Smrg   case 'p':
45032001f49Smrg      if (poutline) {
45132001f49Smrg	 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
45232001f49Smrg	 poutline = 0;
45332001f49Smrg      }
45432001f49Smrg      else {
45532001f49Smrg	 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
45632001f49Smrg	 poutline = 1;
45732001f49Smrg      }
45832001f49Smrg      break;
45932001f49Smrg   case 'j':
46032001f49Smrg      joyactive = (!joyactive);
46132001f49Smrg      break;
46232001f49Smrg   case 'h':
46332001f49Smrg      help = (!help);
46432001f49Smrg      break;
46532001f49Smrg   case 'f':
46632001f49Smrg      fog = (!fog);
46732001f49Smrg      break;
46832001f49Smrg   case 't':
46932001f49Smrg      usetex = (!usetex);
47032001f49Smrg      break;
47132001f49Smrg   case 'b':
47232001f49Smrg      if (bfcull) {
47332001f49Smrg	 glDisable(GL_CULL_FACE);
47432001f49Smrg	 bfcull = 0;
47532001f49Smrg      }
47632001f49Smrg      else {
47732001f49Smrg	 glEnable(GL_CULL_FACE);
47832001f49Smrg	 bfcull = 1;
47932001f49Smrg      }
48032001f49Smrg      break;
48132001f49Smrg#ifdef XMESA
48232001f49Smrg   case ' ':
48332001f49Smrg      XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
48432001f49Smrg      fullscreen = (!fullscreen);
48532001f49Smrg      break;
48632001f49Smrg#endif
48732001f49Smrg   }
48832001f49Smrg}
48932001f49Smrg
49032001f49Smrgstatic void
49132001f49Smrgspecial(int k, int x, int y)
49232001f49Smrg{
49332001f49Smrg   switch (k) {
49432001f49Smrg   case GLUT_KEY_LEFT:
49532001f49Smrg      alpha += 2.0;
49632001f49Smrg      break;
49732001f49Smrg   case GLUT_KEY_RIGHT:
49832001f49Smrg      alpha -= 2.0;
49932001f49Smrg      break;
50032001f49Smrg   case GLUT_KEY_DOWN:
50132001f49Smrg      beta -= 2.0;
50232001f49Smrg      break;
50332001f49Smrg   case GLUT_KEY_UP:
50432001f49Smrg      beta += 2.0;
50532001f49Smrg      break;
50632001f49Smrg   }
50732001f49Smrg}
50832001f49Smrg
50932001f49Smrgstatic void
51032001f49Smrgcalccolor(GLfloat height, GLfloat c[3])
51132001f49Smrg{
51232001f49Smrg   GLfloat color[4][3] = {
51332001f49Smrg      {1.0, 1.0, 1.0},
51432001f49Smrg      {0.0, 0.8, 0.0},
51532001f49Smrg      {1.0, 1.0, 0.3},
51632001f49Smrg      {0.0, 0.0, 0.8}
51732001f49Smrg   };
51832001f49Smrg   GLfloat fact;
51932001f49Smrg
52032001f49Smrg   height = height * (1.0 / 255.0);
52132001f49Smrg
52232001f49Smrg   if (height >= 0.9) {
52332001f49Smrg      c[0] = color[0][0];
52432001f49Smrg      c[1] = color[0][1];
52532001f49Smrg      c[2] = color[0][2];
52632001f49Smrg      return;
52732001f49Smrg   }
52832001f49Smrg
52932001f49Smrg   if ((height < 0.9) && (height >= 0.7)) {
53032001f49Smrg      fact = (height - 0.7) * 5.0;
53132001f49Smrg      c[0] = fact * color[0][0] + (1.0 - fact) * color[1][0];
53232001f49Smrg      c[1] = fact * color[0][1] + (1.0 - fact) * color[1][1];
53332001f49Smrg      c[2] = fact * color[0][2] + (1.0 - fact) * color[1][2];
53432001f49Smrg      return;
53532001f49Smrg   }
53632001f49Smrg
53732001f49Smrg   if ((height < 0.7) && (height >= 0.6)) {
53832001f49Smrg      fact = (height - 0.6) * 10.0;
53932001f49Smrg      c[0] = fact * color[1][0] + (1.0 - fact) * color[2][0];
54032001f49Smrg      c[1] = fact * color[1][1] + (1.0 - fact) * color[2][1];
54132001f49Smrg      c[2] = fact * color[1][2] + (1.0 - fact) * color[2][2];
54232001f49Smrg      return;
54332001f49Smrg   }
54432001f49Smrg
54532001f49Smrg   if ((height < 0.6) && (height >= 0.5)) {
54632001f49Smrg      fact = (height - 0.5) * 10.0;
54732001f49Smrg      c[0] = fact * color[2][0] + (1.0 - fact) * color[3][0];
54832001f49Smrg      c[1] = fact * color[2][1] + (1.0 - fact) * color[3][1];
54932001f49Smrg      c[2] = fact * color[2][2] + (1.0 - fact) * color[3][2];
55032001f49Smrg      return;
55132001f49Smrg   }
55232001f49Smrg
55332001f49Smrg   c[0] = color[3][0];
55432001f49Smrg   c[1] = color[3][1];
55532001f49Smrg   c[2] = color[3][2];
55632001f49Smrg}
55732001f49Smrg
55832001f49Smrgstatic void
55932001f49Smrgloadpic(void)
56032001f49Smrg{
56132001f49Smrg   GLubyte bufferter[256 * 256], terrainpic[256 * 256];
56232001f49Smrg   FILE *FilePic;
56332001f49Smrg   int i, tmp;
56432001f49Smrg   GLenum gluerr;
56532001f49Smrg   size_t result;
56632001f49Smrg
56732001f49Smrg   if ((FilePic = fopen(DEMOS_DATA_DIR "terrain.dat", "r")) == NULL) {
56832001f49Smrg      fprintf(stderr, "Error loading terrain.dat\n");
56932001f49Smrg      exit(-1);
57032001f49Smrg   }
57132001f49Smrg   result = fread(bufferter, 256 * 256, 1, FilePic);
57232001f49Smrg   assert(result == 1);
57332001f49Smrg   fclose(FilePic);
57432001f49Smrg
57532001f49Smrg   for (i = 0; i < (256 * 256); i++) {
57632001f49Smrg      terrain[i] = (bufferter[i] * (heightMnt / 255.0f));
57732001f49Smrg      calccolor((GLfloat) bufferter[i], terraincolor[i]);
57832001f49Smrg      tmp = (((int) bufferter[i]) + 96);
57932001f49Smrg      terrainpic[i] = (tmp > 255) ? 255 : tmp;
58032001f49Smrg   }
58132001f49Smrg
58232001f49Smrg   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
58332001f49Smrg   if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 1, 256, 256, GL_LUMINANCE,
58432001f49Smrg				   GL_UNSIGNED_BYTE,
58532001f49Smrg				   (GLvoid *) (&terrainpic[0])))) {
58632001f49Smrg      fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr));
58732001f49Smrg      exit(-1);
58832001f49Smrg   }
58932001f49Smrg
59032001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
59132001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
59232001f49Smrg
59332001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
59432001f49Smrg		   GL_LINEAR_MIPMAP_LINEAR);
59532001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
59632001f49Smrg
59732001f49Smrg   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
59832001f49Smrg   glEnable(GL_TEXTURE_2D);
59932001f49Smrg}
60032001f49Smrg
60132001f49Smrgstatic void
60232001f49Smrginit(void)
60332001f49Smrg{
60432001f49Smrg   float fogcolor[4] = { 0.6, 0.7, 0.7, 1.0 };
60532001f49Smrg
60632001f49Smrg   glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
60732001f49Smrg   glClearDepth(1.0);
60832001f49Smrg   glDepthFunc(GL_LEQUAL);
60932001f49Smrg   glShadeModel(GL_SMOOTH);
61032001f49Smrg   glEnable(GL_DEPTH_TEST);
61132001f49Smrg   glEnable(GL_CULL_FACE);
61232001f49Smrg
61332001f49Smrg   glDisable(GL_BLEND);
61432001f49Smrg   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
61532001f49Smrg
61632001f49Smrg   glEnable(GL_FOG);
61732001f49Smrg   glFogi(GL_FOG_MODE, GL_EXP2);
61832001f49Smrg   glFogfv(GL_FOG_COLOR, fogcolor);
61932001f49Smrg   glFogf(GL_FOG_DENSITY, 0.0007);
62032001f49Smrg#ifdef FX
62132001f49Smrg   glHint(GL_FOG_HINT, GL_NICEST);
62232001f49Smrg#endif
62332001f49Smrg
62432001f49Smrg   reshape(scrwidth, scrheight);
62532001f49Smrg}
62632001f49Smrg
62732001f49Smrg
62832001f49Smrgint
62932001f49Smrgmain(int ac, char **av)
63032001f49Smrg{
63132001f49Smrg   glutInitWindowSize(WIDTH, HEIGHT);
63232001f49Smrg   glutInit(&ac, av);
63332001f49Smrg
63432001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
63532001f49Smrg
63632001f49Smrg   if (!(win = glutCreateWindow("Terrain"))) {
63732001f49Smrg      fprintf(stderr, "Error, couldn't open window\n");
63832001f49Smrg      return -1;
63932001f49Smrg   }
64032001f49Smrg
64132001f49Smrg   ModZMnt = 0.0f;
64232001f49Smrg   loadpic();
64332001f49Smrg
64432001f49Smrg   init();
64532001f49Smrg
64632001f49Smrg#ifndef FX
64732001f49Smrg   glDisable(GL_TEXTURE_2D);
64832001f49Smrg   usetex = 0;
64932001f49Smrg#endif
65032001f49Smrg
65132001f49Smrg   glutReshapeFunc(reshape);
65232001f49Smrg   glutDisplayFunc(drawscene);
65332001f49Smrg   glutKeyboardFunc(key);
65432001f49Smrg   glutSpecialFunc(special);
65532001f49Smrg   glutIdleFunc(drawscene);
65632001f49Smrg
65732001f49Smrg   glutMainLoop();
65832001f49Smrg
65932001f49Smrg   return 0;
66032001f49Smrg}
661