skyfly.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:23k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*
  2.  * skyfly.c     $Revision: 1.5 $
  3.  */
  4. #include <assert.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <time.h>
  8. #include <errno.h>
  9. #include <GL/glut.h>
  10. #include <math.h>
  11. #include "skyfly.h"
  12. #if !defined(GL_VERSION_1_1)
  13. #if defined(GL_EXT_texture_object)
  14. #define glBindTexture(A,B)     glBindTextureEXT(A,B)
  15. #define glGenTextures(A,B)     glGenTexturesEXT(A,B)
  16. #define glDeleteTextures(A,B)  glDeleteTexturesEXT(A,B)
  17. #else
  18. #define glBindTexture(A,B)
  19. #define glGenTextures(A,B)
  20. #define glDeleteTextures(A,B)
  21. #endif
  22. #if defined(GL_EXT_texture)
  23. #define GL_RGB5 GL_RGB5_EXT
  24. #else
  25. #define GL_RGB5 GL_RGB
  26. #endif
  27. #endif
  28. #define ERR_WARNING                     0x1
  29. #define ERR_FATAL                       0x2
  30. #define ERR_SYSERR                      0x4
  31. #define AMALLOC(a, type, num, func)     {                     
  32. if((int)(a = (type*)malloc(sizeof(type)*(num))) <= 0)     
  33. err_msg(ERR_FATAL, func, "amalloc failed");           
  34. }
  35. float   ScaleZ   = 2.3;     /* Terrain height scale factor */
  36. int     CellDim = 4;        /* Terrain cell is CellDim X Celldim quads */
  37. int     NumCells = 36;      /* Terrain grid is NumCells X NumCells cells */
  38. int     GridDim;            /* Terrain grid is GridDim X GridDim quads */
  39. float   XYScale;            /* Conversion from world-space to grid index */
  40. float   CellSize;           /* World-space size of cell */
  41. int     Init_pos;           /* if true, set initial position and kbd mode */
  42. float   Init_x, Init_y, Init_z, Init_azimuth;
  43. int     rgbmode = GL_TRUE;
  44. /* Color index ramp info */
  45. int sky_base, terr_base;
  46. int plane_colors[3];
  47. /*
  48.  * Data that changes from frame to frame needs to be double-buffered because
  49.  * two processes may be working on two different frames at the same time.
  50.  */
  51. typedef struct buffered_data_struct {
  52.         /* objects */
  53.         perfobj_t       paper_plane_pos_obj[NUM_PLANES];
  54.         perfobj_t       viewer_pos_obj;
  55.         /* flags */
  56.         unsigned int   paper_plane_pos_flags[2];
  57.         unsigned int   viewer_pos_flags[2];
  58.         /* data */
  59.         float  paper_plane_position[NUM_PLANES][6];
  60.         float  viewer_position[4];
  61. } buffered_data;
  62. /*
  63.  * This is the per-pipe data structure which holds pipe id, semaphores,
  64.  * and variable data buffers. Both gfxpipe and buffer structures live in
  65.  * shared memory so the sim can communicate with its forked children.
  66.  */
  67. typedef struct gfxpipe_data_struct {
  68.         int             gfxpipenum;
  69. buffered_data   **buffers;
  70. } gfxpipe_data;
  71. static gfxpipe_data     *gfxpipe;       /* A processes' gfxpipe struct */
  72. static gfxpipe_data     *gfxpipes[1];   /* Maximum of 1 graphics pipe */
  73. static int              num_pipes;
  74. float            fog_params[4];  /* Fog and clear color */
  75. static float            fog_density = 0.025*2;
  76. float            far_cull  = 31.;    /* Far clip distance from eye */
  77. int mipmap = 0;
  78. static int              texmode = GL_NEAREST;
  79. static int              threecomp = 1;
  80. int  dither = GL_TRUE, fog = GL_TRUE;
  81. int     Wxsize = 320, Wysize = 240; /* Default to 320x240 window */
  82. /*
  83.  * All non-variable data like geometry is stored in shared memory. This way
  84.  * forked processes avoid duplicating data unnecessarily.
  85.  */
  86. shared_data     *SharedData;
  87. /* //////////////////////////////////////////////////////////////////////// */
  88. void sim_proc(void);
  89. void sim_cyclops(void);
  90. void sim_dualchannel(void);
  91. void sim_singlechannel(void);
  92. void cull_proc(void);
  93. void draw_proc(void);
  94. void sim_exit(void);
  95. void init_misc(void); 
  96. void init_shmem(void); 
  97. void init_terrain(void);
  98. void init_clouds(void);
  99. void init_paper_planes(void);
  100. void init_positions(void);
  101. void init_gfxpipes(void);
  102. void init_gl(int gfxpipenum);
  103. void err_msg(int type, char* func, char* error);
  104. void fly(perfobj_t *viewer_pos);
  105. void fly_paper_planes(perfobj_t *paper_plane_pos);
  106. float terrain_height(void);
  107. void init_skyfly(void)
  108. {
  109.     init_shmem();
  110.     init_gfxpipes();
  111.     init_clouds();
  112.     init_terrain();
  113.     init_paper_planes();
  114.     init_positions();
  115.     gfxpipe = gfxpipes[0];
  116.     init_gl(gfxpipe->gfxpipenum);
  117. }
  118. /*
  119.  * This is a single-channel version of the dual-channel simulation
  120.  * described above.
  121.  */
  122. void sim_singlechannel(void)
  123. {
  124. buffered_data  **buffered = gfxpipes[0]->buffers;
  125. fly(&(buffered[0]->viewer_pos_obj));
  126. fly_paper_planes(buffered[0]->paper_plane_pos_obj);
  127. }
  128. /*-------------------------------------- Cull ------------------------------*/
  129. /*
  130.  *   The cull and draw processes operate in a classic producer/consumer, 
  131.  * write/read configuration using a ring buffer. The ring consists of pointers
  132.  * to perfobj's instead of actual geometric data. This is important because
  133.  * you want to minimize the amount of data 'shared' between two processes that
  134.  * run on different processors in order to reduce cache invalidations.
  135.  *   enter_in_ring and get_from_ring spin on ring full and ring empty 
  136.  * conditions respectively.
  137.  *   Since cull/draw are shared group processes(sproc), the ring buffer is
  138.  * in the virtual address space of both processes and shared memory is not
  139.  * necessary.
  140. */
  141. #define RING_SIZE   1000    /* Size of ring */
  142. typedef struct render_ring_struct {
  143.     volatile unsigned int      head, tail;
  144.     perfobj_t                   **ring;
  145. } render_ring;
  146. render_ring ringbuffer;
  147. void        enter_in_ring(perfobj_t *perfobj);
  148. perfobj_t*  get_from_ring(void);
  149. void cull_proc(void)
  150. {
  151.     static struct cull {
  152.         perfobj_t       **cells;
  153.         perfobj_t       viewer_pos_obj[2];
  154.         unsigned int   viewer_pos_flags[4];
  155.         float           viewer_position[2][4];
  156.         float           fovx, side, farr, epsilon, plane_epsilon;
  157.     } cull;
  158.     static int init = 0;
  159.     if (!init) {
  160.         int             x, y;
  161.         cull.fovx = FOV *(float) Wxsize /(float) Wysize;
  162.         cull.side = far_cull / cosf(cull.fovx / 2.);
  163.         cull.farr = 2.* cull.side * sinf(cull.fovx / 2.);
  164.         cull.epsilon = sqrtf(2.) * CellSize / 2.;
  165.         cull.plane_epsilon = .5;
  166.         cull.cells = (perfobj_t **) malloc(NumCells * NumCells * sizeof(perfobj_t *));
  167.         for (x = 0; x < NumCells; x++)
  168.             for (y = 0; y < NumCells; y++)
  169.                 cull.cells[x * NumCells + y] =
  170.                     &(SharedData->terrain_cells[x * NumCells + y]);
  171.         ringbuffer.ring = malloc(RING_SIZE * sizeof(perfobj_t *));
  172.         ringbuffer.head = ringbuffer.tail = 0;
  173.         cull.viewer_pos_obj[0].flags = cull.viewer_pos_flags;
  174.         cull.viewer_pos_obj[0].vdata = cull.viewer_position[0];
  175.         cull.viewer_pos_obj[1].flags = cull.viewer_pos_flags;
  176.         cull.viewer_pos_obj[1].vdata = cull.viewer_position[1];
  177.         *(cull.viewer_pos_flags) = PD_VIEWER_POS;
  178.         *(cull.viewer_pos_flags + 1) = PD_END;
  179.         init = 1;
  180.     }
  181. {
  182. float           *viewer;
  183. float           vX, vY, vazimuth, px, py;
  184. float           left_area, right_area;
  185. float           left_dx, left_dy, right_dx, right_dy;
  186. float           ax, ay, bx, by, cx, cy;
  187. float           minx, maxx, miny, maxy;
  188. int             i, buffer = 0;
  189. int             x, y, x0, y0, x1, y1;
  190. perfobj_t      *viewer_pos, *paper_plane_pos;
  191. buffered_data  *buffered;
  192. perfobj_t      *terrain_texture = &(SharedData->terrain_texture_obj);
  193. perfobj_t      *paper_plane = &(SharedData->paper_plane_obj);
  194. perfobj_t      *paper_plane_start = &(SharedData->paper_plane_start_obj);
  195. perfobj_t      *paper_plane_end = &(SharedData->paper_plane_end_obj);
  196. perfobj_t      *clouds_texture = &(SharedData->clouds_texture_obj);
  197. perfobj_t      *clouds = &(SharedData->clouds_obj);
  198. buffered = gfxpipe->buffers[buffer];
  199. viewer_pos = &(buffered->viewer_pos_obj);
  200. paper_plane_pos = buffered->paper_plane_pos_obj;
  201. vX = *((float *) viewer_pos->vdata + 0);
  202. vY = *((float *) viewer_pos->vdata + 1);
  203. vazimuth = *((float *) viewer_pos->vdata + 3);
  204. viewer = cull.viewer_position[buffer];
  205. viewer[0] = vX;
  206. viewer[1] = vY;
  207. viewer[2] = *((float *) viewer_pos->vdata + 2);
  208. viewer[3] = vazimuth;
  209. /*
  210.  * Begin cull to viewing frustrum
  211.  */
  212. ax = (vX - sinf(-vazimuth + cull.fovx *.5) * cull.side);
  213. ay = (vY + cosf(-vazimuth + cull.fovx *.5) * cull.side);
  214. bx = vX;
  215. by = vY;
  216. cx = (vX + sinf(vazimuth + cull.fovx *.5) * cull.side);
  217. cy = (vY + cosf(vazimuth + cull.fovx *.5) * cull.side);
  218. minx = MIN(MIN(ax, bx), cx);
  219. miny = MIN(MIN(ay, by), cy);
  220. maxx = MAX(MAX(ax, bx), cx);
  221. maxy = MAX(MAX(ay, by), cy);
  222. x0 = MAX((int) (minx / CellSize), 0);
  223. x1 = MIN((int) (maxx / CellSize) + 1, NumCells);
  224. y0 = MAX((int) (miny / CellSize), 0);
  225. y1 = MIN((int) (maxy / CellSize) + 1, NumCells);
  226. left_dx = ax - bx;
  227. left_dy = ay - by;
  228. right_dx = cx - bx;
  229. right_dy = cy - by;
  230. enter_in_ring(&cull.viewer_pos_obj[buffer]);
  231. if (viewer[2]<SKY_HIGH) {
  232.    /* draw clouds first */
  233.    enter_in_ring(clouds_texture);
  234.    enter_in_ring(clouds);
  235. }
  236. enter_in_ring(terrain_texture);
  237. /*
  238.  * Add visible cells to ring buffer 
  239.  */
  240. for (x = x0; x < x1; x++) {
  241. for (y = y0; y < y1; y++) {
  242. float           cntrx =(x +.5) * CellSize;
  243. float           cntry =(y +.5) * CellSize;
  244. left_area = left_dx * (cntry - by) - left_dy * (cntrx - bx);
  245. right_area = right_dx * (cntry - by) - right_dy * (cntrx - bx);
  246. if ((left_area < cull.epsilon * cull.side && right_area > -cull.epsilon * cull.side)) {
  247. enter_in_ring(cull.cells[x * NumCells + y]);
  248. }
  249. }
  250. }
  251. enter_in_ring(paper_plane_start);
  252. /*
  253.  * Add visible planes to ring buffer
  254. */
  255. for (i = 0; i < NUM_PLANES; i++) {
  256. px = *((float *) paper_plane_pos[i].vdata + 0);
  257. py = *((float *) paper_plane_pos[i].vdata + 1);
  258. left_area = left_dx * (py - by) - left_dy * (px - bx);
  259. right_area = right_dx * (py - by) - right_dy * (px - bx);
  260. if (left_area < cull.plane_epsilon * cull.side && right_area > -cull.plane_epsilon * cull.side) {
  261. enter_in_ring(&paper_plane_pos[i]);
  262. enter_in_ring(paper_plane);
  263. }
  264. }
  265. enter_in_ring(paper_plane_end);
  266. if (viewer[2]>SKY_HIGH) {
  267.    /* draw clouds after everything else */
  268.    enter_in_ring(clouds_texture);
  269.    enter_in_ring(clouds);
  270. }
  271. enter_in_ring((perfobj_t *) 0);     /* 0 indicates end of frame */
  272. buffer = !buffer;
  273. }
  274. }
  275. void enter_in_ring(perfobj_t *perfobj)
  276. {
  277. while (ringbuffer.head == RING_SIZE+ringbuffer.tail-1) {}
  278. ringbuffer.ring[ringbuffer.head % RING_SIZE] = perfobj;
  279. ringbuffer.head++;
  280. }
  281. perfobj_t* get_from_ring(void)
  282. {
  283.     static perfobj_t *pobj;
  284.     while(ringbuffer.tail == ringbuffer.head) {}
  285.     pobj = ringbuffer.ring[ringbuffer.tail % RING_SIZE];
  286.     ringbuffer.tail++;
  287.     return pobj;        
  288. }
  289. /*-------------------------------------- Draw ------------------------------*/
  290. void draw_proc(void)
  291. {
  292. perfobj_t      *too_draw;
  293. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  294. while ((too_draw = get_from_ring())) {
  295. drawperfobj(too_draw);
  296. }
  297. }
  298. /*------------------------------- Init -----------------------------------*/
  299. void init_texture_and_lighting(void);
  300. void init_buffered_data(buffered_data *buffered);
  301. void init_misc(void)
  302. {
  303. float   density;
  304. threecomp = rgbmode;
  305. /*
  306.  * Compute fog and clear color to be linear interpolation between blue
  307.  * and white.
  308.  */
  309. density = 1.- expf(-5.5 * fog_density * fog_density *
  310.   far_cull * far_cull);
  311. density = MAX(MIN(density, 1.), 0.);
  312. fog_params[0] = .23 + density *.57;
  313. fog_params[1] = .35 + density *.45;
  314. fog_params[2] = .78 + density *.22;
  315. fog_params[3] = 1.0f;
  316. }
  317. void init_shmem(void)
  318. {
  319. int    i;
  320.     unsigned int  *flagsptr;
  321.     perfobj_vert_t *vertsptr;
  322.     int             nflags, nverts;
  323.     AMALLOC(SharedData, shared_data, 1, "init_shmem");
  324.     AMALLOC(SharedData->terrain_cells, perfobj_t,
  325.             NumCells * NumCells, "init_shmem");
  326.     AMALLOC(SharedData->terrain_cell_flags, unsigned int *,
  327.             NumCells * NumCells, "init_shmem");
  328.     AMALLOC(SharedData->terrain_cell_verts, perfobj_vert_t *,
  329.             NumCells * NumCells, "init_shmem");
  330.     /*
  331.      * Allocate the flags and vertices of all terrain cells in 2 big chunks
  332.      * to improve data locality and consequently, cache hits 
  333.      */
  334.     nflags = 2 * CellDim + 1;
  335. AMALLOC(flagsptr, unsigned int, nflags * NumCells * NumCells, "init_shmem");
  336. nverts = (CellDim + 1) * 2 * CellDim;
  337. AMALLOC(vertsptr, perfobj_vert_t, nverts * NumCells * NumCells, "init_shmem");
  338. for (i = 0; i < NumCells * NumCells; i++) {
  339. SharedData->terrain_cell_flags[i] = flagsptr;
  340. flagsptr += nflags;
  341. SharedData->terrain_cell_verts[i] = vertsptr;
  342. vertsptr += nverts;
  343. }
  344. }
  345. /*
  346.  * Initialize gfxpipe data structures. There is one set of semaphores
  347.  * per pipe.
  348.  */
  349. void init_gfxpipes(void)
  350. {
  351. int             i, j;
  352. num_pipes = 1;
  353. for (i = 0; i < num_pipes; i++) {
  354. AMALLOC(gfxpipes[i], gfxpipe_data, 1, "initgfxpipes");
  355. AMALLOC(gfxpipes[i]->buffers, buffered_data *, NBUFFERS,
  356. "init_gfxpipes");
  357. gfxpipes[i]->gfxpipenum = i;
  358. }
  359. for (j = 0; j < NBUFFERS; j++) {
  360. AMALLOC(gfxpipes[0]->buffers[j], buffered_data, 1,
  361. "init_gfxpipes");
  362. init_buffered_data(gfxpipes[0]->buffers[j]);
  363. }
  364. }
  365. void init_buffered_data(buffered_data *buffered)
  366. {
  367.     int             i;
  368.     perfobj_t      *pobj;
  369.     pobj = &(buffered->viewer_pos_obj);
  370.     pobj->flags = buffered->viewer_pos_flags;
  371.     pobj->vdata = buffered->viewer_position;
  372.     *(buffered->viewer_pos_flags) = PD_VIEWER_POS;
  373.     *(buffered->viewer_pos_flags + 1) = PD_END;
  374.     for (i = 0; i < NUM_PLANES; i++) {
  375.         pobj = &(buffered->paper_plane_pos_obj[i]);
  376.         pobj->flags = buffered->paper_plane_pos_flags;
  377.         pobj->vdata = buffered->paper_plane_position[i];
  378.     }
  379.     *(buffered->paper_plane_pos_flags) = PD_PAPER_PLANE_POS;
  380.     *(buffered->paper_plane_pos_flags + 1) = PD_END;
  381. }
  382. /* ARGSUSED */
  383. void init_gl(int gfxpipenum)
  384. {
  385. glDrawBuffer(GL_BACK);
  386. glClear(GL_COLOR_BUFFER_BIT);
  387. if (!rgbmode)
  388. glIndexi(0);
  389. set_fog(fog);
  390. glEnable(GL_CULL_FACE);
  391. glEnable(GL_DEPTH_TEST);
  392.     set_dither(dither);
  393. glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
  394. init_texture_and_lighting();
  395. glMatrixMode(GL_PROJECTION);
  396. gluPerspective(FOV * RAD_TO_DEG, (float)Wxsize/(float)Wysize,
  397.  .1, far_cull *.95);
  398. glMatrixMode(GL_MODELVIEW);
  399. glHint(GL_FOG_HINT, GL_FASTEST);
  400. glFogi(GL_FOG_MODE, GL_EXP2);
  401. glFogf(GL_FOG_DENSITY, fog_density);
  402. if (rgbmode) {
  403. glFogfv(GL_FOG_COLOR, fog_params);
  404. if (fog && fog_density > 0)
  405. glEnable(GL_FOG);
  406. } else if (FOG_LEVELS > 1) {
  407. glFogi(GL_FOG_INDEX, FOG_LEVELS-1);
  408. if (fog)
  409. glEnable(GL_FOG);
  410. }
  411. }
  412. unsigned char* read_bwimage(char *name, int *w, int *h);
  413. void init_texture_and_lighting(void)
  414. {
  415.     unsigned char  *bwimage256, *bwimage128;
  416.     int             w, h;
  417.     if(!(bwimage256 = (unsigned char*) read_bwimage("terrain.bw", &w, &h)))
  418.        if(!(bwimage256 = (unsigned char *) 
  419.                 read_bwimage("/usr/demos/data/textures/terrain.bw", &w, &h)))
  420. err_msg(ERR_FATAL, "init_texture_and_lighting()",
  421. "Can't open terrain.bw");
  422. if(w != 256 || h != 256)
  423. err_msg(ERR_FATAL, "init_texture_and_lighting()",
  424. "terrain.bw must be 256x256");
  425. if (!(bwimage128 = (unsigned char *) read_bwimage("clouds.bw", &w, &h)))
  426. if (!(bwimage128 = (unsigned char *)
  427.   read_bwimage("/usr/demos/data/textures/clouds.bw", &w, &h)))
  428. err_msg(ERR_FATAL, "init_misc()", "Can't open clouds.bw");
  429. if (w != 128 || h != 128)
  430. err_msg(ERR_FATAL, "init_misc()", "clouds.bw must be 128x128");
  431. if (mipmap)
  432. texmode = GL_LINEAR_MIPMAP_LINEAR;
  433. else
  434. texmode = GL_NEAREST;
  435. if (!threecomp) {
  436. /*
  437.  * 1 and 2-component textures offer the highest performance on SkyWriter
  438.  * so they are the most recommended.
  439.  */
  440. glBindTexture(GL_TEXTURE_2D, 1);
  441. if (!mipmap)
  442. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texmode);
  443. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texmode);
  444. if (mipmap)
  445. gluBuild2DMipmaps(GL_TEXTURE_2D, /*0,*/ 1, 256, 256, /*0,*/ GL_LUMINANCE, GL_UNSIGNED_BYTE, bwimage256);
  446. else if (rgbmode)
  447. glTexImage2D(GL_TEXTURE_2D, 0, 1, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bwimage256);
  448. else {
  449. #define TXSIZE 128
  450. GLubyte buf[TXSIZE*TXSIZE];
  451. int ii;
  452. gluScaleImage(GL_LUMINANCE, 256, 256, GL_UNSIGNED_BYTE, bwimage256,
  453.   TXSIZE, TXSIZE, GL_UNSIGNED_BYTE, buf);
  454. for (ii = 0; ii < TXSIZE*TXSIZE; ii++) {
  455. buf[ii] = terr_base +
  456. FOG_LEVELS * (buf[ii] >> (8-TERR_BITS));
  457. }
  458. #ifdef GL_COLOR_INDEX8_EXT  /* Requires SGI_index_texture and EXT_paletted_texture */
  459. glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, TXSIZE, TXSIZE,
  460.  0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buf);
  461. #endif
  462. #undef TXSIZE
  463. }
  464. glBindTexture(GL_TEXTURE_2D, 2);
  465. if (!mipmap)
  466. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texmode);
  467. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texmode);
  468. if (mipmap)
  469. gluBuild2DMipmaps(GL_TEXTURE_2D, /*0,*/ 1, 128, 128, /*0,*/ GL_LUMINANCE, GL_UNSIGNED_BYTE, bwimage128);
  470. else if (rgbmode)
  471. glTexImage2D(GL_TEXTURE_2D, 0, 1, 128, 128, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, bwimage128);
  472. else {
  473. #define TXSIZE 64
  474. GLubyte buf[TXSIZE*TXSIZE];
  475. int ii;
  476. gluScaleImage(GL_LUMINANCE, 128, 128, GL_UNSIGNED_BYTE, bwimage128,
  477.   TXSIZE, TXSIZE, GL_UNSIGNED_BYTE, buf);
  478. for (ii = 0; ii < TXSIZE*TXSIZE; ii++) {
  479. buf[ii] = sky_base +
  480. FOG_LEVELS * (buf[ii] >> (8-SKY_BITS));
  481. }
  482. #ifdef GL_COLOR_INDEX8_EXT  /* Requires SGI_index_texture and EXT_paletted_texture */
  483. glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, TXSIZE, TXSIZE,
  484.  0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buf);
  485. #endif
  486. #undef TXSIZE
  487. }
  488. } else {
  489. float r0, r1, g0, g1, b0, b1;
  490. int i;
  491. unsigned char *t256 = (unsigned char *)malloc(256*256*3);
  492. /* terrain */
  493. r0 = 0.40f;   r1 = 0.30f;
  494. g0 = 0.30f;   g1 = 0.70f;
  495. b0 = 0.15f;   b1 = 0.10f;
  496. for(i = 0; i < 256*256; i++) {
  497. float t = bwimage256[i] / 255.0f;
  498. t256[3*i+0] = (unsigned char) (255.0f * (r0 + t*t * (r1-r0)));
  499. t256[3*i+1] = (unsigned char) (255.0f * (g0 + t * (g1-g0)));
  500. t256[3*i+2] = (unsigned char) (255.0f * (b0 + t*t * (b1-b0)));
  501. }
  502. glBindTexture(GL_TEXTURE_2D, 1);
  503. if (!mipmap)
  504. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texmode);
  505. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texmode);
  506. if (mipmap)
  507. gluBuild2DMipmaps(GL_TEXTURE_2D, /*0,*/ 3, 256, 256, /*0,*/ GL_RGB, GL_UNSIGNED_BYTE, t256);
  508. else
  509. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, t256);
  510. /* sky without fog */
  511. r0 = 0.23;  r1 = 1.0f;
  512. g0 = 0.35;  g1 = 1.0f;
  513. b0 = 0.78;  b1 = 1.0f;
  514. for(i = 0; i < 128*128; i++) {
  515. float t = bwimage128[i] / 255.0f;
  516. t256[3*i+0] = (unsigned char) (255.0f * (r0 + t * (r1-r0)));
  517. t256[3*i+1] = (unsigned char) (255.0f * (g0 + t * (g1-g0)));
  518. t256[3*i+2] = (unsigned char) (255.0f * (b0 + t * (b1-b0)));
  519. }
  520. glBindTexture(GL_TEXTURE_2D, 2);
  521. if (!mipmap)
  522. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texmode);
  523. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texmode);
  524. if (mipmap)
  525. gluBuild2DMipmaps(GL_TEXTURE_2D, /*0,*/ 3, 128, 128, /*0,*/ GL_RGB, GL_UNSIGNED_BYTE, t256);
  526. else
  527. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, t256);
  528. /* sky with fog */
  529. r0 = fog_params[0];  r1 = 1.0f;
  530. g0 = fog_params[1];  g1 = 1.0f;
  531. b0 = fog_params[2];  b1 = 1.0f;
  532. for(i = 0; i < 128*128; i++) {
  533. float t = bwimage128[i] / 255.0f;
  534. t256[3*i+0] = (unsigned char) (255.0f * (r0 + t * (r1-r0)));
  535. t256[3*i+1] = (unsigned char) (255.0f * (g0 + t * (g1-g0)));
  536. t256[3*i+2] = (unsigned char) (255.0f * (b0 + t * (b1-b0)));
  537. }
  538. glBindTexture(GL_TEXTURE_2D, 3);
  539. if (!mipmap)
  540. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texmode);
  541. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texmode);
  542. if (mipmap)
  543. gluBuild2DMipmaps(GL_TEXTURE_2D, /*0,*/ 3, 128, 128, /*0,*/ GL_RGB, GL_UNSIGNED_BYTE, t256);
  544. else
  545. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, t256);
  546. free(t256);
  547. }
  548. free(bwimage256);
  549. free(bwimage128);
  550. /* both textures use BLEND environment */
  551. if (rgbmode) {
  552.             if (threecomp) {
  553.                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  554.             }
  555.             else {
  556.                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
  557.             }
  558. } else if (FOG_LEVELS > 1) {
  559.             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
  560. } else {
  561.             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  562. }
  563. {
  564.             GLfloat position[] = { LX, LY, LZ, 0., };
  565.             GLfloat one[] = { 1.0, 1.0, 1.0, 1.0 };
  566.             if (rgbmode)
  567.                 glLightfv(GL_LIGHT0, GL_AMBIENT, one);
  568.             glLightfv(GL_LIGHT0, GL_POSITION, position);
  569.             glLightfv(GL_LIGHT0, GL_DIFFUSE, one);
  570.             glLightfv(GL_LIGHT0, GL_SPECULAR, one);
  571. }
  572. if (rgbmode) {
  573. GLfloat ambient[] = { 0.3, 0.3, 0.1, 0.0 };
  574. GLfloat diffuse[] = { 0.7, 0.7, 0.1, 0.0 };
  575. GLfloat zero[] = { 0.0, 0.0, 0.0, 0.0 };
  576. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
  577. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
  578. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
  579. } else {
  580. glMaterialiv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, plane_colors);
  581. }
  582. {
  583. glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
  584. glEnable(GL_LIGHT0);
  585. }
  586. }
  587. void lightpos(void)
  588. {
  589.     GLfloat position[] = { LX, LY, LZ, 0., };
  590.     glLightfv(GL_LIGHT0, GL_POSITION, position);
  591. }
  592. void texenv(int env)
  593. {
  594.     GLfloat colors[3][4] = { { 0., 0., 0., 0., },
  595.                              { .1, .1, .1, 0., },       /* terrain */
  596.                              { 1., 1., 1., 0., }, };    /* sky */
  597.     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, colors[env]);
  598. }
  599. /*-------------------------------- Utility ---------------------------------*/
  600. void err_msg(int type, char* func, char* error)
  601. {
  602. char    msg[512];
  603. if (type & ERR_WARNING) {
  604. fprintf(stderr, "Warning:  ");
  605. sprintf(msg, "Warning:  %s", error);
  606. }
  607. else if (type & ERR_FATAL) {
  608. fprintf(stderr, "FATAL:  ");
  609. sprintf(msg, "FATAL:  %s", error);
  610. }
  611. fprintf(stderr, "%s: %sn", func, error);
  612. if (type & ERR_SYSERR) {
  613. perror("perror() = ");
  614. fprintf(stderr, "errno = %dn", errno);
  615. }
  616. fflush(stderr);
  617. if (type & ERR_FATAL) {
  618. exit(-1);
  619. }
  620. }
  621. void set_fog(int enable)
  622. {
  623.     fog = enable;
  624.     if (fog) {
  625.         glEnable(GL_FOG);
  626.         if (rgbmode)
  627.             glClearColor(fog_params[0], fog_params[1], fog_params[2], 1.0);
  628.         else {
  629.             glClearIndex(sky_base + FOG_LEVELS - 1);
  630.         }
  631.     } else {
  632.         glDisable(GL_FOG);
  633.         if (rgbmode)
  634.             glClearColor(0.23, 0.35, 0.78, 1.0);
  635.         else {
  636.             glClearIndex(sky_base);
  637.         }
  638.     }
  639. }
  640. void set_dither(int enable)
  641. {
  642.     dither = enable;
  643.     if (dither) {
  644.         glEnable(GL_DITHER);
  645.     } else {
  646.         glDisable(GL_DITHER);
  647.     }
  648. }