132001f49Smrg
232001f49Smrg/* projtex.c - by David Yu and David Blythe, SGI */
332001f49Smrg
432001f49Smrg/**
532001f49Smrg ** Demonstrates simple projective texture mapping.
632001f49Smrg **
732001f49Smrg ** Button1 changes view, Button2 moves texture.
832001f49Smrg **
932001f49Smrg ** (See: Segal, Korobkin, van Widenfelt, Foran, and Haeberli
1032001f49Smrg **  "Fast Shadows and Lighting Effects Using Texture Mapping", SIGGRAPH '92)
1132001f49Smrg **
1232001f49Smrg ** 1994,1995 -- David G Yu
1332001f49Smrg **
1432001f49Smrg ** cc -o projtex projtex.c texture.c -lglut -lGLU -lGL -lX11 -lm
1532001f49Smrg **/
1632001f49Smrg
1732001f49Smrg#include <assert.h>
1832001f49Smrg#include <stdio.h>
1932001f49Smrg#include <stdlib.h>
2032001f49Smrg#include <math.h>
2132001f49Smrg#include <GL/glew.h>
2232001f49Smrg#include "glut_wrap.h"
2332001f49Smrg#include "readtex.h"
2432001f49Smrg
2532001f49Smrg
2632001f49Smrg/* Some <math.h> files do not define M_PI... */
2732001f49Smrg#ifndef M_PI
2832001f49Smrg#define M_PI 3.14159265358979323846
2932001f49Smrg#endif
3032001f49Smrg
3132001f49Smrg#define MAX_TEX 4
3232001f49Smrgint NumTextures = 1;
3332001f49Smrg
3432001f49Smrgint winWidth, winHeight;
3532001f49Smrg
3632001f49SmrgGLboolean redrawContinuously = GL_FALSE;
3732001f49Smrg
3832001f49Smrgfloat angle, axis[3];
3932001f49Smrgenum MoveModes {
4032001f49Smrg  MoveNone, MoveView, MoveObject, MoveTexture
4132001f49Smrg};
4232001f49Smrgenum MoveModes mode = MoveNone;
4332001f49Smrg
4432001f49SmrgGLfloat objectXform[4][4];
4532001f49SmrgGLfloat textureXform[MAX_TEX][4][4];
4632001f49Smrg
4732001f49Smrgvoid (*drawObject) (void);
4832001f49Smrgvoid (*loadTexture) (void);
4932001f49SmrgGLboolean textureEnabled = GL_TRUE;
5032001f49SmrgGLboolean showProjection = GL_TRUE;
5132001f49SmrgGLboolean linearFilter = GL_TRUE;
5232001f49Smrg
5332001f49Smrgchar *texFilename[MAX_TEX] = {
5432001f49Smrg   DEMOS_DATA_DIR "girl.rgb",
5532001f49Smrg   DEMOS_DATA_DIR "tile.rgb",
5632001f49Smrg   DEMOS_DATA_DIR "bw.rgb",
5732001f49Smrg   DEMOS_DATA_DIR "reflect.rgb"
5832001f49Smrg};
5932001f49Smrg
6032001f49Smrg
6132001f49SmrgGLfloat zoomFactor = 1.0;
6232001f49Smrg
6332001f49Smrg/*****************************************************************/
6432001f49Smrg
6532001f49Smrg
6632001f49Smrgstatic void
6732001f49SmrgActiveTexture(int i)
6832001f49Smrg{
6932001f49Smrg   glActiveTextureARB(i);
7032001f49Smrg}
7132001f49Smrg
7232001f49Smrg
7332001f49Smrg/* matrix = identity */
7432001f49Smrgstatic void
7532001f49SmrgmatrixIdentity(GLfloat matrix[16])
7632001f49Smrg{
7732001f49Smrg  matrix[0] = 1.0;
7832001f49Smrg  matrix[1] = 0.0;
7932001f49Smrg  matrix[2] = 0.0;
8032001f49Smrg  matrix[3] = 0.0;
8132001f49Smrg  matrix[4] = 0.0;
8232001f49Smrg  matrix[5] = 1.0;
8332001f49Smrg  matrix[6] = 0.0;
8432001f49Smrg  matrix[7] = 0.0;
8532001f49Smrg  matrix[8] = 0.0;
8632001f49Smrg  matrix[9] = 0.0;
8732001f49Smrg  matrix[10] = 1.0;
8832001f49Smrg  matrix[11] = 0.0;
8932001f49Smrg  matrix[12] = 0.0;
9032001f49Smrg  matrix[13] = 0.0;
9132001f49Smrg  matrix[14] = 0.0;
9232001f49Smrg  matrix[15] = 1.0;
9332001f49Smrg}
9432001f49Smrg
9532001f49Smrg/* matrix2 = transpose(matrix1) */
9632001f49Smrgstatic void
9732001f49SmrgmatrixTranspose(GLfloat matrix2[16], GLfloat matrix1[16])
9832001f49Smrg{
9932001f49Smrg  matrix2[0] = matrix1[0];
10032001f49Smrg  matrix2[1] = matrix1[4];
10132001f49Smrg  matrix2[2] = matrix1[8];
10232001f49Smrg  matrix2[3] = matrix1[12];
10332001f49Smrg
10432001f49Smrg  matrix2[4] = matrix1[1];
10532001f49Smrg  matrix2[5] = matrix1[5];
10632001f49Smrg  matrix2[6] = matrix1[9];
10732001f49Smrg  matrix2[7] = matrix1[13];
10832001f49Smrg
10932001f49Smrg  matrix2[8] = matrix1[2];
11032001f49Smrg  matrix2[9] = matrix1[6];
11132001f49Smrg  matrix2[10] = matrix1[10];
11232001f49Smrg  matrix2[11] = matrix1[14];
11332001f49Smrg
11432001f49Smrg  matrix2[12] = matrix1[3];
11532001f49Smrg  matrix2[13] = matrix1[7];
11632001f49Smrg  matrix2[14] = matrix1[14];
11732001f49Smrg  matrix2[15] = matrix1[15];
11832001f49Smrg}
11932001f49Smrg
12032001f49Smrg/*****************************************************************/
12132001f49Smrg
12232001f49Smrg/* load SGI .rgb image (pad with a border of the specified width and color) */
12332001f49Smrg#if 0
12432001f49Smrgstatic void
12532001f49SmrgimgLoad(char *filenameIn, int borderIn, GLfloat borderColorIn[4],
12632001f49Smrg  int *wOut, int *hOut, GLubyte ** imgOut)
12732001f49Smrg{
12832001f49Smrg  int border = borderIn;
12932001f49Smrg  int width, height;
13032001f49Smrg  int w, h;
13132001f49Smrg  GLubyte *image, *img, *p;
13232001f49Smrg  int i, j, components;
13332001f49Smrg
13432001f49Smrg  image = (GLubyte *) read_texture(filenameIn, &width, &height, &components);
13532001f49Smrg  w = width + 2 * border;
13632001f49Smrg  h = height + 2 * border;
13732001f49Smrg  img = (GLubyte *) calloc(w * h, 4 * sizeof(unsigned char));
13832001f49Smrg
13932001f49Smrg  p = img;
14032001f49Smrg  for (j = -border; j < height + border; ++j) {
14132001f49Smrg    for (i = -border; i < width + border; ++i) {
14232001f49Smrg      if (0 <= j && j <= height - 1 && 0 <= i && i <= width - 1) {
14332001f49Smrg        p[0] = image[4 * (j * width + i) + 0];
14432001f49Smrg        p[1] = image[4 * (j * width + i) + 1];
14532001f49Smrg        p[2] = image[4 * (j * width + i) + 2];
14632001f49Smrg        p[3] = 0xff;
14732001f49Smrg      } else {
14832001f49Smrg        p[0] = borderColorIn[0] * 0xff;
14932001f49Smrg        p[1] = borderColorIn[1] * 0xff;
15032001f49Smrg        p[2] = borderColorIn[2] * 0xff;
15132001f49Smrg        p[3] = borderColorIn[3] * 0xff;
15232001f49Smrg      }
15332001f49Smrg      p += 4;
15432001f49Smrg    }
15532001f49Smrg  }
15632001f49Smrg  free(image);
15732001f49Smrg  *wOut = w;
15832001f49Smrg  *hOut = h;
15932001f49Smrg  *imgOut = img;
16032001f49Smrg}
16132001f49Smrg#endif
16232001f49Smrg
16332001f49Smrg
16432001f49Smrg/*****************************************************************/
16532001f49Smrg
16632001f49Smrg/* Load the image file specified on the command line as the current texture */
16732001f49Smrgstatic void
16832001f49SmrgloadImageTextures(void)
16932001f49Smrg{
17032001f49Smrg  GLfloat borderColor[4] =
17132001f49Smrg  {1.0, 1.0, 1.0, 1.0};
17232001f49Smrg  int tex;
17332001f49Smrg
17432001f49Smrg  for (tex = 0; tex < NumTextures; tex++) {
17532001f49Smrg     GLubyte *image, *texData3, *texData4;
17632001f49Smrg     GLint imgWidth, imgHeight;
17732001f49Smrg     GLenum imgFormat;
17832001f49Smrg     int i, j;
17932001f49Smrg
18032001f49Smrg     printf("loading %s\n", texFilename[tex]);
18132001f49Smrg     image = LoadRGBImage(texFilename[tex], &imgWidth, &imgHeight, &imgFormat);
18232001f49Smrg     if (!image) {
18332001f49Smrg        printf("can't find %s\n", texFilename[tex]);
18432001f49Smrg        exit(1);
18532001f49Smrg     }
18632001f49Smrg     assert(imgFormat == GL_RGB);
18732001f49Smrg
18832001f49Smrg     /* scale to 256x256 */
18932001f49Smrg     texData3 = malloc(256 * 256 * 4);
19032001f49Smrg     texData4 = malloc(256 * 256 * 4);
19132001f49Smrg     assert(texData3);
19232001f49Smrg     assert(texData4);
19332001f49Smrg     gluScaleImage(imgFormat, imgWidth, imgHeight, GL_UNSIGNED_BYTE, image,
19432001f49Smrg                   256, 256, GL_UNSIGNED_BYTE, texData3);
19532001f49Smrg
19632001f49Smrg     /* convert to rgba */
19732001f49Smrg     for (i = 0; i < 256 * 256; i++) {
19832001f49Smrg        texData4[i*4+0] = texData3[i*3+0];
19932001f49Smrg        texData4[i*4+1] = texData3[i*3+1];
20032001f49Smrg        texData4[i*4+2] = texData3[i*3+2];
20132001f49Smrg        texData4[i*4+3] = 128;
20232001f49Smrg     }
20332001f49Smrg
20432001f49Smrg     /* put transparent border around image */
20532001f49Smrg     for (i = 0; i < 256; i++) {
20632001f49Smrg        texData4[i*4+0] = 255;
20732001f49Smrg        texData4[i*4+1] = 255;
20832001f49Smrg        texData4[i*4+2] = 255;
20932001f49Smrg        texData4[i*4+3] = 0;
21032001f49Smrg     }
21132001f49Smrg     j = 256 * 255 * 4;
21232001f49Smrg     for (i = 0; i < 256; i++) {
21332001f49Smrg        texData4[j + i*4+0] = 255;
21432001f49Smrg        texData4[j + i*4+1] = 255;
21532001f49Smrg        texData4[j + i*4+2] = 255;
21632001f49Smrg        texData4[j + i*4+3] = 0;
21732001f49Smrg     }
21832001f49Smrg     for (i = 0; i < 256; i++) {
21932001f49Smrg        j = i * 256 * 4;
22032001f49Smrg        texData4[j+0] = 255;
22132001f49Smrg        texData4[j+1] = 255;
22232001f49Smrg        texData4[j+2] = 255;
22332001f49Smrg        texData4[j+3] = 0;
22432001f49Smrg     }
22532001f49Smrg     for (i = 0; i < 256; i++) {
22632001f49Smrg        j = i * 256 * 4 + 255 * 4;
22732001f49Smrg        texData4[j+0] = 255;
22832001f49Smrg        texData4[j+1] = 255;
22932001f49Smrg        texData4[j+2] = 255;
23032001f49Smrg        texData4[j+3] = 0;
23132001f49Smrg     }
23232001f49Smrg
23332001f49Smrg     ActiveTexture(GL_TEXTURE0_ARB + tex);
23432001f49Smrg     glBindTexture(GL_TEXTURE_2D, tex + 1);
23532001f49Smrg
23632001f49Smrg     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
23732001f49Smrg     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
23832001f49Smrg                  GL_RGBA, GL_UNSIGNED_BYTE, texData4);
23932001f49Smrg
24032001f49Smrg     if (linearFilter) {
24132001f49Smrg       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
24232001f49Smrg       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
24332001f49Smrg     } else {
24432001f49Smrg       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
24532001f49Smrg       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
24632001f49Smrg     }
24732001f49Smrg     glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
24832001f49Smrg
24932001f49Smrg     free(texData3);
25032001f49Smrg     free(texData4);
25132001f49Smrg     free(image);
25232001f49Smrg  }
25332001f49Smrg}
25432001f49Smrg
25532001f49Smrg/* Create a simple spotlight pattern and make it the current texture */
25632001f49Smrgstatic void
25732001f49SmrgloadSpotlightTexture(void)
25832001f49Smrg{
25932001f49Smrg  static int texWidth = 64, texHeight = 64;
26032001f49Smrg  static GLubyte *texData;
26132001f49Smrg  GLfloat borderColor[4] =
26232001f49Smrg  {0.1, 0.1, 0.1, 1.0};
26332001f49Smrg
26432001f49Smrg  if (!texData) {
26532001f49Smrg    GLubyte *p;
26632001f49Smrg    int i, j;
26732001f49Smrg
26832001f49Smrg    texData = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
26932001f49Smrg
27032001f49Smrg    p = texData;
27132001f49Smrg    for (j = 0; j < texHeight; ++j) {
27232001f49Smrg      float dy = (texHeight * 0.5 - j + 0.5) / (texHeight * 0.5);
27332001f49Smrg
27432001f49Smrg      for (i = 0; i < texWidth; ++i) {
27532001f49Smrg        float dx = (texWidth * 0.5 - i + 0.5) / (texWidth * 0.5);
27632001f49Smrg        float r = cos(M_PI / 2.0 * sqrt(dx * dx + dy * dy));
27732001f49Smrg        float c;
27832001f49Smrg
27932001f49Smrg        r = (r < 0) ? 0 : r * r;
28032001f49Smrg        c = 0xff * (r + borderColor[0]);
28132001f49Smrg        p[0] = (c <= 0xff) ? c : 0xff;
28232001f49Smrg        c = 0xff * (r + borderColor[1]);
28332001f49Smrg        p[1] = (c <= 0xff) ? c : 0xff;
28432001f49Smrg        c = 0xff * (r + borderColor[2]);
28532001f49Smrg        p[2] = (c <= 0xff) ? c : 0xff;
28632001f49Smrg        c = 0xff * (r + borderColor[3]);
28732001f49Smrg        p[3] = (c <= 0xff) ? c : 0xff;
28832001f49Smrg        p += 4;
28932001f49Smrg      }
29032001f49Smrg    }
29132001f49Smrg  }
29232001f49Smrg  if (linearFilter) {
29332001f49Smrg    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
29432001f49Smrg    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
29532001f49Smrg  } else {
29632001f49Smrg    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
29732001f49Smrg    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
29832001f49Smrg  }
29932001f49Smrg  glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
30032001f49Smrg  gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
30132001f49Smrg    GL_RGBA, GL_UNSIGNED_BYTE, texData);
30232001f49Smrg}
30332001f49Smrg
30432001f49Smrg/*****************************************************************/
30532001f49Smrg
30632001f49Smrgstatic void
30732001f49SmrgcheckErrors(void)
30832001f49Smrg{
30932001f49Smrg  GLenum error;
31032001f49Smrg  while ((error = glGetError()) != GL_NO_ERROR) {
31132001f49Smrg    fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error));
31232001f49Smrg  }
31332001f49Smrg}
31432001f49Smrg
31532001f49Smrgstatic void
31632001f49SmrgdrawCube(void)
31732001f49Smrg{
31832001f49Smrg  glBegin(GL_QUADS);
31932001f49Smrg
32032001f49Smrg  glNormal3f(-1.0, 0.0, 0.0);
32132001f49Smrg  glColor3f(0.80, 0.50, 0.50);
32232001f49Smrg  glVertex3f(-0.5, -0.5, -0.5);
32332001f49Smrg  glVertex3f(-0.5, -0.5, 0.5);
32432001f49Smrg  glVertex3f(-0.5, 0.5, 0.5);
32532001f49Smrg  glVertex3f(-0.5, 0.5, -0.5);
32632001f49Smrg
32732001f49Smrg  glNormal3f(1.0, 0.0, 0.0);
32832001f49Smrg  glColor3f(0.50, 0.80, 0.50);
32932001f49Smrg  glVertex3f(0.5, 0.5, 0.5);
33032001f49Smrg  glVertex3f(0.5, -0.5, 0.5);
33132001f49Smrg  glVertex3f(0.5, -0.5, -0.5);
33232001f49Smrg  glVertex3f(0.5, 0.5, -0.5);
33332001f49Smrg
33432001f49Smrg  glNormal3f(0.0, -1.0, 0.0);
33532001f49Smrg  glColor3f(0.50, 0.50, 0.80);
33632001f49Smrg  glVertex3f(-0.5, -0.5, -0.5);
33732001f49Smrg  glVertex3f(0.5, -0.5, -0.5);
33832001f49Smrg  glVertex3f(0.5, -0.5, 0.5);
33932001f49Smrg  glVertex3f(-0.5, -0.5, 0.5);
34032001f49Smrg
34132001f49Smrg  glNormal3f(0.0, 1.0, 0.0);
34232001f49Smrg  glColor3f(0.50, 0.80, 0.80);
34332001f49Smrg  glVertex3f(0.5, 0.5, 0.5);
34432001f49Smrg  glVertex3f(0.5, 0.5, -0.5);
34532001f49Smrg  glVertex3f(-0.5, 0.5, -0.5);
34632001f49Smrg  glVertex3f(-0.5, 0.5, 0.5);
34732001f49Smrg
34832001f49Smrg  glNormal3f(0.0, 0.0, -1.0);
34932001f49Smrg  glColor3f(0.80, 0.50, 0.80);
35032001f49Smrg  glVertex3f(-0.5, -0.5, -0.5);
35132001f49Smrg  glVertex3f(-0.5, 0.5, -0.5);
35232001f49Smrg  glVertex3f(0.5, 0.5, -0.5);
35332001f49Smrg  glVertex3f(0.5, -0.5, -0.5);
35432001f49Smrg
35532001f49Smrg  glNormal3f(0.0, 0.0, 1.0);
35632001f49Smrg  glColor3f(1.00, 0.80, 0.50);
35732001f49Smrg  glVertex3f(0.5, 0.5, 0.5);
35832001f49Smrg  glVertex3f(-0.5, 0.5, 0.5);
35932001f49Smrg  glVertex3f(-0.5, -0.5, 0.5);
36032001f49Smrg  glVertex3f(0.5, -0.5, 0.5);
36132001f49Smrg  glEnd();
36232001f49Smrg}
36332001f49Smrg
36432001f49Smrgstatic void
36532001f49SmrgdrawDodecahedron(void)
36632001f49Smrg{
36732001f49Smrg#define A (0.5 * 1.61803)  /* (sqrt(5) + 1) / 2 */
36832001f49Smrg#define B (0.5 * 0.61803)  /* (sqrt(5) - 1) / 2 */
36932001f49Smrg#define C (0.5 * 1.0)
37032001f49Smrg  GLfloat vertexes[20][3] =
37132001f49Smrg  {
37232001f49Smrg    {-A, 0.0, B},
37332001f49Smrg    {-A, 0.0, -B},
37432001f49Smrg    {A, 0.0, -B},
37532001f49Smrg    {A, 0.0, B},
37632001f49Smrg    {B, -A, 0.0},
37732001f49Smrg    {-B, -A, 0.0},
37832001f49Smrg    {-B, A, 0.0},
37932001f49Smrg    {B, A, 0.0},
38032001f49Smrg    {0.0, B, -A},
38132001f49Smrg    {0.0, -B, -A},
38232001f49Smrg    {0.0, -B, A},
38332001f49Smrg    {0.0, B, A},
38432001f49Smrg    {-C, -C, C},
38532001f49Smrg    {-C, -C, -C},
38632001f49Smrg    {C, -C, -C},
38732001f49Smrg    {C, -C, C},
38832001f49Smrg    {-C, C, C},
38932001f49Smrg    {-C, C, -C},
39032001f49Smrg    {C, C, -C},
39132001f49Smrg    {C, C, C},
39232001f49Smrg  };
39332001f49Smrg#undef A
39432001f49Smrg#undef B
39532001f49Smrg#undef C
39632001f49Smrg  GLint polygons[12][5] =
39732001f49Smrg  {
39832001f49Smrg    {0, 12, 10, 11, 16},
39932001f49Smrg    {1, 17, 8, 9, 13},
40032001f49Smrg    {2, 14, 9, 8, 18},
40132001f49Smrg    {3, 19, 11, 10, 15},
40232001f49Smrg    {4, 14, 2, 3, 15},
40332001f49Smrg    {5, 12, 0, 1, 13},
40432001f49Smrg    {6, 17, 1, 0, 16},
40532001f49Smrg    {7, 19, 3, 2, 18},
40632001f49Smrg    {8, 17, 6, 7, 18},
40732001f49Smrg    {9, 14, 4, 5, 13},
40832001f49Smrg    {10, 12, 5, 4, 15},
40932001f49Smrg    {11, 19, 7, 6, 16},
41032001f49Smrg  };
41132001f49Smrg  int i;
41232001f49Smrg
41332001f49Smrg  glColor3f(0.75, 0.75, 0.75);
41432001f49Smrg  for (i = 0; i < 12; ++i) {
41532001f49Smrg    GLfloat *p0, *p1, *p2, d;
41632001f49Smrg    GLfloat u[3], v[3], n[3];
41732001f49Smrg
41832001f49Smrg    p0 = &vertexes[polygons[i][0]][0];
41932001f49Smrg    p1 = &vertexes[polygons[i][1]][0];
42032001f49Smrg    p2 = &vertexes[polygons[i][2]][0];
42132001f49Smrg
42232001f49Smrg    u[0] = p2[0] - p1[0];
42332001f49Smrg    u[1] = p2[1] - p1[1];
42432001f49Smrg    u[2] = p2[2] - p1[2];
42532001f49Smrg
42632001f49Smrg    v[0] = p0[0] - p1[0];
42732001f49Smrg    v[1] = p0[1] - p1[1];
42832001f49Smrg    v[2] = p0[2] - p1[2];
42932001f49Smrg
43032001f49Smrg    n[0] = u[1] * v[2] - u[2] * v[1];
43132001f49Smrg    n[1] = u[2] * v[0] - u[0] * v[2];
43232001f49Smrg    n[2] = u[0] * v[1] - u[1] * v[0];
43332001f49Smrg
43432001f49Smrg    d = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
43532001f49Smrg    n[0] *= d;
43632001f49Smrg    n[1] *= d;
43732001f49Smrg    n[2] *= d;
43832001f49Smrg
43932001f49Smrg    glBegin(GL_POLYGON);
44032001f49Smrg    glNormal3fv(n);
44132001f49Smrg    glVertex3fv(p0);
44232001f49Smrg    glVertex3fv(p1);
44332001f49Smrg    glVertex3fv(p2);
44432001f49Smrg    glVertex3fv(vertexes[polygons[i][3]]);
44532001f49Smrg    glVertex3fv(vertexes[polygons[i][4]]);
44632001f49Smrg    glEnd();
44732001f49Smrg  }
44832001f49Smrg}
44932001f49Smrg
45032001f49Smrgstatic void
45132001f49SmrgdrawSphere(void)
45232001f49Smrg{
45332001f49Smrg  int numMajor = 24;
45432001f49Smrg  int numMinor = 32;
45532001f49Smrg  float radius = 0.8;
45632001f49Smrg  double majorStep = (M_PI / numMajor);
45732001f49Smrg  double minorStep = (2.0 * M_PI / numMinor);
45832001f49Smrg  int i, j;
45932001f49Smrg
46032001f49Smrg  glColor3f(0.50, 0.50, 0.50);
46132001f49Smrg  for (i = 0; i < numMajor; ++i) {
46232001f49Smrg    double a = i * majorStep;
46332001f49Smrg    double b = a + majorStep;
46432001f49Smrg    double r0 = radius * sin(a);
46532001f49Smrg    double r1 = radius * sin(b);
46632001f49Smrg    GLfloat z0 = radius * cos(a);
46732001f49Smrg    GLfloat z1 = radius * cos(b);
46832001f49Smrg
46932001f49Smrg    glBegin(GL_TRIANGLE_STRIP);
47032001f49Smrg    for (j = 0; j <= numMinor; ++j) {
47132001f49Smrg      double c = j * minorStep;
47232001f49Smrg      GLfloat x = cos(c);
47332001f49Smrg      GLfloat y = sin(c);
47432001f49Smrg
47532001f49Smrg      glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
47632001f49Smrg      glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
47732001f49Smrg      glVertex3f(x * r0, y * r0, z0);
47832001f49Smrg
47932001f49Smrg      glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
48032001f49Smrg      glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
48132001f49Smrg      glVertex3f(x * r1, y * r1, z1);
48232001f49Smrg    }
48332001f49Smrg    glEnd();
48432001f49Smrg  }
48532001f49Smrg}
48632001f49Smrg
48732001f49Smrg/*****************************************************************/
48832001f49Smrg
48932001f49Smrgfloat xmin = -0.035, xmax = 0.035;
49032001f49Smrgfloat ymin = -0.035, ymax = 0.035;
49132001f49Smrgfloat nnear = 0.1;
49232001f49Smrgfloat ffar = 1.9;
49332001f49Smrgfloat distance = -1.0;
49432001f49Smrg
49532001f49Smrgstatic void
49632001f49SmrgloadTextureProjection(int texUnit, GLfloat m[16])
49732001f49Smrg{
49832001f49Smrg  GLfloat mInverse[4][4];
49932001f49Smrg
50032001f49Smrg  /* Should use true inverse, but since m consists only of rotations, we can
50132001f49Smrg     just use the transpose. */
50232001f49Smrg  matrixTranspose((GLfloat *) mInverse, m);
50332001f49Smrg
50432001f49Smrg  ActiveTexture(GL_TEXTURE0_ARB + texUnit);
50532001f49Smrg  glMatrixMode(GL_TEXTURE);
50632001f49Smrg  glLoadIdentity();
50732001f49Smrg  glTranslatef(0.5, 0.5, 0.0);
50832001f49Smrg  glScalef(0.5, 0.5, 1.0);
50932001f49Smrg  glFrustum(xmin, xmax, ymin, ymax, nnear, ffar);
51032001f49Smrg  glTranslatef(0.0, 0.0, distance);
51132001f49Smrg  glMultMatrixf((GLfloat *) mInverse);
51232001f49Smrg  glMatrixMode(GL_MODELVIEW);
51332001f49Smrg}
51432001f49Smrg
51532001f49Smrgstatic void
51632001f49SmrgdrawTextureProjection(void)
51732001f49Smrg{
51832001f49Smrg  float t = ffar / nnear;
51932001f49Smrg  GLfloat n[4][3];
52032001f49Smrg  GLfloat f[4][3];
52132001f49Smrg
52232001f49Smrg  n[0][0] = xmin;
52332001f49Smrg  n[0][1] = ymin;
52432001f49Smrg  n[0][2] = -(nnear + distance);
52532001f49Smrg
52632001f49Smrg  n[1][0] = xmax;
52732001f49Smrg  n[1][1] = ymin;
52832001f49Smrg  n[1][2] = -(nnear + distance);
52932001f49Smrg
53032001f49Smrg  n[2][0] = xmax;
53132001f49Smrg  n[2][1] = ymax;
53232001f49Smrg  n[2][2] = -(nnear + distance);
53332001f49Smrg
53432001f49Smrg  n[3][0] = xmin;
53532001f49Smrg  n[3][1] = ymax;
53632001f49Smrg  n[3][2] = -(nnear + distance);
53732001f49Smrg
53832001f49Smrg  f[0][0] = xmin * t;
53932001f49Smrg  f[0][1] = ymin * t;
54032001f49Smrg  f[0][2] = -(ffar + distance);
54132001f49Smrg
54232001f49Smrg  f[1][0] = xmax * t;
54332001f49Smrg  f[1][1] = ymin * t;
54432001f49Smrg  f[1][2] = -(ffar + distance);
54532001f49Smrg
54632001f49Smrg  f[2][0] = xmax * t;
54732001f49Smrg  f[2][1] = ymax * t;
54832001f49Smrg  f[2][2] = -(ffar + distance);
54932001f49Smrg
55032001f49Smrg  f[3][0] = xmin * t;
55132001f49Smrg  f[3][1] = ymax * t;
55232001f49Smrg  f[3][2] = -(ffar + distance);
55332001f49Smrg
55432001f49Smrg  glColor3f(1.0, 1.0, 0.0);
55532001f49Smrg  glBegin(GL_LINE_LOOP);
55632001f49Smrg  glVertex3fv(n[0]);
55732001f49Smrg  glVertex3fv(n[1]);
55832001f49Smrg  glVertex3fv(n[2]);
55932001f49Smrg  glVertex3fv(n[3]);
56032001f49Smrg  glVertex3fv(f[3]);
56132001f49Smrg  glVertex3fv(f[2]);
56232001f49Smrg  glVertex3fv(f[1]);
56332001f49Smrg  glVertex3fv(f[0]);
56432001f49Smrg  glVertex3fv(n[0]);
56532001f49Smrg  glVertex3fv(n[1]);
56632001f49Smrg  glVertex3fv(f[1]);
56732001f49Smrg  glVertex3fv(f[0]);
56832001f49Smrg  glVertex3fv(f[3]);
56932001f49Smrg  glVertex3fv(f[2]);
57032001f49Smrg  glVertex3fv(n[2]);
57132001f49Smrg  glVertex3fv(n[3]);
57232001f49Smrg  glEnd();
57332001f49Smrg}
57432001f49Smrg
57532001f49Smrg/*****************************************************************/
57632001f49Smrg
57732001f49Smrgstatic void
57832001f49Smrginitialize(void)
57932001f49Smrg{
58032001f49Smrg  GLfloat light0Pos[4] =
58132001f49Smrg  {0.3, 0.3, 0.0, 1.0};
58232001f49Smrg  GLfloat matAmb[4] =
58332001f49Smrg  {0.01, 0.01, 0.01, 1.00};
58432001f49Smrg  GLfloat matDiff[4] =
58532001f49Smrg  {0.65, 0.65, 0.65, 1.00};
58632001f49Smrg  GLfloat matSpec[4] =
58732001f49Smrg  {0.30, 0.30, 0.30, 1.00};
58832001f49Smrg  GLfloat matShine = 10.0;
58932001f49Smrg  GLfloat eyePlaneS[] =
59032001f49Smrg  {1.0, 0.0, 0.0, 0.0};
59132001f49Smrg  GLfloat eyePlaneT[] =
59232001f49Smrg  {0.0, 1.0, 0.0, 0.0};
59332001f49Smrg  GLfloat eyePlaneR[] =
59432001f49Smrg  {0.0, 0.0, 1.0, 0.0};
59532001f49Smrg  GLfloat eyePlaneQ[] =
59632001f49Smrg  {0.0, 0.0, 0.0, 1.0};
59732001f49Smrg  int i;
59832001f49Smrg
59932001f49Smrg  /* Setup Misc.  */
60032001f49Smrg  glClearColor(0.41, 0.41, 0.31, 0.0);
60132001f49Smrg
60232001f49Smrg  glEnable(GL_DEPTH_TEST);
60332001f49Smrg
60432001f49Smrg  /*  glLineWidth(2.0);*/
60532001f49Smrg
60632001f49Smrg  glCullFace(GL_FRONT);
60732001f49Smrg  glEnable(GL_CULL_FACE);
60832001f49Smrg
60932001f49Smrg  glMatrixMode(GL_PROJECTION);
61032001f49Smrg  glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
61132001f49Smrg  glMatrixMode(GL_MODELVIEW);
61232001f49Smrg  glTranslatef(0, 0, -2);
61332001f49Smrg
61432001f49Smrg  matrixIdentity((GLfloat *) objectXform);
61532001f49Smrg  for (i = 0; i < NumTextures; i++) {
61632001f49Smrg     matrixIdentity((GLfloat *) textureXform[i]);
61732001f49Smrg  }
61832001f49Smrg
61932001f49Smrg  glMatrixMode(GL_PROJECTION);
62032001f49Smrg  glPushMatrix();
62132001f49Smrg  glLoadIdentity();
62232001f49Smrg  glOrtho(0, 1, 0, 1, -1, 1);
62332001f49Smrg  glMatrixMode(GL_MODELVIEW);
62432001f49Smrg  glPushMatrix();
62532001f49Smrg  glLoadIdentity();
62632001f49Smrg
62732001f49Smrg  glRasterPos2i(0, 0);
62832001f49Smrg
62932001f49Smrg  glPopMatrix();
63032001f49Smrg  glMatrixMode(GL_PROJECTION);
63132001f49Smrg  glPopMatrix();
63232001f49Smrg  glMatrixMode(GL_MODELVIEW);
63332001f49Smrg
63432001f49Smrg  /* Setup Lighting */
63532001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb);
63632001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
63732001f49Smrg  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
63832001f49Smrg  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
63932001f49Smrg
64032001f49Smrg  glEnable(GL_COLOR_MATERIAL);
64132001f49Smrg
64232001f49Smrg  glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
64332001f49Smrg  glEnable(GL_LIGHT0);
64432001f49Smrg
64532001f49Smrg  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
64632001f49Smrg  glEnable(GL_LIGHTING);
64732001f49Smrg
64832001f49Smrg  /* Setup Texture */
64932001f49Smrg
65032001f49Smrg  (*loadTexture) ();
65132001f49Smrg
65232001f49Smrg
65332001f49Smrg  for (i = 0; i < NumTextures; i++) {
65432001f49Smrg     ActiveTexture(GL_TEXTURE0_ARB + i);
65532001f49Smrg
65632001f49Smrg     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
65732001f49Smrg     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
65832001f49Smrg     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
65932001f49Smrg
66032001f49Smrg     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
66132001f49Smrg     glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS);
66232001f49Smrg
66332001f49Smrg     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
66432001f49Smrg     glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT);
66532001f49Smrg
66632001f49Smrg     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
66732001f49Smrg     glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR);
66832001f49Smrg
66932001f49Smrg     glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
67032001f49Smrg     glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ);
67132001f49Smrg  }
67232001f49Smrg}
67332001f49Smrg
67432001f49Smrgstatic void
67532001f49Smrgdisplay(void)
67632001f49Smrg{
67732001f49Smrg  int i;
67832001f49Smrg
67932001f49Smrg  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
68032001f49Smrg
68132001f49Smrg  if (textureEnabled) {
68232001f49Smrg    if (mode == MoveTexture || mode == MoveView) {
68332001f49Smrg      /* Have OpenGL compute the new transformation (simple but slow). */
68432001f49Smrg      for (i = 0; i < NumTextures; i++) {
68532001f49Smrg        glPushMatrix();
68632001f49Smrg        glLoadIdentity();
68732001f49Smrg#if 0
68832001f49Smrg        if (i & 1)
68932001f49Smrg           glRotatef(angle, axis[0], axis[1], axis[2]);
69032001f49Smrg        else
69132001f49Smrg#endif
69232001f49Smrg           glRotatef(angle*(i+1), axis[0], axis[1], axis[2]);
69332001f49Smrg
69432001f49Smrg        glMultMatrixf((GLfloat *) textureXform[i]);
69532001f49Smrg        glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) textureXform[i]);
69632001f49Smrg        glPopMatrix();
69732001f49Smrg      }
69832001f49Smrg    }
69932001f49Smrg    for (i = 0; i < NumTextures; i++) {
70032001f49Smrg       loadTextureProjection(i, (GLfloat *) textureXform[i]);
70132001f49Smrg    }
70232001f49Smrg
70332001f49Smrg    if (showProjection) {
70432001f49Smrg      for (i = 0; i < NumTextures; i++) {
70532001f49Smrg        ActiveTexture(GL_TEXTURE0_ARB + i);
70632001f49Smrg        glPushMatrix();
70732001f49Smrg        glMultMatrixf((GLfloat *) textureXform[i]);
70832001f49Smrg        glDisable(GL_LIGHTING);
70932001f49Smrg        drawTextureProjection();
71032001f49Smrg        glEnable(GL_LIGHTING);
71132001f49Smrg        glPopMatrix();
71232001f49Smrg      }
71332001f49Smrg    }
71432001f49Smrg    for (i = 0; i < NumTextures; i++) {
71532001f49Smrg      ActiveTexture(GL_TEXTURE0_ARB + i);
71632001f49Smrg      glEnable(GL_TEXTURE_2D);
71732001f49Smrg      glEnable(GL_TEXTURE_GEN_S);
71832001f49Smrg      glEnable(GL_TEXTURE_GEN_T);
71932001f49Smrg      glEnable(GL_TEXTURE_GEN_R);
72032001f49Smrg      glEnable(GL_TEXTURE_GEN_Q);
72132001f49Smrg    }
72232001f49Smrg  }
72332001f49Smrg  if (mode == MoveObject || mode == MoveView) {
72432001f49Smrg    /* Have OpenGL compute the new transformation (simple but slow). */
72532001f49Smrg    glPushMatrix();
72632001f49Smrg    glLoadIdentity();
72732001f49Smrg    glRotatef(angle, axis[0], axis[1], axis[2]);
72832001f49Smrg    glMultMatrixf((GLfloat *) objectXform);
72932001f49Smrg    glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
73032001f49Smrg    glPopMatrix();
73132001f49Smrg  }
73232001f49Smrg  glPushMatrix();
73332001f49Smrg  glMultMatrixf((GLfloat *) objectXform);
73432001f49Smrg  (*drawObject) ();
73532001f49Smrg  glPopMatrix();
73632001f49Smrg
73732001f49Smrg  for (i = 0; i < NumTextures; i++) {
73832001f49Smrg    ActiveTexture(GL_TEXTURE0_ARB + i);
73932001f49Smrg    glDisable(GL_TEXTURE_2D);
74032001f49Smrg    glDisable(GL_TEXTURE_GEN_S);
74132001f49Smrg    glDisable(GL_TEXTURE_GEN_T);
74232001f49Smrg    glDisable(GL_TEXTURE_GEN_R);
74332001f49Smrg    glDisable(GL_TEXTURE_GEN_Q);
74432001f49Smrg  }
74532001f49Smrg
74632001f49Smrg  if (zoomFactor > 1.0) {
74732001f49Smrg    glDisable(GL_DEPTH_TEST);
74832001f49Smrg    glCopyPixels(0, 0, winWidth / zoomFactor, winHeight / zoomFactor, GL_COLOR);
74932001f49Smrg    glEnable(GL_DEPTH_TEST);
75032001f49Smrg  }
75132001f49Smrg  glFlush();
75232001f49Smrg  glutSwapBuffers();
75332001f49Smrg  checkErrors();
75432001f49Smrg}
75532001f49Smrg
75632001f49Smrg/*****************************************************************/
75732001f49Smrg
75832001f49Smrg/* simple trackball-like motion control */
75932001f49Smrgstatic float lastPos[3];
76032001f49Smrgstatic int lastTime;
76132001f49Smrg
76232001f49Smrgstatic void
76332001f49Smrgptov(int x, int y, int width, int height, float v[3])
76432001f49Smrg{
76532001f49Smrg  float d, a;
76632001f49Smrg
76732001f49Smrg  /* project x,y onto a hemi-sphere centered within width, height */
76832001f49Smrg  v[0] = (2.0 * x - width) / width;
76932001f49Smrg  v[1] = (height - 2.0 * y) / height;
77032001f49Smrg  d = sqrt(v[0] * v[0] + v[1] * v[1]);
77132001f49Smrg  v[2] = cos((M_PI / 2.0) * ((d < 1.0) ? d : 1.0));
77232001f49Smrg  a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
77332001f49Smrg  v[0] *= a;
77432001f49Smrg  v[1] *= a;
77532001f49Smrg  v[2] *= a;
77632001f49Smrg}
77732001f49Smrg
77832001f49Smrgstatic void
77932001f49SmrgstartMotion(int x, int y, int but, int time)
78032001f49Smrg{
78132001f49Smrg  if (but == GLUT_LEFT_BUTTON) {
78232001f49Smrg    mode = MoveView;
78332001f49Smrg  } else if (but == GLUT_MIDDLE_BUTTON) {
78432001f49Smrg    mode = MoveTexture;
78532001f49Smrg  } else {
78632001f49Smrg    return;
78732001f49Smrg  }
78832001f49Smrg
78932001f49Smrg  lastTime = time;
79032001f49Smrg  ptov(x, y, winWidth, winHeight, lastPos);
79132001f49Smrg}
79232001f49Smrg
79332001f49Smrgstatic void
79432001f49Smrganimate(void)
79532001f49Smrg{
79632001f49Smrg  glutPostRedisplay();
79732001f49Smrg}
79832001f49Smrg
79932001f49Smrgstatic void
80032001f49Smrgvis(int visible)
80132001f49Smrg{
80232001f49Smrg  if (visible == GLUT_VISIBLE) {
80332001f49Smrg    if (redrawContinuously)
80432001f49Smrg      glutIdleFunc(animate);
80532001f49Smrg  } else {
80632001f49Smrg    if (redrawContinuously)
80732001f49Smrg      glutIdleFunc(NULL);
80832001f49Smrg  }
80932001f49Smrg}
81032001f49Smrg
81132001f49Smrgstatic void
81232001f49SmrgstopMotion(int but, int time)
81332001f49Smrg{
81432001f49Smrg  if ((but == GLUT_LEFT_BUTTON && mode == MoveView) ||
81532001f49Smrg    (but == GLUT_MIDDLE_BUTTON && mode == MoveTexture)) {
81632001f49Smrg  } else {
81732001f49Smrg    return;
81832001f49Smrg  }
81932001f49Smrg
82032001f49Smrg  if (time == lastTime) {
82132001f49Smrg     /*    redrawContinuously = GL_TRUE;*/
82232001f49Smrg    glutIdleFunc(animate);
82332001f49Smrg  } else {
82432001f49Smrg    angle = 0.0;
82532001f49Smrg    redrawContinuously = GL_FALSE;
82632001f49Smrg    glutIdleFunc(0);
82732001f49Smrg  }
82832001f49Smrg  if (!redrawContinuously) {
82932001f49Smrg    mode = MoveNone;
83032001f49Smrg  }
83132001f49Smrg}
83232001f49Smrg
83332001f49Smrgstatic void
83432001f49SmrgtrackMotion(int x, int y)
83532001f49Smrg{
83632001f49Smrg  float curPos[3], dx, dy, dz;
83732001f49Smrg
83832001f49Smrg  ptov(x, y, winWidth, winHeight, curPos);
83932001f49Smrg
84032001f49Smrg  dx = curPos[0] - lastPos[0];
84132001f49Smrg  dy = curPos[1] - lastPos[1];
84232001f49Smrg  dz = curPos[2] - lastPos[2];
84332001f49Smrg  angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
84432001f49Smrg
84532001f49Smrg  axis[0] = lastPos[1] * curPos[2] - lastPos[2] * curPos[1];
84632001f49Smrg  axis[1] = lastPos[2] * curPos[0] - lastPos[0] * curPos[2];
84732001f49Smrg  axis[2] = lastPos[0] * curPos[1] - lastPos[1] * curPos[0];
84832001f49Smrg
84932001f49Smrg  lastTime = glutGet(GLUT_ELAPSED_TIME);
85032001f49Smrg  lastPos[0] = curPos[0];
85132001f49Smrg  lastPos[1] = curPos[1];
85232001f49Smrg  lastPos[2] = curPos[2];
85332001f49Smrg  glutPostRedisplay();
85432001f49Smrg}
85532001f49Smrg
85632001f49Smrg/*****************************************************************/
85732001f49Smrg
85832001f49Smrgstatic void
85932001f49Smrgobject(void)
86032001f49Smrg{
86132001f49Smrg  static int object;
86232001f49Smrg
86332001f49Smrg  object++;
86432001f49Smrg  object %= 3;
86532001f49Smrg  switch (object) {
86632001f49Smrg  case 0:
86732001f49Smrg    drawObject = drawCube;
86832001f49Smrg    break;
86932001f49Smrg  case 1:
87032001f49Smrg    drawObject = drawDodecahedron;
87132001f49Smrg    break;
87232001f49Smrg  case 2:
87332001f49Smrg    drawObject = drawSphere;
87432001f49Smrg    break;
87532001f49Smrg  default:
87632001f49Smrg    break;
87732001f49Smrg  }
87832001f49Smrg}
87932001f49Smrg
88032001f49Smrgstatic void
88132001f49Smrgnop(void)
88232001f49Smrg{
88332001f49Smrg}
88432001f49Smrg
88532001f49Smrgstatic void
88632001f49Smrgtexture(void)
88732001f49Smrg{
88832001f49Smrg  static int texture = 0;
88932001f49Smrg
89032001f49Smrg  texture++;
89132001f49Smrg  texture %= 3;
89232001f49Smrg  if (texture == 1 && texFilename == NULL) {
89332001f49Smrg    /* Skip file texture if not loaded. */
89432001f49Smrg    texture++;
89532001f49Smrg  }
89632001f49Smrg  switch (texture) {
89732001f49Smrg  case 0:
89832001f49Smrg    loadTexture = nop;
89932001f49Smrg    textureEnabled = GL_FALSE;
90032001f49Smrg    break;
90132001f49Smrg  case 1:
90232001f49Smrg    loadTexture = loadImageTextures;
90332001f49Smrg    (*loadTexture) ();
90432001f49Smrg    textureEnabled = GL_TRUE;
90532001f49Smrg    break;
90632001f49Smrg  case 2:
90732001f49Smrg    loadTexture = loadSpotlightTexture;
90832001f49Smrg    (*loadTexture) ();
90932001f49Smrg    textureEnabled = GL_TRUE;
91032001f49Smrg    break;
91132001f49Smrg  default:
91232001f49Smrg    break;
91332001f49Smrg  }
91432001f49Smrg}
91532001f49Smrg
91632001f49Smrgstatic void
91732001f49Smrghelp(void)
91832001f49Smrg{
91932001f49Smrg  printf("'h'   - help\n");
92032001f49Smrg  printf("'l'   - toggle linear/nearest filter\n");
92132001f49Smrg  printf("'s'   - toggle projection frustum\n");
92232001f49Smrg  printf("'t'   - toggle projected texture\n");
92332001f49Smrg  printf("'o'   - toggle object\n");
92432001f49Smrg  printf("'z'   - increase zoom factor\n");
92532001f49Smrg  printf("'Z'   - decrease zoom factor\n");
92632001f49Smrg  printf("left mouse     - move view\n");
92732001f49Smrg  printf("middle mouse   - move projection\n");
92832001f49Smrg}
92932001f49Smrg
93032001f49Smrg/* ARGSUSED1 */
93132001f49Smrgstatic void
93232001f49Smrgkey(unsigned char key, int x, int y)
93332001f49Smrg{
93432001f49Smrg  switch (key) {
93532001f49Smrg  case '\033':
93632001f49Smrg    exit(0);
93732001f49Smrg    break;
93832001f49Smrg  case 'l':
93932001f49Smrg    linearFilter = !linearFilter;
94032001f49Smrg    (*loadTexture) ();
94132001f49Smrg    break;
94232001f49Smrg  case 's':
94332001f49Smrg    showProjection = !showProjection;
94432001f49Smrg    break;
94532001f49Smrg  case 't':
94632001f49Smrg    texture();
94732001f49Smrg    break;
94832001f49Smrg  case 'o':
94932001f49Smrg    object();
95032001f49Smrg    break;
95132001f49Smrg  case 'z':
95232001f49Smrg    zoomFactor += 1.0;
95332001f49Smrg    glPixelZoom(zoomFactor, zoomFactor);
95432001f49Smrg    glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
95532001f49Smrg    break;
95632001f49Smrg  case 'Z':
95732001f49Smrg    zoomFactor -= 1.0;
95832001f49Smrg    if (zoomFactor < 1.0)
95932001f49Smrg      zoomFactor = 1.0;
96032001f49Smrg    glPixelZoom(zoomFactor, zoomFactor);
96132001f49Smrg    glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
96232001f49Smrg    break;
96332001f49Smrg  case 'h':
96432001f49Smrg    help();
96532001f49Smrg    break;
96632001f49Smrg  }
96732001f49Smrg  glutPostRedisplay();
96832001f49Smrg}
96932001f49Smrg
97032001f49Smrgstatic void
97132001f49Smrgmouse(int button, int state, int x, int y)
97232001f49Smrg{
97332001f49Smrg  if (state == GLUT_DOWN)
97432001f49Smrg    startMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME));
97532001f49Smrg  else if (state == GLUT_UP)
97632001f49Smrg    stopMotion(button, glutGet(GLUT_ELAPSED_TIME));
97732001f49Smrg  glutPostRedisplay();
97832001f49Smrg}
97932001f49Smrg
98032001f49Smrgstatic void
98132001f49Smrgreshape(int w, int h)
98232001f49Smrg{
98332001f49Smrg  winWidth = w;
98432001f49Smrg  winHeight = h;
98532001f49Smrg  glViewport(0, 0, w / zoomFactor, h / zoomFactor);
98632001f49Smrg}
98732001f49Smrg
98832001f49Smrg
98932001f49Smrgstatic void
99032001f49Smrgmenu(int selection)
99132001f49Smrg{
99232001f49Smrg  if (selection == 666) {
99332001f49Smrg    exit(0);
99432001f49Smrg  }
99532001f49Smrg  key((unsigned char) selection, 0, 0);
99632001f49Smrg}
99732001f49Smrg
99832001f49Smrgint
99932001f49Smrgmain(int argc, char **argv)
100032001f49Smrg{
100132001f49Smrg  glutInitWindowSize(500,500);
100232001f49Smrg  glutInit(&argc, argv);
100332001f49Smrg  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
100432001f49Smrg  (void) glutCreateWindow("projtex");
100532001f49Smrg  glewInit();
100632001f49Smrg
100732001f49Smrg  if (argc > 1) {
100832001f49Smrg     NumTextures = atoi(argv[1]);
100932001f49Smrg  }
101032001f49Smrg  assert(NumTextures <= MAX_TEX);
101132001f49Smrg
101232001f49Smrg  loadTexture = loadImageTextures;
101332001f49Smrg  drawObject = drawCube;
101432001f49Smrg  initialize();
101532001f49Smrg  glutDisplayFunc(display);
101632001f49Smrg  glutKeyboardFunc(key);
101732001f49Smrg  glutReshapeFunc(reshape);
101832001f49Smrg  glutMouseFunc(mouse);
101932001f49Smrg  glutMotionFunc(trackMotion);
102032001f49Smrg  glutVisibilityFunc(vis);
102132001f49Smrg  glutCreateMenu(menu);
102232001f49Smrg  glutAddMenuEntry("Toggle showing projection", 's');
102332001f49Smrg  glutAddMenuEntry("Switch texture", 't');
102432001f49Smrg  glutAddMenuEntry("Switch object", 'o');
102532001f49Smrg  glutAddMenuEntry("Toggle filtering", 'l');
102632001f49Smrg  glutAddMenuEntry("Quit", 666);
102732001f49Smrg  glutAttachMenu(GLUT_RIGHT_BUTTON);
102832001f49Smrg  texture();
102932001f49Smrg  glutMainLoop();
103032001f49Smrg  return 0;             /* ANSI C requires main to return int. */
103132001f49Smrg}
1032