Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. /*
  2. * This program is under the GNU GPL.
  3. * Use at your own risk.
  4. *
  5. * written by David Bucciarelli (tech.hmw@plus.it)
  6. * Humanware s.r.l.
  7. *
  8. * based on a Mikael SkiZoWalker's (MoDEL) / France (Skizo@Hol.Fr) demo
  9. */
  10. #include <assert.h>
  11. #include <stdio.h>
  12. #include <math.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <time.h>
  16. #ifdef WIN32
  17. #include <windows.h>
  18. #endif
  19. #include <GL/glut.h>
  20. #ifdef XMESA
  21. #include "GL/xmesa.h"
  22. static int fullscreen = 1;
  23. #endif
  24. #ifndef M_PI
  25. #define M_PI 3.14159265
  26. #endif
  27. #define heightMnt 450
  28. #define lenghtXmnt 62
  29. #define lenghtYmnt 62
  30. #define stepXmnt 96.0
  31. #define stepYmnt 96.0
  32. #define WIDTH 640
  33. #define HEIGHT 480
  34. static GLint T0 = 0;
  35. static GLint Frames = 0;
  36. #define TSCALE 4
  37. #define FOV 85
  38. static GLfloat terrain[256 * 256];
  39. static GLfloat terraincolor[256 * 256][3];
  40. static int win = 0;
  41. static int fog = 1;
  42. static int bfcull = 1;
  43. static int usetex = 1;
  44. static int poutline = 0;
  45. static int help = 1;
  46. static int joyavailable = 0;
  47. static int joyactive = 0;
  48. static float ModZMnt;
  49. static long GlobalMnt = 0;
  50. static int scrwidth = WIDTH;
  51. static int scrheight = HEIGHT;
  52. #define OBSSTARTX 992.0
  53. #define OBSSTARTY 103.0
  54. static float obs[3] = { OBSSTARTX, heightMnt * 1.3, OBSSTARTY };
  55. static float dir[3], v1[2], v2[2];
  56. static float v = 900.0;
  57. static float alpha = 75.0;
  58. static float beta = 90.0;
  59. static void
  60. calcposobs(void)
  61. {
  62. float alpha1, alpha2;
  63. static double t0 = -1.;
  64. double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
  65. if (t0 < 0.0)
  66. t0 = t;
  67. dt = t - t0;
  68. t0 = t;
  69. dir[0] = sin(alpha * M_PI / 180.0);
  70. dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
  71. dir[1] = cos(beta * M_PI / 180.0);
  72. if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
  73. dir[0] = 0;
  74. if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
  75. dir[1] = 0;
  76. if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
  77. dir[2] = 0;
  78. alpha1 = alpha + FOV / 2.0;
  79. v1[0] = sin(alpha1 * M_PI / 180.0);
  80. v1[1] = cos(alpha1 * M_PI / 180.0);
  81. alpha2 = alpha - FOV / 2.0;
  82. v2[0] = sin(alpha2 * M_PI / 180.0);
  83. v2[1] = cos(alpha2 * M_PI / 180.0);
  84. obs[0] += v * dir[0] * dt;
  85. obs[1] += v * dir[1] * dt;
  86. obs[2] += v * dir[2] * dt;
  87. if (obs[1] < 0.0)
  88. obs[1] = 0.0;
  89. }
  90. static void
  91. reshape(int width, int height)
  92. {
  93. scrwidth = width;
  94. scrheight = height;
  95. glViewport(0, 0, (GLint) width, (GLint) height);
  96. glMatrixMode(GL_PROJECTION);
  97. glLoadIdentity();
  98. gluPerspective(50.0, ((GLfloat) width / (GLfloat) height),
  99. lenghtXmnt * stepYmnt * 0.01, lenghtXmnt * stepYmnt * 0.7);
  100. glMatrixMode(GL_MODELVIEW);
  101. glLoadIdentity();
  102. }
  103. static int
  104. clipstrip(float y, float *start, float *end)
  105. {
  106. float x1, x2, t1, t2, tmp;
  107. if (v1[1] == 0.0) {
  108. t1 = 0.0;
  109. x1 = -HUGE_VAL;
  110. }
  111. else {
  112. t1 = y / v1[1];
  113. x1 = t1 * v1[0];
  114. }
  115. if (v2[1] == 0.0) {
  116. t2 = 0.0;
  117. x2 = HUGE_VAL;
  118. }
  119. else {
  120. t2 = y / v2[1];
  121. x2 = t2 * v2[0];
  122. }
  123. if (((x1 < -(lenghtXmnt * stepXmnt) / 2) && (t2 <= 0.0)) ||
  124. ((t1 <= 0.0) && (x2 > (lenghtXmnt * stepXmnt) / 2)) ||
  125. ((t1 < 0.0) && (t2 < 0.0)))
  126. return 0;
  127. if ((t1 == 0.0) && (t2 == 0.0)) {
  128. if ((v1[0] < 0.0) && (v1[1] > 0.0) && (v2[0] < 0.0) && (v2[1] < 0.0)) {
  129. *start = -(lenghtXmnt * stepXmnt) / 2;
  130. *end = stepXmnt;
  131. return 1;
  132. }
  133. else {
  134. if ((v1[0] > 0.0) && (v1[1] < 0.0) && (v2[0] > 0.0) && (v2[1] > 0.0)) {
  135. *start = -stepXmnt;
  136. *end = (lenghtXmnt * stepXmnt) / 2;
  137. return 1;
  138. }
  139. else
  140. return 0;
  141. }
  142. }
  143. else {
  144. if (t2 < 0.0) {
  145. if (x1 < 0.0)
  146. x2 = -(lenghtXmnt * stepXmnt) / 2;
  147. else
  148. x2 = (lenghtXmnt * stepXmnt) / 2;
  149. }
  150. if (t1 < 0.0) {
  151. if (x2 < 0.0)
  152. x1 = -(lenghtXmnt * stepXmnt) / 2;
  153. else
  154. x1 = (lenghtXmnt * stepXmnt) / 2;
  155. }
  156. }
  157. if (x1 > x2) {
  158. tmp = x1;
  159. x1 = x2;
  160. x2 = tmp;
  161. }
  162. x1 -= stepXmnt;
  163. if (x1 < -(lenghtXmnt * stepXmnt) / 2)
  164. x1 = -(lenghtXmnt * stepXmnt) / 2;
  165. x2 += stepXmnt;
  166. if (x2 > (lenghtXmnt * stepXmnt) / 2)
  167. x2 = (lenghtXmnt * stepXmnt) / 2;
  168. *start = ((int) (x1 / stepXmnt)) * stepXmnt;
  169. *end = ((int) (x2 / stepXmnt)) * stepXmnt;
  170. return 1;
  171. }
  172. static void
  173. printstring(void *font, char *string)
  174. {
  175. int len, i;
  176. len = (int) strlen(string);
  177. for (i = 0; i < len; i++)
  178. glutBitmapCharacter(font, string[i]);
  179. }
  180. static void
  181. printhelp(void)
  182. {
  183. glEnable(GL_BLEND);
  184. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  185. glColor4f(0.0, 0.0, 0.0, 0.5);
  186. glRecti(40, 40, 600, 440);
  187. glDisable(GL_BLEND);
  188. glColor3f(1.0, 0.0, 0.0);
  189. glRasterPos2i(300, 420);
  190. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
  191. glRasterPos2i(60, 390);
  192. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
  193. glRasterPos2i(60, 360);
  194. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Toggle Textures");
  195. glRasterPos2i(60, 330);
  196. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
  197. glRasterPos2i(60, 300);
  198. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "p - Wire frame");
  199. glRasterPos2i(60, 270);
  200. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Toggle Back face culling");
  201. glRasterPos2i(60, 240);
  202. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
  203. glRasterPos2i(60, 210);
  204. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
  205. glRasterPos2i(60, 180);
  206. printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
  207. glRasterPos2i(60, 150);
  208. if (joyavailable)
  209. printstring(GLUT_BITMAP_TIMES_ROMAN_24,
  210. "j - Toggle jostick control (Joystick control available)");
  211. else
  212. printstring(GLUT_BITMAP_TIMES_ROMAN_24,
  213. "(No Joystick control available)");
  214. }
  215. static void
  216. drawterrain(void)
  217. {
  218. int h, i, idx, ox, oy;
  219. float j, k, start, end;
  220. ox = (int) (obs[0] / stepXmnt);
  221. oy = (int) (obs[2] / stepYmnt);
  222. GlobalMnt = ((ox * TSCALE) & 255) + ((oy * TSCALE) & 255) * 256;
  223. glPushMatrix();
  224. glTranslatef((float) ox * stepXmnt, 0, (float) oy * stepYmnt);
  225. for (h = 0, k = -(lenghtYmnt * stepYmnt) / 2; h < lenghtYmnt;
  226. k += stepYmnt, h++) {
  227. if (!clipstrip(k, &start, &end))
  228. continue;
  229. glBegin(GL_TRIANGLE_STRIP); /* I hope that the optimizer will be able to improve this code */
  230. for (i = (int) (lenghtXmnt / 2 + start / stepXmnt), j = start; j <= end;
  231. j += stepXmnt, i++) {
  232. idx = (i * TSCALE + h * 256 * TSCALE + GlobalMnt) & 65535;
  233. glColor3fv(terraincolor[idx]);
  234. glTexCoord2f((ox + i) / 8.0, (oy + h) / 8.0);
  235. glVertex3f(j, terrain[idx], k);
  236. idx =
  237. (i * TSCALE + h * 256 * TSCALE + 256 * TSCALE +
  238. GlobalMnt) & 65535;
  239. glColor3fv(terraincolor[idx]);
  240. glTexCoord2f((ox + i) / 8.0, (oy + h + 1) / 8.0);
  241. glVertex3f(j, terrain[idx], k + stepYmnt);
  242. }
  243. glEnd();
  244. }
  245. glDisable(GL_CULL_FACE);
  246. glDisable(GL_TEXTURE_2D);
  247. glEnable(GL_BLEND);
  248. glBegin(GL_QUADS);
  249. glColor4f(0.1, 0.7, 1.0, 0.4);
  250. glVertex3f(-(lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
  251. -(lenghtYmnt * stepYmnt) / 2.0);
  252. glVertex3f(-(lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
  253. (lenghtYmnt * stepYmnt) / 2.0);
  254. glVertex3f((lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
  255. (lenghtYmnt * stepYmnt) / 2.0);
  256. glVertex3f((lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
  257. -(lenghtYmnt * stepYmnt) / 2.0);
  258. glEnd();
  259. glDisable(GL_BLEND);
  260. if (bfcull)
  261. glEnable(GL_CULL_FACE);
  262. glEnable(GL_TEXTURE_2D);
  263. glPopMatrix();
  264. }
  265. static void
  266. dojoy(void)
  267. {
  268. #ifdef WIN32
  269. static UINT max[2] = { 0, 0 };
  270. static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
  271. MMRESULT res;
  272. JOYINFO joy;
  273. res = joyGetPos(JOYSTICKID1, &joy);
  274. if (res == JOYERR_NOERROR) {
  275. joyavailable = 1;
  276. if (max[0] < joy.wXpos)
  277. max[0] = joy.wXpos;
  278. if (min[0] > joy.wXpos)
  279. min[0] = joy.wXpos;
  280. center[0] = (max[0] + min[0]) / 2;
  281. if (max[1] < joy.wYpos)
  282. max[1] = joy.wYpos;
  283. if (min[1] > joy.wYpos)
  284. min[1] = joy.wYpos;
  285. center[1] = (max[1] + min[1]) / 2;
  286. if (joyactive) {
  287. if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
  288. alpha +=
  289. 2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
  290. if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
  291. beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
  292. if (joy.wButtons & JOY_BUTTON1)
  293. v += 0.5;
  294. if (joy.wButtons & JOY_BUTTON2)
  295. v -= 0.5;
  296. }
  297. }
  298. else
  299. joyavailable = 0;
  300. #endif
  301. }
  302. static void
  303. drawscene(void)
  304. {
  305. static char frbuf[80] = "";
  306. dojoy();
  307. glShadeModel(GL_SMOOTH);
  308. glEnable(GL_DEPTH_TEST);
  309. if (usetex)
  310. glEnable(GL_TEXTURE_2D);
  311. else
  312. glDisable(GL_TEXTURE_2D);
  313. if (fog)
  314. glEnable(GL_FOG);
  315. else
  316. glDisable(GL_FOG);
  317. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  318. glPushMatrix();
  319. calcposobs();
  320. gluLookAt(obs[0], obs[1], obs[2],
  321. obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
  322. 0.0, 1.0, 0.0);
  323. drawterrain();
  324. glPopMatrix();
  325. glDisable(GL_TEXTURE_2D);
  326. glDisable(GL_DEPTH_TEST);
  327. glDisable(GL_FOG);
  328. glShadeModel(GL_FLAT);
  329. glMatrixMode(GL_PROJECTION);
  330. glLoadIdentity();
  331. glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
  332. glMatrixMode(GL_MODELVIEW);
  333. glLoadIdentity();
  334. glColor3f(1.0, 0.0, 0.0);
  335. glRasterPos2i(10, 10);
  336. printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
  337. glRasterPos2i(350, 470);
  338. printstring(GLUT_BITMAP_HELVETICA_10,
  339. "Terrain V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
  340. glRasterPos2i(434, 457);
  341. printstring(GLUT_BITMAP_HELVETICA_10,
  342. "Based on a Mickael's demo (Skizo@Hol.Fr)");
  343. if (help)
  344. printhelp();
  345. reshape(scrwidth, scrheight);
  346. glutSwapBuffers();
  347. Frames++;
  348. {
  349. GLint t = glutGet(GLUT_ELAPSED_TIME);
  350. if (t - T0 >= 2000) {
  351. GLfloat seconds = (t - T0) / 1000.0;
  352. GLfloat fps = Frames / seconds;
  353. sprintf(frbuf, "Frame rate: %f", fps);
  354. T0 = t;
  355. Frames = 0;
  356. }
  357. }
  358. }
  359. static void
  360. key(unsigned char k, int x, int y)
  361. {
  362. switch (k) {
  363. case 27:
  364. exit(0);
  365. break;
  366. case 'a':
  367. v += 50.;
  368. break;
  369. case 'z':
  370. v -= 50.;
  371. break;
  372. case 'p':
  373. if (poutline) {
  374. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  375. poutline = 0;
  376. }
  377. else {
  378. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  379. poutline = 1;
  380. }
  381. break;
  382. case 'j':
  383. joyactive = (!joyactive);
  384. break;
  385. case 'h':
  386. help = (!help);
  387. break;
  388. case 'f':
  389. fog = (!fog);
  390. break;
  391. case 't':
  392. usetex = (!usetex);
  393. break;
  394. case 'b':
  395. if (bfcull) {
  396. glDisable(GL_CULL_FACE);
  397. bfcull = 0;
  398. }
  399. else {
  400. glEnable(GL_CULL_FACE);
  401. bfcull = 1;
  402. }
  403. break;
  404. #ifdef XMESA
  405. case ' ':
  406. XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
  407. fullscreen = (!fullscreen);
  408. break;
  409. #endif
  410. }
  411. }
  412. static void
  413. special(int k, int x, int y)
  414. {
  415. switch (k) {
  416. case GLUT_KEY_LEFT:
  417. alpha += 2.0;
  418. break;
  419. case GLUT_KEY_RIGHT:
  420. alpha -= 2.0;
  421. break;
  422. case GLUT_KEY_DOWN:
  423. beta -= 2.0;
  424. break;
  425. case GLUT_KEY_UP:
  426. beta += 2.0;
  427. break;
  428. }
  429. }
  430. static void
  431. calccolor(GLfloat height, GLfloat c[3])
  432. {
  433. GLfloat color[4][3] = {
  434. {1.0, 1.0, 1.0},
  435. {0.0, 0.8, 0.0},
  436. {1.0, 1.0, 0.3},
  437. {0.0, 0.0, 0.8}
  438. };
  439. GLfloat fact;
  440. height = height * (1.0 / 255.0);
  441. if (height >= 0.9) {
  442. c[0] = color[0][0];
  443. c[1] = color[0][1];
  444. c[2] = color[0][2];
  445. return;
  446. }
  447. if ((height < 0.9) && (height >= 0.7)) {
  448. fact = (height - 0.7) * 5.0;
  449. c[0] = fact * color[0][0] + (1.0 - fact) * color[1][0];
  450. c[1] = fact * color[0][1] + (1.0 - fact) * color[1][1];
  451. c[2] = fact * color[0][2] + (1.0 - fact) * color[1][2];
  452. return;
  453. }
  454. if ((height < 0.7) && (height >= 0.6)) {
  455. fact = (height - 0.6) * 10.0;
  456. c[0] = fact * color[1][0] + (1.0 - fact) * color[2][0];
  457. c[1] = fact * color[1][1] + (1.0 - fact) * color[2][1];
  458. c[2] = fact * color[1][2] + (1.0 - fact) * color[2][2];
  459. return;
  460. }
  461. if ((height < 0.6) && (height >= 0.5)) {
  462. fact = (height - 0.5) * 10.0;
  463. c[0] = fact * color[2][0] + (1.0 - fact) * color[3][0];
  464. c[1] = fact * color[2][1] + (1.0 - fact) * color[3][1];
  465. c[2] = fact * color[2][2] + (1.0 - fact) * color[3][2];
  466. return;
  467. }
  468. c[0] = color[3][0];
  469. c[1] = color[3][1];
  470. c[2] = color[3][2];
  471. }
  472. static void
  473. loadpic(void)
  474. {
  475. GLubyte bufferter[256 * 256], terrainpic[256 * 256];
  476. FILE *FilePic;
  477. int i, tmp;
  478. GLenum gluerr;
  479. size_t result;
  480. if ((FilePic = fopen("terrain.dat", "r")) == NULL) {
  481. fprintf(stderr, "Error loading terrain.dat\n");
  482. exit(-1);
  483. }
  484. result = fread(bufferter, 256 * 256, 1, FilePic);
  485. assert(result == 1);
  486. fclose(FilePic);
  487. for (i = 0; i < (256 * 256); i++) {
  488. terrain[i] = (bufferter[i] * (heightMnt / 255.0f));
  489. calccolor((GLfloat) bufferter[i], terraincolor[i]);
  490. tmp = (((int) bufferter[i]) + 96);
  491. terrainpic[i] = (tmp > 255) ? 255 : tmp;
  492. }
  493. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  494. if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 1, 256, 256, GL_LUMINANCE,
  495. GL_UNSIGNED_BYTE,
  496. (GLvoid *) (&terrainpic[0])))) {
  497. fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr));
  498. exit(-1);
  499. }
  500. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  501. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  502. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  503. GL_LINEAR_MIPMAP_LINEAR);
  504. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  505. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  506. glEnable(GL_TEXTURE_2D);
  507. }
  508. static void
  509. init(void)
  510. {
  511. float fogcolor[4] = { 0.6, 0.7, 0.7, 1.0 };
  512. glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
  513. glClearDepth(1.0);
  514. glDepthFunc(GL_LEQUAL);
  515. glShadeModel(GL_SMOOTH);
  516. glEnable(GL_DEPTH_TEST);
  517. glEnable(GL_CULL_FACE);
  518. glDisable(GL_BLEND);
  519. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  520. glEnable(GL_FOG);
  521. glFogi(GL_FOG_MODE, GL_EXP2);
  522. glFogfv(GL_FOG_COLOR, fogcolor);
  523. glFogf(GL_FOG_DENSITY, 0.0007);
  524. #ifdef FX
  525. glHint(GL_FOG_HINT, GL_NICEST);
  526. #endif
  527. reshape(scrwidth, scrheight);
  528. }
  529. int
  530. main(int ac, char **av)
  531. {
  532. glutInitWindowSize(WIDTH, HEIGHT);
  533. glutInit(&ac, av);
  534. glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
  535. if (!(win = glutCreateWindow("Terrain"))) {
  536. fprintf(stderr, "Error, couldn't open window\n");
  537. return -1;
  538. }
  539. ModZMnt = 0.0f;
  540. loadpic();
  541. init();
  542. #ifndef FX
  543. glDisable(GL_TEXTURE_2D);
  544. usetex = 0;
  545. #endif
  546. glutReshapeFunc(reshape);
  547. glutDisplayFunc(drawscene);
  548. glutKeyboardFunc(key);
  549. glutSpecialFunc(special);
  550. glutIdleFunc(drawscene);
  551. glutMainLoop();
  552. return 0;
  553. }