132001f49Smrg/*-----------------------------
232001f49Smrg * stex3d.c GL example of the mesa 3d-texture extention to simulate procedural
332001f49Smrg *            texturing, it uses a perlin noise and turbulence functions.
432001f49Smrg *
532001f49Smrg * Author:   Daniel Barrero
632001f49Smrg *           barrero@irit.fr
732001f49Smrg *           dbarrero@pegasus.uniandes.edu.co
832001f49Smrg *
932001f49Smrg * Converted to GLUT by brianp on 1/1/98
1032001f49Smrg * Massive clean-up on 2002/10/23 by brianp
1132001f49Smrg *
1232001f49Smrg *
1332001f49Smrg * cc stex3d.c -o stex3d -lglut -lMesaGLU -lMesaGL -lX11 -lXext -lm
1432001f49Smrg *
1532001f49Smrg *---------------------------- */
1632001f49Smrg
1732001f49Smrg#include <string.h>
1832001f49Smrg#include <stdio.h>
1932001f49Smrg#include <stdlib.h>
2032001f49Smrg#include <math.h>
2132001f49Smrg#include <GL/glew.h>
2232001f49Smrg#include "glut_wrap.h"
2332001f49Smrg
2432001f49Smrg
2532001f49Smrg#ifndef M_PI
2632001f49Smrg#define M_PI            3.14159265358979323846
2732001f49Smrg#endif
2832001f49Smrg
2932001f49Smrg#define NOISE_TEXTURE 1
3032001f49Smrg#define GRADIENT_TEXTURE 2
3132001f49Smrg
3232001f49Smrg#define TORUS 1
3332001f49Smrg#define SPHERE 2
3432001f49Smrg
3532001f49Smrgstatic int tex_width=64, tex_height=64, tex_depth=64;
3632001f49Smrgstatic float angx=0, angy=0, angz=0;
3732001f49Smrgstatic int texgen = 2, animate = 1, smooth = 1, wireframe = 0;
3832001f49Smrgstatic int CurTexture = NOISE_TEXTURE, CurObject = TORUS;
3932001f49Smrgstatic GLenum Filter = GL_LINEAR;
4032001f49Smrg
4132001f49Smrg
4232001f49Smrgstatic void
4332001f49SmrgBuildTorus(void)
4432001f49Smrg{
4532001f49Smrg   GLint i, j;
4632001f49Smrg   float theta1, phi1, theta2, phi2, rings, sides;
4732001f49Smrg   float v0[03], v1[3], v2[3], v3[3];
4832001f49Smrg   float t0[03], t1[3], t2[3], t3[3];
4932001f49Smrg   float n0[3], n1[3], n2[3], n3[3];
5032001f49Smrg   float innerRadius = 0.25;
5132001f49Smrg   float outerRadius = 0.5;
5232001f49Smrg   float scalFac;
5332001f49Smrg
5432001f49Smrg   rings = 16;
5532001f49Smrg   sides = 12;
5632001f49Smrg   scalFac = 1 / (outerRadius * 2);
5732001f49Smrg
5832001f49Smrg   glNewList(TORUS, GL_COMPILE);
5932001f49Smrg   for (i = 0; i < rings; i++) {
6032001f49Smrg      theta1 = (float) i *2.0 * M_PI / rings;
6132001f49Smrg      theta2 = (float) (i + 1) * 2.0 * M_PI / rings;
6232001f49Smrg      for (j = 0; j < sides; j++) {
6332001f49Smrg	 phi1 = (float) j *2.0 * M_PI / sides;
6432001f49Smrg	 phi2 = (float) (j + 1) * 2.0 * M_PI / sides;
6532001f49Smrg
6632001f49Smrg	 v0[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi1));
6732001f49Smrg	 v0[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi1));
6832001f49Smrg	 v0[2] = innerRadius * sin(phi1);
6932001f49Smrg
7032001f49Smrg	 v1[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi1));
7132001f49Smrg	 v1[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi1));
7232001f49Smrg	 v1[2] = innerRadius * sin(phi1);
7332001f49Smrg	 v2[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi2));
7432001f49Smrg	 v2[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi2));
7532001f49Smrg	 v2[2] = innerRadius * sin(phi2);
7632001f49Smrg
7732001f49Smrg	 v3[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi2));
7832001f49Smrg	 v3[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi2));
7932001f49Smrg	 v3[2] = innerRadius * sin(phi2);
8032001f49Smrg
8132001f49Smrg	 n0[0] = cos(theta1) * (cos(phi1));
8232001f49Smrg	 n0[1] = -sin(theta1) * (cos(phi1));
8332001f49Smrg	 n0[2] = sin(phi1);
8432001f49Smrg
8532001f49Smrg	 n1[0] = cos(theta2) * (cos(phi1));
8632001f49Smrg	 n1[1] = -sin(theta2) * (cos(phi1));
8732001f49Smrg	 n1[2] = sin(phi1);
8832001f49Smrg
8932001f49Smrg	 n2[0] = cos(theta2) * (cos(phi2));
9032001f49Smrg	 n2[1] = -sin(theta2) * (cos(phi2));
9132001f49Smrg	 n2[2] = sin(phi2);
9232001f49Smrg
9332001f49Smrg	 n3[0] = cos(theta1) * (cos(phi2));
9432001f49Smrg	 n3[1] = -sin(theta1) * (cos(phi2));
9532001f49Smrg	 n3[2] = sin(phi2);
9632001f49Smrg
9732001f49Smrg	 t0[0] = v0[0] * scalFac + 0.5;
9832001f49Smrg	 t0[1] = v0[1] * scalFac + 0.5;
9932001f49Smrg	 t0[2] = v0[2] * scalFac + 0.5;
10032001f49Smrg
10132001f49Smrg	 t1[0] = v1[0] * scalFac + 0.5;
10232001f49Smrg	 t1[1] = v1[1] * scalFac + 0.5;
10332001f49Smrg	 t1[2] = v1[2] * scalFac + 0.5;
10432001f49Smrg
10532001f49Smrg	 t2[0] = v2[0] * scalFac + 0.5;
10632001f49Smrg	 t2[1] = v2[1] * scalFac + 0.5;
10732001f49Smrg	 t2[2] = v2[2] * scalFac + 0.5;
10832001f49Smrg
10932001f49Smrg	 t3[0] = v3[0] * scalFac + 0.5;
11032001f49Smrg	 t3[1] = v3[1] * scalFac + 0.5;
11132001f49Smrg	 t3[2] = v3[2] * scalFac + 0.5;
11232001f49Smrg
11332001f49Smrg	 glBegin(GL_POLYGON);
11432001f49Smrg	 glNormal3fv(n3);
11532001f49Smrg	 glTexCoord3fv(t3);
11632001f49Smrg	 glVertex3fv(v3);
11732001f49Smrg	 glNormal3fv(n2);
11832001f49Smrg	 glTexCoord3fv(t2);
11932001f49Smrg	 glVertex3fv(v2);
12032001f49Smrg	 glNormal3fv(n1);
12132001f49Smrg	 glTexCoord3fv(t1);
12232001f49Smrg	 glVertex3fv(v1);
12332001f49Smrg	 glNormal3fv(n0);
12432001f49Smrg	 glTexCoord3fv(t0);
12532001f49Smrg	 glVertex3fv(v0);
12632001f49Smrg	 glEnd();
12732001f49Smrg      }
12832001f49Smrg   }
12932001f49Smrg   glEndList();
13032001f49Smrg}
13132001f49Smrg
13232001f49Smrg
13332001f49Smrg/*--------------------------------------------------------------------
13432001f49Smrg noise function over R3 - implemented by a pseudorandom tricubic spline
13532001f49Smrg              EXCERPTED FROM SIGGRAPH 92, COURSE 23
13632001f49Smrg                        PROCEDURAL MODELING
13732001f49Smrg                             Ken Perlin
13832001f49Smrg                           New York University
13932001f49Smrg----------------------------------------------------------------------*/
14032001f49Smrg
14132001f49Smrg
14232001f49Smrg#define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
14332001f49Smrg#define B 128
14432001f49Smrgstatic int p[B + B + 2];
14532001f49Smrgstatic float g[B + B + 2][3];
14632001f49Smrg#define setup(i,b0,b1,r0,r1) \
14732001f49Smrg        t = vec[i] + 10000.; \
14832001f49Smrg        b0 = ((int)t) & (B-1); \
14932001f49Smrg        b1 = (b0+1) & (B-1); \
15032001f49Smrg        r0 = t - (int)t; \
15132001f49Smrg        r1 = r0 - 1.;
15232001f49Smrg
15332001f49Smrgstatic float
15432001f49Smrgnoise3(float vec[3])
15532001f49Smrg{
15632001f49Smrg   int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
15732001f49Smrg   float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v;
15832001f49Smrg   register int i, j;
15932001f49Smrg
16032001f49Smrg   setup(0, bx0, bx1, rx0, rx1);
16132001f49Smrg   setup(1, by0, by1, ry0, ry1);
16232001f49Smrg   setup(2, bz0, bz1, rz0, rz1);
16332001f49Smrg
16432001f49Smrg   i = p[bx0];
16532001f49Smrg   j = p[bx1];
16632001f49Smrg
16732001f49Smrg   b00 = p[i + by0];
16832001f49Smrg   b10 = p[j + by0];
16932001f49Smrg   b01 = p[i + by1];
17032001f49Smrg   b11 = p[j + by1];
17132001f49Smrg
17232001f49Smrg#define at(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
17332001f49Smrg#define surve(t) ( t * t * (3. - 2. * t) )
17432001f49Smrg#define lerp(t, a, b) ( a + t * (b - a) )
17532001f49Smrg
17632001f49Smrg   sx = surve(rx0);
17732001f49Smrg   sy = surve(ry0);
17832001f49Smrg   sz = surve(rz0);
17932001f49Smrg
18032001f49Smrg   q = g[b00 + bz0];
18132001f49Smrg   u = at(rx0, ry0, rz0);
18232001f49Smrg   q = g[b10 + bz0];
18332001f49Smrg   v = at(rx1, ry0, rz0);
18432001f49Smrg   a = lerp(sx, u, v);
18532001f49Smrg
18632001f49Smrg   q = g[b01 + bz0];
18732001f49Smrg   u = at(rx0, ry1, rz0);
18832001f49Smrg   q = g[b11 + bz0];
18932001f49Smrg   v = at(rx1, ry1, rz0);
19032001f49Smrg   b = lerp(sx, u, v);
19132001f49Smrg
19232001f49Smrg   c = lerp(sy, a, b);		/* interpolate in y at lo x */
19332001f49Smrg
19432001f49Smrg   q = g[b00 + bz1];
19532001f49Smrg   u = at(rx0, ry0, rz1);
19632001f49Smrg   q = g[b10 + bz1];
19732001f49Smrg   v = at(rx1, ry0, rz1);
19832001f49Smrg   a = lerp(sx, u, v);
19932001f49Smrg
20032001f49Smrg   q = g[b01 + bz1];
20132001f49Smrg   u = at(rx0, ry1, rz1);
20232001f49Smrg   q = g[b11 + bz1];
20332001f49Smrg   v = at(rx1, ry1, rz1);
20432001f49Smrg   b = lerp(sx, u, v);
20532001f49Smrg
20632001f49Smrg   d = lerp(sy, a, b);		/* interpolate in y at hi x */
20732001f49Smrg
20832001f49Smrg   return 1.5 * lerp(sz, c, d);	/* interpolate in z */
20932001f49Smrg}
21032001f49Smrg
21132001f49Smrgstatic void
21232001f49SmrginitNoise(void)
21332001f49Smrg{
21432001f49Smrg   /*long random(); */
21532001f49Smrg   int i, j, k;
21632001f49Smrg   float v[3], s;
21732001f49Smrg
21832001f49Smrg   /* Create an array of random gradient vectors uniformly on the unit sphere */
21932001f49Smrg   /*srandom(1); */
22032001f49Smrg   srand(1);
22132001f49Smrg   for (i = 0; i < B; i++) {
22232001f49Smrg      do {			/* Choose uniformly in a cube */
22332001f49Smrg	 for (j = 0; j < 3; j++)
22432001f49Smrg	    v[j] = (float) ((rand() % (B + B)) - B) / B;
22532001f49Smrg	 s = DOT(v, v);
22632001f49Smrg      } while (s > 1.0);	/* If not in sphere try again */
22732001f49Smrg      s = sqrt(s);
22832001f49Smrg      for (j = 0; j < 3; j++)	/* Else normalize */
22932001f49Smrg	 g[i][j] = v[j] / s;
23032001f49Smrg   }
23132001f49Smrg
23232001f49Smrg   /* Create a pseudorandom permutation of [1..B] */
23332001f49Smrg   for (i = 0; i < B; i++)
23432001f49Smrg      p[i] = i;
23532001f49Smrg   for (i = B; i > 0; i -= 2) {
23632001f49Smrg      k = p[i];
23732001f49Smrg      p[i] = p[j = rand() % B];
23832001f49Smrg      p[j] = k;
23932001f49Smrg   }
24032001f49Smrg
24132001f49Smrg   /* Extend g and p arrays to allow for faster indexing */
24232001f49Smrg   for (i = 0; i < B + 2; i++) {
24332001f49Smrg      p[B + i] = p[i];
24432001f49Smrg      for (j = 0; j < 3; j++)
24532001f49Smrg	 g[B + i][j] = g[i][j];
24632001f49Smrg   }
24732001f49Smrg}
24832001f49Smrg
24932001f49Smrg
25032001f49Smrgstatic float
25132001f49Smrgturbulence(float point[3], float lofreq, float hifreq)
25232001f49Smrg{
25332001f49Smrg   float freq, t, p[3];
25432001f49Smrg
25532001f49Smrg   p[0] = point[0] + 123.456;
25632001f49Smrg   p[1] = point[1];
25732001f49Smrg   p[2] = point[2];
25832001f49Smrg
25932001f49Smrg   t = 0;
26032001f49Smrg   for (freq = lofreq; freq < hifreq; freq *= 2.) {
26132001f49Smrg      t += fabs(noise3(p)) / freq;
26232001f49Smrg      p[0] *= 2.;
26332001f49Smrg      p[1] *= 2.;
26432001f49Smrg      p[2] *= 2.;
26532001f49Smrg   }
26632001f49Smrg   return t - 0.3;		/* readjust to make mean value = 0.0 */
26732001f49Smrg}
26832001f49Smrg
26932001f49Smrg
27032001f49Smrgstatic void
27132001f49Smrgcreate3Dtexture(void)
27232001f49Smrg{
27332001f49Smrg   unsigned char *voxels = NULL;
27432001f49Smrg   int i, j, k;
27532001f49Smrg   unsigned char *vp;
27632001f49Smrg   float vec[3];
27732001f49Smrg   int tmp;
27832001f49Smrg
27932001f49Smrg   printf("creating 3d textures...\n");
28032001f49Smrg   voxels =
28132001f49Smrg      (unsigned char *)
28232001f49Smrg      malloc((size_t) (4 * tex_width * tex_height * tex_depth));
28332001f49Smrg   vp = voxels;
28432001f49Smrg   for (i = 0; i < tex_width; i++) {
28532001f49Smrg      vec[0] = i;
28632001f49Smrg      for (j = 0; j < tex_height; j++) {
28732001f49Smrg	 vec[1] = j;
28832001f49Smrg	 for (k = 0; k < tex_depth; k++) {
28932001f49Smrg	    vec[2] = k;
29032001f49Smrg	    tmp = (sin(k * i * j + turbulence(vec, 0.01, 1)) + 1) * 127.5;
29132001f49Smrg	    *vp++ = 0;
29232001f49Smrg	    *vp++ = 0;
29332001f49Smrg	    *vp++ = tmp;
29432001f49Smrg	    *vp++ = tmp + 128;
29532001f49Smrg	 }
29632001f49Smrg      }
29732001f49Smrg   }
29832001f49Smrg
29932001f49Smrg   printf("setting up 3d texture...\n");
30032001f49Smrg
30132001f49Smrg   glBindTexture(GL_TEXTURE_3D, NOISE_TEXTURE);
30232001f49Smrg   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
30332001f49Smrg   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
30432001f49Smrg   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
30532001f49Smrg   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
30632001f49Smrg
30732001f49Smrg   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
30832001f49Smrg   glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,
30932001f49Smrg		tex_width, tex_height, tex_depth,
31032001f49Smrg		0, GL_RGBA, GL_UNSIGNED_BYTE, voxels);
31132001f49Smrg   if (glGetError() == GL_OUT_OF_MEMORY)
31232001f49Smrg      printf("stex3d: Out of memory allocating %d x %d x %d RGBA texture",
31332001f49Smrg             tex_width, tex_height, tex_depth);
31432001f49Smrg
31532001f49Smrg   free(voxels);
31632001f49Smrg
31732001f49Smrg   printf("finished setting up 3d texture image.\n");
31832001f49Smrg}
31932001f49Smrg
32032001f49Smrg
32132001f49Smrgstatic void
32232001f49SmrgprintHelp(void)
32332001f49Smrg{
32432001f49Smrg   printf("\nUsage: stex3d  <cmd line options>\n");
32532001f49Smrg   printf(" cmd line options:\n");
32632001f49Smrg   printf("      -wxxx   Width of the texture (Default=64)\n");
32732001f49Smrg   printf("      -hxxx   Height of the texture (Default=64)\n");
32832001f49Smrg   printf("      -dxxx   Depth of the texture (Default=64)\n");
32932001f49Smrg   printf(" Keyboard Options:\n");
33032001f49Smrg   printf("    up/down   rotate around X\n");
33132001f49Smrg   printf("  left/right  rotate around Y\n");
33232001f49Smrg   printf("      z/Z     rotate around Z\n");
33332001f49Smrg   printf("       a      toggle animation\n");
33432001f49Smrg   printf("       s      toggle smooth shading\n");
33532001f49Smrg   printf("       t      toggle texgen mode\n");
33632001f49Smrg   printf("       o      toggle object: torus/sphere\n");
33732001f49Smrg   printf("       i      toggle texture image: noise/gradient\n");
33832001f49Smrg   printf("       f      toggle linear/nearest filtering\n");
33932001f49Smrg}
34032001f49Smrg
34132001f49Smrg
34232001f49Smrgstatic GLenum
34332001f49SmrgparseCmdLine(int argc, char **argv)
34432001f49Smrg{
34532001f49Smrg   GLint i;
34632001f49Smrg
34732001f49Smrg   for (i = 1; i < argc; i++) {
34832001f49Smrg      if (strcmp(argv[i], "-help") == 0) {
34932001f49Smrg	 printHelp();
35032001f49Smrg	 return GL_FALSE;
35132001f49Smrg      }
35232001f49Smrg      else if (strstr(argv[i], "-w") != NULL) {
35332001f49Smrg	 tex_width = atoi((argv[i]) + 2);
35432001f49Smrg      }
35532001f49Smrg      else if (strstr(argv[i], "-h") != NULL) {
35632001f49Smrg	 tex_height = atoi((argv[i]) + 2);
35732001f49Smrg      }
35832001f49Smrg      else if (strstr(argv[i], "-d") != NULL) {
35932001f49Smrg	 tex_depth = atoi((argv[i]) + 2);
36032001f49Smrg      }
36132001f49Smrg      else {
36232001f49Smrg	 printf("%s (Bad option).\n", argv[i]);
36332001f49Smrg	 printHelp();
36432001f49Smrg	 return GL_FALSE;
36532001f49Smrg      }
36632001f49Smrg   }
36732001f49Smrg   if (tex_width == 0 || tex_height == 0 || tex_depth == 0) {
36832001f49Smrg      printf("%s (Bad option).\n", "size parameters can't be 0");
36932001f49Smrg      printHelp();
37032001f49Smrg      return GL_FALSE;
37132001f49Smrg   }
37232001f49Smrg   return GL_TRUE;
37332001f49Smrg}
37432001f49Smrg
37532001f49Smrg
37632001f49Smrgstatic void
37732001f49SmrgdrawScene(void)
37832001f49Smrg{
37932001f49Smrg   static const GLfloat sPlane[4] = { 0.5, 0, 0, -.5 };
38032001f49Smrg   static const GLfloat tPlane[4] = { 0, 0.5, 0, -.5 };
38132001f49Smrg   static const GLfloat rPlane[4] = { 0, 0, 0.5, -.5 };
38232001f49Smrg
38332001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
38432001f49Smrg   glPushMatrix();
38532001f49Smrg   if (texgen == 2) {
38632001f49Smrg      glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
38732001f49Smrg      glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
38832001f49Smrg      glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
38932001f49Smrg   }
39032001f49Smrg
39132001f49Smrg   glRotatef(angx, 1.0, 0.0, 0.0);
39232001f49Smrg   glRotatef(angy, 0.0, 1.0, 0.0);
39332001f49Smrg   glRotatef(angz, 0.0, 0.0, 1.0);
39432001f49Smrg
39532001f49Smrg   if (texgen == 1) {
39632001f49Smrg      glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
39732001f49Smrg      glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
39832001f49Smrg      glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
39932001f49Smrg   }
40032001f49Smrg
40132001f49Smrg   if (texgen) {
40232001f49Smrg      glEnable(GL_TEXTURE_GEN_S);
40332001f49Smrg      glEnable(GL_TEXTURE_GEN_T);
40432001f49Smrg      glEnable(GL_TEXTURE_GEN_R);
40532001f49Smrg   }
40632001f49Smrg   else {
40732001f49Smrg      glDisable(GL_TEXTURE_GEN_S);
40832001f49Smrg      glDisable(GL_TEXTURE_GEN_T);
40932001f49Smrg      glDisable(GL_TEXTURE_GEN_R);
41032001f49Smrg   }
41132001f49Smrg
41232001f49Smrg   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, Filter);
41332001f49Smrg   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, Filter);
41432001f49Smrg
41532001f49Smrg   glCallList(CurObject);
41632001f49Smrg   glPopMatrix();
41732001f49Smrg
41832001f49Smrg   glutSwapBuffers();
41932001f49Smrg}
42032001f49Smrg
42132001f49Smrg
42232001f49Smrgstatic void
42332001f49Smrgresize(int w, int h)
42432001f49Smrg{
42532001f49Smrg   float ar = (float) w / (float) h;
42632001f49Smrg   float ax = 0.6 * ar;
42732001f49Smrg   float ay = 0.6;
42832001f49Smrg   glViewport(0, 0, (GLint) w, (GLint) h);
42932001f49Smrg   glMatrixMode(GL_PROJECTION);
43032001f49Smrg   glLoadIdentity();
43132001f49Smrg   glFrustum(-ax, ax, -ay, ay, 2, 20);
43232001f49Smrg   /*glOrtho(-2, 2, -2, 2, -10, 10);*/
43332001f49Smrg   glMatrixMode(GL_MODELVIEW);
43432001f49Smrg   glLoadIdentity();
43532001f49Smrg   glTranslatef(0, 0, -4);
43632001f49Smrg}
43732001f49Smrg
43832001f49Smrg
43932001f49Smrgstatic void
44032001f49SmrgIdle(void)
44132001f49Smrg{
44232001f49Smrg   float t = glutGet(GLUT_ELAPSED_TIME);
44332001f49Smrg   angx = 0.01 * t;
44432001f49Smrg   angy = 0.03 * t;
44532001f49Smrg   angz += 0;
44632001f49Smrg   glutPostRedisplay();
44732001f49Smrg}
44832001f49Smrg
44932001f49Smrg
45032001f49Smrgstatic void
45132001f49SmrgSpecialKey(int k, int x, int y)
45232001f49Smrg{
45332001f49Smrg  switch (k) {
45432001f49Smrg  case GLUT_KEY_UP:
45532001f49Smrg    angx += 5.0;
45632001f49Smrg    break;
45732001f49Smrg  case GLUT_KEY_DOWN:
45832001f49Smrg    angx -= 5.0;
45932001f49Smrg    break;
46032001f49Smrg  case GLUT_KEY_LEFT:
46132001f49Smrg    angy += 5.0;
46232001f49Smrg    break;
46332001f49Smrg  case GLUT_KEY_RIGHT:
46432001f49Smrg    angy -= 5.0;
46532001f49Smrg    break;
46632001f49Smrg  default:
46732001f49Smrg    return;
46832001f49Smrg  }
46932001f49Smrg  glutPostRedisplay();
47032001f49Smrg}
47132001f49Smrg
47232001f49Smrg
47332001f49Smrgstatic void
47432001f49SmrgKeyHandler(unsigned char key, int x, int y)
47532001f49Smrg{
47632001f49Smrg   static const char *mode[] = {
47732001f49Smrg      "glTexCoord3f (no texgen)",
47832001f49Smrg      "texgen fixed to object coords",
47932001f49Smrg      "texgen fixed to eye coords"
48032001f49Smrg   };
48132001f49Smrg   (void) x;
48232001f49Smrg   (void) y;
48332001f49Smrg   switch (key) {
48432001f49Smrg   case 27:
48532001f49Smrg   case 'q':
48632001f49Smrg   case 'Q':			/* quit game. */
48732001f49Smrg      exit(0);
48832001f49Smrg      break;
48932001f49Smrg   case 'z':
49032001f49Smrg      angz += 10;
49132001f49Smrg      break;
49232001f49Smrg   case 'Z':
49332001f49Smrg      angz -= 10;
49432001f49Smrg      break;
49532001f49Smrg   case 's':
49632001f49Smrg      smooth = !smooth;
49732001f49Smrg      if (smooth)
49832001f49Smrg         glShadeModel(GL_SMOOTH);
49932001f49Smrg      else
50032001f49Smrg         glShadeModel(GL_FLAT);
50132001f49Smrg      break;
50232001f49Smrg   case 't':
50332001f49Smrg      texgen++;
50432001f49Smrg      if (texgen > 2)
50532001f49Smrg         texgen = 0;
50632001f49Smrg      printf("Texgen: %s\n", mode[texgen]);
50732001f49Smrg      break;
50832001f49Smrg   case 'o':
50932001f49Smrg      if (CurObject == TORUS)
51032001f49Smrg         CurObject = SPHERE;
51132001f49Smrg      else
51232001f49Smrg         CurObject = TORUS;
51332001f49Smrg      break;
51432001f49Smrg   case 'f':
51532001f49Smrg      if (Filter == GL_LINEAR)
51632001f49Smrg         Filter = GL_NEAREST;
51732001f49Smrg      else
51832001f49Smrg         Filter = GL_LINEAR;
51932001f49Smrg      break;
52032001f49Smrg   case 'i':
52132001f49Smrg      if (CurTexture == NOISE_TEXTURE)
52232001f49Smrg         CurTexture = GRADIENT_TEXTURE;
52332001f49Smrg      else
52432001f49Smrg         CurTexture = NOISE_TEXTURE;
52532001f49Smrg      glBindTexture(GL_TEXTURE_3D, CurTexture);
52632001f49Smrg      break;
52732001f49Smrg   case 'a':
52832001f49Smrg   case ' ':
52932001f49Smrg      animate = !animate;
53032001f49Smrg      if (animate)
53132001f49Smrg         glutIdleFunc(Idle);
53232001f49Smrg      else
53332001f49Smrg         glutIdleFunc(NULL);
53432001f49Smrg      break;
53532001f49Smrg   case 'w':
53632001f49Smrg      wireframe = !wireframe;
53732001f49Smrg      if (wireframe)
53832001f49Smrg         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
53932001f49Smrg      else
54032001f49Smrg         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
54132001f49Smrg      break;
54232001f49Smrg   default:
54332001f49Smrg      break;
54432001f49Smrg   }
54532001f49Smrg   glutPostRedisplay();
54632001f49Smrg}
54732001f49Smrg
54832001f49Smrg
54932001f49Smrgstatic void
55032001f49Smrgcreate3Dgradient(void)
55132001f49Smrg{
55232001f49Smrg   unsigned char *v;
55332001f49Smrg   int i, j, k;
55432001f49Smrg   unsigned char *voxels = NULL;
55532001f49Smrg
55632001f49Smrg   voxels = (unsigned char *) malloc(4 * tex_width * tex_height * tex_depth);
55732001f49Smrg   v = voxels;
55832001f49Smrg
55932001f49Smrg   for (i = 0; i < tex_depth; i++) {
56032001f49Smrg      for (j = 0; j < tex_height; j++) {
56132001f49Smrg	 for (k = 0; k < tex_width; k++) {
56232001f49Smrg	    GLint r = (255 * i) / (tex_depth - 1);
56332001f49Smrg	    GLint g = (255 * j) / (tex_height - 1);
56432001f49Smrg	    GLint b = (255 * k) / (tex_width - 1);
56532001f49Smrg	    *v++ = r;
56632001f49Smrg	    *v++ = g;
56732001f49Smrg	    *v++ = b;
56832001f49Smrg	    *v++ = 255;
56932001f49Smrg	 }
57032001f49Smrg      }
57132001f49Smrg   }
57232001f49Smrg
57332001f49Smrg
57432001f49Smrg   glBindTexture(GL_TEXTURE_3D, GRADIENT_TEXTURE);
57532001f49Smrg   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
57632001f49Smrg   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
57732001f49Smrg   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
57832001f49Smrg   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
57932001f49Smrg
58032001f49Smrg   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
58132001f49Smrg   glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,
58232001f49Smrg		tex_width, tex_height, tex_depth,
58332001f49Smrg		0, GL_RGBA, GL_UNSIGNED_BYTE, voxels);
58432001f49Smrg   if (glGetError() == GL_OUT_OF_MEMORY)
58532001f49Smrg      printf("stex3d: Out of memory allocating %d x %d x %d RGBA texture",
58632001f49Smrg             tex_width, tex_height, tex_depth);
58732001f49Smrg
58832001f49Smrg   free(voxels);
58932001f49Smrg}
59032001f49Smrg
59132001f49Smrg
59232001f49Smrg
59332001f49Smrgstatic void
59432001f49Smrginit(void)
59532001f49Smrg{
59632001f49Smrg   static const GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
59732001f49Smrg   static const GLfloat mat_shininess[] = { 25.0 };
59832001f49Smrg   static const GLfloat gray[] = { 0.6, 0.6, 0.6, 0.0 };
59932001f49Smrg   static const GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 };
60032001f49Smrg   static const GLfloat light_position[] = { 0.0, 1.0, 1.0, 0.0 };
60132001f49Smrg
60232001f49Smrg   int max;
60332001f49Smrg
60432001f49Smrg   /* see if we have OpenGL 1.2 or later, for 3D texturing */
60532001f49Smrg   {
60632001f49Smrg      const char *version = (const char *) glGetString(GL_VERSION);
60732001f49Smrg      if (strncmp(version, "1.0", 3) == 0 || strncmp(version, "1.1", 3) == 0) {
60832001f49Smrg	 printf("Sorry, OpenGL 1.2 or later is required\n");
60932001f49Smrg	 exit(1);
61032001f49Smrg      }
61132001f49Smrg   }
61232001f49Smrg   printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
61332001f49Smrg   glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max);
61432001f49Smrg   printf("GL_MAX_3D_TEXTURE_SIZE: %d\n", max);
61532001f49Smrg   printf("Current 3D texture size: %d x %d x %d\n",
61632001f49Smrg          tex_width, tex_height, tex_depth);
61732001f49Smrg
61832001f49Smrg   /* init light */
61932001f49Smrg   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
62032001f49Smrg   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
62132001f49Smrg   glLightfv(GL_LIGHT1, GL_POSITION, light_position);
62232001f49Smrg   glLightfv(GL_LIGHT1, GL_AMBIENT, gray);
62332001f49Smrg   glLightfv(GL_LIGHT1, GL_DIFFUSE, white);
62432001f49Smrg   glLightfv(GL_LIGHT1, GL_SPECULAR, white);
62532001f49Smrg   glColorMaterial(GL_FRONT, GL_DIFFUSE);
62632001f49Smrg   glEnable(GL_COLOR_MATERIAL);
62732001f49Smrg   glEnable(GL_LIGHTING);
62832001f49Smrg   glEnable(GL_LIGHT1);
62932001f49Smrg
63032001f49Smrg   glClearColor(.5, .5, .5, 0);
63132001f49Smrg
63232001f49Smrg   {
63332001f49Smrg      GLUquadricObj *q;
63432001f49Smrg      q = gluNewQuadric();
63532001f49Smrg      gluQuadricTexture( q, GL_TRUE );
63632001f49Smrg      glNewList(SPHERE, GL_COMPILE);
63732001f49Smrg      gluSphere( q, 0.95, 30, 15 );
63832001f49Smrg      glEndList();
63932001f49Smrg      gluDeleteQuadric(q);
64032001f49Smrg   }
64132001f49Smrg
64232001f49Smrg   BuildTorus();
64332001f49Smrg
64432001f49Smrg
64532001f49Smrg   create3Dgradient();
64632001f49Smrg
64732001f49Smrg   initNoise();
64832001f49Smrg   create3Dtexture();
64932001f49Smrg
65032001f49Smrg   glEnable(GL_TEXTURE_3D);
65132001f49Smrg
65232001f49Smrg   /*
65332001f49Smrg      glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA);
65432001f49Smrg      glEnable(GL_BLEND);
65532001f49Smrg    */
65632001f49Smrg   glEnable(GL_DEPTH_TEST);
65732001f49Smrg
65832001f49Smrg   glColor3f(0.6, 0.7, 0.8);
65932001f49Smrg}
66032001f49Smrg
66132001f49Smrg
66232001f49Smrgint
66332001f49Smrgmain(int argc, char **argv)
66432001f49Smrg{
66532001f49Smrg   glutInit(&argc, argv);
66632001f49Smrg
66732001f49Smrg   if (parseCmdLine(argc, argv) == GL_FALSE) {
66832001f49Smrg      exit(0);
66932001f49Smrg   }
67032001f49Smrg
67132001f49Smrg   glutInitWindowPosition(0, 0);
67232001f49Smrg   glutInitWindowSize(400, 400);
67332001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
67432001f49Smrg
67532001f49Smrg   if (glutCreateWindow("stex3d") <= 0) {
67632001f49Smrg      exit(0);
67732001f49Smrg   }
67832001f49Smrg
67932001f49Smrg   glewInit();
68032001f49Smrg
68132001f49Smrg   init();
68232001f49Smrg
68332001f49Smrg   printHelp();
68432001f49Smrg
68532001f49Smrg   glutReshapeFunc(resize);
68632001f49Smrg   glutKeyboardFunc(KeyHandler);
68732001f49Smrg   glutSpecialFunc(SpecialKey);
68832001f49Smrg   glutDisplayFunc(drawScene);
68932001f49Smrg   if (animate)
69032001f49Smrg      glutIdleFunc(Idle);
69132001f49Smrg   glutMainLoop();
69232001f49Smrg   return 0;
69332001f49Smrg}
69432001f49Smrg
695