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
932001f49Smrg#include <stdio.h>
1032001f49Smrg#include <stdlib.h>
1132001f49Smrg#include <math.h>
1232001f49Smrg#include <string.h>
1332001f49Smrg
1432001f49Smrg#if defined (WIN32)|| defined(_WIN32)
1532001f49Smrg#include <windows.h>
1632001f49Smrg#include <mmsystem.h>
1732001f49Smrg#endif
1832001f49Smrg
1932001f49Smrg#include <GL/glew.h> /* for GL_RESCALE_NORMAL_EXT */
2032001f49Smrg#include "glut_wrap.h"
2132001f49Smrg
2232001f49Smrg#include "readtex.h"
2332001f49Smrg
2432001f49Smrg#ifdef XMESA
2532001f49Smrg#include "GL/xmesa.h"
2632001f49Smrgstatic int fullscreen = 1;
2732001f49Smrg#endif
2832001f49Smrg
2932001f49Smrgstatic int WIDTH = 640;
3032001f49Smrgstatic int HEIGHT = 480;
3132001f49Smrg
3232001f49Smrgstatic GLint T0;
3332001f49Smrgstatic GLint Frames;
3432001f49Smrg
3532001f49Smrg#define MAX_LOD 9
3632001f49Smrg
3732001f49Smrg#define TEX_SKY_WIDTH 256
3832001f49Smrg#define TEX_SKY_HEIGHT TEX_SKY_WIDTH
3932001f49Smrg
4032001f49Smrg#ifndef M_PI
4132001f49Smrg#define M_PI 3.1415926535
4232001f49Smrg#endif
4332001f49Smrg
4432001f49Smrg#define FROM_NONE   0
4532001f49Smrg#define FROM_DOWN   1
4632001f49Smrg#define FROM_UP     2
4732001f49Smrg#define FROM_LEFT   3
4832001f49Smrg#define FROM_RIGHT  4
4932001f49Smrg#define FROM_FRONT  5
5032001f49Smrg#define FROM_BACK   6
5132001f49Smrg
5232001f49Smrgstatic int win = 0;
5332001f49Smrg
5432001f49Smrgstatic float obs[3] = { 3.8, 0.0, 0.0 };
5532001f49Smrgstatic float dir[3];
5632001f49Smrgstatic float v = 0.0;
5732001f49Smrgstatic float alpha = -90.0;
5832001f49Smrgstatic float beta = 90.0;
5932001f49Smrg
6032001f49Smrgstatic int fog = 1;
6132001f49Smrgstatic int bfcull = 1;
6232001f49Smrgstatic int usetex = 1;
6332001f49Smrgstatic int help = 1;
6432001f49Smrgstatic int poutline = 0;
6532001f49Smrgstatic int normext = 1;
6632001f49Smrgstatic int joyavailable = 0;
6732001f49Smrgstatic int joyactive = 0;
6832001f49Smrgstatic int LODbias = 3;
6932001f49Smrgstatic int maxdepth = MAX_LOD;
7032001f49Smrg
7132001f49Smrgstatic unsigned int totpoly = 0;
7232001f49Smrg
7332001f49Smrgstatic GLuint t1id, t2id;
7432001f49Smrgstatic GLuint skydlist, LODdlist[MAX_LOD], LODnumpoly[MAX_LOD];
7532001f49Smrg
7632001f49Smrgstatic void
7732001f49Smrginitlight(void)
7832001f49Smrg{
7932001f49Smrg   GLfloat lspec[4] = { 1.0, 1.0, 1.0, 1.0 };
8032001f49Smrg   static GLfloat lightpos[4] = { 30, 15.0, 30.0, 1.0 };
8132001f49Smrg
8232001f49Smrg   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
8332001f49Smrg   glLightfv(GL_LIGHT0, GL_SPECULAR, lspec);
8432001f49Smrg
8532001f49Smrg   glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32.0);
8632001f49Smrg   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, lspec);
8732001f49Smrg}
8832001f49Smrg
8932001f49Smrgstatic void
9032001f49Smrginitdlists(void)
9132001f49Smrg{
9232001f49Smrg   static int slicetable[MAX_LOD][2] = {
9332001f49Smrg      {21, 10},
9432001f49Smrg      {18, 9},
9532001f49Smrg      {15, 8},
9632001f49Smrg      {12, 7},
9732001f49Smrg      {9, 6},
9832001f49Smrg      {7, 5},
9932001f49Smrg      {5, 4},
10032001f49Smrg      {4, 3},
10132001f49Smrg      {3, 2}
10232001f49Smrg   };
10332001f49Smrg   GLUquadricObj *obj;
10432001f49Smrg   int i, xslices, yslices;
10532001f49Smrg
10632001f49Smrg   obj = gluNewQuadric();
10732001f49Smrg
10832001f49Smrg   skydlist = glGenLists(1);
10932001f49Smrg   glNewList(skydlist, GL_COMPILE);
11032001f49Smrg   glBindTexture(GL_TEXTURE_2D, t2id);
11132001f49Smrg   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
11232001f49Smrg   glColor3f(1.0f, 1.0f, 1.0f);
11332001f49Smrg
11432001f49Smrg   gluQuadricDrawStyle(obj, GLU_FILL);
11532001f49Smrg   gluQuadricNormals(obj, GLU_NONE);
11632001f49Smrg   gluQuadricTexture(obj, GL_TRUE);
11732001f49Smrg   gluQuadricOrientation(obj, GLU_INSIDE);
11832001f49Smrg   gluSphere(obj, 40.0f, 18, 9);
11932001f49Smrg
12032001f49Smrg   glEndList();
12132001f49Smrg
12232001f49Smrg   for (i = 0; i < MAX_LOD; i++) {
12332001f49Smrg      LODdlist[i] = glGenLists(1);
12432001f49Smrg      glNewList(LODdlist[i], GL_COMPILE);
12532001f49Smrg
12632001f49Smrg      gluQuadricDrawStyle(obj, GLU_FILL);
12732001f49Smrg      gluQuadricNormals(obj, GLU_SMOOTH);
12832001f49Smrg      gluQuadricTexture(obj, GL_TRUE);
12932001f49Smrg      gluQuadricOrientation(obj, GLU_OUTSIDE);
13032001f49Smrg      xslices = slicetable[i][0];
13132001f49Smrg      yslices = slicetable[i][1];
13232001f49Smrg      gluSphere(obj, 1.0f, xslices, yslices);
13332001f49Smrg      LODnumpoly[i] = xslices * (yslices - 2) + 2 * (xslices - 1);
13432001f49Smrg
13532001f49Smrg      glEndList();
13632001f49Smrg   }
13732001f49Smrg
13832001f49Smrg   gluDeleteQuadric(obj);
13932001f49Smrg}
14032001f49Smrg
14132001f49Smrgstatic void
14232001f49Smrginittextures(void)
14332001f49Smrg{
14432001f49Smrg   GLubyte tsky[TEX_SKY_HEIGHT][TEX_SKY_WIDTH][3];
14532001f49Smrg   GLuint x, y;
14632001f49Smrg   GLfloat fact;
14732001f49Smrg   GLenum gluerr;
14832001f49Smrg
14932001f49Smrg   /* Brick */
15032001f49Smrg
15132001f49Smrg   glGenTextures(1, &t1id);
15232001f49Smrg   glBindTexture(GL_TEXTURE_2D, t1id);
15332001f49Smrg
15432001f49Smrg   if (!LoadRGBMipmaps(DEMOS_DATA_DIR "bw.rgb", 3)) {
15532001f49Smrg      fprintf(stderr, "Error reading a texture.\n");
15632001f49Smrg      exit(-1);
15732001f49Smrg   }
15832001f49Smrg
15932001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
16032001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
16132001f49Smrg
16232001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
16332001f49Smrg		   GL_LINEAR_MIPMAP_LINEAR);
16432001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
16532001f49Smrg
16632001f49Smrg   /* Sky */
16732001f49Smrg
16832001f49Smrg   glGenTextures(1, &t2id);
16932001f49Smrg   glBindTexture(GL_TEXTURE_2D, t2id);
17032001f49Smrg
17132001f49Smrg   for (y = 0; y < TEX_SKY_HEIGHT; y++)
17232001f49Smrg      for (x = 0; x < TEX_SKY_WIDTH; x++)
17332001f49Smrg	 if (y < TEX_SKY_HEIGHT / 2) {
17432001f49Smrg	    fact = y / (GLfloat) (TEX_SKY_HEIGHT / 2);
17532001f49Smrg	    tsky[y][x][0] =
17632001f49Smrg	       (GLubyte) (255.0f * (0.1f * fact + 0.3f * (1.0f - fact)));
17732001f49Smrg	    tsky[y][x][1] =
17832001f49Smrg	       (GLubyte) (255.0f * (0.2f * fact + 1.0f * (1.0f - fact)));
17932001f49Smrg	    tsky[y][x][2] = 255;
18032001f49Smrg	 }
18132001f49Smrg	 else {
18232001f49Smrg	    tsky[y][x][0] = tsky[TEX_SKY_HEIGHT - y - 1][x][0];
18332001f49Smrg	    tsky[y][x][1] = tsky[TEX_SKY_HEIGHT - y - 1][x][1];
18432001f49Smrg	    tsky[y][x][2] = 255;
18532001f49Smrg	 }
18632001f49Smrg
18732001f49Smrg   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
18832001f49Smrg   if (
18932001f49Smrg       (gluerr =
19032001f49Smrg	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TEX_SKY_WIDTH, TEX_SKY_HEIGHT,
19132001f49Smrg			  GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) (tsky)))) {
19232001f49Smrg      fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr));
19332001f49Smrg      exit(-1);
19432001f49Smrg   }
19532001f49Smrg
19632001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
19732001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
19832001f49Smrg
19932001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
20032001f49Smrg		   GL_LINEAR_MIPMAP_LINEAR);
20132001f49Smrg   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
20232001f49Smrg}
20332001f49Smrg
20432001f49Smrgstatic void
20532001f49Smrgcalcposobs(void)
20632001f49Smrg{
20732001f49Smrg   dir[0] = sin(alpha * M_PI / 180.0);
20832001f49Smrg   dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
20932001f49Smrg   dir[2] = cos(beta * M_PI / 180.0);
21032001f49Smrg
21132001f49Smrg   if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
21232001f49Smrg      dir[0] = 0;
21332001f49Smrg   if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
21432001f49Smrg      dir[1] = 0;
21532001f49Smrg   if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
21632001f49Smrg      dir[2] = 0;
21732001f49Smrg
21832001f49Smrg   obs[0] += v * dir[0];
21932001f49Smrg   obs[1] += v * dir[1];
22032001f49Smrg   obs[2] += v * dir[2];
22132001f49Smrg}
22232001f49Smrg
22332001f49Smrgstatic void
22432001f49Smrgspecial(int k, int x, int y)
22532001f49Smrg{
22632001f49Smrg   switch (k) {
22732001f49Smrg   case GLUT_KEY_LEFT:
22832001f49Smrg      alpha -= 2.0;
22932001f49Smrg      break;
23032001f49Smrg   case GLUT_KEY_RIGHT:
23132001f49Smrg      alpha += 2.0;
23232001f49Smrg      break;
23332001f49Smrg   case GLUT_KEY_DOWN:
23432001f49Smrg      beta -= 2.0;
23532001f49Smrg      break;
23632001f49Smrg   case GLUT_KEY_UP:
23732001f49Smrg      beta += 2.0;
23832001f49Smrg      break;
23932001f49Smrg   }
24032001f49Smrg}
24132001f49Smrg
24232001f49Smrgstatic void
24332001f49Smrgcleanup(void)
24432001f49Smrg{
24532001f49Smrg   int i;
24632001f49Smrg
24732001f49Smrg   glDeleteTextures(1, &t1id);
24832001f49Smrg   glDeleteTextures(1, &t2id);
24932001f49Smrg
25032001f49Smrg   glDeleteLists(skydlist, 1);
25132001f49Smrg   for (i = 0; i < MAX_LOD; i++) {
25232001f49Smrg      glDeleteLists(LODdlist[i], 1);
25332001f49Smrg      glDeleteLists(LODnumpoly[i], 1);
25432001f49Smrg   }
25532001f49Smrg
25632001f49Smrg   glutDestroyWindow(glutGetWindow());
25732001f49Smrg}
25832001f49Smrg
25932001f49Smrg
26032001f49Smrgstatic void
26132001f49Smrgkey(unsigned char k, int x, int y)
26232001f49Smrg{
26332001f49Smrg   switch (k) {
26432001f49Smrg   case 27:
26532001f49Smrg      cleanup();
26632001f49Smrg      exit(0);
26732001f49Smrg      break;
26832001f49Smrg
26932001f49Smrg   case 'a':
27032001f49Smrg      v += 0.01;
27132001f49Smrg      break;
27232001f49Smrg   case 'z':
27332001f49Smrg      v -= 0.01;
27432001f49Smrg      break;
27532001f49Smrg
27632001f49Smrg#ifdef XMESA
27732001f49Smrg   case ' ':
27832001f49Smrg      fullscreen = (!fullscreen);
27932001f49Smrg      XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
28032001f49Smrg      break;
28132001f49Smrg#endif
28232001f49Smrg
28332001f49Smrg   case '+':
28432001f49Smrg      LODbias--;
28532001f49Smrg      break;
28632001f49Smrg   case '-':
28732001f49Smrg      LODbias++;
28832001f49Smrg      break;
28932001f49Smrg   case 'j':
29032001f49Smrg      joyactive = (!joyactive);
29132001f49Smrg      break;
29232001f49Smrg   case 'h':
29332001f49Smrg      help = (!help);
29432001f49Smrg      break;
29532001f49Smrg   case 'f':
29632001f49Smrg      fog = (!fog);
29732001f49Smrg      break;
29832001f49Smrg   case 't':
29932001f49Smrg      usetex = (!usetex);
30032001f49Smrg      break;
30132001f49Smrg   case 'n':
30232001f49Smrg      normext = (!normext);
30332001f49Smrg      break;
30432001f49Smrg   case 'b':
30532001f49Smrg      if (bfcull) {
30632001f49Smrg	 glDisable(GL_CULL_FACE);
30732001f49Smrg	 bfcull = 0;
30832001f49Smrg      }
30932001f49Smrg      else {
31032001f49Smrg	 glEnable(GL_CULL_FACE);
31132001f49Smrg	 bfcull = 1;
31232001f49Smrg      }
31332001f49Smrg      break;
31432001f49Smrg   case 'p':
31532001f49Smrg      if (poutline) {
31632001f49Smrg	 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
31732001f49Smrg	 poutline = 0;
31832001f49Smrg	 usetex = 1;
31932001f49Smrg      }
32032001f49Smrg      else {
32132001f49Smrg	 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
32232001f49Smrg	 poutline = 1;
32332001f49Smrg	 usetex = 0;
32432001f49Smrg      }
32532001f49Smrg      break;
32632001f49Smrg   }
32732001f49Smrg}
32832001f49Smrg
32932001f49Smrgstatic void
33032001f49Smrgreshape(int w, int h)
33132001f49Smrg{
33232001f49Smrg   WIDTH = w;
33332001f49Smrg   HEIGHT = h;
33432001f49Smrg   glMatrixMode(GL_PROJECTION);
33532001f49Smrg   glLoadIdentity();
33632001f49Smrg   gluPerspective(90.0, w / (float) h, 0.8, 100.0);
33732001f49Smrg   glMatrixMode(GL_MODELVIEW);
33832001f49Smrg   glLoadIdentity();
33932001f49Smrg   glViewport(0, 0, w, h);
34032001f49Smrg}
34132001f49Smrg
34232001f49Smrgstatic void
34332001f49Smrgprintstring(void *font, char *string)
34432001f49Smrg{
34532001f49Smrg   int len, i;
34632001f49Smrg
34732001f49Smrg   len = (int) strlen(string);
34832001f49Smrg   for (i = 0; i < len; i++)
34932001f49Smrg      glutBitmapCharacter(font, string[i]);
35032001f49Smrg}
35132001f49Smrg
35232001f49Smrgstatic void
35332001f49Smrgprinthelp(void)
35432001f49Smrg{
35532001f49Smrg   glEnable(GL_BLEND);
35632001f49Smrg   glColor4f(0.5, 0.5, 0.5, 0.5);
35732001f49Smrg   glRecti(40, 40, 600, 440);
35832001f49Smrg   glDisable(GL_BLEND);
35932001f49Smrg
36032001f49Smrg   glColor3f(1.0, 0.0, 0.0);
36132001f49Smrg   glRasterPos2i(300, 420);
36232001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
36332001f49Smrg
36432001f49Smrg   glRasterPos2i(60, 390);
36532001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
36632001f49Smrg   glRasterPos2i(60, 360);
36732001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Toggle Textures");
36832001f49Smrg   glRasterPos2i(60, 330);
36932001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
37032001f49Smrg   glRasterPos2i(60, 300);
37132001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Toggle Back face culling");
37232001f49Smrg   glRasterPos2i(60, 270);
37332001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
37432001f49Smrg   glRasterPos2i(60, 240);
37532001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
37632001f49Smrg   glRasterPos2i(60, 210);
37732001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
37832001f49Smrg   glRasterPos2i(60, 180);
37932001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "p - Toggle Wire frame");
38032001f49Smrg   glRasterPos2i(60, 150);
38132001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24,
38232001f49Smrg	       "n - Toggle GL_EXT_rescale_normal extension");
38332001f49Smrg   glRasterPos2i(60, 120);
38432001f49Smrg   printstring(GLUT_BITMAP_TIMES_ROMAN_24,
38532001f49Smrg	       "+/- - Increase/decrease the Object maximum LOD");
38632001f49Smrg
38732001f49Smrg   glRasterPos2i(60, 90);
38832001f49Smrg   if (joyavailable)
38932001f49Smrg      printstring(GLUT_BITMAP_TIMES_ROMAN_24,
39032001f49Smrg		  "j - Toggle jostick control (Joystick control available)");
39132001f49Smrg   else
39232001f49Smrg      printstring(GLUT_BITMAP_TIMES_ROMAN_24,
39332001f49Smrg		  "(No Joystick control available)");
39432001f49Smrg}
39532001f49Smrg
39632001f49Smrgstatic void
39732001f49Smrgdojoy(void)
39832001f49Smrg{
39932001f49Smrg#ifdef _WIN32
40032001f49Smrg   static UINT max[2] = { 0, 0 };
40132001f49Smrg   static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
40232001f49Smrg   MMRESULT res;
40332001f49Smrg   JOYINFO joy;
40432001f49Smrg
40532001f49Smrg   res = joyGetPos(JOYSTICKID1, &joy);
40632001f49Smrg
40732001f49Smrg   if (res == JOYERR_NOERROR) {
40832001f49Smrg      joyavailable = 1;
40932001f49Smrg
41032001f49Smrg      if (max[0] < joy.wXpos)
41132001f49Smrg	 max[0] = joy.wXpos;
41232001f49Smrg      if (min[0] > joy.wXpos)
41332001f49Smrg	 min[0] = joy.wXpos;
41432001f49Smrg      center[0] = (max[0] + min[0]) / 2;
41532001f49Smrg
41632001f49Smrg      if (max[1] < joy.wYpos)
41732001f49Smrg	 max[1] = joy.wYpos;
41832001f49Smrg      if (min[1] > joy.wYpos)
41932001f49Smrg	 min[1] = joy.wYpos;
42032001f49Smrg      center[1] = (max[1] + min[1]) / 2;
42132001f49Smrg
42232001f49Smrg      if (joyactive) {
42332001f49Smrg	 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
42432001f49Smrg	    alpha -=
42532001f49Smrg	       2.0 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
42632001f49Smrg	 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
42732001f49Smrg	    beta += 2.0 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
42832001f49Smrg
42932001f49Smrg	 if (joy.wButtons & JOY_BUTTON1)
43032001f49Smrg	    v += 0.01;
43132001f49Smrg	 if (joy.wButtons & JOY_BUTTON2)
43232001f49Smrg	    v -= 0.01;
43332001f49Smrg      }
43432001f49Smrg   }
43532001f49Smrg   else
43632001f49Smrg      joyavailable = 0;
43732001f49Smrg#endif
43832001f49Smrg}
43932001f49Smrg
44032001f49Smrgstatic void
44132001f49Smrgdrawipers(int depth, int from)
44232001f49Smrg{
44332001f49Smrg   int lod;
44432001f49Smrg
44532001f49Smrg   if (depth == maxdepth)
44632001f49Smrg      return;
44732001f49Smrg
44832001f49Smrg   lod = depth + LODbias;
44932001f49Smrg   if (lod < 0)
45032001f49Smrg      lod = 0;
45132001f49Smrg   if (lod >= MAX_LOD)
45232001f49Smrg      return;
45332001f49Smrg
45432001f49Smrg   switch (from) {
45532001f49Smrg   case FROM_NONE:
45632001f49Smrg      glCallList(LODdlist[lod]);
45732001f49Smrg
45832001f49Smrg      depth++;
45932001f49Smrg      drawipers(depth, FROM_DOWN);
46032001f49Smrg      drawipers(depth, FROM_UP);
46132001f49Smrg      drawipers(depth, FROM_FRONT);
46232001f49Smrg      drawipers(depth, FROM_BACK);
46332001f49Smrg      drawipers(depth, FROM_LEFT);
46432001f49Smrg      drawipers(depth, FROM_RIGHT);
46532001f49Smrg      break;
46632001f49Smrg   case FROM_FRONT:
46732001f49Smrg      glPushMatrix();
46832001f49Smrg      glTranslatef(0.0f, -1.5f, 0.0f);
46932001f49Smrg      glScalef(0.5f, 0.5f, 0.5f);
47032001f49Smrg
47132001f49Smrg      glCallList(LODdlist[lod]);
47232001f49Smrg
47332001f49Smrg      depth++;
47432001f49Smrg      drawipers(depth, FROM_DOWN);
47532001f49Smrg      drawipers(depth, FROM_UP);
47632001f49Smrg      drawipers(depth, FROM_FRONT);
47732001f49Smrg      drawipers(depth, FROM_LEFT);
47832001f49Smrg      drawipers(depth, FROM_RIGHT);
47932001f49Smrg      glPopMatrix();
48032001f49Smrg      break;
48132001f49Smrg   case FROM_BACK:
48232001f49Smrg      glPushMatrix();
48332001f49Smrg      glTranslatef(0.0f, 1.5f, 0.0f);
48432001f49Smrg      glScalef(0.5f, 0.5f, 0.5f);
48532001f49Smrg
48632001f49Smrg      glCallList(LODdlist[lod]);
48732001f49Smrg
48832001f49Smrg      depth++;
48932001f49Smrg      drawipers(depth, FROM_DOWN);
49032001f49Smrg      drawipers(depth, FROM_UP);
49132001f49Smrg      drawipers(depth, FROM_BACK);
49232001f49Smrg      drawipers(depth, FROM_LEFT);
49332001f49Smrg      drawipers(depth, FROM_RIGHT);
49432001f49Smrg      glPopMatrix();
49532001f49Smrg      break;
49632001f49Smrg   case FROM_LEFT:
49732001f49Smrg      glPushMatrix();
49832001f49Smrg      glTranslatef(-1.5f, 0.0f, 0.0f);
49932001f49Smrg      glScalef(0.5f, 0.5f, 0.5f);
50032001f49Smrg
50132001f49Smrg      glCallList(LODdlist[lod]);
50232001f49Smrg
50332001f49Smrg      depth++;
50432001f49Smrg      drawipers(depth, FROM_DOWN);
50532001f49Smrg      drawipers(depth, FROM_UP);
50632001f49Smrg      drawipers(depth, FROM_FRONT);
50732001f49Smrg      drawipers(depth, FROM_BACK);
50832001f49Smrg      drawipers(depth, FROM_LEFT);
50932001f49Smrg      glPopMatrix();
51032001f49Smrg      break;
51132001f49Smrg   case FROM_RIGHT:
51232001f49Smrg      glPushMatrix();
51332001f49Smrg      glTranslatef(1.5f, 0.0f, 0.0f);
51432001f49Smrg      glScalef(0.5f, 0.5f, 0.5f);
51532001f49Smrg
51632001f49Smrg      glCallList(LODdlist[lod]);
51732001f49Smrg
51832001f49Smrg      depth++;
51932001f49Smrg      drawipers(depth, FROM_DOWN);
52032001f49Smrg      drawipers(depth, FROM_UP);
52132001f49Smrg      drawipers(depth, FROM_FRONT);
52232001f49Smrg      drawipers(depth, FROM_BACK);
52332001f49Smrg      drawipers(depth, FROM_RIGHT);
52432001f49Smrg      glPopMatrix();
52532001f49Smrg      break;
52632001f49Smrg   case FROM_DOWN:
52732001f49Smrg      glPushMatrix();
52832001f49Smrg      glTranslatef(0.0f, 0.0f, 1.5f);
52932001f49Smrg      glScalef(0.5f, 0.5f, 0.5f);
53032001f49Smrg
53132001f49Smrg      glCallList(LODdlist[lod]);
53232001f49Smrg
53332001f49Smrg      depth++;
53432001f49Smrg      drawipers(depth, FROM_DOWN);
53532001f49Smrg      drawipers(depth, FROM_FRONT);
53632001f49Smrg      drawipers(depth, FROM_BACK);
53732001f49Smrg      drawipers(depth, FROM_LEFT);
53832001f49Smrg      drawipers(depth, FROM_RIGHT);
53932001f49Smrg      glPopMatrix();
54032001f49Smrg      break;
54132001f49Smrg   case FROM_UP:
54232001f49Smrg      glPushMatrix();
54332001f49Smrg      glTranslatef(0.0f, 0.0f, -1.5f);
54432001f49Smrg      glScalef(0.5f, 0.5f, 0.5f);
54532001f49Smrg
54632001f49Smrg      glCallList(LODdlist[lod]);
54732001f49Smrg
54832001f49Smrg      depth++;
54932001f49Smrg      drawipers(depth, FROM_UP);
55032001f49Smrg      drawipers(depth, FROM_FRONT);
55132001f49Smrg      drawipers(depth, FROM_BACK);
55232001f49Smrg      drawipers(depth, FROM_LEFT);
55332001f49Smrg      drawipers(depth, FROM_RIGHT);
55432001f49Smrg      glPopMatrix();
55532001f49Smrg      break;
55632001f49Smrg   }
55732001f49Smrg
55832001f49Smrg   totpoly += LODnumpoly[lod];
55932001f49Smrg}
56032001f49Smrg
56132001f49Smrgstatic void
56232001f49Smrgdraw(void)
56332001f49Smrg{
56432001f49Smrg   static char frbuf[80] = "";
56532001f49Smrg   static GLfloat alpha = 0.0f;
56632001f49Smrg   static GLfloat beta = 0.0f;
56732001f49Smrg   static float fr = 0.0;
56832001f49Smrg   static double t0 = -1.;
56932001f49Smrg   double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
57032001f49Smrg   if (t0 < 0.0)
57132001f49Smrg      t0 = t;
57232001f49Smrg   dt = t - t0;
57332001f49Smrg   t0 = t;
57432001f49Smrg
57532001f49Smrg   dojoy();
57632001f49Smrg
57732001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
57832001f49Smrg
57932001f49Smrg   if (usetex)
58032001f49Smrg      glEnable(GL_TEXTURE_2D);
58132001f49Smrg   else
58232001f49Smrg      glDisable(GL_TEXTURE_2D);
58332001f49Smrg
58432001f49Smrg   if (fog)
58532001f49Smrg      glEnable(GL_FOG);
58632001f49Smrg   else
58732001f49Smrg      glDisable(GL_FOG);
58832001f49Smrg
58932001f49Smrg   glPushMatrix();
59032001f49Smrg   calcposobs();
59132001f49Smrg   gluLookAt(obs[0], obs[1], obs[2],
59232001f49Smrg	     obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
59332001f49Smrg	     0.0, 0.0, 1.0);
59432001f49Smrg
59532001f49Smrg   /* Scene */
59632001f49Smrg   glEnable(GL_DEPTH_TEST);
59732001f49Smrg
59832001f49Smrg   glShadeModel(GL_SMOOTH);
59932001f49Smrg   glBindTexture(GL_TEXTURE_2D, t1id);
60032001f49Smrg   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
60132001f49Smrg   glColor3f(1.0f, 1.0f, 1.0f);
60232001f49Smrg   glEnable(GL_LIGHT0);
60332001f49Smrg   glEnable(GL_LIGHTING);
60432001f49Smrg
60532001f49Smrg   if (normext)
60632001f49Smrg      glEnable(GL_RESCALE_NORMAL_EXT);
60732001f49Smrg   else
60832001f49Smrg      glEnable(GL_NORMALIZE);
60932001f49Smrg
61032001f49Smrg   glPushMatrix();
61132001f49Smrg   glRotatef(alpha, 0.0f, 0.0f, 1.0f);
61232001f49Smrg   glRotatef(beta, 1.0f, 0.0f, 0.0f);
61332001f49Smrg   totpoly = 0;
61432001f49Smrg   drawipers(0, FROM_NONE);
61532001f49Smrg   glPopMatrix();
61632001f49Smrg
61732001f49Smrg   alpha += 4.f * dt;
61832001f49Smrg   beta += 2.4f * dt;
61932001f49Smrg
62032001f49Smrg   glDisable(GL_LIGHTING);
62132001f49Smrg   glDisable(GL_LIGHT0);
62232001f49Smrg   glShadeModel(GL_FLAT);
62332001f49Smrg
62432001f49Smrg   if (normext)
62532001f49Smrg      glDisable(GL_RESCALE_NORMAL_EXT);
62632001f49Smrg   else
62732001f49Smrg      glDisable(GL_NORMALIZE);
62832001f49Smrg
62932001f49Smrg   glCallList(skydlist);
63032001f49Smrg
63132001f49Smrg   glPopMatrix();
63232001f49Smrg
63332001f49Smrg   /* Help Screen */
63432001f49Smrg
63532001f49Smrg   sprintf(frbuf,
63632001f49Smrg	   "Frame rate: %0.2f   LOD: %d   Tot. poly.: %d   Poly/sec: %.1f",
63732001f49Smrg	   fr, LODbias, totpoly, totpoly * fr);
63832001f49Smrg
63932001f49Smrg   glDisable(GL_TEXTURE_2D);
64032001f49Smrg   glDisable(GL_FOG);
64132001f49Smrg   glShadeModel(GL_FLAT);
64232001f49Smrg   glDisable(GL_DEPTH_TEST);
64332001f49Smrg
64432001f49Smrg   glMatrixMode(GL_PROJECTION);
64532001f49Smrg   glPushMatrix();
64632001f49Smrg   glLoadIdentity();
64732001f49Smrg   glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
64832001f49Smrg
64932001f49Smrg   glMatrixMode(GL_MODELVIEW);
65032001f49Smrg   glLoadIdentity();
65132001f49Smrg
65232001f49Smrg   glColor3f(1.0, 0.0, 0.0);
65332001f49Smrg   glRasterPos2i(10, 10);
65432001f49Smrg   printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
65532001f49Smrg   glRasterPos2i(350, 470);
65632001f49Smrg   printstring(GLUT_BITMAP_HELVETICA_10,
65732001f49Smrg	       "IperS V1.0 Written by David Bucciarelli (tech.hmw@plus.it)");
65832001f49Smrg
65932001f49Smrg   if (help)
66032001f49Smrg      printhelp();
66132001f49Smrg
66232001f49Smrg   glMatrixMode(GL_PROJECTION);
66332001f49Smrg   glPopMatrix();
66432001f49Smrg   glMatrixMode(GL_MODELVIEW);
66532001f49Smrg
66632001f49Smrg   glutSwapBuffers();
66732001f49Smrg
66832001f49Smrg   Frames++;
66932001f49Smrg   {
67032001f49Smrg      GLint t = glutGet(GLUT_ELAPSED_TIME);
67132001f49Smrg      if (t - T0 >= 2000) {
67232001f49Smrg         GLfloat seconds = (t - T0) / 1000.0;
67332001f49Smrg         fr = Frames / seconds;
67432001f49Smrg         printf("Frame rate: %f\n", fr);
67532001f49Smrg         fflush(stdout);
67632001f49Smrg         T0 = t;
67732001f49Smrg         Frames = 0;
67832001f49Smrg      }
67932001f49Smrg   }
68032001f49Smrg}
68132001f49Smrg
68232001f49Smrgint
68332001f49Smrgmain(int ac, char **av)
68432001f49Smrg{
68532001f49Smrg   float fogcolor[4] = { 0.7, 0.7, 0.7, 1.0 };
68632001f49Smrg
68732001f49Smrg   fprintf(stderr,
68832001f49Smrg	   "IperS V1.0\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
68932001f49Smrg
69032001f49Smrg   glutInitWindowSize(WIDTH, HEIGHT);
69132001f49Smrg   glutInit(&ac, av);
69232001f49Smrg
69332001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
69432001f49Smrg
69532001f49Smrg   if (!(win = glutCreateWindow("IperS"))) {
69632001f49Smrg      fprintf(stderr, "Error, couldn't open window\n");
69732001f49Smrg      exit(-1);
69832001f49Smrg   }
69932001f49Smrg
70032001f49Smrg   reshape(WIDTH, HEIGHT);
70132001f49Smrg
70232001f49Smrg   glShadeModel(GL_SMOOTH);
70332001f49Smrg   glEnable(GL_DEPTH_TEST);
70432001f49Smrg   glEnable(GL_CULL_FACE);
70532001f49Smrg   glEnable(GL_TEXTURE_2D);
70632001f49Smrg
70732001f49Smrg   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
70832001f49Smrg
70932001f49Smrg   glEnable(GL_FOG);
71032001f49Smrg   glFogi(GL_FOG_MODE, GL_EXP2);
71132001f49Smrg   glFogfv(GL_FOG_COLOR, fogcolor);
71232001f49Smrg
71332001f49Smrg   glFogf(GL_FOG_DENSITY, 0.006);
71432001f49Smrg
71532001f49Smrg   glHint(GL_FOG_HINT, GL_NICEST);
71632001f49Smrg
71732001f49Smrg   inittextures();
71832001f49Smrg   initdlists();
71932001f49Smrg   initlight();
72032001f49Smrg
72132001f49Smrg   glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
72232001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
72332001f49Smrg
72432001f49Smrg   calcposobs();
72532001f49Smrg
72632001f49Smrg   glutReshapeFunc(reshape);
72732001f49Smrg   glutDisplayFunc(draw);
72832001f49Smrg   glutKeyboardFunc(key);
72932001f49Smrg   glutSpecialFunc(special);
73032001f49Smrg   glutIdleFunc(draw);
73132001f49Smrg
73232001f49Smrg   glutMainLoop();
73332001f49Smrg   cleanup();
73432001f49Smrg
73532001f49Smrg   return 0;
73632001f49Smrg}
737