summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--progs/demos/fire.c732
-rw-r--r--progs/demos/gltestperf.c580
-rw-r--r--progs/demos/ipers.c704
-rw-r--r--progs/demos/particles.cxx219
-rw-r--r--progs/demos/particles.h81
-rw-r--r--progs/demos/rain.cxx388
-rw-r--r--progs/demos/ray.c908
-rw-r--r--progs/demos/shadow.c117
-rw-r--r--progs/demos/teapot.c575
-rw-r--r--progs/demos/terrain.c653
-rw-r--r--progs/demos/tunnel.c514
-rw-r--r--progs/demos/tunnel2.c618
-rw-r--r--progs/demos/tunneldat.c83
13 files changed, 6172 insertions, 0 deletions
diff --git a/progs/demos/fire.c b/progs/demos/fire.c
new file mode 100644
index 00000000000..056598d5c31
--- /dev/null
+++ b/progs/demos/fire.c
@@ -0,0 +1,732 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+
+#ifdef WIN32
+#include <windows.h>
+#include <mmsystem.h>
+#endif
+
+#include <GL/glut.h>
+#include "../util/readtex.c"
+
+#ifdef XMESA
+#include "GL/xmesa.h"
+static int fullscreen = 1;
+#endif
+
+#ifndef M_PI
+#define M_PI 3.1415926535
+#endif
+
+#define vinit(a,i,j,k) {\
+ (a)[0]=i;\
+ (a)[1]=j;\
+ (a)[2]=k;\
+}
+
+#define vinit4(a,i,j,k,w) {\
+ (a)[0]=i;\
+ (a)[1]=j;\
+ (a)[2]=k;\
+ (a)[3]=w;\
+}
+
+
+#define vadds(a,dt,b) {\
+ (a)[0]+=(dt)*(b)[0];\
+ (a)[1]+=(dt)*(b)[1];\
+ (a)[2]+=(dt)*(b)[2];\
+}
+
+#define vequ(a,b) {\
+ (a)[0]=(b)[0];\
+ (a)[1]=(b)[1];\
+ (a)[2]=(b)[2];\
+}
+
+#define vinter(a,dt,b,c) {\
+ (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\
+ (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\
+ (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\
+}
+
+#define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
+
+#define vclamp(v) {\
+ (v)[0]=clamp((v)[0]);\
+ (v)[1]=clamp((v)[1]);\
+ (v)[2]=clamp((v)[2]);\
+}
+
+static int WIDTH = 640;
+static int HEIGHT = 480;
+
+#define FRAME 50
+#define DIMP 20.0
+#define DIMTP 16.0
+
+#define RIDCOL 0.4
+
+#define NUMTREE 50
+#define TREEINR 2.5
+#define TREEOUTR 8.0
+
+#define AGRAV -9.8
+
+typedef struct
+{
+ int age;
+ float p[3][3];
+ float v[3];
+ float c[3][4];
+}
+part;
+
+static float treepos[NUMTREE][3];
+
+static float black[3] = { 0.0, 0.0, 0.0 };
+static float blu[3] = { 0.0, 0.2, 1.0 };
+static float blu2[3] = { 0.0, 1.0, 1.0 };
+
+static float fogcolor[4] = { 1.0, 1.0, 1.0, 1.0 };
+
+static float q[4][3] = {
+ {-DIMP, 0.0, -DIMP},
+ {DIMP, 0.0, -DIMP},
+ {DIMP, 0.0, DIMP},
+ {-DIMP, 0.0, DIMP}
+};
+
+static float qt[4][2] = {
+ {-DIMTP, -DIMTP},
+ {DIMTP, -DIMTP},
+ {DIMTP, DIMTP},
+ {-DIMTP, DIMTP}
+};
+
+static int win = 0;
+
+static int np;
+static float eject_r, dt, maxage, eject_vy, eject_vl;
+static short shadows;
+static float ridtri;
+static int fog = 1;
+static int help = 1;
+static int joyavailable = 0;
+static int joyactive = 0;
+
+static part *p;
+
+static GLuint groundid;
+static GLuint treeid;
+
+static float obs[3] = { 2.0, 1.0, 0.0 };
+static float dir[3];
+static float v = 0.0;
+static float alpha = -90.0;
+static float beta = 90.0;
+
+static float
+gettime(void)
+{
+ static clock_t told = 0;
+ clock_t tnew, ris;
+
+ tnew = clock();
+
+ ris = tnew - told;
+
+ told = tnew;
+
+ return (ris / (float) CLOCKS_PER_SEC);
+}
+
+float
+vrnd(void)
+{
+ return (((float) rand()) / RAND_MAX);
+}
+
+static void
+setnewpart(part * p)
+{
+ float a, v[3], *c;
+
+ p->age = 0;
+
+ a = vrnd() * 3.14159265359 * 2.0;
+
+ vinit(v, sin(a) * eject_r * vrnd(), 0.15, cos(a) * eject_r * vrnd());
+ vinit(p->p[0], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
+ v[2] + vrnd() * ridtri);
+ vinit(p->p[1], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
+ v[2] + vrnd() * ridtri);
+ vinit(p->p[2], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
+ v[2] + vrnd() * ridtri);
+
+ vinit(p->v, v[0] * eject_vl / (eject_r / 2),
+ vrnd() * eject_vy + eject_vy / 2, v[2] * eject_vl / (eject_r / 2));
+
+ c = blu;
+
+ vinit4(p->c[0], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
+ c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
+ c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
+ vinit4(p->c[1], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
+ c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
+ c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
+ vinit4(p->c[2], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
+ c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
+ c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
+}
+
+static void
+setpart(part * p)
+{
+ float fact;
+
+ if (p->p[0][1] < 0.1) {
+ setnewpart(p);
+ return;
+ }
+
+ p->v[1] += AGRAV * dt;
+
+ vadds(p->p[0], dt, p->v);
+ vadds(p->p[1], dt, p->v);
+ vadds(p->p[2], dt, p->v);
+
+ p->age++;
+
+ if ((p->age) > maxage) {
+ vequ(p->c[0], blu2);
+ vequ(p->c[1], blu2);
+ vequ(p->c[2], blu2);
+ }
+ else {
+ fact = 1.0 / maxage;
+ vadds(p->c[0], fact, blu2);
+ vclamp(p->c[0]);
+ p->c[0][3] = fact * (maxage - p->age);
+
+ vadds(p->c[1], fact, blu2);
+ vclamp(p->c[1]);
+ p->c[1][3] = fact * (maxage - p->age);
+
+ vadds(p->c[2], fact, blu2);
+ vclamp(p->c[2]);
+ p->c[2][3] = fact * (maxage - p->age);
+ }
+}
+
+static void
+drawtree(float x, float y, float z)
+{
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0, 0.0);
+ glVertex3f(x - 1.5, y + 0.0, z);
+
+ glTexCoord2f(1.0, 0.0);
+ glVertex3f(x + 1.5, y + 0.0, z);
+
+ glTexCoord2f(1.0, 1.0);
+ glVertex3f(x + 1.5, y + 3.0, z);
+
+ glTexCoord2f(0.0, 1.0);
+ glVertex3f(x - 1.5, y + 3.0, z);
+
+
+ glTexCoord2f(0.0, 0.0);
+ glVertex3f(x, y + 0.0, z - 1.5);
+
+ glTexCoord2f(1.0, 0.0);
+ glVertex3f(x, y + 0.0, z + 1.5);
+
+ glTexCoord2f(1.0, 1.0);
+ glVertex3f(x, y + 3.0, z + 1.5);
+
+ glTexCoord2f(0.0, 1.0);
+ glVertex3f(x, y + 3.0, z - 1.5);
+
+ glEnd();
+
+}
+
+static void
+calcposobs(void)
+{
+ dir[0] = sin(alpha * M_PI / 180.0);
+ dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
+ dir[1] = cos(beta * M_PI / 180.0);
+
+ obs[0] += v * dir[0];
+ obs[1] += v * dir[1];
+ obs[2] += v * dir[2];
+}
+
+static void
+printstring(void *font, char *string)
+{
+ int len, i;
+
+ len = (int) strlen(string);
+ for (i = 0; i < len; i++)
+ glutBitmapCharacter(font, string[i]);
+}
+
+static void
+reshape(int width, int height)
+{
+ WIDTH = width;
+ HEIGHT = height;
+ glViewport(0, 0, (GLint) width, (GLint) height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(70.0, width / (float) height, 0.1, 30.0);
+
+ glMatrixMode(GL_MODELVIEW);
+}
+
+static void
+printhelp(void)
+{
+ glColor4f(0.0, 0.0, 0.0, 0.5);
+ glRecti(40, 40, 600, 440);
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(300, 420);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
+
+ glRasterPos2i(60, 390);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Togle Help");
+
+ glRasterPos2i(60, 360);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Increase particle size");
+ glRasterPos2i(60, 330);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "T - Decrease particle size");
+
+ glRasterPos2i(60, 300);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "r - Increase emission radius");
+ glRasterPos2i(60, 270);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "R - Decrease emission radius");
+
+ glRasterPos2i(60, 240);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Togle Fog");
+ glRasterPos2i(60, 210);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "s - Togle shadows");
+ glRasterPos2i(60, 180);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
+ glRasterPos2i(60, 150);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
+ glRasterPos2i(60, 120);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
+
+ glRasterPos2i(60, 90);
+ if (joyavailable)
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "j - Togle jostick control (Joystick control available)");
+ else
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "(No Joystick control available)");
+}
+
+static void
+dojoy(void)
+{
+#ifdef WIN32
+ static UINT max[2] = { 0, 0 };
+ static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
+ MMRESULT res;
+ JOYINFO joy;
+
+ res = joyGetPos(JOYSTICKID1, &joy);
+
+ if (res == JOYERR_NOERROR) {
+ joyavailable = 1;
+
+ if (max[0] < joy.wXpos)
+ max[0] = joy.wXpos;
+ if (min[0] > joy.wXpos)
+ min[0] = joy.wXpos;
+ center[0] = (max[0] + min[0]) / 2;
+
+ if (max[1] < joy.wYpos)
+ max[1] = joy.wYpos;
+ if (min[1] > joy.wYpos)
+ min[1] = joy.wYpos;
+ center[1] = (max[1] + min[1]) / 2;
+
+ if (joyactive) {
+ if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
+ alpha +=
+ 2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
+ if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
+ beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
+
+ if (joy.wButtons & JOY_BUTTON1)
+ v += 0.01;
+ if (joy.wButtons & JOY_BUTTON2)
+ v -= 0.01;
+ }
+ }
+ else
+ joyavailable = 0;
+#endif
+}
+
+static void
+drawfire(void)
+{
+ static int count = 0;
+ static char frbuf[80];
+ int j;
+ float fr;
+
+ dojoy();
+
+ glEnable(GL_DEPTH_TEST);
+
+ if (fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ glDepthMask(GL_TRUE);
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ calcposobs();
+ gluLookAt(obs[0], obs[1], obs[2],
+ obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
+ 0.0, 1.0, 0.0);
+
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, groundid);
+ glBegin(GL_QUADS);
+ glTexCoord2fv(qt[0]);
+ glVertex3fv(q[0]);
+ glTexCoord2fv(qt[1]);
+ glVertex3fv(q[1]);
+ glTexCoord2fv(qt[2]);
+ glVertex3fv(q[2]);
+ glTexCoord2fv(qt[3]);
+ glVertex3fv(q[3]);
+ glEnd();
+
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GEQUAL, 0.9);
+
+ glBindTexture(GL_TEXTURE_2D, treeid);
+ for (j = 0; j < NUMTREE; j++)
+ drawtree(treepos[j][0], treepos[j][1], treepos[j][2]);
+
+ glDisable(GL_TEXTURE_2D);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_ALPHA_TEST);
+
+ if (shadows) {
+ glBegin(GL_TRIANGLES);
+ for (j = 0; j < np; j++) {
+ glColor4f(black[0], black[1], black[2], p[j].c[0][3]);
+ glVertex3f(p[j].p[0][0], 0.1, p[j].p[0][2]);
+
+ glColor4f(black[0], black[1], black[2], p[j].c[1][3]);
+ glVertex3f(p[j].p[1][0], 0.1, p[j].p[1][2]);
+
+ glColor4f(black[0], black[1], black[2], p[j].c[2][3]);
+ glVertex3f(p[j].p[2][0], 0.1, p[j].p[2][2]);
+ }
+ glEnd();
+ }
+
+ glBegin(GL_TRIANGLES);
+ for (j = 0; j < np; j++) {
+ glColor4fv(p[j].c[0]);
+ glVertex3fv(p[j].p[0]);
+
+ glColor4fv(p[j].c[1]);
+ glVertex3fv(p[j].p[1]);
+
+ glColor4fv(p[j].c[2]);
+ glVertex3fv(p[j].p[2]);
+
+ setpart(&p[j]);
+ }
+ glEnd();
+
+ if ((count % FRAME) == 0) {
+ fr = gettime();
+ sprintf(frbuf, "Frame rate: %f", FRAME / fr);
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_ALPHA_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_FOG);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(10, 10);
+ printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
+ glRasterPos2i(370, 470);
+ printstring(GLUT_BITMAP_HELVETICA_10,
+ "Fire V1.5 Written by David Bucciarelli ([email protected])");
+
+ if (help)
+ printhelp();
+
+ reshape(WIDTH, HEIGHT);
+ glPopMatrix();
+
+ glutSwapBuffers();
+
+ count++;
+}
+
+
+static void
+special(int key, int x, int y)
+{
+ switch (key) {
+ case GLUT_KEY_LEFT:
+ alpha += 2.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ alpha -= 2.0;
+ break;
+ case GLUT_KEY_DOWN:
+ beta -= 2.0;
+ break;
+ case GLUT_KEY_UP:
+ beta += 2.0;
+ break;
+ }
+}
+
+static void
+key(unsigned char key, int x, int y)
+{
+ switch (key) {
+ case 27:
+ exit(0);
+ break;
+
+ case 'a':
+ v += 0.01;
+ break;
+ case 'z':
+ v -= 0.01;
+ break;
+
+ case 'j':
+ joyactive = (!joyactive);
+ break;
+ case 'h':
+ help = (!help);
+ break;
+ case 'f':
+ fog = (!fog);
+ break;
+ case 's':
+ shadows = !shadows;
+ break;
+ case 'R':
+ eject_r -= 0.03;
+ break;
+ case 'r':
+ eject_r += 0.03;
+ break;
+ case 't':
+ ridtri += 0.005;
+ break;
+ case 'T':
+ ridtri -= 0.005;
+ break;
+#ifdef XMESA
+ case ' ':
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+ fullscreen = (!fullscreen);
+ break;
+#endif
+ }
+}
+
+static void
+inittextures(void)
+{
+ GLenum gluerr;
+ GLubyte tex[128][128][4];
+
+ glGenTextures(1, &groundid);
+ glBindTexture(GL_TEXTURE_2D, groundid);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB)) {
+ fprintf(stderr, "Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+
+ glGenTextures(1, &treeid);
+ glBindTexture(GL_TEXTURE_2D, treeid);
+
+ {
+ int w, h;
+ GLenum format;
+ int x, y;
+ GLubyte *image = LoadRGBImage("../images/tree2.rgb", &w, &h, &format);
+
+ if (!image) {
+ fprintf(stderr, "Error reading a texture.\n");
+ exit(-1);
+ }
+
+ for (y = 0; y < 128; y++)
+ for (x = 0; x < 128; x++) {
+ tex[x][y][0] = image[(y + x * 128) * 3];
+ tex[x][y][1] = image[(y + x * 128) * 3 + 1];
+ tex[x][y][2] = image[(y + x * 128) * 3 + 2];
+ if ((tex[x][y][0] == tex[x][y][1]) &&
+ (tex[x][y][1] == tex[x][y][2]) && (tex[x][y][2] == 255))
+ tex[x][y][3] = 0;
+ else
+ tex[x][y][3] = 255;
+ }
+
+ if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 128, 128, GL_RGBA,
+ GL_UNSIGNED_BYTE, (GLvoid *) (tex)))) {
+ fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
+ exit(-1);
+ }
+ }
+
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+static void
+inittree(void)
+{
+ int i;
+ float dist;
+
+ for (i = 0; i < NUMTREE; i++)
+ do {
+ treepos[i][0] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
+ treepos[i][1] = 0.0;
+ treepos[i][2] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
+ dist =
+ sqrt(treepos[i][0] * treepos[i][0] +
+ treepos[i][2] * treepos[i][2]);
+ } while ((dist < TREEINR) || (dist > TREEOUTR));
+}
+
+int
+main(int ac, char **av)
+{
+ int i;
+
+ fprintf(stderr,
+ "Fire V1.5\nWritten by David Bucciarelli ([email protected])\n");
+
+ /* Default settings */
+
+ WIDTH = 640;
+ HEIGHT = 480;
+ np = 800;
+ eject_r = 0.1;
+ dt = 0.015;
+ eject_vy = 4;
+ eject_vl = 1;
+ shadows = 1;
+ ridtri = 0.1;
+
+ maxage = 1.0 / dt;
+
+ if (ac == 2)
+ np = atoi(av[1]);
+
+ if (ac == 4) {
+ WIDTH = atoi(av[2]);
+ HEIGHT = atoi(av[3]);
+ }
+
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(WIDTH, HEIGHT);
+ glutInit(&ac, av);
+
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
+
+ if (!(win = glutCreateWindow("Fire"))) {
+ fprintf(stderr, "Error opening a window.\n");
+ exit(-1);
+ }
+
+ reshape(WIDTH, HEIGHT);
+
+ inittextures();
+
+ glShadeModel(GL_FLAT);
+ glEnable(GL_DEPTH_TEST);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_EXP);
+ glFogfv(GL_FOG_COLOR, fogcolor);
+ glFogf(GL_FOG_DENSITY, 0.1);
+#ifdef FX
+ glHint(GL_FOG_HINT, GL_NICEST);
+#endif
+
+ p = malloc(sizeof(part) * np);
+
+ for (i = 0; i < np; i++)
+ setnewpart(&p[i]);
+
+ inittree();
+
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+ glutDisplayFunc(drawfire);
+ glutIdleFunc(drawfire);
+ glutReshapeFunc(reshape);
+ glutMainLoop();
+
+ return (0);
+}
diff --git a/progs/demos/gltestperf.c b/progs/demos/gltestperf.c
new file mode 100644
index 00000000000..2df168ba54d
--- /dev/null
+++ b/progs/demos/gltestperf.c
@@ -0,0 +1,580 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <GL/glut.h>
+
+typedef struct
+{
+ char *name;
+ char *unit;
+ void (*init) (void);
+ int (*run) (int, int);
+ int type;
+ int numsize;
+ int size[10];
+}
+benchmark;
+
+static int frontbuffer = 1;
+
+/***************************************************************************/
+
+static void
+init_test01(void)
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluOrtho2D(-0.5, 639.5, -0.5, 479.5);
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_FLAT);
+ glDisable(GL_DEPTH_TEST);
+
+ glClearColor(0.0, 0.1, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColor3f(1.0, 0.0, 0.0);
+}
+
+static int
+test01(int size, int num)
+{
+ int x, y;
+
+ glBegin(GL_POINTS);
+ for (y = 0; y < num; y++)
+ for (x = 0; x < 480; x++)
+ glVertex2i(x, x);
+ glEnd();
+
+ return 480 * num;
+}
+
+/***************************************************************************/
+
+static void
+init_test02(void)
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluOrtho2D(-0.5, 639.5, -0.5, 479.5);
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+
+ glClearColor(0.0, 0.1, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+static int
+test02(int size, int num)
+{
+ int x, y;
+
+ glBegin(GL_LINES);
+ for (y = 0; y < num; y++)
+ for (x = 0; x < size; x++) {
+ glColor3f(0.0, 1.0, y / (float) num);
+ glVertex2i(0, size - 1);
+ glColor3f(1.0, 0.0, x / (float) size);
+ glVertex2i(x, x);
+ }
+ glEnd();
+
+ return num * size;
+}
+
+/***************************************************************************/
+
+static void
+init_test03(void)
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, 1.0, -1000.0 * 480.0);
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_DEPTH_TEST);
+
+ glClearColor(0.0, 0.1, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+static int
+test03(int size, int num)
+{
+ int x, y, z;
+
+ glBegin(GL_TRIANGLES);
+ for (y = 0; y < num; y++)
+ for (x = 0; x < size; x += 5) {
+ z = num * size - (y * size + x);
+ glColor3f(0.0, 1.0, 0.0);
+ glVertex3i(0, x, z);
+
+ glColor3f(1.0, 0.0, x / (float) size);
+ glVertex3i(size - 1 - x, 0, z);
+
+ glColor3f(1.0, x / (float) size, 0.0);
+ glVertex3i(x, size - 1 - x, z);
+ }
+ glEnd();
+
+ return size * num / 5;
+}
+
+/***************************************************************************/
+
+static void
+init_test04(void)
+{
+ int x, y;
+ GLubyte tex[128 * 128 * 3];
+ GLenum gluerr;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, 1.0, -1000.0 * 480.0);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_DEPTH_TEST);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ for (y = 0; y < 128; y++)
+ for (x = 0; x < 128; x++) {
+ tex[(x + y * 128) * 3 + 0] = ((x % (128 / 4)) < (128 / 8)) ? 255 : 0;
+ tex[(x + y * 128) * 3 + 1] = ((y % (128 / 4)) < (128 / 8)) ? 255 : 0;
+ tex[(x + y * 128) * 3 + 2] = x;
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 128, 128, GL_RGB,
+ GL_UNSIGNED_BYTE, (GLvoid *) (&tex[0])))) {
+ fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glEnable(GL_TEXTURE_2D);
+
+ glClearColor(0.0, 0.1, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+static int
+test04(int size, int num)
+{
+ int x, y, z;
+
+ glBegin(GL_TRIANGLES);
+ for (y = 0; y < num; y++)
+ for (x = 0; x < size; x += 5) {
+ z = num * size - (y * size + x);
+ glTexCoord2f(1.0, 1.0);
+ glColor3f(1.0, 0.0, 0.0);
+ glVertex3i(0, x, z);
+
+ glTexCoord2f(0.0, 1.0);
+ glColor3f(0.0, 1.0, 0.0);
+ glVertex3i(size - 1 - x, 0, z);
+
+ glTexCoord2f(1.0, 0.0);
+ glColor3f(0.0, 0.0, 1.0);
+ glVertex3i(x, size - 1 - x, z);
+ }
+ glEnd();
+
+ return num * size / 5;
+}
+
+/***************************************************************************/
+
+static void
+init_test05(void)
+{
+ int x, y;
+ GLubyte tex[128 * 128 * 3];
+ GLenum gluerr;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_DEPTH_TEST);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ for (y = 0; y < 128; y++)
+ for (x = 0; x < 128; x++) {
+ tex[(x + y * 128) * 3 + 0] = ((x % (128 / 4)) < (128 / 8)) ? 255 : 0;
+ tex[(x + y * 128) * 3 + 1] = ((y % (128 / 4)) < (128 / 8)) ? 255 : 0;
+ tex[(x + y * 128) * 3 + 2] = x;
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 128, 128, GL_RGB,
+ GL_UNSIGNED_BYTE, (GLvoid *) (&tex[0])))) {
+ fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glEnable(GL_TEXTURE_2D);
+
+ glDepthFunc(GL_ALWAYS);
+
+ glClearColor(0.0, 0.1, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+static int
+test05(int size, int num)
+{
+ int y;
+ float v0[3], v1[3], v2[3], v3[3];
+ float cv0[3], cv1[3], cv2[3], cv3[3];
+ float tv0[3], tv1[3], tv2[3], tv3[3];
+
+ v0[0] = 320 - size / 2;
+ v0[1] = 240 - size / 2;
+ v0[2] = 0.0;
+ v1[0] = 320 + size / 2;
+ v1[1] = 240 - size / 2;
+ v1[2] = 0.0;
+ v2[0] = 320 - size / 2;
+ v2[1] = 240 + size / 2;
+ v2[2] = 0.0;
+ v3[0] = 320 + size / 2;
+ v3[1] = 240 + size / 2;
+ v3[2] = 0.0;
+ cv0[0] = 1.0;
+ cv0[1] = 0.0;
+ cv0[2] = 0.0;
+ cv1[0] = 1.0;
+ cv1[1] = 1.0;
+ cv1[2] = 0.0;
+ cv2[0] = 1.0;
+ cv2[1] = 0.0;
+ cv2[2] = 1.0;
+ cv3[0] = 1.0;
+ cv3[1] = 1.0;
+ cv3[2] = 1.0;
+ tv0[0] = 0.0;
+ tv0[1] = 0.0;
+ tv0[2] = 0.0;
+ tv1[0] = 1.0;
+ tv1[1] = 0.0;
+ tv1[2] = 0.0;
+ tv2[0] = 0.0;
+ tv2[1] = 1.0;
+ tv2[2] = 0.0;
+ tv3[0] = 1.0;
+ tv3[1] = 1.0;
+ tv3[2] = 0.0;
+
+ glBegin(GL_TRIANGLE_STRIP);
+ for (y = 0; y < num; y++) {
+ glColor3fv(cv0);
+ glTexCoord2fv(tv0);
+ glVertex3fv(v0);
+
+ glColor3fv(cv1);
+ glTexCoord2fv(tv1);
+ glVertex3fv(v1);
+
+ glColor3fv(cv2);
+ glTexCoord2fv(tv2);
+ glVertex3fv(v2);
+
+ glColor3fv(cv3);
+ glTexCoord2fv(tv3);
+ glVertex3fv(v3);
+ }
+ glEnd();
+
+ return 4 * num - 2;
+}
+
+/***************************************************************************/
+
+static void
+init_test06(void)
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluOrtho2D(-0.5, 639.5, -0.5, 479.5);
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_DEPTH_TEST);
+
+ glClearColor(0.0, 0.1, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+static int
+test06(int size, int num)
+{
+ int y;
+
+ for (y = 0; y < num; y++) {
+ glClearColor(y / (float) num, 0.1, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ return num;
+}
+
+/***************************************************************************/
+
+#define BMARKS_TIME 5.0
+
+#define NUM_BMARKS 6
+
+/* 554 ~= sqrt(640*480) */
+
+static benchmark bmarks[NUM_BMARKS] = {
+ {"Simple Points", "Pnts", init_test01, test01, 0, 0,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+ {"Smooth Lines", "Lins", init_test02, test02, 1, 5,
+ {480, 250, 100, 50, 25, 0, 0, 0, 0, 0}},
+ {"ZSmooth Triangles", "Tris", init_test03, test03, 1, 5,
+ {480, 250, 100, 50, 25, 0, 0, 0, 0, 0}},
+ {"ZSmooth Tex Blend Triangles", "Tris", init_test04, test04, 1, 5,
+ {480, 250, 100, 50, 25, 0, 0, 0, 0, 0}},
+ {"ZSmooth Tex Blend TMesh Triangles", "Tris", init_test05, test05, 2, 8,
+ {400, 250, 100, 50, 25, 10, 5, 2, 0, 0}},
+ {"Color/Depth Buffer Clears", "Clrs", init_test06, test06, 3, 0,
+ {554, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
+};
+
+/***************************************************************************/
+
+static void
+dotest0param(benchmark * bmark)
+{
+ float stime, etime, dtime, tottime, maxtime, mintime;
+ int num, numelem, calibnum, j;
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ bmark->init();
+
+ stime = glutGet(GLUT_ELAPSED_TIME);
+
+ dtime = 0.0;
+ calibnum = 0;
+ while (dtime < 2.0) {
+ bmark->run(0, 1);
+ glFinish();
+ etime = glutGet(GLUT_ELAPSED_TIME);
+ dtime = (etime - stime) / 1000.0;
+ calibnum++;
+ }
+ glPopAttrib();
+
+ fprintf(stderr, "Elapsed time for the calibration test (%d): %f\n",
+ calibnum, dtime);
+
+ num = (int) ((BMARKS_TIME / dtime) * calibnum);
+
+ if (num < 1)
+ num = 1;
+
+ fprintf(stderr, "Selected number of benchmark iterations: %d\n", num);
+
+ mintime = HUGE_VAL;
+ maxtime = -HUGE_VAL;
+
+ for (tottime = 0.0, j = 0; j < 5; j++) {
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ bmark->init();
+
+ stime = glutGet(GLUT_ELAPSED_TIME);
+ numelem = bmark->run(0, num);
+ glFinish();
+ etime = glutGet(GLUT_ELAPSED_TIME);
+
+ glPopAttrib();
+
+ dtime = (etime - stime) / 1000.0;
+ tottime += dtime;
+
+ fprintf(stderr, "Elapsed time for run %d: %f\n", j, dtime);
+
+ if (dtime < mintime)
+ mintime = dtime;
+ if (dtime > maxtime)
+ maxtime = dtime;
+ }
+
+ tottime -= mintime + maxtime;
+
+ fprintf(stdout, "%s\n%f %s/sec", bmark->name, numelem / (tottime / 3.0),
+ bmark->unit);
+
+ if (bmark->type == 3)
+ fprintf(stdout, ", MPixel Fill/sec: %f\n\n",
+ (numelem * bmark->size[0] * (float) bmark->size[0]) /
+ (1000000.0 * tottime / 3.0));
+ else
+ fprintf(stdout, "\n\n");
+}
+
+/***************************************************************************/
+
+static void
+dotest1param(benchmark * bmark)
+{
+ float stime, etime, dtime, tottime, maxtime, mintime;
+ int num, numelem, calibnum, j, k;
+
+ fprintf(stdout, "%s\n", bmark->name);
+
+ for (j = 0; j < bmark->numsize; j++) {
+ fprintf(stderr, "Current size: %d\n", bmark->size[j]);
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ bmark->init();
+
+ stime = glutGet(GLUT_ELAPSED_TIME);
+
+ dtime = 0.0;
+ calibnum = 0;
+ while (dtime < 2.0) {
+ bmark->run(bmark->size[j], 1);
+ glFinish();
+ etime = glutGet(GLUT_ELAPSED_TIME);
+ dtime = (etime - stime) / 1000.0;
+ calibnum++;
+ }
+ glPopAttrib();
+
+ fprintf(stderr, "Elapsed time for the calibration test (%d): %f\n",
+ calibnum, dtime);
+
+ num = (int) ((BMARKS_TIME / dtime) * calibnum);
+
+ if (num < 1)
+ num = 1;
+
+ fprintf(stderr, "Selected number of benchmark iterations: %d\n", num);
+
+ mintime = HUGE_VAL;
+ maxtime = -HUGE_VAL;
+
+ for (numelem = 1, tottime = 0.0, k = 0; k < 5; k++) {
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ bmark->init();
+
+ stime = glutGet(GLUT_ELAPSED_TIME);
+ numelem = bmark->run(bmark->size[j], num);
+ glFinish();
+ etime = glutGet(GLUT_ELAPSED_TIME);
+
+ glPopAttrib();
+
+ dtime = (etime - stime) / 1000.0;
+ tottime += dtime;
+
+ fprintf(stderr, "Elapsed time for run %d: %f\n", k, dtime);
+
+ if (dtime < mintime)
+ mintime = dtime;
+ if (dtime > maxtime)
+ maxtime = dtime;
+ }
+
+ tottime -= mintime + maxtime;
+
+ fprintf(stdout, "SIZE=%03d => %f %s/sec", bmark->size[j],
+ numelem / (tottime / 3.0), bmark->unit);
+ if (bmark->type == 2)
+ fprintf(stdout, ", MPixel Fill/sec: %f\n",
+ (numelem * bmark->size[j] * bmark->size[j] / 2) /
+ (1000000.0 * tottime / 3.0));
+ else
+ fprintf(stdout, "\n");
+ }
+
+ fprintf(stdout, "\n\n");
+}
+
+/***************************************************************************/
+
+static void
+display(void)
+{
+ int i;
+
+ if (frontbuffer)
+ glDrawBuffer(GL_FRONT);
+ else
+ glDrawBuffer(GL_BACK);
+
+ for (i = 0; i < NUM_BMARKS; i++) {
+ fprintf(stderr, "Benchmark: %d\n", i);
+
+ switch (bmarks[i].type) {
+ case 0:
+ case 3:
+ dotest0param(&bmarks[i]);
+ break;
+ case 1:
+ case 2:
+ dotest1param(&bmarks[i]);
+ break;
+ }
+ }
+
+ exit(0);
+}
+
+int
+main(int ac, char **av)
+{
+ fprintf(stderr, "GLTest v1.0\nWritten by David Bucciarelli\n");
+
+ if (ac == 2)
+ frontbuffer = 0;
+
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(640, 480);
+ glutCreateWindow("OpenGL/Mesa Performances");
+ glutDisplayFunc(display);
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/progs/demos/ipers.c b/progs/demos/ipers.c
new file mode 100644
index 00000000000..76da4c01f13
--- /dev/null
+++ b/progs/demos/ipers.c
@@ -0,0 +1,704 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+
+#ifdef WIN32
+#include <windows.h>
+#include <mmsystem.h>
+#endif
+
+#include <GL/glut.h>
+
+#include "../util/readtex.c"
+
+#ifdef XMESA
+#include "GL/xmesa.h"
+static int fullscreen = 1;
+#endif
+
+static int WIDTH = 640;
+static int HEIGHT = 480;
+
+#define MAX_LOD 9
+
+#define TEX_SKY_WIDTH 256
+#define TEX_SKY_HEIGHT TEX_SKY_WIDTH
+
+#ifndef M_PI
+#define M_PI 3.1415926535
+#endif
+
+#define FROM_NONE 0
+#define FROM_DOWN 1
+#define FROM_UP 2
+#define FROM_LEFT 3
+#define FROM_RIGHT 4
+#define FROM_FRONT 5
+#define FROM_BACK 6
+
+static int win = 0;
+
+static float obs[3] = { 3.8, 0.0, 0.0 };
+static float dir[3];
+static float v = 0.0;
+static float alpha = -90.0;
+static float beta = 90.0;
+
+static int fog = 1;
+static int bfcull = 1;
+static int usetex = 1;
+static int help = 1;
+static int poutline = 0;
+static int normext = 1;
+static int joyavailable = 0;
+static int joyactive = 0;
+static int LODbias = 3;
+static int maxdepth = MAX_LOD;
+
+static unsigned int totpoly = 0;
+
+static GLuint t1id, t2id;
+static GLuint skydlist, LODdlist[MAX_LOD], LODnumpoly[MAX_LOD];
+
+static void
+initlight(void)
+{
+ GLfloat lspec[4] = { 1.0, 1.0, 1.0, 1.0 };
+ static GLfloat lightpos[4] = { 30, 15.0, 30.0, 1.0 };
+
+ glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, lspec);
+
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32.0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, lspec);
+}
+
+static void
+initdlists(void)
+{
+ static slicetable[MAX_LOD][2] = {
+ {21, 10},
+ {18, 9},
+ {15, 8},
+ {12, 7},
+ {9, 6},
+ {7, 5},
+ {5, 4},
+ {4, 3},
+ {3, 2}
+ };
+ GLUquadricObj *obj;
+ int i, xslices, yslices;
+
+ obj = gluNewQuadric();
+
+ skydlist = glGenLists(1);
+ glNewList(skydlist, GL_COMPILE);
+ glBindTexture(GL_TEXTURE_2D, t2id);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glColor3f(1.0f, 1.0f, 1.0f);
+
+ gluQuadricDrawStyle(obj, GLU_FILL);
+ gluQuadricNormals(obj, GLU_NONE);
+ gluQuadricTexture(obj, GL_TRUE);
+ gluQuadricOrientation(obj, GLU_INSIDE);
+ gluSphere(obj, 40.0f, 18, 9);
+
+ glEndList();
+
+ for (i = 0; i < MAX_LOD; i++) {
+ LODdlist[i] = glGenLists(1);
+ glNewList(LODdlist[i], GL_COMPILE);
+
+ gluQuadricDrawStyle(obj, GLU_FILL);
+ gluQuadricNormals(obj, GLU_SMOOTH);
+ gluQuadricTexture(obj, GL_TRUE);
+ gluQuadricOrientation(obj, GLU_OUTSIDE);
+ xslices = slicetable[i][0];
+ yslices = slicetable[i][1];
+ gluSphere(obj, 1.0f, xslices, yslices);
+ LODnumpoly[i] = xslices * (yslices - 2) + 2 * (xslices - 1);
+
+ glEndList();
+ }
+}
+
+static void
+inittextures(void)
+{
+ GLubyte tsky[TEX_SKY_HEIGHT][TEX_SKY_WIDTH][3];
+ GLuint x, y;
+ GLfloat fact;
+ GLenum gluerr;
+
+ /* Brick */
+
+ glGenTextures(1, &t1id);
+ glBindTexture(GL_TEXTURE_2D, t1id);
+
+ if (!LoadRGBMipmaps("../images/bw.rgb", 3)) {
+ fprintf(stderr, "Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ /* Sky */
+
+ glGenTextures(1, &t2id);
+ glBindTexture(GL_TEXTURE_2D, t2id);
+
+ for (y = 0; y < TEX_SKY_HEIGHT; y++)
+ for (x = 0; x < TEX_SKY_WIDTH; x++)
+ if (y < TEX_SKY_HEIGHT / 2) {
+ fact = y / (GLfloat) (TEX_SKY_HEIGHT / 2);
+ tsky[y][x][0] =
+ (GLubyte) (255.0f * (0.1f * fact + 0.3f * (1.0f - fact)));
+ tsky[y][x][1] =
+ (GLubyte) (255.0f * (0.2f * fact + 1.0f * (1.0f - fact)));
+ tsky[y][x][2] = 255;
+ }
+ else {
+ tsky[y][x][0] = tsky[TEX_SKY_HEIGHT - y - 1][x][0];
+ tsky[y][x][1] = tsky[TEX_SKY_HEIGHT - y - 1][x][1];
+ tsky[y][x][2] = 255;
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ if (
+ (gluerr =
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TEX_SKY_WIDTH, TEX_SKY_HEIGHT,
+ GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) (tsky)))) {
+ fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+}
+
+static float
+gettime(void)
+{
+ static clock_t told = 0;
+ clock_t tnew, ris;
+
+ tnew = clock();
+
+ ris = tnew - told;
+
+ told = tnew;
+
+ return (ris / (float) CLOCKS_PER_SEC);
+}
+
+static void
+calcposobs(void)
+{
+ dir[0] = sin(alpha * M_PI / 180.0);
+ dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
+ dir[2] = cos(beta * M_PI / 180.0);
+
+ obs[0] += v * dir[0];
+ obs[1] += v * dir[1];
+ obs[2] += v * dir[2];
+}
+
+static void
+special(int k, int x, int y)
+{
+ switch (k) {
+ case GLUT_KEY_LEFT:
+ alpha -= 2.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ alpha += 2.0;
+ break;
+ case GLUT_KEY_DOWN:
+ beta -= 2.0;
+ break;
+ case GLUT_KEY_UP:
+ beta += 2.0;
+ break;
+ }
+}
+
+static void
+key(unsigned char k, int x, int y)
+{
+ switch (k) {
+ case 27:
+ exit(0);
+ break;
+
+ case 'a':
+ v += 0.01;
+ break;
+ case 'z':
+ v -= 0.01;
+ break;
+
+#ifdef XMESA
+ case ' ':
+ fullscreen = (!fullscreen);
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+ break;
+#endif
+
+ case '+':
+ LODbias--;
+ break;
+ case '-':
+ LODbias++;
+ break;
+ case 'j':
+ joyactive = (!joyactive);
+ break;
+ case 'h':
+ help = (!help);
+ break;
+ case 'f':
+ fog = (!fog);
+ break;
+ case 't':
+ usetex = (!usetex);
+ break;
+ case 'n':
+ normext = (!normext);
+ break;
+ case 'b':
+ if (bfcull) {
+ glDisable(GL_CULL_FACE);
+ bfcull = 0;
+ }
+ else {
+ glEnable(GL_CULL_FACE);
+ bfcull = 1;
+ }
+ break;
+ case 'p':
+ if (poutline) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ poutline = 0;
+ usetex = 1;
+ }
+ else {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ poutline = 1;
+ usetex = 0;
+ }
+ break;
+ }
+}
+
+static void
+reshape(int w, int h)
+{
+ WIDTH = w;
+ HEIGHT = h;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(90.0, w / (float) h, 0.8, 100.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glViewport(0, 0, w, h);
+}
+
+static void
+printstring(void *font, char *string)
+{
+ int len, i;
+
+ len = (int) strlen(string);
+ for (i = 0; i < len; i++)
+ glutBitmapCharacter(font, string[i]);
+}
+
+static void
+printhelp(void)
+{
+ glEnable(GL_BLEND);
+ glColor4f(0.5, 0.5, 0.5, 0.5);
+ glRecti(40, 40, 600, 440);
+ glDisable(GL_BLEND);
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(300, 420);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
+
+ glRasterPos2i(60, 390);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
+ glRasterPos2i(60, 360);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Toggle Textures");
+ glRasterPos2i(60, 330);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
+ glRasterPos2i(60, 300);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Toggle Back face culling");
+ glRasterPos2i(60, 270);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
+ glRasterPos2i(60, 240);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
+ glRasterPos2i(60, 210);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
+ glRasterPos2i(60, 180);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "p - Toggle Wire frame");
+ glRasterPos2i(60, 150);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "b - Toggle GL_EXT_rescale_normal extension");
+ glRasterPos2i(60, 120);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "+/- - Increase/decrease the Object maximum LOD");
+
+ glRasterPos2i(60, 90);
+ if (joyavailable)
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "j - Toggle jostick control (Joystick control available)");
+ else
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "(No Joystick control available)");
+}
+
+static void
+dojoy(void)
+{
+#ifdef _WIN32
+ static UINT max[2] = { 0, 0 };
+ static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
+ MMRESULT res;
+ JOYINFO joy;
+
+ res = joyGetPos(JOYSTICKID1, &joy);
+
+ if (res == JOYERR_NOERROR) {
+ joyavailable = 1;
+
+ if (max[0] < joy.wXpos)
+ max[0] = joy.wXpos;
+ if (min[0] > joy.wXpos)
+ min[0] = joy.wXpos;
+ center[0] = (max[0] + min[0]) / 2;
+
+ if (max[1] < joy.wYpos)
+ max[1] = joy.wYpos;
+ if (min[1] > joy.wYpos)
+ min[1] = joy.wYpos;
+ center[1] = (max[1] + min[1]) / 2;
+
+ if (joyactive) {
+ if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
+ alpha -=
+ 2.0 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
+ if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
+ beta += 2.0 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
+
+ if (joy.wButtons & JOY_BUTTON1)
+ v += 0.01;
+ if (joy.wButtons & JOY_BUTTON2)
+ v -= 0.01;
+ }
+ }
+ else
+ joyavailable = 0;
+#endif
+}
+
+static void
+drawipers(int depth, int from)
+{
+ int lod;
+
+ if (depth == maxdepth)
+ return;
+
+ lod = depth + LODbias;
+ if (lod < 0)
+ lod = 0;
+ if (lod >= MAX_LOD)
+ return;
+
+ switch (from) {
+ case FROM_NONE:
+ glCallList(LODdlist[lod]);
+
+ depth++;
+ drawipers(depth, FROM_DOWN);
+ drawipers(depth, FROM_UP);
+ drawipers(depth, FROM_FRONT);
+ drawipers(depth, FROM_BACK);
+ drawipers(depth, FROM_LEFT);
+ drawipers(depth, FROM_RIGHT);
+ break;
+ case FROM_FRONT:
+ glPushMatrix();
+ glTranslatef(0.0f, -1.5f, 0.0f);
+ glScalef(0.5f, 0.5f, 0.5f);
+
+ glCallList(LODdlist[lod]);
+
+ depth++;
+ drawipers(depth, FROM_DOWN);
+ drawipers(depth, FROM_UP);
+ drawipers(depth, FROM_FRONT);
+ drawipers(depth, FROM_LEFT);
+ drawipers(depth, FROM_RIGHT);
+ glPopMatrix();
+ break;
+ case FROM_BACK:
+ glPushMatrix();
+ glTranslatef(0.0f, 1.5f, 0.0f);
+ glScalef(0.5f, 0.5f, 0.5f);
+
+ glCallList(LODdlist[lod]);
+
+ depth++;
+ drawipers(depth, FROM_DOWN);
+ drawipers(depth, FROM_UP);
+ drawipers(depth, FROM_BACK);
+ drawipers(depth, FROM_LEFT);
+ drawipers(depth, FROM_RIGHT);
+ glPopMatrix();
+ break;
+ case FROM_LEFT:
+ glPushMatrix();
+ glTranslatef(-1.5f, 0.0f, 0.0f);
+ glScalef(0.5f, 0.5f, 0.5f);
+
+ glCallList(LODdlist[lod]);
+
+ depth++;
+ drawipers(depth, FROM_DOWN);
+ drawipers(depth, FROM_UP);
+ drawipers(depth, FROM_FRONT);
+ drawipers(depth, FROM_BACK);
+ drawipers(depth, FROM_LEFT);
+ glPopMatrix();
+ break;
+ case FROM_RIGHT:
+ glPushMatrix();
+ glTranslatef(1.5f, 0.0f, 0.0f);
+ glScalef(0.5f, 0.5f, 0.5f);
+
+ glCallList(LODdlist[lod]);
+
+ depth++;
+ drawipers(depth, FROM_DOWN);
+ drawipers(depth, FROM_UP);
+ drawipers(depth, FROM_FRONT);
+ drawipers(depth, FROM_BACK);
+ drawipers(depth, FROM_RIGHT);
+ glPopMatrix();
+ break;
+ case FROM_DOWN:
+ glPushMatrix();
+ glTranslatef(0.0f, 0.0f, 1.5f);
+ glScalef(0.5f, 0.5f, 0.5f);
+
+ glCallList(LODdlist[lod]);
+
+ depth++;
+ drawipers(depth, FROM_DOWN);
+ drawipers(depth, FROM_FRONT);
+ drawipers(depth, FROM_BACK);
+ drawipers(depth, FROM_LEFT);
+ drawipers(depth, FROM_RIGHT);
+ glPopMatrix();
+ break;
+ case FROM_UP:
+ glPushMatrix();
+ glTranslatef(0.0f, 0.0f, -1.5f);
+ glScalef(0.5f, 0.5f, 0.5f);
+
+ glCallList(LODdlist[lod]);
+
+ depth++;
+ drawipers(depth, FROM_UP);
+ drawipers(depth, FROM_FRONT);
+ drawipers(depth, FROM_BACK);
+ drawipers(depth, FROM_LEFT);
+ drawipers(depth, FROM_RIGHT);
+ glPopMatrix();
+ break;
+ }
+
+ totpoly += LODnumpoly[lod];
+}
+
+static void
+draw(void)
+{
+ static int count = 0;
+ static char frbuf[80];
+ static GLfloat alpha = 0.0f;
+ static GLfloat beta = 0.0f;
+ float fr;
+
+ dojoy();
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (usetex)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+
+ if (fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ glPushMatrix();
+ calcposobs();
+ gluLookAt(obs[0], obs[1], obs[2],
+ obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
+ 0.0, 0.0, 1.0);
+
+ /* Scene */
+ glEnable(GL_DEPTH_TEST);
+
+ glShadeModel(GL_SMOOTH);
+ glBindTexture(GL_TEXTURE_2D, t1id);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glColor3f(1.0f, 1.0f, 1.0f);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHTING);
+
+ if (normext)
+ glEnable(GL_RESCALE_NORMAL_EXT);
+ else
+ glEnable(GL_NORMALIZE);
+
+ glPushMatrix();
+ glRotatef(alpha, 0.0f, 0.0f, 1.0f);
+ glRotatef(beta, 1.0f, 0.0f, 0.0f);
+ totpoly = 0;
+ drawipers(0, FROM_NONE);
+ glPopMatrix();
+
+ alpha += 0.5f;
+ beta += 0.3f;
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_LIGHT0);
+ glShadeModel(GL_FLAT);
+
+ if (normext)
+ glDisable(GL_RESCALE_NORMAL_EXT);
+ else
+ glDisable(GL_NORMALIZE);
+
+ glCallList(skydlist);
+
+ glPopMatrix();
+
+ /* Help Screen */
+
+ fr = gettime();
+ sprintf(frbuf,
+ "Frame rate: %0.2f LOD: %d Tot. poly.: %d Poly/sec: %.1f",
+ 1.0 / fr, LODbias, totpoly, totpoly / fr);
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_FOG);
+ glShadeModel(GL_FLAT);
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(10, 10);
+ printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
+ glRasterPos2i(350, 470);
+ printstring(GLUT_BITMAP_HELVETICA_10,
+ "IperS V1.0 Written by David Bucciarelli ([email protected])");
+
+ if (help)
+ printhelp();
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ glutSwapBuffers();
+
+ count++;
+}
+
+int
+main(int ac, char **av)
+{
+ float fogcolor[4] = { 0.7, 0.7, 0.7, 1.0 };
+
+ fprintf(stderr,
+ "IperS V1.0\nWritten by David Bucciarelli ([email protected])\n");
+
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(WIDTH, HEIGHT);
+ glutInit(&ac, av);
+
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
+
+ if (!(win = glutCreateWindow("IperS"))) {
+ fprintf(stderr, "Error, couldn't open window\n");
+ exit(-1);
+ }
+
+ reshape(WIDTH, HEIGHT);
+
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_EXP2);
+ glFogfv(GL_FOG_COLOR, fogcolor);
+
+ glFogf(GL_FOG_DENSITY, 0.006);
+
+ glHint(GL_FOG_HINT, GL_NICEST);
+
+ inittextures();
+ initdlists();
+ initlight();
+
+ glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ calcposobs();
+
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+ glutIdleFunc(draw);
+
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/progs/demos/particles.cxx b/progs/demos/particles.cxx
new file mode 100644
index 00000000000..b88c318e0bc
--- /dev/null
+++ b/progs/demos/particles.cxx
@@ -0,0 +1,219 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdlib.h>
+
+#include "particles.h"
+
+#define vinit(a,i,j,k) {\
+ (a)[0]=i;\
+ (a)[1]=j;\
+ (a)[2]=k;\
+}
+
+#define vadds(a,dt,b) {\
+ (a)[0]+=(dt)*(b)[0];\
+ (a)[1]+=(dt)*(b)[1];\
+ (a)[2]+=(dt)*(b)[2];\
+}
+
+#define vequ(a,b) {\
+ (a)[0]=(b)[0];\
+ (a)[1]=(b)[1];\
+ (a)[2]=(b)[2];\
+}
+
+#define vinter(a,dt,b,c) {\
+ (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\
+ (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\
+ (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\
+}
+
+#define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
+
+#define vclamp(v) {\
+ (v)[0]=clamp((v)[0]);\
+ (v)[1]=clamp((v)[1]);\
+ (v)[2]=clamp((v)[2]);\
+}
+
+
+float rainParticle::min[3];
+float rainParticle::max[3];
+float rainParticle::partLength=0.2f;
+
+
+static float vrnd(void)
+{
+ return(((float)rand())/RAND_MAX);
+}
+
+
+particle::particle()
+{
+ age=0.0f;
+
+ vinit(acc,0.0f,0.0f,0.0f);
+ vinit(vel,0.0f,0.0f,0.0f);
+ vinit(pos,0.0f,0.0f,0.0f);
+}
+
+void particle::elapsedTime(float dt)
+{
+ age+=dt;
+
+ vadds(vel,dt,acc);
+
+ vadds(pos,dt,vel);
+}
+
+/////////////////////////////////////////
+// Particle System
+/////////////////////////////////////////
+
+particleSystem::particleSystem()
+{
+ t=0.0f;
+
+ part=NULL;
+
+ particleNum=0;
+}
+
+particleSystem::~particleSystem()
+{
+ if(part)
+ free(part);
+}
+
+void particleSystem::addParticle(particle *p)
+{
+ if(!part) {
+ part=(particle **)calloc(1,sizeof(particle *));
+ part[0]=p;
+ particleNum=1;
+ } else {
+ particleNum++;
+ part=(particle **)realloc(part,sizeof(particle *)*particleNum);
+ part[particleNum-1]=p;
+ }
+}
+
+void particleSystem::reset(void)
+{
+ if(part)
+ free(part);
+
+ t=0.0f;
+
+ part=NULL;
+
+ particleNum=0;
+}
+
+void particleSystem::draw(void)
+{
+ if(!part)
+ return;
+
+ part[0]->beginDraw();
+ for(unsigned int i=0;i<particleNum;i++)
+ part[i]->draw();
+ part[0]->endDraw();
+}
+
+void particleSystem::addTime(float dt)
+{
+ if(!part)
+ return;
+
+ for(unsigned int i=0;i<particleNum;i++) {
+ part[i]->elapsedTime(dt);
+ part[i]->checkAge();
+ }
+}
+
+/////////////////////////////////////////
+// Rain
+/////////////////////////////////////////
+
+void rainParticle::init(void)
+{
+ age=0.0f;
+
+ acc[0]=0.0f;
+ acc[1]=-0.98f;
+ acc[2]=0.0f;
+
+ vel[0]=0.0f;
+ vel[1]=0.0f;
+ vel[2]=0.0f;
+
+ oldpos[0]=pos[0]=min[0]+(max[0]-min[0])*vrnd();
+ oldpos[1]=pos[1]=max[1]+0.2f*max[1]*vrnd();
+ oldpos[2]=pos[2]=min[2]+(max[2]-min[2])*vrnd();
+
+ vadds(oldpos,-partLength,vel);
+}
+
+rainParticle::rainParticle()
+{
+ init();
+}
+
+void rainParticle::setRainingArea(float minx, float miny, float minz,
+ float maxx, float maxy, float maxz)
+{
+ vinit(min,minx,miny,minz);
+ vinit(max,maxx,maxy,maxz);
+}
+
+void rainParticle::setLength(float l)
+{
+ partLength=l;
+}
+
+void rainParticle::draw(void)
+{
+ glColor4f(0.7f,0.95f,1.0f,0.0f);
+ glVertex3fv(oldpos);
+
+ glColor4f(0.3f,0.7f,1.0f,1.0f);
+ glVertex3fv(pos);
+}
+
+void rainParticle::checkAge(void)
+{
+ if(pos[1]<min[1])
+ init();
+}
+
+void rainParticle::elapsedTime(float dt)
+{
+ particle::elapsedTime(dt);
+
+ if(pos[0]<min[0])
+ pos[0]=max[0]-(min[0]-pos[0]);
+ if(pos[2]<min[2])
+ pos[2]=max[2]-(min[2]-pos[2]);
+
+ if(pos[0]>max[0])
+ pos[0]=min[0]+(pos[0]-max[0]);
+ if(pos[2]>max[2])
+ pos[2]=min[2]+(pos[2]-max[2]);
+
+ vequ(oldpos,pos);
+ vadds(oldpos,-partLength,vel);
+}
+
+void rainParticle::randomHeight(void)
+{
+ pos[1]=(max[1]-min[1])*vrnd()+min[1];
+
+ oldpos[1]=pos[1]-partLength*vel[1];
+}
diff --git a/progs/demos/particles.h b/progs/demos/particles.h
new file mode 100644
index 00000000000..a49dd691e4a
--- /dev/null
+++ b/progs/demos/particles.h
@@ -0,0 +1,81 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#ifndef PARTICLES_H
+#define PARTICLES_H
+
+#include <GL/gl.h>
+
+class particle {
+ protected:
+ float age; // in seconds
+ float acc[3];
+ float vel[3];
+ float pos[3];
+
+ public:
+ particle();
+ virtual ~particle() {};
+
+ virtual void beginDraw(void) {};
+ virtual void draw(void)=0;
+ virtual void endDraw(void) {};
+
+ virtual void elapsedTime(float);
+ virtual void checkAge(void) {};
+};
+
+class particleSystem {
+ protected:
+ particle **part;
+
+ float t;
+
+ unsigned long particleNum;
+ public:
+ particleSystem();
+ ~particleSystem();
+
+ void addParticle(particle *);
+
+ void reset(void);
+
+ void draw(void);
+
+ void addTime(float);
+};
+
+class rainParticle : public particle {
+ protected:
+ static float min[3];
+ static float max[3];
+ static float partLength;
+
+ float oldpos[3];
+
+ void init(void);
+ public:
+ rainParticle();
+
+ static void setRainingArea(float, float, float,
+ float, float, float);
+ static void setLength(float);
+ static float getLength(void) { return partLength; };
+
+ void beginDraw(void) { glBegin(GL_LINES); };
+ void draw(void);
+ void endDraw(void) { glEnd(); };
+
+ void elapsedTime(float);
+
+ void checkAge(void);
+
+ void randomHeight(void);
+};
+
+#endif
diff --git a/progs/demos/rain.cxx b/progs/demos/rain.cxx
new file mode 100644
index 00000000000..4a7ecde3c82
--- /dev/null
+++ b/progs/demos/rain.cxx
@@ -0,0 +1,388 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+#include <GL/glut.h>
+
+#include "particles.h"
+extern "C" {
+#include "image.h"
+}
+
+#ifdef WIN32
+#include <windows.h>
+#include <mmsystem.h>
+#endif
+
+#ifdef XMESA
+#include "GL/xmesa.h"
+static int fullscreen=1;
+#endif
+
+static int WIDTH=640;
+static int HEIGHT=480;
+static int NUMPART=7500;
+
+#define FRAME 50
+
+static float fogcolor[4]={1.0,1.0,1.0,1.0};
+
+#define DIMP 40.0
+#define DIMTP 32.0
+
+static float q[4][3]={
+ {-DIMP,0.0,-DIMP},
+ {DIMP,0.0,-DIMP},
+ {DIMP,0.0,DIMP},
+ {-DIMP,0.0,DIMP}
+};
+
+static float qt[4][2]={
+ {-DIMTP,-DIMTP},
+ {DIMTP,-DIMTP},
+ {DIMTP,DIMTP},
+ {-DIMTP,DIMTP}
+};
+
+static int win=0;
+
+static int fog=1;
+static int help=1;
+
+static GLuint groundid;
+
+static float obs[3]={2.0,1.0,0.0};
+static float dir[3];
+static float v=0.0;
+static float alpha=-90.0;
+static float beta=90.0;
+
+static particleSystem *ps;
+
+static float gettime()
+{
+ static clock_t told=0;
+ clock_t tnew,ris;
+
+ tnew=clock();
+
+ ris=tnew-told;
+
+ told=tnew;
+
+ return(ris/(float)CLOCKS_PER_SEC);
+}
+
+static float gettimerain()
+{
+ static clock_t told=0;
+ clock_t tnew,ris;
+
+ tnew=clock();
+
+ ris=tnew-told;
+
+ told=tnew;
+
+ return(ris/(float)CLOCKS_PER_SEC);
+}
+
+static void calcposobs(void)
+{
+ dir[0]=sin(alpha*M_PI/180.0);
+ dir[2]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
+ dir[1]=cos(beta*M_PI/180.0);
+
+ obs[0]+=v*dir[0];
+ obs[1]+=v*dir[1];
+ obs[2]+=v*dir[2];
+
+ rainParticle::setRainingArea(obs[0]-7.0f,-0.2f,obs[2]-7.0f,obs[0]+7.0f,8.0f,obs[2]+7.0f);
+}
+
+static void printstring(void *font, char *string)
+{
+ int len,i;
+
+ len=(int)strlen(string);
+ for(i=0;i<len;i++)
+ glutBitmapCharacter(font,string[i]);
+}
+
+static void reshape(int width, int height)
+{
+ WIDTH=width;
+ HEIGHT=height;
+ glViewport(0,0,(GLint)width,(GLint)height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(70.0,width/(float)height,0.1,30.0);
+
+ glMatrixMode(GL_MODELVIEW);
+}
+
+static void printhelp(void)
+{
+ glEnable(GL_BLEND);
+ glColor4f(0.0,0.0,0.0,0.5);
+ glRecti(40,40,600,440);
+ glDisable(GL_BLEND);
+
+ glColor3f(1.0,0.0,0.0);
+ glRasterPos2i(300,420);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
+
+ glRasterPos2i(60,390);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Togle Help");
+
+ glRasterPos2i(60,360);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Togle Fog");
+ glRasterPos2i(60,330);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
+ glRasterPos2i(60,300);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
+ glRasterPos2i(60,270);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
+ glRasterPos2i(60,240);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"l - Increase rain length");
+ glRasterPos2i(60,210);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"k - Increase rain length");
+}
+
+static void drawrain(void)
+{
+ static int count=0;
+ static char frbuf[80];
+ float fr;
+
+ glEnable(GL_DEPTH_TEST);
+
+ if(fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ glDepthMask(GL_TRUE);
+ glClearColor(1.0,1.0,1.0,1.0);
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ calcposobs();
+ gluLookAt(obs[0],obs[1],obs[2],
+ obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
+ 0.0,1.0,0.0);
+
+ glColor4f(1.0,1.0,1.0,1.0);
+
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D,groundid);
+ glBegin(GL_QUADS);
+ glTexCoord2fv(qt[0]);
+ glVertex3fv(q[0]);
+ glTexCoord2fv(qt[1]);
+ glVertex3fv(q[1]);
+ glTexCoord2fv(qt[2]);
+ glVertex3fv(q[2]);
+ glTexCoord2fv(qt[3]);
+ glVertex3fv(q[3]);
+ glEnd();
+
+ // Particle System
+
+ glDisable(GL_TEXTURE_2D);
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_BLEND);
+
+ ps->draw();
+ ps->addTime(gettimerain());
+
+ glShadeModel(GL_FLAT);
+
+
+ if((count % FRAME)==0) {
+ fr=gettime();
+ sprintf(frbuf,"Frame rate: %f",FRAME/fr);
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_FOG);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glColor3f(1.0,0.0,0.0);
+ glRasterPos2i(10,10);
+ printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
+ glRasterPos2i(350,470);
+ printstring(GLUT_BITMAP_HELVETICA_10,"Rain V1.0 Written by David Bucciarelli ([email protected])");
+
+ if(help)
+ printhelp();
+
+ reshape(WIDTH,HEIGHT);
+ glPopMatrix();
+
+ glutSwapBuffers();
+
+ count++;
+}
+
+
+static void special(int key, int x, int y)
+{
+ switch (key) {
+ case GLUT_KEY_LEFT:
+ alpha+=2.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ alpha-=2.0;
+ break;
+ case GLUT_KEY_DOWN:
+ beta-=2.0;
+ break;
+ case GLUT_KEY_UP:
+ beta+=2.0;
+ break;
+ }
+}
+
+static void key(unsigned char key, int x, int y)
+{
+ switch (key) {
+ case 27:
+ exit(0);
+ break;
+
+ case 'a':
+ v+=0.01;
+ break;
+ case 'z':
+ v-=0.01;
+ break;
+
+ case 'l':
+ rainParticle::setLength(rainParticle::getLength()+0.025f);
+ break;
+ case 'k':
+ rainParticle::setLength(rainParticle::getLength()-0.025f);
+ break;
+
+ case 'h':
+ help=(!help);
+ break;
+ case 'f':
+ fog=(!fog);
+ break;
+#ifdef XMESA
+ case ' ':
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+ fullscreen=(!fullscreen);
+ break;
+#endif
+ }
+}
+
+static void inittextures(void)
+{
+ IMAGE *img;
+ GLenum gluerr;
+
+ glGenTextures(1,&groundid);
+ glBindTexture(GL_TEXTURE_2D,groundid);
+
+ if(!(img=ImageLoad("s128.rgb"))) {
+ fprintf(stderr,"Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT,4);
+ if((gluerr=(GLenum)gluBuild2DMipmaps(GL_TEXTURE_2D, 3, img->sizeX, img->sizeY, GL_RGB,
+ GL_UNSIGNED_BYTE, (GLvoid *)(img->data)))) {
+ fprintf(stderr,"GLULib%s\n",gluErrorString(gluerr));
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
+}
+
+static void initparticle(void)
+{
+ ps=new particleSystem;
+
+ rainParticle::setRainingArea(-7.0f,-0.2f,-7.0f,7.0f,8.0f,7.0f);
+
+ for(int i=0;i<NUMPART;i++) {
+ rainParticle *p=new rainParticle;
+ p->randomHeight();
+
+ ps->addParticle((particle *)p);
+ }
+}
+
+int main(int ac,char **av)
+{
+ fprintf(stderr,"Rain V1.0\nWritten by David Bucciarelli ([email protected])\n");
+
+ /* Default settings */
+
+ WIDTH=640;
+ HEIGHT=480;
+
+ glutInitWindowPosition(0,0);
+ glutInitWindowSize(WIDTH,HEIGHT);
+ glutInit(&ac,av);
+
+ glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
+
+ if(!(win=glutCreateWindow("Rain"))) {
+ fprintf(stderr,"Error opening a window.\n");
+ exit(-1);
+ }
+
+ reshape(WIDTH,HEIGHT);
+
+ inittextures();
+
+ glShadeModel(GL_FLAT);
+ glEnable(GL_DEPTH_TEST);
+
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE,GL_EXP);
+ glFogfv(GL_FOG_COLOR,fogcolor);
+ glFogf(GL_FOG_DENSITY,0.1);
+#ifdef FX
+ glHint(GL_FOG_HINT,GL_NICEST);
+#endif
+
+ initparticle();
+
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+ glutDisplayFunc(drawrain);
+ glutIdleFunc(drawrain);
+ glutReshapeFunc(reshape);
+ glutMainLoop();
+
+ return(0);
+}
diff --git a/progs/demos/ray.c b/progs/demos/ray.c
new file mode 100644
index 00000000000..24f27a05393
--- /dev/null
+++ b/progs/demos/ray.c
@@ -0,0 +1,908 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <GL/glut.h>
+
+#ifdef XMESA
+#include "GL/xmesa.h"
+static int fullscreen = 1;
+#endif
+
+static int WIDTH = 640;
+static int HEIGHT = 480;
+
+#define FRAME 50
+
+#define BASESIZE 7.5f
+#define SPHERE_RADIUS 0.75f
+
+#define TEX_CHECK_WIDTH 256
+#define TEX_CHECK_HEIGHT 256
+#define TEX_CHECK_SLOT_SIZE (TEX_CHECK_HEIGHT/16)
+#define TEX_CHECK_NUMSLOT (TEX_CHECK_HEIGHT/TEX_CHECK_SLOT_SIZE)
+
+#define TEX_REFLECT_WIDTH 256
+#define TEX_REFLECT_HEIGHT 256
+#define TEX_REFLECT_SLOT_SIZE (TEX_REFLECT_HEIGHT/16)
+#define TEX_REFLECT_NUMSLOT (TEX_REFLECT_HEIGHT/TEX_REFLECT_SLOT_SIZE)
+
+#ifndef M_PI
+#define M_PI 3.1415926535
+#endif
+
+#define EPSILON 0.0001
+
+#define clamp255(a) ( (a)<(0.0f) ? (0.0f) : ((a)>(255.0f) ? (255.0f) : (a)) )
+
+#define fabs(x) ((x)<0.0f?-(x):(x))
+
+#define vequ(a,b) { (a)[0]=(b)[0]; (a)[1]=(b)[1]; (a)[2]=(b)[2]; }
+#define vsub(a,b,c) { (a)[0]=(b)[0]-(c)[0]; (a)[1]=(b)[1]-(c)[1]; (a)[2]=(b)[2]-(c)[2]; }
+#define dprod(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
+#define vnormalize(a,b) { \
+ register float m_norm; \
+ m_norm=sqrt((double)dprod((a),(a))); \
+ (a)[0] /=m_norm; \
+ (a)[1] /=m_norm; \
+ (a)[2] /=m_norm; }
+
+static GLubyte checkmap[TEX_CHECK_HEIGHT][TEX_CHECK_WIDTH][3];
+static GLuint checkid;
+static int checkmap_currentslot = 0;
+
+static GLubyte reflectmap[TEX_REFLECT_HEIGHT][TEX_REFLECT_WIDTH][3];
+static GLuint reflectid;
+static int reflectmap_currentslot = 0;
+
+static GLuint lightdlist;
+static GLuint objdlist;
+
+static float lightpos[3] = { 2.1, 2.1, 2.8 };
+static float objpos[3] = { 0.0, 0.0, 1.0 };
+
+static float sphere_pos[TEX_CHECK_HEIGHT][TEX_REFLECT_WIDTH][3];
+
+static int win = 0;
+
+static float fogcolor[4] = { 0.05, 0.05, 0.05, 1.0 };
+
+static float obs[3] = { 7.0, 0.0, 2.0 };
+static float dir[3];
+static float v = 0.0;
+static float alpha = -90.0;
+static float beta = 90.0;
+
+static int fog = 1;
+static int bfcull = 1;
+static int poutline = 0;
+static int help = 1;
+static int showcheckmap = 1;
+static int showreflectmap = 1;
+static int joyavailable = 0;
+static int joyactive = 0;
+
+static float
+gettime(void)
+{
+ static float told = 0.0f;
+ float tnew, ris;
+
+ tnew = glutGet(GLUT_ELAPSED_TIME);
+
+ ris = tnew - told;
+
+ told = tnew;
+
+ return ris / 1000.0;
+}
+
+static void
+calcposobs(void)
+{
+ dir[0] = sin(alpha * M_PI / 180.0);
+ dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
+ dir[2] = cos(beta * M_PI / 180.0);
+
+ obs[0] += v * dir[0];
+ obs[1] += v * dir[1];
+ obs[2] += v * dir[2];
+}
+
+static void
+special(int k, int x, int y)
+{
+ switch (k) {
+ case GLUT_KEY_LEFT:
+ alpha -= 2.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ alpha += 2.0;
+ break;
+ case GLUT_KEY_DOWN:
+ beta -= 2.0;
+ break;
+ case GLUT_KEY_UP:
+ beta += 2.0;
+ break;
+ }
+}
+
+static void
+key(unsigned char k, int x, int y)
+{
+ switch (k) {
+ case 27:
+ exit(0);
+ break;
+
+ case 's':
+ lightpos[1] -= 0.1;
+ break;
+ case 'd':
+ lightpos[1] += 0.1;
+ break;
+ case 'e':
+ lightpos[0] -= 0.1;
+ break;
+ case 'x':
+ lightpos[0] += 0.1;
+ break;
+ case 'w':
+ lightpos[2] -= 0.1;
+ break;
+ case 'r':
+ lightpos[2] += 0.1;
+ break;
+
+ case 'j':
+ objpos[1] -= 0.1;
+ break;
+ case 'k':
+ objpos[1] += 0.1;
+ break;
+ case 'i':
+ objpos[0] -= 0.1;
+ break;
+ case 'm':
+ objpos[0] += 0.1;
+ break;
+ case 'u':
+ objpos[2] -= 0.1;
+ break;
+ case 'o':
+ objpos[2] += 0.1;
+ break;
+
+ case 'a':
+ v += 0.005;
+ break;
+ case 'z':
+ v -= 0.005;
+ break;
+
+ case 'g':
+ joyactive = (!joyactive);
+ break;
+ case 'h':
+ help = (!help);
+ break;
+ case 'f':
+ fog = (!fog);
+ break;
+
+ case '1':
+ showcheckmap = (!showcheckmap);
+ break;
+ case '2':
+ showreflectmap = (!showreflectmap);
+ break;
+
+ case 'b':
+ if (bfcull) {
+ glDisable(GL_CULL_FACE);
+ bfcull = 0;
+ }
+ else {
+ glEnable(GL_CULL_FACE);
+ bfcull = 1;
+ }
+ break;
+ case 'p':
+ if (poutline) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ poutline = 0;
+ }
+ else {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ poutline = 1;
+ }
+ break;
+#ifdef XMESA
+ case ' ':
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+ fullscreen = (!fullscreen);
+ break;
+#endif
+ }
+}
+
+static void
+reshape(int w, int h)
+{
+ WIDTH = w;
+ HEIGHT = h;
+ glViewport(0, 0, w, h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(45.0, w / (float) h, 0.8, 40.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+static void
+printstring(void *font, char *string)
+{
+ int len, i;
+
+ len = (int) strlen(string);
+ for (i = 0; i < len; i++)
+ glutBitmapCharacter(font, string[i]);
+}
+
+static void
+printhelp(void)
+{
+ glEnable(GL_BLEND);
+ glColor4f(0.5, 0.5, 0.5, 0.5);
+ glRecti(40, 40, 600, 440);
+ glDisable(GL_BLEND);
+
+ glColor3f(0.0, 0.0, 1.0);
+ glRasterPos2i(300, 420);
+ printstring(GLUT_BITMAP_HELVETICA_18, "Help");
+
+ glRasterPos2i(60, 390);
+ printstring(GLUT_BITMAP_HELVETICA_12, "h - Togle Help");
+ glRasterPos2i(60, 370);
+ printstring(GLUT_BITMAP_HELVETICA_12, "f - Togle Fog");
+ glRasterPos2i(60, 350);
+ printstring(GLUT_BITMAP_HELVETICA_12, "b - Togle Back face culling");
+ glRasterPos2i(60, 330);
+ printstring(GLUT_BITMAP_HELVETICA_12, "p - Togle Wire frame");
+ glRasterPos2i(60, 310);
+ printstring(GLUT_BITMAP_HELVETICA_12, "Arrow Keys - Rotate");
+ glRasterPos2i(60, 290);
+ printstring(GLUT_BITMAP_HELVETICA_12, "a - Increase velocity");
+ glRasterPos2i(60, 270);
+ printstring(GLUT_BITMAP_HELVETICA_12, "z - Decrease velocity");
+
+ glRasterPos2i(60, 250);
+ if (joyavailable)
+ printstring(GLUT_BITMAP_HELVETICA_12,
+ "j - Togle jostick control (Joystick control available)");
+ else
+ printstring(GLUT_BITMAP_HELVETICA_12,
+ "(No Joystick control available)");
+
+ glRasterPos2i(60, 230);
+ printstring(GLUT_BITMAP_HELVETICA_12,
+ "To move the light source: s - left, d - right, e - far, x - near, w - down r - up");
+ glRasterPos2i(60, 210);
+ printstring(GLUT_BITMAP_HELVETICA_12,
+ "To move the mirror sphere: j - left, k - right, i - far, m - near, u - down o - up");
+
+ glRasterPos2i(60, 190);
+ printstring(GLUT_BITMAP_HELVETICA_12,
+ "1 - Togle the plane texture map window");
+
+ glRasterPos2i(60, 170);
+ printstring(GLUT_BITMAP_HELVETICA_12,
+ "2 - Togle the sphere texture map window");
+}
+
+static GLboolean
+seelight(float p[3], float dir[3])
+{
+ float c[3], b, a, d, t, dist[3];
+
+ vsub(c, p, objpos);
+ b = -dprod(c, dir);
+ a = dprod(c, c) - SPHERE_RADIUS * SPHERE_RADIUS;
+
+ if ((d = b * b - a) < 0.0 || (b < 0.0 && a > 0.0))
+ return GL_FALSE;
+
+ d = sqrt(d);
+
+ t = b - d;
+
+ if (t < EPSILON) {
+ t = b + d;
+ if (t < EPSILON)
+ return GL_FALSE;
+ }
+
+ vsub(dist, lightpos, p);
+ if (dprod(dist, dist) < t * t)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static int
+colorcheckmap(float ppos[3], float c[3])
+{
+ static float norm[3] = { 0.0f, 0.0f, 1.0f };
+ float ldir[3], vdir[3], h[3], dfact, kfact, r, g, b;
+ int x, y;
+
+ x = (int) ((ppos[0] + BASESIZE / 2) * (10.0f / BASESIZE));
+ if ((x < 0) || (x > 10))
+ return GL_FALSE;
+
+ y = (int) ((ppos[1] + BASESIZE / 2) * (10.0f / BASESIZE));
+ if ((y < 0) || (y > 10))
+ return GL_FALSE;
+
+ r = 255.0f;
+ if (y & 1) {
+ if (x & 1)
+ g = 255.0f;
+ else
+ g = 0.0f;
+ }
+ else {
+ if (x & 1)
+ g = 0.0f;
+ else
+ g = 255.0f;
+ }
+ b = 0.0f;
+
+ vsub(ldir, lightpos, ppos);
+ vnormalize(ldir, ldir);
+
+ if (seelight(ppos, ldir)) {
+ c[0] = r * 0.05f;
+ c[1] = g * 0.05f;
+ c[2] = b * 0.05f;
+
+ return GL_TRUE;
+ }
+
+ dfact = dprod(ldir, norm);
+ if (dfact < 0.0f)
+ dfact = 0.0f;
+
+ vsub(vdir, obs, ppos);
+ vnormalize(vdir, vdir);
+ h[0] = 0.5f * (vdir[0] + ldir[0]);
+ h[1] = 0.5f * (vdir[1] + ldir[1]);
+ h[2] = 0.5f * (vdir[2] + ldir[2]);
+ kfact = dprod(h, norm);
+ kfact =
+ kfact * kfact * kfact * kfact * kfact * kfact * kfact * 7.0f * 255.0f;
+
+ r = r * dfact + kfact;
+ g = g * dfact + kfact;
+ b = b * dfact + kfact;
+
+ c[0] = clamp255(r);
+ c[1] = clamp255(g);
+ c[2] = clamp255(b);
+
+ return GL_TRUE;
+}
+
+static void
+updatecheckmap(int slot)
+{
+ float c[3], ppos[3];
+ int x, y;
+
+ glBindTexture(GL_TEXTURE_2D, checkid);
+
+ ppos[2] = 0.0f;
+ for (y = slot * TEX_CHECK_SLOT_SIZE; y < (slot + 1) * TEX_CHECK_SLOT_SIZE;
+ y++) {
+ ppos[1] = (y / (float) TEX_CHECK_HEIGHT) * BASESIZE - BASESIZE / 2;
+
+ for (x = 0; x < TEX_CHECK_WIDTH; x++) {
+ ppos[0] = (x / (float) TEX_CHECK_WIDTH) * BASESIZE - BASESIZE / 2;
+
+ colorcheckmap(ppos, c);
+ checkmap[y][x][0] = (GLubyte) c[0];
+ checkmap[y][x][1] = (GLubyte) c[1];
+ checkmap[y][x][2] = (GLubyte) c[2];
+ }
+ }
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, slot * TEX_CHECK_SLOT_SIZE,
+ TEX_CHECK_WIDTH, TEX_CHECK_SLOT_SIZE, GL_RGB,
+ GL_UNSIGNED_BYTE,
+ &checkmap[slot * TEX_CHECK_SLOT_SIZE][0][0]);
+
+}
+
+static void
+updatereflectmap(int slot)
+{
+ float rf, r, g, b, t, dfact, kfact, rdir[3];
+ float rcol[3], ppos[3], norm[3], ldir[3], h[3], vdir[3], planepos[3];
+ int x, y;
+
+ glBindTexture(GL_TEXTURE_2D, reflectid);
+
+ for (y = slot * TEX_REFLECT_SLOT_SIZE;
+ y < (slot + 1) * TEX_REFLECT_SLOT_SIZE; y++)
+ for (x = 0; x < TEX_REFLECT_WIDTH; x++) {
+ ppos[0] = sphere_pos[y][x][0] + objpos[0];
+ ppos[1] = sphere_pos[y][x][1] + objpos[1];
+ ppos[2] = sphere_pos[y][x][2] + objpos[2];
+
+ vsub(norm, ppos, objpos);
+ vnormalize(norm, norm);
+
+ vsub(ldir, lightpos, ppos);
+ vnormalize(ldir, ldir);
+ vsub(vdir, obs, ppos);
+ vnormalize(vdir, vdir);
+
+ rf = 2.0f * dprod(norm, vdir);
+ if (rf > EPSILON) {
+ rdir[0] = rf * norm[0] - vdir[0];
+ rdir[1] = rf * norm[1] - vdir[1];
+ rdir[2] = rf * norm[2] - vdir[2];
+
+ t = -objpos[2] / rdir[2];
+
+ if (t > EPSILON) {
+ planepos[0] = objpos[0] + t * rdir[0];
+ planepos[1] = objpos[1] + t * rdir[1];
+ planepos[2] = 0.0f;
+
+ if (!colorcheckmap(planepos, rcol))
+ rcol[0] = rcol[1] = rcol[2] = 0.0f;
+ }
+ else
+ rcol[0] = rcol[1] = rcol[2] = 0.0f;
+ }
+ else
+ rcol[0] = rcol[1] = rcol[2] = 0.0f;
+
+ dfact = 0.1f * dprod(ldir, norm);
+
+ if (dfact < 0.0f) {
+ dfact = 0.0f;
+ kfact = 0.0f;
+ }
+ else {
+ h[0] = 0.5f * (vdir[0] + ldir[0]);
+ h[1] = 0.5f * (vdir[1] + ldir[1]);
+ h[2] = 0.5f * (vdir[2] + ldir[2]);
+ kfact = dprod(h, norm);
+ kfact *= kfact;
+ kfact *= kfact;
+ kfact *= kfact;
+ kfact *= kfact;
+ kfact *= 10.0f;
+ }
+
+ r = dfact + kfact;
+ g = dfact + kfact;
+ b = dfact + kfact;
+
+ r *= 255.0f;
+ g *= 255.0f;
+ b *= 255.0f;
+
+ r += rcol[0];
+ g += rcol[1];
+ b += rcol[2];
+
+ r = clamp255(r);
+ g = clamp255(g);
+ b = clamp255(b);
+
+ reflectmap[y][x][0] = (GLubyte) r;
+ reflectmap[y][x][1] = (GLubyte) g;
+ reflectmap[y][x][2] = (GLubyte) b;
+ }
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, slot * TEX_REFLECT_SLOT_SIZE,
+ TEX_REFLECT_WIDTH, TEX_REFLECT_SLOT_SIZE, GL_RGB,
+ GL_UNSIGNED_BYTE,
+ &reflectmap[slot * TEX_REFLECT_SLOT_SIZE][0][0]);
+}
+
+static void
+drawbase(void)
+{
+ glColor3f(0.0, 0.0, 0.0);
+ glBindTexture(GL_TEXTURE_2D, checkid);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex3f(-BASESIZE / 2.0f, -BASESIZE / 2.0f, 0.0f);
+
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex3f(BASESIZE / 2.0f, -BASESIZE / 2.0f, 0.0f);
+
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex3f(BASESIZE / 2.0f, BASESIZE / 2.0f, 0.0f);
+
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex3f(-BASESIZE / 2.0f, BASESIZE / 2.0f, 0.0f);
+
+ glEnd();
+}
+
+static void
+drawobj(void)
+{
+ glColor3f(0.0, 0.0, 0.0);
+ glBindTexture(GL_TEXTURE_2D, reflectid);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ glPushMatrix();
+ glTranslatef(objpos[0], objpos[1], objpos[2]);
+ glCallList(objdlist);
+ glPopMatrix();
+}
+
+static void
+dojoy(void)
+{
+#ifdef WIN32
+ static UINT max[2] = { 0, 0 };
+ static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
+ MMRESULT res;
+ JOYINFO joy;
+
+ res = joyGetPos(JOYSTICKID1, &joy);
+
+ if (res == JOYERR_NOERROR) {
+ joyavailable = 1;
+
+ if (max[0] < joy.wXpos)
+ max[0] = joy.wXpos;
+ if (min[0] > joy.wXpos)
+ min[0] = joy.wXpos;
+ center[0] = (max[0] + min[0]) / 2;
+
+ if (max[1] < joy.wYpos)
+ max[1] = joy.wYpos;
+ if (min[1] > joy.wYpos)
+ min[1] = joy.wYpos;
+ center[1] = (max[1] + min[1]) / 2;
+
+ if (joyactive) {
+ if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
+ alpha -=
+ 2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
+ if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
+ beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
+
+ if (joy.wButtons & JOY_BUTTON1)
+ v += 0.005;
+ if (joy.wButtons & JOY_BUTTON2)
+ v -= 0.005;
+ }
+ }
+ else
+ joyavailable = 0;
+#endif
+}
+
+static void
+updatemaps(void)
+{
+ updatecheckmap(checkmap_currentslot);
+ checkmap_currentslot = (checkmap_currentslot + 1) % TEX_CHECK_NUMSLOT;
+
+ updatereflectmap(reflectmap_currentslot);
+ reflectmap_currentslot =
+ (reflectmap_currentslot + 1) % TEX_REFLECT_NUMSLOT;
+}
+
+static void
+draw(void)
+{
+ static int count = 0;
+ static char frbuf[80];
+ float fr;
+
+ dojoy();
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_DEPTH_TEST);
+ if (fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ glPushMatrix();
+ calcposobs();
+
+ gluLookAt(obs[0], obs[1], obs[2],
+ obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
+ 0.0, 0.0, 1.0);
+
+ drawbase();
+ drawobj();
+
+ glColor3f(1.0, 1.0, 1.0);
+ glDisable(GL_TEXTURE_2D);
+
+ glPushMatrix();
+ glTranslatef(lightpos[0], lightpos[1], lightpos[2]);
+ glCallList(lightdlist);
+ glPopMatrix();
+
+ glPopMatrix();
+
+ if ((count % FRAME) == 0) {
+ fr = gettime();
+ sprintf(frbuf, "Frame rate: %f", FRAME / fr);
+ }
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_FOG);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+
+ glColor3f(0.0f, 0.3f, 1.0f);
+
+ if (showcheckmap) {
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, checkid);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex2i(10, 30);
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex2i(10 + 90, 30);
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex2i(10 + 90, 30 + 90);
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex2i(10, 30 + 90);
+ glEnd();
+
+ glDisable(GL_TEXTURE_2D);
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(10, 30);
+ glVertex2i(10 + 90, 30);
+ glVertex2i(10 + 90, 30 + 90);
+ glVertex2i(10, 30 + 90);
+ glEnd();
+ glRasterPos2i(105, 65);
+ printstring(GLUT_BITMAP_HELVETICA_18, "Plane Texture Map");
+ }
+
+ if (showreflectmap) {
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, reflectid);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex2i(540, 30);
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex2i(540 + 90, 30);
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex2i(540 + 90, 30 + 90);
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex2i(540, 30 + 90);
+ glEnd();
+
+ glDisable(GL_TEXTURE_2D);
+ glBegin(GL_LINE_LOOP);
+ glVertex2i(540, 30);
+ glVertex2i(540 + 90, 30);
+ glVertex2i(540 + 90, 30 + 90);
+ glVertex2i(540, 30 + 90);
+ glEnd();
+ glRasterPos2i(360, 65);
+ printstring(GLUT_BITMAP_HELVETICA_18, "Sphere Texture Map");
+ }
+
+ glDisable(GL_TEXTURE_2D);
+
+ glRasterPos2i(10, 10);
+ printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
+ glRasterPos2i(360, 470);
+ printstring(GLUT_BITMAP_HELVETICA_10,
+ "Ray V1.0 Written by David Bucciarelli ([email protected])");
+
+ if (help)
+ printhelp();
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ updatemaps();
+
+ glutSwapBuffers();
+
+ count++;
+}
+
+static void
+inittextures(void)
+{
+ int y;
+
+ glGenTextures(1, &checkid);
+ glBindTexture(GL_TEXTURE_2D, checkid);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, TEX_CHECK_WIDTH, TEX_CHECK_HEIGHT,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, checkmap);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ for (y = 0; y < TEX_CHECK_NUMSLOT; y++)
+ updatecheckmap(y);
+
+
+
+ glGenTextures(1, &reflectid);
+ glBindTexture(GL_TEXTURE_2D, reflectid);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, TEX_REFLECT_WIDTH, TEX_REFLECT_HEIGHT,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, reflectmap);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ for (y = 0; y < TEX_REFLECT_NUMSLOT; y++)
+ updatereflectmap(y);
+
+
+}
+
+static void
+initspherepos(void)
+{
+ float alpha, beta, sa, ca, sb, cb;
+ int x, y;
+
+ for (y = 0; y < TEX_REFLECT_HEIGHT; y++) {
+ beta = M_PI - y * (M_PI / TEX_REFLECT_HEIGHT);
+
+ for (x = 0; x < TEX_REFLECT_WIDTH; x++) {
+ alpha = -x * (2.0f * M_PI / TEX_REFLECT_WIDTH);
+
+ sa = sin(alpha);
+ ca = cos(alpha);
+
+ sb = sin(beta);
+ cb = cos(beta);
+
+ sphere_pos[y][x][0] = SPHERE_RADIUS * sa * sb;
+ sphere_pos[y][x][1] = SPHERE_RADIUS * ca * sb;
+ sphere_pos[y][x][2] = SPHERE_RADIUS * cb;
+ }
+ }
+}
+
+static void
+initdlists(void)
+{
+ GLUquadricObj *obj;
+
+ obj = gluNewQuadric();
+
+ lightdlist = glGenLists(1);
+ glNewList(lightdlist, GL_COMPILE);
+ gluQuadricDrawStyle(obj, GLU_FILL);
+ gluQuadricNormals(obj, GLU_NONE);
+ gluQuadricTexture(obj, GL_TRUE);
+ gluSphere(obj, 0.25f, 6, 6);
+ glEndList();
+
+ objdlist = glGenLists(1);
+ glNewList(objdlist, GL_COMPILE);
+ gluQuadricDrawStyle(obj, GLU_FILL);
+ gluQuadricNormals(obj, GLU_NONE);
+ gluQuadricTexture(obj, GL_TRUE);
+ gluSphere(obj, SPHERE_RADIUS, 16, 16);
+ glEndList();
+}
+
+int
+main(int ac, char **av)
+{
+ fprintf(stderr,
+ "Ray V1.0\nWritten by David Bucciarelli ([email protected])\n");
+
+ /*
+ if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
+ fprintf(stderr,"Error setting the process class.\n");
+ return 0;
+ }
+
+ if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
+ fprintf(stderr,"Error setting the process priority.\n");
+ return 0;
+ }
+ */
+
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(WIDTH, HEIGHT);
+ glutInit(&ac, av);
+
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
+
+ if (!(win = glutCreateWindow("Ray"))) {
+ fprintf(stderr, "Error, couldn't open window\n");
+ return -1;
+ }
+
+ reshape(WIDTH, HEIGHT);
+
+ glShadeModel(GL_FLAT);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_EXP2);
+ glFogfv(GL_FOG_COLOR, fogcolor);
+
+ glFogf(GL_FOG_DENSITY, 0.01);
+#ifdef FX
+ glHint(GL_FOG_HINT, GL_NICEST);
+#endif
+
+ calcposobs();
+
+ initspherepos();
+
+ inittextures();
+ initdlists();
+
+ glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
+
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+ glutIdleFunc(draw);
+
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/progs/demos/shadow.c b/progs/demos/shadow.c
new file mode 100644
index 00000000000..a1b3fdeca7a
--- /dev/null
+++ b/progs/demos/shadow.c
@@ -0,0 +1,117 @@
+/**
+(c) Copyright 1993, Silicon Graphics, Inc.
+
+ALL RIGHTS RESERVED
+
+Permission to use, copy, modify, and distribute this software
+for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that
+both the copyright notice and this permission notice appear in
+supporting documentation, and that the name of Silicon
+Graphics, Inc. not be used in advertising or publicity
+pertaining to distribution of the software without specific,
+written prior permission.
+
+THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
+"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
+OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
+EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
+ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
+INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
+SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
+NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
+OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+US Government Users Restricted Rights
+
+Use, duplication, or disclosure by the Government is subject to
+restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+(c)(1)(ii) of the Rights in Technical Data and Computer
+Software clause at DFARS 252.227-7013 and/or in similar or
+successor clauses in the FAR or the DOD or NASA FAR
+Supplement. Unpublished-- rights reserved under the copyright
+laws of the United States. Contractor/manufacturer is Silicon
+Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
+94039-7311.
+
+OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+*/
+
+/* Taken from the projshadow.c - by Tom McReynolds, SGI */
+
+/* Modified by David Bucciarelli */
+
+/* Rendering shadows using projective shadows. */
+
+#include <GL/glut.h>
+
+enum {
+ X, Y, Z, W
+};
+enum {
+ A, B, C, D
+};
+
+/* create a matrix that will project the desired shadow */
+void
+shadowmatrix(GLfloat shadowMat[4][4],
+ GLfloat groundplane[4],
+ GLfloat lightpos[4])
+{
+ GLfloat dot;
+
+ /* find dot product between light position vector and ground plane normal */
+ dot = groundplane[X] * lightpos[X] +
+ groundplane[Y] * lightpos[Y] +
+ groundplane[Z] * lightpos[Z] +
+ groundplane[W] * lightpos[W];
+
+ shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
+ shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
+ shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
+ shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
+
+ shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
+ shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
+ shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
+ shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
+
+ shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
+ shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
+ shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
+ shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
+
+ shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
+ shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
+ shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
+ shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
+
+}
+
+/* find the plane equation given 3 points */
+void
+findplane(GLfloat plane[4],
+ GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
+{
+ GLfloat vec0[3], vec1[3];
+
+ /* need 2 vectors to find cross product */
+ vec0[X] = v1[X] - v0[X];
+ vec0[Y] = v1[Y] - v0[Y];
+ vec0[Z] = v1[Z] - v0[Z];
+
+ vec1[X] = v2[X] - v0[X];
+ vec1[Y] = v2[Y] - v0[Y];
+ vec1[Z] = v2[Z] - v0[Z];
+
+ /* find cross product to get A, B, and C of plane equation */
+ plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
+ plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
+ plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
+
+ plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
+}
diff --git a/progs/demos/teapot.c b/progs/demos/teapot.c
new file mode 100644
index 00000000000..addee03a3da
--- /dev/null
+++ b/progs/demos/teapot.c
@@ -0,0 +1,575 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <GL/glut.h>
+#include "../util/readtex.c"
+#include "shadow.c"
+
+#ifdef XMESA
+#include "GL/xmesa.h"
+static int fullscreen=1;
+#endif
+
+static int WIDTH=640;
+static int HEIGHT=480;
+
+#define FRAME 50
+
+#define BASESIZE 10.0
+
+#define BASERES 12
+#define TEAPOTRES 3
+
+#ifndef M_PI
+#define M_PI 3.1415926535
+#endif
+
+extern void shadowmatrix(GLfloat [4][4], GLfloat [4], GLfloat [4]);
+extern void findplane(GLfloat [4], GLfloat [3], GLfloat [3], GLfloat [3]);
+
+
+static int win=0;
+
+static float obs[3]={5.0,0.0,1.0};
+static float dir[3];
+static float v=0.0;
+static float alpha=-90.0;
+static float beta=90.0;
+
+static GLfloat baseshadow[4][4];
+static GLfloat lightpos[4]={2.3,0.0,3.0,1.0};
+static GLfloat lightdir[3]={-2.3,0.0,-3.0};
+static GLfloat lightalpha=0.0;
+
+static int fog=1;
+static int bfcull=1;
+static int usetex=1;
+static int help=1;
+static int joyavailable=0;
+static int joyactive=0;
+
+static GLuint t1id,t2id;
+static GLuint teapotdlist,basedlist,lightdlist;
+
+static float gettime(void)
+{
+ static clock_t told=0;
+ clock_t tnew,ris;
+
+ tnew=clock();
+
+ ris=tnew-told;
+
+ told=tnew;
+
+ return(ris/(float)CLOCKS_PER_SEC);
+}
+
+static void calcposobs(void)
+{
+ dir[0]=sin(alpha*M_PI/180.0);
+ dir[1]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
+ dir[2]=cos(beta*M_PI/180.0);
+
+ obs[0]+=v*dir[0];
+ obs[1]+=v*dir[1];
+ obs[2]+=v*dir[2];
+}
+
+static void special(int k, int x, int y)
+{
+ switch(k) {
+ case GLUT_KEY_LEFT:
+ alpha-=2.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ alpha+=2.0;
+ break;
+ case GLUT_KEY_DOWN:
+ beta-=2.0;
+ break;
+ case GLUT_KEY_UP:
+ beta+=2.0;
+ break;
+ }
+}
+
+static void key(unsigned char k, int x, int y)
+{
+ switch(k) {
+ case 27:
+ exit(0);
+ break;
+
+ case 'a':
+ v+=0.005;
+ break;
+ case 'z':
+ v-=0.005;
+ break;
+
+ case 'j':
+ joyactive=(!joyactive);
+ break;
+ case 'h':
+ help=(!help);
+ break;
+ case 'f':
+ fog=(!fog);
+ break;
+ case 't':
+ usetex=(!usetex);
+ break;
+ case 'b':
+ if(bfcull) {
+ glDisable(GL_CULL_FACE);
+ bfcull=0;
+ } else {
+ glEnable(GL_CULL_FACE);
+ bfcull=1;
+ }
+ break;
+#ifdef XMESA
+ case ' ':
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+ fullscreen=(!fullscreen);
+ break;
+#endif
+ }
+}
+
+static void reshape(int w, int h)
+{
+ WIDTH=w;
+ HEIGHT=h;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(45.0,w/(float)h,0.2,40.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glViewport(0,0,w,h);
+}
+
+static void printstring(void *font, char *string)
+{
+ int len,i;
+
+ len=(int)strlen(string);
+ for(i=0;i<len;i++)
+ glutBitmapCharacter(font,string[i]);
+}
+
+static void printhelp(void)
+{
+ glEnable(GL_BLEND);
+ glColor4f(0.5,0.5,0.5,0.5);
+ glRecti(40,40,600,440);
+ glDisable(GL_BLEND);
+
+ glColor3f(1.0,0.0,0.0);
+ glRasterPos2i(300,420);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
+
+ glRasterPos2i(60,390);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Togle Help");
+ glRasterPos2i(60,360);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"t - Togle Textures");
+ glRasterPos2i(60,330);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Togle Fog");
+ glRasterPos2i(60,300);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"b - Togle Back face culling");
+ glRasterPos2i(60,270);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
+ glRasterPos2i(60,240);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
+ glRasterPos2i(60,210);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
+
+ glRasterPos2i(60,180);
+ if(joyavailable)
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"j - Togle jostick control (Joystick control available)");
+ else
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,"(No Joystick control available)");
+}
+
+static void drawbase(void)
+{
+ int i,j;
+ float x,y,dx,dy;
+
+ glBindTexture(GL_TEXTURE_2D,t1id);
+
+ dx=BASESIZE/BASERES;
+ dy=-BASESIZE/BASERES;
+ for(y=BASESIZE/2.0,j=0;j<BASERES;y+=dy,j++) {
+ glBegin(GL_QUAD_STRIP);
+ glColor3f(1.0,1.0,1.0);
+ glNormal3f(0.0,0.0,1.0);
+ for(x=-BASESIZE/2.0,i=0;i<BASERES;x+=dx,i++) {
+ glTexCoord2f(x,y);
+ glVertex3f(x,y,0.0);
+
+ glTexCoord2f(x,y+dy);
+ glVertex3f(x,y+dy,0.0);
+ }
+ glEnd();
+ }
+}
+
+static void drawteapot(void)
+{
+ static float xrot=0.0;
+ static float zrot=0.0;
+
+ glPushMatrix();
+ glRotatef(lightalpha,0.0,0.0,1.0);
+ glMultMatrixf((GLfloat *)baseshadow);
+ glRotatef(-lightalpha,0.0,0.0,1.0);
+
+ glTranslatef(0.0,0.0,1.0);
+ glRotatef(xrot,1.0,0.0,0.0);
+ glRotatef(zrot,0.0,0.0,1.0);
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+
+ glColor3f(0.0,0.0,0.0);
+ glCallList(teapotdlist);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LIGHTING);
+ if(usetex)
+ glEnable(GL_TEXTURE_2D);
+
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(0.0,0.0,1.0);
+ glRotatef(xrot,1.0,0.0,0.0);
+ glRotatef(zrot,0.0,0.0,1.0);
+
+ glCallList(teapotdlist);
+ glPopMatrix();
+
+ xrot+=2.0;
+ zrot+=1.0;
+}
+
+static void drawlight1(void)
+{
+ glPushMatrix();
+ glRotatef(lightalpha,0.0,0.0,1.0);
+ glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
+ glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightdir);
+
+ glPopMatrix();
+}
+
+static void drawlight2(void)
+{
+ glPushMatrix();
+ glRotatef(lightalpha,0.0,0.0,1.0);
+ glTranslatef(lightpos[0],lightpos[1],lightpos[2]);
+
+ glDisable(GL_TEXTURE_2D);
+ glCallList(lightdlist);
+ if(usetex)
+ glEnable(GL_TEXTURE_2D);
+
+ glPopMatrix();
+
+ lightalpha+=1.0;
+}
+
+static void dojoy(void)
+{
+#ifdef WIN32
+ static UINT max[2]={0,0};
+ static UINT min[2]={0xffffffff,0xffffffff},center[2];
+ MMRESULT res;
+ JOYINFO joy;
+
+ res=joyGetPos(JOYSTICKID1,&joy);
+
+ if(res==JOYERR_NOERROR) {
+ joyavailable=1;
+
+ if(max[0]<joy.wXpos)
+ max[0]=joy.wXpos;
+ if(min[0]>joy.wXpos)
+ min[0]=joy.wXpos;
+ center[0]=(max[0]+min[0])/2;
+
+ if(max[1]<joy.wYpos)
+ max[1]=joy.wYpos;
+ if(min[1]>joy.wYpos)
+ min[1]=joy.wYpos;
+ center[1]=(max[1]+min[1])/2;
+
+ if(joyactive) {
+ if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
+ alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
+ if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
+ beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
+
+ if(joy.wButtons & JOY_BUTTON1)
+ v+=0.005;
+ if(joy.wButtons & JOY_BUTTON2)
+ v-=0.005;
+ }
+ } else
+ joyavailable=0;
+#endif
+}
+
+static void draw(void)
+{
+ static int count=0;
+ static char frbuf[80];
+ float fr;
+
+ dojoy();
+
+ glEnable(GL_DEPTH_TEST);
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ if(usetex)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+
+ if(fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ glEnable(GL_LIGHTING);
+
+ glShadeModel(GL_SMOOTH);
+
+ glPushMatrix();
+ calcposobs();
+
+ gluLookAt(obs[0],obs[1],obs[2],
+ obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
+ 0.0,0.0,1.0);
+
+ drawlight1();
+ glCallList(basedlist);
+ drawteapot();
+ drawlight2();
+ glPopMatrix();
+
+ if((count % FRAME)==0) {
+ fr=gettime();
+ sprintf(frbuf,"Frame rate: %f",FRAME/fr);
+ }
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_FOG);
+ glShadeModel(GL_FLAT);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glColor3f(1.0,0.0,0.0);
+ glRasterPos2i(10,10);
+ printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
+ glRasterPos2i(350,470);
+ printstring(GLUT_BITMAP_HELVETICA_10,"Teapot V1.2 Written by David Bucciarelli ([email protected])");
+
+ if(help)
+ printhelp();
+
+ reshape(WIDTH,HEIGHT);
+
+ glutSwapBuffers();
+
+ count++;
+}
+
+static void inittextures(void)
+{
+ GLenum gluerr;
+
+ glGenTextures(1,&t1id);
+ glBindTexture(GL_TEXTURE_2D,t1id);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT,4);
+ if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) {
+ fprintf(stderr,"Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+
+ glGenTextures(1,&t2id);
+ glBindTexture(GL_TEXTURE_2D,t2id);
+
+ if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
+ fprintf(stderr,"Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+}
+
+static void initlight(void)
+{
+ float lamb[4]={0.2,0.2,0.2,1.0};
+ float lspec[4]={1.0,1.0,1.0,1.0};
+
+ glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0);
+ glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0);
+ glLightfv(GL_LIGHT0,GL_AMBIENT,lamb);
+ glLightfv(GL_LIGHT0,GL_SPECULAR,lspec);
+
+ glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,20.0);
+ glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,lspec);
+
+ glEnable(GL_LIGHT0);
+}
+
+static void initdlists(void)
+{
+ GLUquadricObj *lcone,*lbase;
+ GLfloat plane[4];
+ GLfloat v0[3]={0.0,0.0,0.0};
+ GLfloat v1[3]={1.0,0.0,0.0};
+ GLfloat v2[3]={0.0,1.0,0.0};
+
+ findplane(plane,v0,v1,v2);
+ shadowmatrix(baseshadow,plane,lightpos);
+
+ teapotdlist=glGenLists(1);
+ glNewList(teapotdlist,GL_COMPILE);
+ glRotatef(90.0,1.0,0.0,0.0);
+ glCullFace(GL_FRONT);
+ glBindTexture(GL_TEXTURE_2D,t2id);
+ glutSolidTeapot(0.75);
+ glCullFace(GL_BACK);
+ glEndList();
+
+ basedlist=glGenLists(1);
+ glNewList(basedlist,GL_COMPILE);
+ drawbase();
+ glEndList();
+
+ lightdlist=glGenLists(1);
+ glNewList(lightdlist,GL_COMPILE);
+ glDisable(GL_LIGHTING);
+
+ lcone=gluNewQuadric();
+ lbase=gluNewQuadric();
+ glRotatef(45.0,0.0,1.0,0.0);
+
+ glColor3f(1.0,1.0,1.0);
+ glCullFace(GL_FRONT);
+ gluDisk(lbase,0.0,0.2,12.0,1.0);
+ glCullFace(GL_BACK);
+
+ glColor3f(0.5,0.0,0.0);
+ gluCylinder(lcone,0.2,0.0,0.5,12,1);
+
+ gluDeleteQuadric(lcone);
+ gluDeleteQuadric(lbase);
+
+ glEnable(GL_LIGHTING);
+ glEndList();
+}
+
+int main(int ac, char **av)
+{
+ float fogcolor[4]={0.025,0.025,0.025,1.0};
+
+ fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli ([email protected])\n");
+
+ /*
+ if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
+ fprintf(stderr,"Error setting the process class.\n");
+ return 0;
+ }
+
+ if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
+ fprintf(stderr,"Error setting the process priority.\n");
+ return 0;
+ }
+ */
+
+ glutInitWindowPosition(0,0);
+ glutInitWindowSize(WIDTH,HEIGHT);
+ glutInit(&ac,av);
+
+ glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
+
+ if(!(win=glutCreateWindow("Teapot"))) {
+ fprintf(stderr,"Error, couldn't open window\n");
+ return -1;
+ }
+
+ reshape(WIDTH,HEIGHT);
+
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE,GL_EXP2);
+ glFogfv(GL_FOG_COLOR,fogcolor);
+
+ glFogf(GL_FOG_DENSITY,0.04);
+ glHint(GL_FOG_HINT,GL_NICEST);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+ calcposobs();
+
+ inittextures();
+ initlight();
+
+ initdlists();
+
+ glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
+
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+ glutIdleFunc(draw);
+
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/progs/demos/terrain.c b/progs/demos/terrain.c
new file mode 100644
index 00000000000..b708ff826de
--- /dev/null
+++ b/progs/demos/terrain.c
@@ -0,0 +1,653 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ *
+ * based on a Mikael SkiZoWalker's (MoDEL) / France ([email protected]) demo
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <time.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <GL/glut.h>
+
+#ifdef XMESA
+#include "GL/xmesa.h"
+static int fullscreen = 1;
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+#define heightMnt 450
+#define lenghtXmnt 62
+#define lenghtYmnt 62
+
+#define stepXmnt 96.0
+#define stepYmnt 96.0
+
+#define WIDTH 640
+#define HEIGHT 480
+
+#define TSCALE 4
+
+#define FRAME 50
+
+#define FOV 85
+
+static GLfloat terrain[256 * 256];
+static GLfloat terraincolor[256 * 256][3];
+
+static int win = 0;
+
+static int fog = 1;
+static int bfcull = 1;
+static int usetex = 1;
+static int poutline = 0;
+static int help = 1;
+static int joyavailable = 0;
+static int joyactive = 0;
+static float ModZMnt;
+static long GlobalMnt = 0;
+
+static int scrwidth = WIDTH;
+static int scrheight = HEIGHT;
+
+#define OBSSTARTX 992.0
+#define OBSSTARTY 103.0
+
+static float obs[3] = { OBSSTARTX, heightMnt * 1.3, OBSSTARTY };
+static float dir[3], v1[2], v2[2];
+static float v = 15.0;
+static float alpha = 75.0;
+static float beta = 90.0;
+
+static float
+gettime(void)
+{
+ static clock_t told = 0;
+ clock_t tnew, ris;
+
+ tnew = clock();
+
+ ris = tnew - told;
+
+ told = tnew;
+
+ return (ris / (float) CLOCKS_PER_SEC);
+}
+
+static void
+calcposobs(void)
+{
+ float alpha1, alpha2;
+
+ dir[0] = sin(alpha * M_PI / 180.0);
+ dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
+ dir[1] = cos(beta * M_PI / 180.0);
+
+ alpha1 = alpha + FOV / 2.0;
+ v1[0] = sin(alpha1 * M_PI / 180.0);
+ v1[1] = cos(alpha1 * M_PI / 180.0);
+
+ alpha2 = alpha - FOV / 2.0;
+ v2[0] = sin(alpha2 * M_PI / 180.0);
+ v2[1] = cos(alpha2 * M_PI / 180.0);
+
+ obs[0] += v * dir[0];
+ obs[1] += v * dir[1];
+ obs[2] += v * dir[2];
+
+ if (obs[1] < 0.0)
+ obs[1] = 0.0;
+}
+
+static void
+reshape(int width, int height)
+{
+ scrwidth = width;
+ scrheight = height;
+ glViewport(0, 0, (GLint) width, (GLint) height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(50.0, ((GLfloat) width / (GLfloat) height),
+ lenghtXmnt * stepYmnt * 0.01, lenghtXmnt * stepYmnt * 0.7);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+int
+clipstrip(float y, float *start, float *end)
+{
+ float x1, x2, t1, t2, tmp;
+
+ if (v1[1] == 0.0) {
+ t1 = 0.0;
+ x1 = -HUGE_VAL;
+ }
+ else {
+ t1 = y / v1[1];
+ x1 = t1 * v1[0];
+ }
+
+ if (v2[1] == 0.0) {
+ t2 = 0.0;
+ x2 = HUGE_VAL;
+ }
+ else {
+ t2 = y / v2[1];
+ x2 = t2 * v2[0];
+ }
+
+ if (((x1 < -(lenghtXmnt * stepXmnt) / 2) && (t2 <= 0.0)) ||
+ ((t1 <= 0.0) && (x2 > (lenghtXmnt * stepXmnt) / 2)) ||
+ ((t1 < 0.0) && (t2 < 0.0)))
+ return 0;
+
+ if ((t1 == 0.0) && (t2 == 0.0)) {
+ if ((v1[0] < 0.0) && (v1[1] > 0.0) && (v2[0] < 0.0) && (v2[1] < 0.0)) {
+ *start = -(lenghtXmnt * stepXmnt) / 2;
+ *end = stepXmnt;
+ return 1;
+ }
+ else {
+ if ((v1[0] > 0.0) && (v1[1] < 0.0) && (v2[0] > 0.0) && (v2[1] > 0.0)) {
+ *start = -stepXmnt;
+ *end = (lenghtXmnt * stepXmnt) / 2;
+ return 1;
+ }
+ else
+ return 0;
+ }
+ }
+ else {
+ if (t2 < 0.0) {
+ if (x1 < 0.0)
+ x2 = -(lenghtXmnt * stepXmnt) / 2;
+ else
+ x2 = (lenghtXmnt * stepXmnt) / 2;
+ }
+
+ if (t1 < 0.0) {
+ if (x2 < 0.0)
+ x1 = -(lenghtXmnt * stepXmnt) / 2;
+ else
+ x1 = (lenghtXmnt * stepXmnt) / 2;
+ }
+ }
+
+ if (x1 > x2) {
+ tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+
+ x1 -= stepXmnt;
+ if (x1 < -(lenghtXmnt * stepXmnt) / 2)
+ x1 = -(lenghtXmnt * stepXmnt) / 2;
+
+ x2 += stepXmnt;
+ if (x2 > (lenghtXmnt * stepXmnt) / 2)
+ x2 = (lenghtXmnt * stepXmnt) / 2;
+
+ *start = ((int) (x1 / stepXmnt)) * stepXmnt;
+ *end = ((int) (x2 / stepXmnt)) * stepXmnt;
+
+ return 1;
+}
+
+static void
+printstring(void *font, char *string)
+{
+ int len, i;
+
+ len = (int) strlen(string);
+ for (i = 0; i < len; i++)
+ glutBitmapCharacter(font, string[i]);
+}
+
+static void
+printhelp(void)
+{
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.0, 0.0, 0.0, 0.5);
+ glRecti(40, 40, 600, 440);
+ glDisable(GL_BLEND);
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(300, 420);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
+
+ glRasterPos2i(60, 390);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Togle Help");
+ glRasterPos2i(60, 360);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Togle Textures");
+ glRasterPos2i(60, 330);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Togle Fog");
+ glRasterPos2i(60, 300);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "p - Wire frame");
+ glRasterPos2i(60, 270);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Togle Back face culling");
+ glRasterPos2i(60, 240);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
+ glRasterPos2i(60, 210);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
+ glRasterPos2i(60, 180);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
+
+ glRasterPos2i(60, 150);
+ if (joyavailable)
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "j - Togle jostick control (Joystick control available)");
+ else
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "(No Joystick control available)");
+}
+
+void
+drawterrain(void)
+{
+ int h, i, idx, ox, oy;
+ float j, k, start, end;
+
+ ox = (int) (obs[0] / stepXmnt);
+ oy = (int) (obs[2] / stepYmnt);
+ GlobalMnt = ((ox * TSCALE) & 255) + ((oy * TSCALE) & 255) * 256;
+
+ glPushMatrix();
+ glTranslatef((float) ox * stepXmnt, 0, (float) oy * stepYmnt);
+
+ for (h = 0, k = -(lenghtYmnt * stepYmnt) / 2; h < lenghtYmnt;
+ k += stepYmnt, h++) {
+ if (!clipstrip(k, &start, &end))
+ continue;
+
+ glBegin(GL_TRIANGLE_STRIP); /* I hope that the optimizer will be able to improve this code */
+ for (i = (int) (lenghtXmnt / 2 + start / stepXmnt), j = start; j <= end;
+ j += stepXmnt, i++) {
+ idx = (i * TSCALE + h * 256 * TSCALE + GlobalMnt) & 65535;
+ glColor3fv(terraincolor[idx]);
+ glTexCoord2f((ox + i) / 8.0, (oy + h) / 8.0);
+ glVertex3f(j, terrain[idx], k);
+
+ idx =
+ (i * TSCALE + h * 256 * TSCALE + 256 * TSCALE +
+ GlobalMnt) & 65535;
+ glColor3fv(terraincolor[idx]);
+ glTexCoord2f((ox + i) / 8.0, (oy + h + 1) / 8.0);
+ glVertex3f(j, terrain[idx], k + stepYmnt);
+ }
+ glEnd();
+ }
+
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBegin(GL_QUADS);
+ glColor4f(0.1, 0.7, 1.0, 0.4);
+ glVertex3f(-(lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
+ -(lenghtYmnt * stepYmnt) / 2.0);
+ glVertex3f(-(lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
+ (lenghtYmnt * stepYmnt) / 2.0);
+ glVertex3f((lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
+ (lenghtYmnt * stepYmnt) / 2.0);
+ glVertex3f((lenghtXmnt * stepXmnt) / 2.0, heightMnt * 0.6,
+ -(lenghtYmnt * stepYmnt) / 2.0);
+ glEnd();
+ glDisable(GL_BLEND);
+ if (bfcull)
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ glPopMatrix();
+
+}
+
+static void
+dojoy(void)
+{
+#ifdef WIN32
+ static UINT max[2] = { 0, 0 };
+ static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
+ MMRESULT res;
+ JOYINFO joy;
+
+ res = joyGetPos(JOYSTICKID1, &joy);
+
+ if (res == JOYERR_NOERROR) {
+ joyavailable = 1;
+
+ if (max[0] < joy.wXpos)
+ max[0] = joy.wXpos;
+ if (min[0] > joy.wXpos)
+ min[0] = joy.wXpos;
+ center[0] = (max[0] + min[0]) / 2;
+
+ if (max[1] < joy.wYpos)
+ max[1] = joy.wYpos;
+ if (min[1] > joy.wYpos)
+ min[1] = joy.wYpos;
+ center[1] = (max[1] + min[1]) / 2;
+
+ if (joyactive) {
+ if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
+ alpha +=
+ 2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
+ if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
+ beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
+
+ if (joy.wButtons & JOY_BUTTON1)
+ v += 0.5;
+ if (joy.wButtons & JOY_BUTTON2)
+ v -= 0.5;
+ }
+ }
+ else
+ joyavailable = 0;
+#endif
+}
+
+void
+drawscene(void)
+{
+ static int count = 0;
+ static char frbuf[80];
+ float fr;
+
+ dojoy();
+
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_DEPTH_TEST);
+
+ if (usetex)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+
+ if (fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+
+ calcposobs();
+ gluLookAt(obs[0], obs[1], obs[2],
+ obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
+ 0.0, 1.0, 0.0);
+
+ drawterrain();
+ glPopMatrix();
+
+ if ((count % FRAME) == 0) {
+ fr = gettime();
+ sprintf(frbuf, "Frame rate: %.3f", FRAME / fr);
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_FOG);
+ glShadeModel(GL_FLAT);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(10, 10);
+ printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
+ glRasterPos2i(350, 470);
+ printstring(GLUT_BITMAP_HELVETICA_10,
+ "Terrain V1.2 Written by David Bucciarelli ([email protected])");
+ glRasterPos2i(434, 457);
+ printstring(GLUT_BITMAP_HELVETICA_10,
+ "Based on a Mickael's demo ([email protected])");
+
+ if (help)
+ printhelp();
+
+ reshape(scrwidth, scrheight);
+
+ glutSwapBuffers();
+
+ count++;
+}
+
+static void
+key(unsigned char k, int x, int y)
+{
+ switch (k) {
+ case 27:
+ exit(0);
+ break;
+ case 'a':
+ v += 0.5;
+ break;
+ case 'z':
+ v -= 0.5;
+ break;
+ case 'p':
+ if (poutline) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ poutline = 0;
+ }
+ else {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ poutline = 1;
+ }
+ break;
+ case 'j':
+ joyactive = (!joyactive);
+ break;
+ case 'h':
+ help = (!help);
+ break;
+ case 'f':
+ fog = (!fog);
+ break;
+ case 't':
+ usetex = (!usetex);
+ break;
+ case 'b':
+ if (bfcull) {
+ glDisable(GL_CULL_FACE);
+ bfcull = 0;
+ }
+ else {
+ glEnable(GL_CULL_FACE);
+ bfcull = 1;
+ }
+ break;
+#ifdef XMESA
+ case ' ':
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+ fullscreen = (!fullscreen);
+ break;
+#endif
+ }
+}
+
+static void
+special(int k, int x, int y)
+{
+ switch (k) {
+ case GLUT_KEY_LEFT:
+ alpha += 2.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ alpha -= 2.0;
+ break;
+ case GLUT_KEY_DOWN:
+ beta -= 2.0;
+ break;
+ case GLUT_KEY_UP:
+ beta += 2.0;
+ break;
+ }
+}
+
+static void
+calccolor(GLfloat height, GLfloat c[3])
+{
+ GLfloat color[4][3] = {
+ {1.0, 1.0, 1.0},
+ {0.0, 0.8, 0.0},
+ {1.0, 1.0, 0.3},
+ {0.0, 0.0, 0.8}
+ };
+ GLfloat fact;
+
+ height = height * (1.0 / 255.0);
+
+ if (height >= 0.9) {
+ c[0] = color[0][0];
+ c[1] = color[0][1];
+ c[2] = color[0][2];
+ return;
+ }
+
+ if ((height < 0.9) && (height >= 0.7)) {
+ fact = (height - 0.7) * 5.0;
+ c[0] = fact * color[0][0] + (1.0 - fact) * color[1][0];
+ c[1] = fact * color[0][1] + (1.0 - fact) * color[1][1];
+ c[2] = fact * color[0][2] + (1.0 - fact) * color[1][2];
+ return;
+ }
+
+ if ((height < 0.7) && (height >= 0.6)) {
+ fact = (height - 0.6) * 10.0;
+ c[0] = fact * color[1][0] + (1.0 - fact) * color[2][0];
+ c[1] = fact * color[1][1] + (1.0 - fact) * color[2][1];
+ c[2] = fact * color[1][2] + (1.0 - fact) * color[2][2];
+ return;
+ }
+
+ if ((height < 0.6) && (height >= 0.5)) {
+ fact = (height - 0.5) * 10.0;
+ c[0] = fact * color[2][0] + (1.0 - fact) * color[3][0];
+ c[1] = fact * color[2][1] + (1.0 - fact) * color[3][1];
+ c[2] = fact * color[2][2] + (1.0 - fact) * color[3][2];
+ return;
+ }
+
+ c[0] = color[3][0];
+ c[1] = color[3][1];
+ c[2] = color[3][2];
+}
+
+static void
+loadpic(void)
+{
+ GLubyte bufferter[256 * 256], terrainpic[256 * 256];
+ FILE *FilePic;
+ int i, tmp;
+ GLenum gluerr;
+
+ if ((FilePic = fopen("terrain.dat", "r")) == NULL) {
+ fprintf(stderr, "Error loading Mnt.bin\n");
+ exit(-1);
+ }
+ fread(bufferter, 256 * 256, 1, FilePic);
+ fclose(FilePic);
+
+ for (i = 0; i < (256 * 256); i++) {
+ terrain[i] = (bufferter[i] * (heightMnt / 255.0f));
+ calccolor((GLfloat) bufferter[i], terraincolor[i]);
+ tmp = (((int) bufferter[i]) + 96);
+ terrainpic[i] = (tmp > 255) ? 255 : tmp;
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 1, 256, 256, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE,
+ (GLvoid *) (&terrainpic[0])))) {
+ fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glEnable(GL_TEXTURE_2D);
+}
+
+static void
+init(void)
+{
+ float fogcolor[4] = { 0.6, 0.7, 0.7, 1.0 };
+
+ glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
+ glClearDepth(1.0);
+ glDepthFunc(GL_LEQUAL);
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+
+ glDisable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_EXP2);
+ glFogfv(GL_FOG_COLOR, fogcolor);
+ glFogf(GL_FOG_DENSITY, 0.0007);
+#ifdef FX
+ glHint(GL_FOG_HINT, GL_NICEST);
+#endif
+
+ reshape(scrwidth, scrheight);
+}
+
+
+int
+main(int ac, char **av)
+{
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(WIDTH, HEIGHT);
+ glutInit(&ac, av);
+
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
+
+ if (!(win = glutCreateWindow("Terrain"))) {
+ fprintf(stderr, "Error, couldn't open window\n");
+ return -1;
+ }
+
+ ModZMnt = 0.0f;
+ loadpic();
+
+ init();
+
+#ifndef FX
+ glDisable(GL_TEXTURE_2D);
+ usetex = 0;
+#endif
+
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(drawscene);
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+ glutIdleFunc(drawscene);
+
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/progs/demos/tunnel.c b/progs/demos/tunnel.c
new file mode 100644
index 00000000000..3cced8b2a93
--- /dev/null
+++ b/progs/demos/tunnel.c
@@ -0,0 +1,514 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <GL/glut.h>
+#include "../util/readtex.c"
+#include "tunneldat.c"
+
+#ifdef XMESA
+#include "GL/xmesa.h"
+static int fullscreen = 1;
+#endif
+
+static int WIDTH = 640;
+static int HEIGHT = 480;
+
+#define FRAME 50
+
+#define NUMBLOC 5
+
+#ifndef M_PI
+#define M_PI 3.1415926535
+#endif
+
+extern int striplength_skin_13[];
+extern float stripdata_skin_13[];
+
+extern int striplength_skin_12[];
+extern float stripdata_skin_12[];
+
+extern int striplength_skin_11[];
+extern float stripdata_skin_11[];
+
+extern int striplength_skin_9[];
+extern float stripdata_skin_9[];
+
+
+static int win = 0;
+
+static float obs[3] = { 1000.0, 0.0, 2.0 };
+static float dir[3];
+static float v = 0.5;
+static float alpha = 90.0;
+static float beta = 90.0;
+
+static int fog = 0;
+static int bfcull = 1;
+static int usetex = 1;
+static int cstrip = 0;
+static int help = 1;
+static int joyavailable = 0;
+static int joyactive = 0;
+
+static GLuint t1id, t2id;
+
+static void
+inittextures(void)
+{
+ GLenum gluerr;
+
+ glGenTextures(1, &t1id);
+ glBindTexture(GL_TEXTURE_2D, t1id);
+
+ if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) {
+ fprintf(stderr, "Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glGenTextures(1, &t2id);
+ glBindTexture(GL_TEXTURE_2D, t2id);
+
+ if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
+ fprintf(stderr, "Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+static void
+drawobjs(int *l, float *f)
+{
+ int mend, j;
+
+ if (cstrip) {
+ float r = 0.33, g = 0.33, b = 0.33;
+
+ for (; (*l) != 0;) {
+ mend = *l++;
+
+ r += 0.33;
+ if (r > 1.0) {
+ r = 0.33;
+ g += 0.33;
+ if (g > 1.0) {
+ g = 0.33;
+ b += 0.33;
+ if (b > 1.0)
+ b = 0.33;
+ }
+ }
+
+ glColor3f(r, g, b);
+ glBegin(GL_TRIANGLE_STRIP);
+ for (j = 0; j < mend; j++) {
+ f += 4;
+ glTexCoord2fv(f);
+ f += 2;
+ glVertex3fv(f);
+ f += 3;
+ }
+ glEnd();
+ }
+ }
+ else
+ for (; (*l) != 0;) {
+ mend = *l++;
+
+ glBegin(GL_TRIANGLE_STRIP);
+ for (j = 0; j < mend; j++) {
+ glColor4fv(f);
+ f += 4;
+ glTexCoord2fv(f);
+ f += 2;
+ glVertex3fv(f);
+ f += 3;
+ }
+ glEnd();
+ }
+}
+
+static float
+gettime(void)
+{
+ static clock_t told = 0;
+ clock_t tnew, ris;
+
+ tnew = clock();
+
+ ris = tnew - told;
+
+ told = tnew;
+
+ return (ris / (float) CLOCKS_PER_SEC);
+}
+
+static void
+calcposobs(void)
+{
+ dir[0] = sin(alpha * M_PI / 180.0);
+ dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
+ dir[2] = cos(beta * M_PI / 180.0);
+
+ obs[0] += v * dir[0];
+ obs[1] += v * dir[1];
+ obs[2] += v * dir[2];
+}
+
+static void
+special(int k, int x, int y)
+{
+ switch (k) {
+ case GLUT_KEY_LEFT:
+ alpha -= 2.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ alpha += 2.0;
+ break;
+ case GLUT_KEY_DOWN:
+ beta -= 2.0;
+ break;
+ case GLUT_KEY_UP:
+ beta += 2.0;
+ break;
+ }
+}
+
+static void
+key(unsigned char k, int x, int y)
+{
+ switch (k) {
+ case 27:
+ exit(0);
+ break;
+
+ case 'a':
+ v += 0.01;
+ break;
+ case 'z':
+ v -= 0.01;
+ break;
+
+#ifdef XMESA
+ case ' ':
+ fullscreen = (!fullscreen);
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+ break;
+#endif
+
+ case 'j':
+ joyactive = (!joyactive);
+ break;
+ case 'h':
+ help = (!help);
+ break;
+ case 'f':
+ fog = (!fog);
+ break;
+ case 't':
+ usetex = (!usetex);
+ break;
+ case 'b':
+ if (bfcull) {
+ glDisable(GL_CULL_FACE);
+ bfcull = 0;
+ }
+ else {
+ glEnable(GL_CULL_FACE);
+ bfcull = 1;
+ }
+ break;
+ case 'm':
+ cstrip = (!cstrip);
+ break;
+
+ case 'd':
+ fprintf(stderr, "Deleting textures...\n");
+ glDeleteTextures(1, &t1id);
+ glDeleteTextures(1, &t2id);
+ fprintf(stderr, "Loading textures...\n");
+ inittextures();
+ fprintf(stderr, "Done.\n");
+ break;
+ }
+}
+
+static void
+reshape(int w, int h)
+{
+ WIDTH = w;
+ HEIGHT = h;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(80.0, w / (float) h, 1.0, 50.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glViewport(0, 0, w, h);
+}
+
+static void
+printstring(void *font, char *string)
+{
+ int len, i;
+
+ len = (int) strlen(string);
+ for (i = 0; i < len; i++)
+ glutBitmapCharacter(font, string[i]);
+}
+
+static void
+printhelp(void)
+{
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.0, 0.0, 0.0, 0.5);
+ glRecti(40, 40, 600, 440);
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(300, 420);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
+
+ glRasterPos2i(60, 390);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Togle Help");
+ glRasterPos2i(60, 360);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Togle Textures");
+ glRasterPos2i(60, 330);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Togle Fog");
+ glRasterPos2i(60, 300);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "m - Togle strips");
+ glRasterPos2i(60, 270);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Togle Back face culling");
+ glRasterPos2i(60, 240);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
+ glRasterPos2i(60, 210);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
+ glRasterPos2i(60, 180);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
+
+ glRasterPos2i(60, 150);
+ if (joyavailable)
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "j - Togle jostick control (Joystick control available)");
+ else
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "(No Joystick control available)");
+}
+
+static void
+dojoy(void)
+{
+#ifdef WIN32
+ static UINT max[2] = { 0, 0 };
+ static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
+ MMRESULT res;
+ JOYINFO joy;
+
+ res = joyGetPos(JOYSTICKID1, &joy);
+
+ if (res == JOYERR_NOERROR) {
+ joyavailable = 1;
+
+ if (max[0] < joy.wXpos)
+ max[0] = joy.wXpos;
+ if (min[0] > joy.wXpos)
+ min[0] = joy.wXpos;
+ center[0] = (max[0] + min[0]) / 2;
+
+ if (max[1] < joy.wYpos)
+ max[1] = joy.wYpos;
+ if (min[1] > joy.wYpos)
+ min[1] = joy.wYpos;
+ center[1] = (max[1] + min[1]) / 2;
+
+ if (joyactive) {
+ if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
+ alpha -=
+ 2.0 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
+ if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
+ beta += 2.0 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
+
+ if (joy.wButtons & JOY_BUTTON1)
+ v += 0.01;
+ if (joy.wButtons & JOY_BUTTON2)
+ v -= 0.01;
+ }
+ }
+ else
+ joyavailable = 0;
+#endif
+}
+
+static void
+draw(void)
+{
+ static int count = 0;
+ static char frbuf[80];
+ int i;
+ float fr, base, offset;
+
+ dojoy();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ if (usetex)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+
+ if (fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ glShadeModel(GL_SMOOTH);
+
+ glPushMatrix();
+ calcposobs();
+ gluLookAt(obs[0], obs[1], obs[2],
+ obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
+ 0.0, 0.0, 1.0);
+
+ if (dir[0] > 0) {
+ offset = 8.0;
+ base = obs[0] - fmod(obs[0], 8.0);
+ }
+ else {
+ offset = -8.0;
+ base = obs[0] + (8.0 - fmod(obs[0], 8.0));
+ }
+
+ glPushMatrix();
+ glTranslatef(base - offset / 2.0, 0.0, 0.0);
+ for (i = 0; i < NUMBLOC; i++) {
+ glTranslatef(offset, 0.0, 0.0);
+ glBindTexture(GL_TEXTURE_2D, t1id);
+ drawobjs(striplength_skin_11, stripdata_skin_11);
+ glBindTexture(GL_TEXTURE_2D, t2id);
+ drawobjs(striplength_skin_12, stripdata_skin_12);
+ drawobjs(striplength_skin_9, stripdata_skin_9);
+ drawobjs(striplength_skin_13, stripdata_skin_13);
+ }
+ glPopMatrix();
+ glPopMatrix();
+
+ if ((count % FRAME) == 0) {
+ fr = gettime();
+ sprintf(frbuf, "Frame rate: %f", FRAME / fr);
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_FOG);
+ glShadeModel(GL_FLAT);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(10, 10);
+ printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
+ glRasterPos2i(350, 470);
+ printstring(GLUT_BITMAP_HELVETICA_10,
+ "Tunnel V1.5 Written by David Bucciarelli ([email protected])");
+
+ if (help)
+ printhelp();
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ glutSwapBuffers();
+
+ count++;
+}
+
+int
+main(int ac, char **av)
+{
+ float fogcolor[4] = { 0.7, 0.7, 0.7, 1.0 };
+
+ fprintf(stderr,
+ "Tunnel V1.5\nWritten by David Bucciarelli ([email protected])\n");
+
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(WIDTH, HEIGHT);
+ glutInit(&ac, av);
+
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+
+ if (!(win = glutCreateWindow("Tunnel"))) {
+ fprintf(stderr, "Error, couldn't open window\n");
+ return -1;
+ }
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(80.0, WIDTH / (float) HEIGHT, 1.0, 50.0);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_EXP2);
+ glFogfv(GL_FOG_COLOR, fogcolor);
+
+ glFogf(GL_FOG_DENSITY, 0.06);
+ glHint(GL_FOG_HINT, GL_NICEST);
+
+ inittextures();
+
+ glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ calcposobs();
+
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+ glutIdleFunc(draw);
+
+ glEnable(GL_BLEND);
+ /*glBlendFunc(GL_SRC_ALPHA_SATURATE,GL_ONE); */
+ /*glEnable(GL_POLYGON_SMOOTH); */
+
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/progs/demos/tunnel2.c b/progs/demos/tunnel2.c
new file mode 100644
index 00000000000..b8cea412b02
--- /dev/null
+++ b/progs/demos/tunnel2.c
@@ -0,0 +1,618 @@
+/*
+ * This program is under the GNU GPL.
+ * Use at your own risk.
+ *
+ * You need TWO Voodoo Graphics boards in order to run
+ * this demo !
+ *
+ * written by David Bucciarelli ([email protected])
+ * Humanware s.r.l.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <GL/glut.h>
+#include "../util/readtex.c"
+#include "tunneldat.c"
+
+#ifdef FX
+#endif
+
+#ifdef XMESA
+#include "GL/xmesa.h"
+static int fullscreen = 1;
+#endif
+
+#ifdef FX
+GLboolean fxMesaSelectCurrentBoard(int);
+#endif
+
+static int WIDTHC0 = 640;
+static int HEIGHTC0 = 480;
+
+static int WIDTHC1 = 640;
+static int HEIGHTC1 = 480;
+
+#define FRAME 50
+
+#define NUMBLOC 5
+
+#ifndef M_PI
+#define M_PI 3.1415926535
+#endif
+
+extern int striplength_skin_13[];
+extern float stripdata_skin_13[];
+
+extern int striplength_skin_12[];
+extern float stripdata_skin_12[];
+
+extern int striplength_skin_11[];
+extern float stripdata_skin_11[];
+
+extern int striplength_skin_9[];
+extern float stripdata_skin_9[];
+
+
+static float obs[3] = { 1000.0, 0.0, 2.0 };
+static float dir[3];
+static float v = 0.5;
+static float alpha = 90.0;
+static float beta = 90.0;
+
+static int fog = 0;
+static int bfcull = 1;
+static int usetex = 1;
+static int cstrip = 0;
+static int help = 1;
+static int joyavailable = 0;
+static int joyactive = 0;
+
+static int channel[2];
+
+static GLuint t1id, t2id;
+
+static void
+inittextures(void)
+{
+ GLenum gluerr;
+
+ glGenTextures(1, &t1id);
+ glBindTexture(GL_TEXTURE_2D, t1id);
+
+ if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) {
+ fprintf(stderr, "Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glGenTextures(1, &t2id);
+ glBindTexture(GL_TEXTURE_2D, t2id);
+
+ if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
+ fprintf(stderr, "Error reading a texture.\n");
+ exit(-1);
+ }
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+static void
+drawobjs(int *l, float *f)
+{
+ int mend, j;
+
+ if (cstrip) {
+ float r = 0.33, g = 0.33, b = 0.33;
+
+ for (; (*l) != 0;) {
+ mend = *l++;
+
+ r += 0.33;
+ if (r > 1.0) {
+ r = 0.33;
+ g += 0.33;
+ if (g > 1.0) {
+ g = 0.33;
+ b += 0.33;
+ if (b > 1.0)
+ b = 0.33;
+ }
+ }
+
+ glColor3f(r, g, b);
+ glBegin(GL_TRIANGLE_STRIP);
+ for (j = 0; j < mend; j++) {
+ f += 4;
+ glTexCoord2fv(f);
+ f += 2;
+ glVertex3fv(f);
+ f += 3;
+ }
+ glEnd();
+ }
+ }
+ else
+ for (; (*l) != 0;) {
+ mend = *l++;
+
+ glBegin(GL_TRIANGLE_STRIP);
+ for (j = 0; j < mend; j++) {
+ glColor4fv(f);
+ f += 4;
+ glTexCoord2fv(f);
+ f += 2;
+ glVertex3fv(f);
+ f += 3;
+ }
+ glEnd();
+ }
+}
+
+static float
+gettime(void)
+{
+ static clock_t told = 0;
+ clock_t tnew, ris;
+
+ tnew = clock();
+
+ ris = tnew - told;
+
+ told = tnew;
+
+ return (ris / (float) CLOCKS_PER_SEC);
+}
+
+static void
+calcposobs(void)
+{
+ dir[0] = sin(alpha * M_PI / 180.0);
+ dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
+ dir[2] = cos(beta * M_PI / 180.0);
+
+ obs[0] += v * dir[0];
+ obs[1] += v * dir[1];
+ obs[2] += v * dir[2];
+}
+
+static void
+special(int k, int x, int y)
+{
+ switch (k) {
+ case GLUT_KEY_LEFT:
+ alpha -= 2.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ alpha += 2.0;
+ break;
+ case GLUT_KEY_DOWN:
+ beta -= 2.0;
+ break;
+ case GLUT_KEY_UP:
+ beta += 2.0;
+ break;
+ }
+}
+
+static void
+key(unsigned char k, int x, int y)
+{
+ switch (k) {
+ case 27:
+ exit(0);
+ break;
+
+ case 'a':
+ v += 0.01;
+ break;
+ case 'z':
+ v -= 0.01;
+ break;
+
+#ifdef XMESA
+ case ' ':
+ fullscreen = (!fullscreen);
+
+ glutSetWindow(channel[0]);
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+
+ glutSetWindow(channel[1]);
+ XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
+ break;
+#endif
+
+ case 'j':
+ joyactive = (!joyactive);
+ break;
+ case 'h':
+ help = (!help);
+ break;
+ case 'f':
+ fog = (!fog);
+ break;
+ case 't':
+ usetex = (!usetex);
+ break;
+ case 'b':
+ if (bfcull) {
+ glDisable(GL_CULL_FACE);
+ bfcull = 0;
+ }
+ else {
+ glEnable(GL_CULL_FACE);
+ bfcull = 1;
+ }
+ break;
+ case 'm':
+ cstrip = (!cstrip);
+ break;
+
+ case 'd':
+ fprintf(stderr, "Deleting textures...\n");
+ glDeleteTextures(1, &t1id);
+ glDeleteTextures(1, &t2id);
+ fprintf(stderr, "Loading textures...\n");
+ inittextures();
+ fprintf(stderr, "Done.\n");
+ break;
+ }
+}
+
+static void
+reshapechannel0(int w, int h)
+{
+ float ratio;
+
+ WIDTHC0 = w;
+ HEIGHTC0 = h;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ ratio = 0.5f * w / (float) h;
+
+ glFrustum(-2.0, 0.0, -1.0 * ratio, 1.0 * ratio, 1.0, 60.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glViewport(0, 0, w, h);
+}
+
+static void
+reshapechannel1(int w, int h)
+{
+ float ratio;
+
+ WIDTHC1 = w;
+ HEIGHTC1 = h;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ ratio = 0.5f * w / (float) h;
+
+ glFrustum(0.0, 2.0, -1.0 * ratio, 1.0 * ratio, 1.0, 60.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glViewport(0, 0, w, h);
+}
+
+static void
+printstring(void *font, char *string)
+{
+ int len, i;
+
+ len = (int) strlen(string);
+ for (i = 0; i < len; i++)
+ glutBitmapCharacter(font, string[i]);
+}
+
+static void
+printhelp(void)
+{
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.0, 0.0, 0.0, 0.5);
+ glRecti(40, 40, 600, 440);
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(300, 420);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
+
+ glRasterPos2i(60, 390);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Togle Help");
+ glRasterPos2i(60, 360);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Togle Textures");
+ glRasterPos2i(60, 330);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Togle Fog");
+ glRasterPos2i(60, 300);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "m - Togle strips");
+ glRasterPos2i(60, 270);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Togle Back face culling");
+ glRasterPos2i(60, 240);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
+ glRasterPos2i(60, 210);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
+ glRasterPos2i(60, 180);
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
+
+ glRasterPos2i(60, 150);
+ if (joyavailable)
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "j - Togle jostick control (Joystick control available)");
+ else
+ printstring(GLUT_BITMAP_TIMES_ROMAN_24,
+ "(No Joystick control available)");
+}
+
+static void
+dojoy(void)
+{
+#ifdef WIN32
+ static UINT max[2] = { 0, 0 };
+ static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
+ MMRESULT res;
+ JOYINFO joy;
+
+ res = joyGetPos(JOYSTICKID1, &joy);
+
+ if (res == JOYERR_NOERROR) {
+ joyavailable = 1;
+
+ if (max[0] < joy.wXpos)
+ max[0] = joy.wXpos;
+ if (min[0] > joy.wXpos)
+ min[0] = joy.wXpos;
+ center[0] = (max[0] + min[0]) / 2;
+
+ if (max[1] < joy.wYpos)
+ max[1] = joy.wYpos;
+ if (min[1] > joy.wYpos)
+ min[1] = joy.wYpos;
+ center[1] = (max[1] + min[1]) / 2;
+
+ if (joyactive) {
+ if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
+ alpha -=
+ 2.0 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
+ if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
+ beta += 2.0 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
+
+ if (joy.wButtons & JOY_BUTTON1)
+ v += 0.01;
+ if (joy.wButtons & JOY_BUTTON2)
+ v -= 0.01;
+ }
+ }
+ else
+ joyavailable = 0;
+#endif
+}
+
+static void
+draw(void)
+{
+ static int count = 0;
+ static char frbuf[80];
+ int i;
+ float fr, base, offset;
+
+ dojoy();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ if (usetex)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+
+ if (fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ glShadeModel(GL_SMOOTH);
+
+ glPushMatrix();
+ calcposobs();
+ gluLookAt(obs[0], obs[1], obs[2],
+ obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
+ 0.0, 0.0, 1.0);
+
+ if (dir[0] > 0) {
+ offset = 8.0;
+ base = obs[0] - fmod(obs[0], 8.0);
+ }
+ else {
+ offset = -8.0;
+ base = obs[0] + (8.0 - fmod(obs[0], 8.0));
+ }
+
+ glPushMatrix();
+ glTranslatef(base - offset / 2.0, 0.0, 0.0);
+ for (i = 0; i < NUMBLOC; i++) {
+ glTranslatef(offset, 0.0, 0.0);
+ glBindTexture(GL_TEXTURE_2D, t1id);
+ drawobjs(striplength_skin_11, stripdata_skin_11);
+ glBindTexture(GL_TEXTURE_2D, t2id);
+ drawobjs(striplength_skin_12, stripdata_skin_12);
+ drawobjs(striplength_skin_9, stripdata_skin_9);
+ drawobjs(striplength_skin_13, stripdata_skin_13);
+ }
+ glPopMatrix();
+ glPopMatrix();
+
+ if ((count % FRAME) == 0) {
+ fr = gettime();
+ sprintf(frbuf, "Frame rate: %f", FRAME / fr);
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_FOG);
+ glShadeModel(GL_FLAT);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glColor3f(1.0, 0.0, 0.0);
+ glRasterPos2i(10, 10);
+ printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
+ glRasterPos2i(350, 470);
+ printstring(GLUT_BITMAP_HELVETICA_10,
+ "Tunnel2 V1.0 Written by David Bucciarelli ([email protected])");
+
+ if (help)
+ printhelp();
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ count++;
+}
+
+static void
+drawchannel0(void)
+{
+ glutSetWindow(channel[0]);
+ draw();
+ glutSwapBuffers();
+}
+
+static void
+drawchannel1(void)
+{
+ glutSetWindow(channel[1]);
+ draw();
+ glutSwapBuffers();
+}
+
+static void
+drawall(void)
+{
+ glutSetWindow(channel[0]);
+ draw();
+ glutSetWindow(channel[1]);
+ draw();
+
+ glutSetWindow(channel[0]);
+ glutSwapBuffers();
+ glutSetWindow(channel[1]);
+ glutSwapBuffers();
+}
+
+static void
+init(void)
+{
+ float fogcolor[4] = { 0.7, 0.7, 0.7, 1.0 };
+
+ glShadeModel(GL_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_EXP2);
+ glFogfv(GL_FOG_COLOR, fogcolor);
+
+ glFogf(GL_FOG_DENSITY, 0.06);
+ glHint(GL_FOG_HINT, GL_NICEST);
+
+ glEnable(GL_BLEND);
+ /*
+ glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
+ glEnable(GL_POLYGON_SMOOTH);
+ */
+
+ glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+int
+main(int ac, char **av)
+{
+ fprintf(stderr,
+ "Tunnel2 V1.0\nWritten by David Bucciarelli ([email protected])\n");
+ fprintf(stderr,
+ "You need TWO Voodoo Graphics boards in order to run this demo !\n");
+
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(WIDTHC0, HEIGHTC0);
+ glutInit(&ac, av);
+
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_ALPHA);
+
+#ifdef FX
+ if (!fxMesaSelectCurrentBoard(0)) {
+ fprintf(stderr, "The first Voodoo Graphics board is missing !?!?\n");
+ return -1;
+ }
+#endif
+ if (!(channel[0] = glutCreateWindow("Channel 0"))) {
+ fprintf(stderr, "Error, couldn't open window\n");
+ return -1;
+ }
+
+ reshapechannel0(WIDTHC0, HEIGHTC0);
+ init();
+ inittextures();
+ glutDisplayFunc(drawchannel0);
+ glutReshapeFunc(reshapechannel0);
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+
+#ifdef FX
+ if (!fxMesaSelectCurrentBoard(1)) {
+ fprintf(stderr, "The second Voodoo Graphics board is missing !\n");
+ exit(-1);
+ }
+#endif
+ glutInitWindowPosition(WIDTHC0, 0);
+ glutInitWindowSize(WIDTHC1, HEIGHTC1);
+ if (!(channel[1] = glutCreateWindow("Channel 1"))) {
+ fprintf(stderr, "Error, couldn't open window\n");
+ exit(-1);
+ }
+
+ reshapechannel1(WIDTHC1, HEIGHTC1);
+ init();
+ inittextures();
+ glutDisplayFunc(drawchannel1);
+ glutReshapeFunc(reshapechannel1);
+ glutKeyboardFunc(key);
+ glutSpecialFunc(special);
+
+ glutIdleFunc(drawall);
+
+ calcposobs();
+
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/progs/demos/tunneldat.c b/progs/demos/tunneldat.c
new file mode 100644
index 00000000000..a4506694be6
--- /dev/null
+++ b/progs/demos/tunneldat.c
@@ -0,0 +1,83 @@
+/* Object: skin_13 */
+
+#if defined(_MSC_VER) && defined(_WIN32)
+#pragma warning( disable : 4305 ) /* 'initializing' : truncation from 'const double' to 'float' */
+#endif
+
+int striplength_skin_13[]={
+10,7,3,5,5,4,4,4,4,5,3,4,5,4,4,4,4,4,4,6,
+6,3,6,3,3,3,3,0};
+
+float stripdata_skin_13[]={
+0.415686,0.415686,0.415686,1.000000,0.000000,1.500000,2.000000,4.000000,0.000000,0.341176,0.341176,0.341176,1.000000,-0.500000,1.500000,4.000000,4.000000,0.000000,0.545098,0.545098,0.545098,1.000000,0.000000,1.000000,2.000000,4.000000,2.000000,0.435294,0.435294,0.435294,1.000000,-0.500000,1.000000,4.000000,4.000000,2.000000,0.517647,0.517647,0.517647,1.000000,0.000000,0.500000,2.000000,4.000000,4.000000,0.450980,0.450980,0.450980,1.000000,-0.500000,0.500000,4.000000,4.000000,4.000000,0.427451,0.427451,0.427451,1.000000,0.000000,0.000000,2.000000,4.000000,6.000000,0.388235,0.388235,0.388235,1.000000,-0.500000,0.000000,4.000000,4.000000,6.000000,0.356863,0.356863,0.356863,1.000000,0.000000,-0.500000,2.000000,4.000000,8.000000,0.333333,0.333333,0.333333,1.000000,-0.500000,-0.500000,4.000000,4.000000,8.000000,
+0.435294,0.435294,0.435294,1.000000,1.500000,1.000000,-4.000000,4.000000,2.000000,0.415686,0.415686,0.415686,1.000000,1.000000,1.500000,-2.000000,4.000000,0.000000,0.545098,0.545098,0.545098,1.000000,1.000000,1.000000,-2.000000,4.000000,2.000000,0.450980,0.450980,0.450980,1.000000,0.500000,1.500000,0.000000,4.000000,0.000000,0.600000,0.600000,0.600000,1.000000,0.500000,1.000000,0.000000,4.000000,2.000000,0.415686,0.415686,0.415686,1.000000,0.000000,1.500000,2.000000,4.000000,0.000000,0.545098,0.545098,0.545098,1.000000,0.000000,1.000000,2.000000,4.000000,2.000000,
+0.435294,0.435294,0.435294,1.000000,1.500000,1.000000,-4.000000,4.000000,2.000000,0.341176,0.341176,0.341176,1.000000,1.500000,1.500000,-4.000000,4.000000,0.000000,0.415686,0.415686,0.415686,1.000000,1.000000,1.500000,-2.000000,4.000000,0.000000,
+0.356863,0.356863,0.356863,1.000000,0.000000,-0.500000,2.000000,4.000000,8.000000,0.364706,0.364706,0.364706,1.000000,0.500000,-0.500000,0.000000,4.000000,8.000000,0.427451,0.427451,0.427451,1.000000,0.000000,0.000000,2.000000,4.000000,6.000000,0.415686,0.415686,0.415686,1.000000,0.395020,-0.133318,0.420032,4.000000,6.533272,0.423529,0.423529,0.423529,1.000000,0.388550,-0.103582,0.445932,4.000000,6.414327,
+0.423529,0.423529,0.423529,1.000000,0.388550,-0.103582,0.445932,4.000000,6.414327,0.427451,0.427451,0.427451,1.000000,0.383423,-0.069344,0.466541,4.000000,6.277375,0.427451,0.427451,0.427451,1.000000,0.000000,0.000000,2.000000,4.000000,6.000000,0.435294,0.435294,0.435294,1.000000,0.380371,-0.034595,0.478689,4.000000,6.138380,0.439216,0.439216,0.439216,1.000000,0.379272,0.000000,0.482673,4.000000,6.000000,
+0.407843,0.407843,0.407843,1.000000,0.414673,-0.191394,0.341301,4.000000,6.765576,0.411765,0.411765,0.411765,1.000000,0.403687,-0.162957,0.385368,4.000000,6.651829,0.364706,0.364706,0.364706,1.000000,0.500000,-0.500000,0.000000,4.000000,8.000000,0.415686,0.415686,0.415686,1.000000,0.395020,-0.133318,0.420032,4.000000,6.533272,
+0.400000,0.400000,0.400000,1.000000,0.438232,-0.232438,0.247284,4.000000,6.929754,0.403922,0.403922,0.403922,1.000000,0.425171,-0.212276,0.299425,4.000000,6.849104,0.364706,0.364706,0.364706,1.000000,0.500000,-0.500000,0.000000,4.000000,8.000000,0.407843,0.407843,0.407843,1.000000,0.414673,-0.191394,0.341301,4.000000,6.765576,
+0.396078,0.396078,0.396078,1.000000,0.467285,-0.260554,0.130636,4.000000,7.042214,0.400000,0.400000,0.400000,1.000000,0.453857,-0.250068,0.184711,4.000000,7.000273,0.364706,0.364706,0.364706,1.000000,0.500000,-0.500000,0.000000,4.000000,8.000000,0.400000,0.400000,0.400000,1.000000,0.438232,-0.232438,0.247284,4.000000,6.929754,
+0.396078,0.396078,0.396078,1.000000,0.500000,-0.270672,0.000000,4.000000,7.082688,0.396078,0.396078,0.396078,1.000000,0.482788,-0.267902,0.068730,4.000000,7.071609,0.364706,0.364706,0.364706,1.000000,0.500000,-0.500000,0.000000,4.000000,8.000000,0.396078,0.396078,0.396078,1.000000,0.467285,-0.260554,0.130636,4.000000,7.042214,
+0.439216,0.439216,0.439216,1.000000,0.379272,0.000000,0.482673,4.000000,6.000000,0.474510,0.474510,0.474510,1.000000,0.379272,0.180448,0.482673,4.000000,5.278208,0.517647,0.517647,0.517647,1.000000,0.000000,0.500000,2.000000,4.000000,4.000000,0.513726,0.513726,0.513726,1.000000,0.379272,0.360896,0.482673,4.000000,4.556417,0.545098,0.545098,0.545098,1.000000,0.379272,0.500000,0.482673,4.000000,4.000000,
+0.545098,0.545098,0.545098,1.000000,0.379272,0.500000,0.482673,4.000000,4.000000,0.545098,0.545098,0.545098,1.000000,0.000000,1.000000,2.000000,4.000000,2.000000,0.517647,0.517647,0.517647,1.000000,0.000000,0.500000,2.000000,4.000000,4.000000,
+0.600000,0.600000,0.600000,1.000000,0.500000,1.000000,0.000000,4.000000,2.000000,0.545098,0.545098,0.545098,1.000000,0.000000,1.000000,2.000000,4.000000,2.000000,0.552941,0.552941,0.552941,1.000000,0.379272,0.541344,0.482673,4.000000,3.834625,0.545098,0.545098,0.545098,1.000000,0.379272,0.500000,0.482673,4.000000,4.000000,
+0.552941,0.552941,0.552941,1.000000,0.379272,0.541344,0.482673,4.000000,3.834625,0.556863,0.556863,0.556863,1.000000,0.459717,0.541344,0.160891,4.000000,3.834625,0.600000,0.600000,0.600000,1.000000,0.500000,1.000000,0.000000,4.000000,2.000000,0.556863,0.556863,0.556863,1.000000,0.500000,0.541344,0.000000,4.000000,3.834625,0.556863,0.556863,0.556863,1.000000,0.540283,0.541344,-0.160891,4.000000,3.834625,
+0.396078,0.396078,0.396078,1.000000,0.517212,-0.267902,-0.068730,4.000000,7.071609,0.396078,0.396078,0.396078,1.000000,0.500000,-0.270672,0.000000,4.000000,7.082688,0.356863,0.356863,0.356863,1.000000,1.000000,-0.500000,-2.000000,4.000000,8.000000,0.364706,0.364706,0.364706,1.000000,0.500000,-0.500000,0.000000,4.000000,8.000000,
+0.400000,0.400000,0.400000,1.000000,0.546143,-0.250068,-0.184711,4.000000,7.000273,0.396078,0.396078,0.396078,1.000000,0.532715,-0.260554,-0.130636,4.000000,7.042214,0.356863,0.356863,0.356863,1.000000,1.000000,-0.500000,-2.000000,4.000000,8.000000,0.396078,0.396078,0.396078,1.000000,0.517212,-0.267902,-0.068730,4.000000,7.071609,
+0.403922,0.403922,0.403922,1.000000,0.574829,-0.212276,-0.299425,4.000000,6.849104,0.400000,0.400000,0.400000,1.000000,0.561768,-0.232438,-0.247284,4.000000,6.929754,0.356863,0.356863,0.356863,1.000000,1.000000,-0.500000,-2.000000,4.000000,8.000000,0.400000,0.400000,0.400000,1.000000,0.546143,-0.250068,-0.184711,4.000000,7.000273,
+0.411765,0.411765,0.411765,1.000000,0.596313,-0.162957,-0.385368,4.000000,6.651829,0.407843,0.407843,0.407843,1.000000,0.585327,-0.191394,-0.341301,4.000000,6.765576,0.356863,0.356863,0.356863,1.000000,1.000000,-0.500000,-2.000000,4.000000,8.000000,0.403922,0.403922,0.403922,1.000000,0.574829,-0.212276,-0.299425,4.000000,6.849104,
+0.423529,0.423529,0.423529,1.000000,0.611450,-0.103582,-0.445931,4.000000,6.414327,0.415686,0.415686,0.415686,1.000000,0.604980,-0.133318,-0.420033,4.000000,6.533272,0.356863,0.356863,0.356863,1.000000,1.000000,-0.500000,-2.000000,4.000000,8.000000,0.411765,0.411765,0.411765,1.000000,0.596313,-0.162957,-0.385368,4.000000,6.651829,
+0.435294,0.435294,0.435294,1.000000,0.619629,-0.034595,-0.478689,4.000000,6.138380,0.427451,0.427451,0.427451,1.000000,0.616577,-0.069344,-0.466541,4.000000,6.277375,0.356863,0.356863,0.356863,1.000000,1.000000,-0.500000,-2.000000,4.000000,8.000000,0.423529,0.423529,0.423529,1.000000,0.611450,-0.103582,-0.445931,4.000000,6.414327,
+0.513726,0.513726,0.513726,1.000000,0.620728,0.360896,-0.482673,4.000000,4.556417,0.474510,0.474510,0.474510,1.000000,0.620728,0.180448,-0.482673,4.000000,5.278208,0.427451,0.427451,0.427451,1.000000,1.000000,0.000000,-2.000000,4.000000,6.000000,0.439216,0.439216,0.439216,1.000000,0.620728,0.000000,-0.482673,4.000000,6.000000,0.356863,0.356863,0.356863,1.000000,1.000000,-0.500000,-2.000000,4.000000,8.000000,0.435294,0.435294,0.435294,1.000000,0.619629,-0.034595,-0.478689,4.000000,6.138380,
+0.333333,0.333333,0.333333,1.000000,1.500000,-0.500000,-4.000000,4.000000,8.000000,0.388235,0.388235,0.388235,1.000000,1.500000,0.000000,-4.000000,4.000000,6.000000,0.427451,0.427451,0.427451,1.000000,1.000000,0.000000,-2.000000,4.000000,6.000000,0.517647,0.517647,0.517647,1.000000,1.000000,0.500000,-2.000000,4.000000,4.000000,0.513726,0.513726,0.513726,1.000000,0.620728,0.360896,-0.482673,4.000000,4.556417,0.545098,0.545098,0.545098,1.000000,0.620728,0.500000,-0.482673,4.000000,4.000000,
+0.333333,0.333333,0.333333,1.000000,1.500000,-0.500000,-4.000000,4.000000,8.000000,0.427451,0.427451,0.427451,1.000000,1.000000,0.000000,-2.000000,4.000000,6.000000,0.356863,0.356863,0.356863,1.000000,1.000000,-0.500000,-2.000000,4.000000,8.000000,
+0.556863,0.556863,0.556863,1.000000,0.540283,0.541344,-0.160891,4.000000,3.834625,0.552941,0.552941,0.552941,1.000000,0.620728,0.541344,-0.482673,4.000000,3.834625,0.545098,0.545098,0.545098,1.000000,1.000000,1.000000,-2.000000,4.000000,2.000000,0.517647,0.517647,0.517647,1.000000,1.000000,0.500000,-2.000000,4.000000,4.000000,0.450980,0.450980,0.450980,1.000000,1.500000,0.500000,-4.000000,4.000000,4.000000,0.388235,0.388235,0.388235,1.000000,1.500000,0.000000,-4.000000,4.000000,6.000000,
+0.517647,0.517647,0.517647,1.000000,1.000000,0.500000,-2.000000,4.000000,4.000000,0.552941,0.552941,0.552941,1.000000,0.620728,0.541344,-0.482673,4.000000,3.834625,0.545098,0.545098,0.545098,1.000000,0.620728,0.500000,-0.482673,4.000000,4.000000,
+0.450980,0.450980,0.450980,1.000000,1.500000,0.500000,-4.000000,4.000000,4.000000,0.435294,0.435294,0.435294,1.000000,1.500000,1.000000,-4.000000,4.000000,2.000000,0.545098,0.545098,0.545098,1.000000,1.000000,1.000000,-2.000000,4.000000,2.000000,
+0.439216,0.439216,0.439216,1.000000,0.379272,0.000000,0.482673,4.000000,6.000000,0.517647,0.517647,0.517647,1.000000,0.000000,0.500000,2.000000,4.000000,4.000000,0.427451,0.427451,0.427451,1.000000,0.000000,0.000000,2.000000,4.000000,6.000000,
+0.556863,0.556863,0.556863,1.000000,0.540283,0.541344,-0.160891,4.000000,3.834625,0.545098,0.545098,0.545098,1.000000,1.000000,1.000000,-2.000000,4.000000,2.000000,0.600000,0.600000,0.600000,1.000000,0.500000,1.000000,0.000000,4.000000,2.000000
+
+};
+
+
+/* Object: skin_12 */
+
+int striplength_skin_12[]={
+12,12,12,12,12,0};
+
+float stripdata_skin_12[]={
+0.498039,0.498039,0.498039,1.000000,-0.099976,1.500000,-2.400000,-4.000000,-0.000002,0.337255,0.337255,0.337255,1.000000,-0.500000,1.500000,-4.000000,-4.000000,-0.000002,0.568627,0.568627,0.568627,1.000000,-0.099976,1.100000,-2.400000,-4.000000,1.599999,0.341176,0.341176,0.341176,1.000000,-0.500000,1.100000,-4.000000,-4.000000,1.599999,0.498039,0.498039,0.498039,1.000000,-0.099976,0.700000,-2.400000,-4.000000,3.200000,0.325490,0.325490,0.325490,1.000000,-0.500000,0.700000,-4.000000,-4.000000,3.199999,0.352941,0.352941,0.352941,1.000000,-0.099976,0.300000,-2.400000,-4.000000,4.800000,0.282353,0.282353,0.282353,1.000000,-0.500000,0.300000,-4.000000,-4.000000,4.800000,0.282353,0.282353,0.282353,1.000000,-0.099976,-0.100000,-2.400000,-4.000000,6.400001,0.254902,0.254902,0.254902,1.000000,-0.500000,-0.100000,-4.000000,-4.000000,6.400000,0.239216,0.239216,0.239216,1.000000,-0.099976,-0.500000,-2.400000,-4.000000,8.000000,0.227451,0.227451,0.227451,1.000000,-0.500000,-0.500000,-4.000000,-4.000000,8.000000,
+0.239216,0.239216,0.239216,1.000000,1.099976,-0.500000,2.400001,-4.000000,8.000000,0.227451,0.227451,0.227451,1.000000,1.500000,-0.500000,4.000002,-4.000000,8.000000,0.282353,0.282353,0.282353,1.000000,1.099976,-0.100000,2.400001,-4.000000,6.400001,0.254902,0.254902,0.254902,1.000000,1.500000,-0.100000,4.000002,-4.000000,6.400001,0.352941,0.352941,0.352941,1.000000,1.099976,0.300000,2.400002,-4.000000,4.800001,0.282353,0.282353,0.282353,1.000000,1.500000,0.300000,4.000002,-4.000000,4.800001,0.498039,0.498039,0.498039,1.000000,1.099976,0.700000,2.400002,-4.000000,3.200000,0.321569,0.321569,0.321569,1.000000,1.500000,0.700000,4.000003,-4.000000,3.200000,0.568627,0.568627,0.568627,1.000000,1.099976,1.100000,2.400002,-4.000000,1.599999,0.341176,0.341176,0.341176,1.000000,1.500000,1.100000,4.000003,-4.000000,1.599999,0.494118,0.494118,0.494118,1.000000,1.099976,1.500000,2.400003,-4.000000,-0.000002,0.337255,0.337255,0.337255,1.000000,1.500000,1.500000,4.000004,-4.000000,-0.000002,
+0.639216,0.639216,0.639216,1.000000,0.300049,1.500000,-0.799999,-4.000000,-0.000002,0.498039,0.498039,0.498039,1.000000,-0.099976,1.500000,-2.400000,-4.000000,-0.000002,0.858824,0.858824,0.858824,1.000000,0.300049,1.100000,-0.799999,-4.000000,1.599999,0.568627,0.568627,0.568627,1.000000,-0.099976,1.100000,-2.400000,-4.000000,1.599999,0.686275,0.686275,0.686275,1.000000,0.300049,0.700000,-0.799999,-4.000000,3.200000,0.498039,0.498039,0.498039,1.000000,-0.099976,0.700000,-2.400000,-4.000000,3.200000,0.419608,0.419608,0.419608,1.000000,0.300049,0.300000,-0.800000,-4.000000,4.800000,0.352941,0.352941,0.352941,1.000000,-0.099976,0.300000,-2.400000,-4.000000,4.800000,0.298039,0.298039,0.298039,1.000000,0.300049,-0.100000,-0.800000,-4.000000,6.400001,0.282353,0.282353,0.282353,1.000000,-0.099976,-0.100000,-2.400000,-4.000000,6.400001,0.247059,0.247059,0.247059,1.000000,0.300049,-0.500000,-0.800000,-4.000000,8.000000,0.239216,0.239216,0.239216,1.000000,-0.099976,-0.500000,-2.400000,-4.000000,8.000000,
+0.639216,0.639216,0.639216,1.000000,0.699951,1.500000,0.800002,-4.000000,-0.000002,0.639216,0.639216,0.639216,1.000000,0.300049,1.500000,-0.799999,-4.000000,-0.000002,0.858824,0.858824,0.858824,1.000000,0.699951,1.100000,0.800001,-4.000000,1.599999,0.858824,0.858824,0.858824,1.000000,0.300049,1.100000,-0.799999,-4.000000,1.599999,0.686275,0.686275,0.686275,1.000000,0.699951,0.700000,0.800001,-4.000000,3.200000,0.686275,0.686275,0.686275,1.000000,0.300049,0.700000,-0.799999,-4.000000,3.200000,0.419608,0.419608,0.419608,1.000000,0.699951,0.300000,0.800001,-4.000000,4.800001,0.419608,0.419608,0.419608,1.000000,0.300049,0.300000,-0.800000,-4.000000,4.800000,0.298039,0.298039,0.298039,1.000000,0.699951,-0.100000,0.800001,-4.000000,6.400001,0.298039,0.298039,0.298039,1.000000,0.300049,-0.100000,-0.800000,-4.000000,6.400001,0.247059,0.247059,0.247059,1.000000,0.699951,-0.500000,0.800000,-4.000000,8.000000,0.247059,0.247059,0.247059,1.000000,0.300049,-0.500000,-0.800000,-4.000000,8.000000,
+0.494118,0.494118,0.494118,1.000000,1.099976,1.500000,2.400003,-4.000000,-0.000002,0.639216,0.639216,0.639216,1.000000,0.699951,1.500000,0.800002,-4.000000,-0.000002,0.568627,0.568627,0.568627,1.000000,1.099976,1.100000,2.400002,-4.000000,1.599999,0.858824,0.858824,0.858824,1.000000,0.699951,1.100000,0.800001,-4.000000,1.599999,0.498039,0.498039,0.498039,1.000000,1.099976,0.700000,2.400002,-4.000000,3.200000,0.686275,0.686275,0.686275,1.000000,0.699951,0.700000,0.800001,-4.000000,3.200000,0.352941,0.352941,0.352941,1.000000,1.099976,0.300000,2.400002,-4.000000,4.800001,0.419608,0.419608,0.419608,1.000000,0.699951,0.300000,0.800001,-4.000000,4.800001,0.282353,0.282353,0.282353,1.000000,1.099976,-0.100000,2.400001,-4.000000,6.400001,0.298039,0.298039,0.298039,1.000000,0.699951,-0.100000,0.800001,-4.000000,6.400001,0.239216,0.239216,0.239216,1.000000,1.099976,-0.500000,2.400001,-4.000000,8.000000,0.247059,0.247059,0.247059,1.000000,0.699951,-0.500000,0.800000,-4.000000,8.000000
+
+};
+
+
+/* Object: skin_11 */
+
+int striplength_skin_11[]={
+12,12,12,12,12,0};
+
+float stripdata_skin_11[]={
+0.145098,0.145098,0.145098,1.000000,-0.099976,1.500000,-2.400000,4.000002,0.000000,0.141176,0.141176,0.141176,1.000000,-0.500000,1.500000,-4.000000,4.000002,0.000000,0.176471,0.176471,0.176471,1.000000,-0.099976,1.100000,-2.400000,2.400001,0.000000,0.145098,0.145098,0.145098,1.000000,-0.500000,1.100000,-4.000000,2.400001,0.000000,0.341176,0.341176,0.341176,1.000000,-0.099976,0.700000,-2.400000,0.800000,0.000000,0.188235,0.188235,0.188235,1.000000,-0.500000,0.700000,-4.000000,0.800000,0.000000,0.450980,0.450980,0.450980,1.000000,-0.099976,0.300000,-2.400000,-0.800000,0.000000,0.247059,0.247059,0.247059,1.000000,-0.500000,0.300000,-4.000000,-0.800000,0.000000,0.439216,0.439216,0.439216,1.000000,-0.099976,-0.100000,-2.400000,-2.400000,0.000000,0.270588,0.270588,0.270588,1.000000,-0.500000,-0.100000,-4.000000,-2.400000,0.000000,0.364706,0.364706,0.364706,1.000000,-0.099976,-0.500000,-2.400000,-4.000000,0.000000,0.258824,0.258824,0.258824,1.000000,-0.500000,-0.500000,-4.000000,-4.000000,0.000000,
+0.364706,0.364706,0.364706,1.000000,1.099976,-0.500000,2.400001,-4.000000,0.000000,0.258824,0.258824,0.258824,1.000000,1.500000,-0.500000,4.000002,-4.000000,0.000000,0.439216,0.439216,0.439216,1.000000,1.099976,-0.100000,2.400001,-2.400001,0.000000,0.270588,0.270588,0.270588,1.000000,1.500000,-0.100000,4.000002,-2.400001,0.000000,0.454902,0.454902,0.454902,1.000000,1.099976,0.300000,2.400002,-0.800000,0.000000,0.247059,0.247059,0.247059,1.000000,1.500000,0.300000,4.000002,-0.800000,0.000000,0.341176,0.341176,0.341176,1.000000,1.099976,0.700000,2.400002,0.800000,0.000000,0.184314,0.184314,0.184314,1.000000,1.500000,0.700000,4.000003,0.800000,0.000000,0.176471,0.176471,0.176471,1.000000,1.099976,1.100000,2.400002,2.400001,0.000000,0.145098,0.145098,0.145098,1.000000,1.500000,1.100000,4.000003,2.400001,0.000000,0.145098,0.145098,0.145098,1.000000,1.099976,1.500000,2.400003,4.000003,0.000000,0.141176,0.141176,0.141176,1.000000,1.500000,1.500000,4.000004,4.000002,0.000000,
+0.145098,0.145098,0.145098,1.000000,0.300049,1.500000,-0.799999,4.000002,0.000000,0.145098,0.145098,0.145098,1.000000,-0.099976,1.500000,-2.400000,4.000002,0.000000,0.262745,0.262745,0.262745,1.000000,0.300049,1.100000,-0.799999,2.400001,0.000000,0.176471,0.176471,0.176471,1.000000,-0.099976,1.100000,-2.400000,2.400001,0.000000,0.580392,0.580392,0.580392,1.000000,0.300049,0.700000,-0.799999,0.800000,0.000000,0.341176,0.341176,0.341176,1.000000,-0.099976,0.700000,-2.400000,0.800000,0.000000,0.709804,0.709804,0.709804,1.000000,0.300049,0.300000,-0.800000,-0.800000,0.000000,0.450980,0.450980,0.450980,1.000000,-0.099976,0.300000,-2.400000,-0.800000,0.000000,0.627451,0.627451,0.627451,1.000000,0.300049,-0.100000,-0.800000,-2.400001,0.000000,0.439216,0.439216,0.439216,1.000000,-0.099976,-0.100000,-2.400000,-2.400000,0.000000,0.458824,0.458824,0.458824,1.000000,0.300049,-0.500000,-0.800000,-4.000000,0.000000,0.364706,0.364706,0.364706,1.000000,-0.099976,-0.500000,-2.400000,-4.000000,0.000000,
+0.145098,0.145098,0.145098,1.000000,0.699951,1.500000,0.800002,4.000002,0.000000,0.145098,0.145098,0.145098,1.000000,0.300049,1.500000,-0.799999,4.000002,0.000000,0.262745,0.262745,0.262745,1.000000,0.699951,1.100000,0.800001,2.400001,0.000000,0.262745,0.262745,0.262745,1.000000,0.300049,1.100000,-0.799999,2.400001,0.000000,0.580392,0.580392,0.580392,1.000000,0.699951,0.700000,0.800001,0.800000,0.000000,0.580392,0.580392,0.580392,1.000000,0.300049,0.700000,-0.799999,0.800000,0.000000,0.713726,0.713726,0.713726,1.000000,0.699951,0.300000,0.800001,-0.800000,0.000000,0.709804,0.709804,0.709804,1.000000,0.300049,0.300000,-0.800000,-0.800000,0.000000,0.631373,0.631373,0.631373,1.000000,0.699951,-0.100000,0.800001,-2.400001,0.000000,0.627451,0.627451,0.627451,1.000000,0.300049,-0.100000,-0.800000,-2.400001,0.000000,0.458824,0.458824,0.458824,1.000000,0.699951,-0.500000,0.800000,-4.000000,0.000000,0.458824,0.458824,0.458824,1.000000,0.300049,-0.500000,-0.800000,-4.000000,0.000000,
+0.145098,0.145098,0.145098,1.000000,1.099976,1.500000,2.400003,4.000003,0.000000,0.145098,0.145098,0.145098,1.000000,0.699951,1.500000,0.800002,4.000002,0.000000,0.176471,0.176471,0.176471,1.000000,1.099976,1.100000,2.400002,2.400001,0.000000,0.262745,0.262745,0.262745,1.000000,0.699951,1.100000,0.800001,2.400001,0.000000,0.341176,0.341176,0.341176,1.000000,1.099976,0.700000,2.400002,0.800000,0.000000,0.580392,0.580392,0.580392,1.000000,0.699951,0.700000,0.800001,0.800000,0.000000,0.454902,0.454902,0.454902,1.000000,1.099976,0.300000,2.400002,-0.800000,0.000000,0.713726,0.713726,0.713726,1.000000,0.699951,0.300000,0.800001,-0.800000,0.000000,0.439216,0.439216,0.439216,1.000000,1.099976,-0.100000,2.400001,-2.400001,0.000000,0.631373,0.631373,0.631373,1.000000,0.699951,-0.100000,0.800001,-2.400001,0.000000,0.364706,0.364706,0.364706,1.000000,1.099976,-0.500000,2.400001,-4.000000,0.000000,0.458824,0.458824,0.458824,1.000000,0.699951,-0.500000,0.800000,-4.000000,0.000000
+
+};
+
+
+/* Object: skin_9 */
+
+int striplength_skin_9[]={
+18,0};
+
+float stripdata_skin_9[]={
+0.384314,0.384314,0.384314,1.000000,-0.500000,1.500000,-4.000000,4.000000,8.000000,0.384314,0.384314,0.384314,1.000000,1.500000,1.500000,4.000000,4.000000,8.000000,0.376471,0.376471,0.376471,1.000000,-0.500000,1.250000,-4.000000,3.695518,9.530733,0.403922,0.403922,0.403922,1.000000,1.500000,1.250000,4.000000,3.695518,9.530733,0.415686,0.415686,0.415686,1.000000,-0.500000,1.000000,-4.000000,2.828427,10.828427,0.431373,0.431373,0.431373,1.000000,1.500000,1.000000,4.000000,2.828427,10.828427,0.435294,0.435294,0.435294,1.000000,-0.500000,0.750000,-4.000000,1.530734,11.695518,0.443137,0.443137,0.443137,1.000000,1.500000,0.750000,4.000000,1.530734,11.695518,0.439216,0.439216,0.439216,1.000000,-0.500000,0.500000,-4.000000,0.000000,12.000000,0.435294,0.435294,0.435294,1.000000,1.500000,0.500000,4.000000,0.000000,12.000000,0.427451,0.427451,0.427451,1.000000,-0.500000,0.250000,-4.000000,-1.530734,11.695518,0.411765,0.411765,0.411765,1.000000,1.500000,0.250000,4.000000,-1.530734,11.695518,0.396078,0.396078,0.396078,1.000000,-0.500000,0.000000,-4.000000,-2.828427,10.828427,0.368627,0.368627,0.368627,1.000000,1.500000,0.000000,4.000000,-2.828427,10.828427,0.341176,0.341176,0.341176,1.000000,-0.500000,-0.250000,-4.000000,-3.695518,9.530733,0.301961,0.301961,0.301961,1.000000,1.500000,-0.250000,4.000000,-3.695518,9.530733,0.294118,0.294118,0.294118,1.000000,-0.500000,-0.500000,-4.000000,-4.000000,8.000000,0.294118,0.294118,0.294118,1.000000,1.500000,-0.500000,4.000000,-4.000000,8.000000
+
+};
+
+