From: Brian Paul Date: Sat, 18 Apr 2009 19:05:51 +0000 (-0600) Subject: demos: move tests/projtex.c to demos/ X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=49c3e7172db1ee2afef6bcd19c3cd55dbe60bd33;p=mesa.git demos: move tests/projtex.c to demos/ And fix compiler warnings. --- diff --git a/progs/demos/Makefile b/progs/demos/Makefile index a1c99c6c545..2fe407972d7 100644 --- a/progs/demos/Makefile +++ b/progs/demos/Makefile @@ -41,6 +41,7 @@ PROGS = \ multiarb \ paltex \ pointblast \ + projtex \ rain \ ray \ readpix \ diff --git a/progs/demos/projtex.c b/progs/demos/projtex.c new file mode 100644 index 00000000000..99154d7bdc8 --- /dev/null +++ b/progs/demos/projtex.c @@ -0,0 +1,1028 @@ + +/* projtex.c - by David Yu and David Blythe, SGI */ + +/** + ** Demonstrates simple projective texture mapping. + ** + ** Button1 changes view, Button2 moves texture. + ** + ** (See: Segal, Korobkin, van Widenfelt, Foran, and Haeberli + ** "Fast Shadows and Lighting Effects Using Texture Mapping", SIGGRAPH '92) + ** + ** 1994,1995 -- David G Yu + ** + ** cc -o projtex projtex.c texture.c -lglut -lGLU -lGL -lX11 -lm + **/ + +#include +#include +#include +#include +#include +#include +#include "readtex.h" + + +/* Some files do not define M_PI... */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define MAX_TEX 4 +int NumTextures = 1; + +int winWidth, winHeight; + +GLboolean redrawContinuously = GL_FALSE; + +float angle, axis[3]; +enum MoveModes { + MoveNone, MoveView, MoveObject, MoveTexture +}; +enum MoveModes mode = MoveNone; + +GLfloat objectXform[4][4]; +GLfloat textureXform[MAX_TEX][4][4]; + +void (*drawObject) (void); +void (*loadTexture) (void); +GLboolean textureEnabled = GL_TRUE; +GLboolean showProjection = GL_TRUE; +GLboolean linearFilter = GL_TRUE; + +char *texFilename[MAX_TEX] = { + "../images/girl.rgb", + "../images/tile.rgb", + "../images/bw.rgb", + "../images/reflect.rgb" +}; + + +GLfloat zoomFactor = 1.0; + +/*****************************************************************/ + + +static void +ActiveTexture(int i) +{ + glActiveTextureARB(i); +} + + +/* matrix = identity */ +static void +matrixIdentity(GLfloat matrix[16]) +{ + matrix[0] = 1.0; + matrix[1] = 0.0; + matrix[2] = 0.0; + matrix[3] = 0.0; + matrix[4] = 0.0; + matrix[5] = 1.0; + matrix[6] = 0.0; + matrix[7] = 0.0; + matrix[8] = 0.0; + matrix[9] = 0.0; + matrix[10] = 1.0; + matrix[11] = 0.0; + matrix[12] = 0.0; + matrix[13] = 0.0; + matrix[14] = 0.0; + matrix[15] = 1.0; +} + +/* matrix2 = transpose(matrix1) */ +static void +matrixTranspose(GLfloat matrix2[16], GLfloat matrix1[16]) +{ + matrix2[0] = matrix1[0]; + matrix2[1] = matrix1[4]; + matrix2[2] = matrix1[8]; + matrix2[3] = matrix1[12]; + + matrix2[4] = matrix1[1]; + matrix2[5] = matrix1[5]; + matrix2[6] = matrix1[9]; + matrix2[7] = matrix1[13]; + + matrix2[8] = matrix1[2]; + matrix2[9] = matrix1[6]; + matrix2[10] = matrix1[10]; + matrix2[11] = matrix1[14]; + + matrix2[12] = matrix1[3]; + matrix2[13] = matrix1[7]; + matrix2[14] = matrix1[14]; + matrix2[15] = matrix1[15]; +} + +/*****************************************************************/ + +/* load SGI .rgb image (pad with a border of the specified width and color) */ +#if 0 +static void +imgLoad(char *filenameIn, int borderIn, GLfloat borderColorIn[4], + int *wOut, int *hOut, GLubyte ** imgOut) +{ + int border = borderIn; + int width, height; + int w, h; + GLubyte *image, *img, *p; + int i, j, components; + + image = (GLubyte *) read_texture(filenameIn, &width, &height, &components); + w = width + 2 * border; + h = height + 2 * border; + img = (GLubyte *) calloc(w * h, 4 * sizeof(unsigned char)); + + p = img; + for (j = -border; j < height + border; ++j) { + for (i = -border; i < width + border; ++i) { + if (0 <= j && j <= height - 1 && 0 <= i && i <= width - 1) { + p[0] = image[4 * (j * width + i) + 0]; + p[1] = image[4 * (j * width + i) + 1]; + p[2] = image[4 * (j * width + i) + 2]; + p[3] = 0xff; + } else { + p[0] = borderColorIn[0] * 0xff; + p[1] = borderColorIn[1] * 0xff; + p[2] = borderColorIn[2] * 0xff; + p[3] = borderColorIn[3] * 0xff; + } + p += 4; + } + } + free(image); + *wOut = w; + *hOut = h; + *imgOut = img; +} +#endif + + +/*****************************************************************/ + +/* Load the image file specified on the command line as the current texture */ +static void +loadImageTextures(void) +{ + GLfloat borderColor[4] = + {1.0, 1.0, 1.0, 1.0}; + int tex; + + for (tex = 0; tex < NumTextures; tex++) { + GLubyte *image, *texData3, *texData4; + GLint imgWidth, imgHeight; + GLenum imgFormat; + int i, j; + + printf("loading %s\n", texFilename[tex]); + image = LoadRGBImage(texFilename[tex], &imgWidth, &imgHeight, &imgFormat); + if (!image) { + printf("can't find %s\n", texFilename[tex]); + exit(1); + } + assert(imgFormat == GL_RGB); + + /* scale to 256x256 */ + texData3 = malloc(256 * 256 * 4); + texData4 = malloc(256 * 256 * 4); + assert(texData3); + assert(texData4); + gluScaleImage(imgFormat, imgWidth, imgHeight, GL_UNSIGNED_BYTE, image, + 256, 256, GL_UNSIGNED_BYTE, texData3); + + /* convert to rgba */ + for (i = 0; i < 256 * 256; i++) { + texData4[i*4+0] = texData3[i*3+0]; + texData4[i*4+1] = texData3[i*3+1]; + texData4[i*4+2] = texData3[i*3+2]; + texData4[i*4+3] = 128; + } + + /* put transparent border around image */ + for (i = 0; i < 256; i++) { + texData4[i*4+0] = 255; + texData4[i*4+1] = 255; + texData4[i*4+2] = 255; + texData4[i*4+3] = 0; + } + j = 256 * 255 * 4; + for (i = 0; i < 256; i++) { + texData4[j + i*4+0] = 255; + texData4[j + i*4+1] = 255; + texData4[j + i*4+2] = 255; + texData4[j + i*4+3] = 0; + } + for (i = 0; i < 256; i++) { + j = i * 256 * 4; + texData4[j+0] = 255; + texData4[j+1] = 255; + texData4[j+2] = 255; + texData4[j+3] = 0; + } + for (i = 0; i < 256; i++) { + j = i * 256 * 4 + 255 * 4; + texData4[j+0] = 255; + texData4[j+1] = 255; + texData4[j+2] = 255; + texData4[j+3] = 0; + } + + ActiveTexture(GL_TEXTURE0_ARB + tex); + glBindTexture(GL_TEXTURE_2D, tex + 1); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texData4); + + if (linearFilter) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + } +} + +/* Create a simple spotlight pattern and make it the current texture */ +static void +loadSpotlightTexture(void) +{ + static int texWidth = 64, texHeight = 64; + static GLubyte *texData; + GLfloat borderColor[4] = + {0.1, 0.1, 0.1, 1.0}; + + if (!texData) { + GLubyte *p; + int i, j; + + texData = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte)); + + p = texData; + for (j = 0; j < texHeight; ++j) { + float dy = (texHeight * 0.5 - j + 0.5) / (texHeight * 0.5); + + for (i = 0; i < texWidth; ++i) { + float dx = (texWidth * 0.5 - i + 0.5) / (texWidth * 0.5); + float r = cos(M_PI / 2.0 * sqrt(dx * dx + dy * dy)); + float c; + + r = (r < 0) ? 0 : r * r; + c = 0xff * (r + borderColor[0]); + p[0] = (c <= 0xff) ? c : 0xff; + c = 0xff * (r + borderColor[1]); + p[1] = (c <= 0xff) ? c : 0xff; + c = 0xff * (r + borderColor[2]); + p[2] = (c <= 0xff) ? c : 0xff; + c = 0xff * (r + borderColor[3]); + p[3] = (c <= 0xff) ? c : 0xff; + p += 4; + } + } + } + if (linearFilter) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight, + GL_RGBA, GL_UNSIGNED_BYTE, texData); +} + +/*****************************************************************/ + +static void +checkErrors(void) +{ + GLenum error; + while ((error = glGetError()) != GL_NO_ERROR) { + fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error)); + } +} + +static void +drawCube(void) +{ + glBegin(GL_QUADS); + + glNormal3f(-1.0, 0.0, 0.0); + glColor3f(0.80, 0.50, 0.50); + glVertex3f(-0.5, -0.5, -0.5); + glVertex3f(-0.5, -0.5, 0.5); + glVertex3f(-0.5, 0.5, 0.5); + glVertex3f(-0.5, 0.5, -0.5); + + glNormal3f(1.0, 0.0, 0.0); + glColor3f(0.50, 0.80, 0.50); + glVertex3f(0.5, 0.5, 0.5); + glVertex3f(0.5, -0.5, 0.5); + glVertex3f(0.5, -0.5, -0.5); + glVertex3f(0.5, 0.5, -0.5); + + glNormal3f(0.0, -1.0, 0.0); + glColor3f(0.50, 0.50, 0.80); + glVertex3f(-0.5, -0.5, -0.5); + glVertex3f(0.5, -0.5, -0.5); + glVertex3f(0.5, -0.5, 0.5); + glVertex3f(-0.5, -0.5, 0.5); + + glNormal3f(0.0, 1.0, 0.0); + glColor3f(0.50, 0.80, 0.80); + glVertex3f(0.5, 0.5, 0.5); + glVertex3f(0.5, 0.5, -0.5); + glVertex3f(-0.5, 0.5, -0.5); + glVertex3f(-0.5, 0.5, 0.5); + + glNormal3f(0.0, 0.0, -1.0); + glColor3f(0.80, 0.50, 0.80); + glVertex3f(-0.5, -0.5, -0.5); + glVertex3f(-0.5, 0.5, -0.5); + glVertex3f(0.5, 0.5, -0.5); + glVertex3f(0.5, -0.5, -0.5); + + glNormal3f(0.0, 0.0, 1.0); + glColor3f(1.00, 0.80, 0.50); + glVertex3f(0.5, 0.5, 0.5); + glVertex3f(-0.5, 0.5, 0.5); + glVertex3f(-0.5, -0.5, 0.5); + glVertex3f(0.5, -0.5, 0.5); + glEnd(); +} + +static void +drawDodecahedron(void) +{ +#define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */ +#define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */ +#define C (0.5 * 1.0) + GLfloat vertexes[20][3] = + { + {-A, 0.0, B}, + {-A, 0.0, -B}, + {A, 0.0, -B}, + {A, 0.0, B}, + {B, -A, 0.0}, + {-B, -A, 0.0}, + {-B, A, 0.0}, + {B, A, 0.0}, + {0.0, B, -A}, + {0.0, -B, -A}, + {0.0, -B, A}, + {0.0, B, A}, + {-C, -C, C}, + {-C, -C, -C}, + {C, -C, -C}, + {C, -C, C}, + {-C, C, C}, + {-C, C, -C}, + {C, C, -C}, + {C, C, C}, + }; +#undef A +#undef B +#undef C + GLint polygons[12][5] = + { + {0, 12, 10, 11, 16}, + {1, 17, 8, 9, 13}, + {2, 14, 9, 8, 18}, + {3, 19, 11, 10, 15}, + {4, 14, 2, 3, 15}, + {5, 12, 0, 1, 13}, + {6, 17, 1, 0, 16}, + {7, 19, 3, 2, 18}, + {8, 17, 6, 7, 18}, + {9, 14, 4, 5, 13}, + {10, 12, 5, 4, 15}, + {11, 19, 7, 6, 16}, + }; + int i; + + glColor3f(0.75, 0.75, 0.75); + for (i = 0; i < 12; ++i) { + GLfloat *p0, *p1, *p2, d; + GLfloat u[3], v[3], n[3]; + + p0 = &vertexes[polygons[i][0]][0]; + p1 = &vertexes[polygons[i][1]][0]; + p2 = &vertexes[polygons[i][2]][0]; + + u[0] = p2[0] - p1[0]; + u[1] = p2[1] - p1[1]; + u[2] = p2[2] - p1[2]; + + v[0] = p0[0] - p1[0]; + v[1] = p0[1] - p1[1]; + v[2] = p0[2] - p1[2]; + + n[0] = u[1] * v[2] - u[2] * v[1]; + n[1] = u[2] * v[0] - u[0] * v[2]; + n[2] = u[0] * v[1] - u[1] * v[0]; + + d = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); + n[0] *= d; + n[1] *= d; + n[2] *= d; + + glBegin(GL_POLYGON); + glNormal3fv(n); + glVertex3fv(p0); + glVertex3fv(p1); + glVertex3fv(p2); + glVertex3fv(vertexes[polygons[i][3]]); + glVertex3fv(vertexes[polygons[i][4]]); + glEnd(); + } +} + +static void +drawSphere(void) +{ + int numMajor = 24; + int numMinor = 32; + float radius = 0.8; + double majorStep = (M_PI / numMajor); + double minorStep = (2.0 * M_PI / numMinor); + int i, j; + + glColor3f(0.50, 0.50, 0.50); + for (i = 0; i < numMajor; ++i) { + double a = i * majorStep; + double b = a + majorStep; + double r0 = radius * sin(a); + double r1 = radius * sin(b); + GLfloat z0 = radius * cos(a); + GLfloat z1 = radius * cos(b); + + glBegin(GL_TRIANGLE_STRIP); + for (j = 0; j <= numMinor; ++j) { + double c = j * minorStep; + GLfloat x = cos(c); + GLfloat y = sin(c); + + glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius); + glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor); + glVertex3f(x * r0, y * r0, z0); + + glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius); + glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor); + glVertex3f(x * r1, y * r1, z1); + } + glEnd(); + } +} + +/*****************************************************************/ + +float xmin = -0.035, xmax = 0.035; +float ymin = -0.035, ymax = 0.035; +float nnear = 0.1; +float ffar = 1.9; +float distance = -1.0; + +static void +loadTextureProjection(int texUnit, GLfloat m[16]) +{ + GLfloat mInverse[4][4]; + + /* Should use true inverse, but since m consists only of rotations, we can + just use the transpose. */ + matrixTranspose((GLfloat *) mInverse, m); + + ActiveTexture(GL_TEXTURE0_ARB + texUnit); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glTranslatef(0.5, 0.5, 0.0); + glScalef(0.5, 0.5, 1.0); + glFrustum(xmin, xmax, ymin, ymax, nnear, ffar); + glTranslatef(0.0, 0.0, distance); + glMultMatrixf((GLfloat *) mInverse); + glMatrixMode(GL_MODELVIEW); +} + +static void +drawTextureProjection(void) +{ + float t = ffar / nnear; + GLfloat n[4][3]; + GLfloat f[4][3]; + + n[0][0] = xmin; + n[0][1] = ymin; + n[0][2] = -(nnear + distance); + + n[1][0] = xmax; + n[1][1] = ymin; + n[1][2] = -(nnear + distance); + + n[2][0] = xmax; + n[2][1] = ymax; + n[2][2] = -(nnear + distance); + + n[3][0] = xmin; + n[3][1] = ymax; + n[3][2] = -(nnear + distance); + + f[0][0] = xmin * t; + f[0][1] = ymin * t; + f[0][2] = -(ffar + distance); + + f[1][0] = xmax * t; + f[1][1] = ymin * t; + f[1][2] = -(ffar + distance); + + f[2][0] = xmax * t; + f[2][1] = ymax * t; + f[2][2] = -(ffar + distance); + + f[3][0] = xmin * t; + f[3][1] = ymax * t; + f[3][2] = -(ffar + distance); + + glColor3f(1.0, 1.0, 0.0); + glBegin(GL_LINE_LOOP); + glVertex3fv(n[0]); + glVertex3fv(n[1]); + glVertex3fv(n[2]); + glVertex3fv(n[3]); + glVertex3fv(f[3]); + glVertex3fv(f[2]); + glVertex3fv(f[1]); + glVertex3fv(f[0]); + glVertex3fv(n[0]); + glVertex3fv(n[1]); + glVertex3fv(f[1]); + glVertex3fv(f[0]); + glVertex3fv(f[3]); + glVertex3fv(f[2]); + glVertex3fv(n[2]); + glVertex3fv(n[3]); + glEnd(); +} + +/*****************************************************************/ + +static void +initialize(void) +{ + GLfloat light0Pos[4] = + {0.3, 0.3, 0.0, 1.0}; + GLfloat matAmb[4] = + {0.01, 0.01, 0.01, 1.00}; + GLfloat matDiff[4] = + {0.65, 0.65, 0.65, 1.00}; + GLfloat matSpec[4] = + {0.30, 0.30, 0.30, 1.00}; + GLfloat matShine = 10.0; + GLfloat eyePlaneS[] = + {1.0, 0.0, 0.0, 0.0}; + GLfloat eyePlaneT[] = + {0.0, 1.0, 0.0, 0.0}; + GLfloat eyePlaneR[] = + {0.0, 0.0, 1.0, 0.0}; + GLfloat eyePlaneQ[] = + {0.0, 0.0, 0.0, 1.0}; + int i; + + /* Setup Misc. */ + glClearColor(0.41, 0.41, 0.31, 0.0); + + glEnable(GL_DEPTH_TEST); + + /* glLineWidth(2.0);*/ + + glCullFace(GL_FRONT); + glEnable(GL_CULL_FACE); + + glMatrixMode(GL_PROJECTION); + glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3); + glMatrixMode(GL_MODELVIEW); + glTranslatef(0, 0, -2); + + matrixIdentity((GLfloat *) objectXform); + for (i = 0; i < NumTextures; i++) { + matrixIdentity((GLfloat *) textureXform[i]); + } + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, 1, 0, 1, -1, 1); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glRasterPos2i(0, 0); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + /* Setup Lighting */ + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine); + + glEnable(GL_COLOR_MATERIAL); + + glLightfv(GL_LIGHT0, GL_POSITION, light0Pos); + glEnable(GL_LIGHT0); + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glEnable(GL_LIGHTING); + + /* Setup Texture */ + + (*loadTexture) (); + + + for (i = 0; i < NumTextures; i++) { + ActiveTexture(GL_TEXTURE0_ARB + i); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS); + + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT); + + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR); + + glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ); + } +} + +static void +display(void) +{ + int i; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (textureEnabled) { + if (mode == MoveTexture || mode == MoveView) { + /* Have OpenGL compute the new transformation (simple but slow). */ + for (i = 0; i < NumTextures; i++) { + glPushMatrix(); + glLoadIdentity(); +#if 0 + if (i & 1) + glRotatef(angle, axis[0], axis[1], axis[2]); + else +#endif + glRotatef(angle*(i+1), axis[0], axis[1], axis[2]); + + glMultMatrixf((GLfloat *) textureXform[i]); + glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) textureXform[i]); + glPopMatrix(); + } + } + for (i = 0; i < NumTextures; i++) { + loadTextureProjection(i, (GLfloat *) textureXform[i]); + } + + if (showProjection) { + for (i = 0; i < NumTextures; i++) { + ActiveTexture(GL_TEXTURE0_ARB + i); + glPushMatrix(); + glMultMatrixf((GLfloat *) textureXform[i]); + glDisable(GL_LIGHTING); + drawTextureProjection(); + glEnable(GL_LIGHTING); + glPopMatrix(); + } + } + for (i = 0; i < NumTextures; i++) { + ActiveTexture(GL_TEXTURE0_ARB + i); + glEnable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_Q); + } + } + if (mode == MoveObject || mode == MoveView) { + /* Have OpenGL compute the new transformation (simple but slow). */ + glPushMatrix(); + glLoadIdentity(); + glRotatef(angle, axis[0], axis[1], axis[2]); + glMultMatrixf((GLfloat *) objectXform); + glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform); + glPopMatrix(); + } + glPushMatrix(); + glMultMatrixf((GLfloat *) objectXform); + (*drawObject) (); + glPopMatrix(); + + for (i = 0; i < NumTextures; i++) { + ActiveTexture(GL_TEXTURE0_ARB + i); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_Q); + } + + if (zoomFactor > 1.0) { + glDisable(GL_DEPTH_TEST); + glCopyPixels(0, 0, winWidth / zoomFactor, winHeight / zoomFactor, GL_COLOR); + glEnable(GL_DEPTH_TEST); + } + glFlush(); + glutSwapBuffers(); + checkErrors(); +} + +/*****************************************************************/ + +/* simple trackball-like motion control */ +static float lastPos[3]; +static int lastTime; + +static void +ptov(int x, int y, int width, int height, float v[3]) +{ + float d, a; + + /* project x,y onto a hemi-sphere centered within width, height */ + v[0] = (2.0 * x - width) / width; + v[1] = (height - 2.0 * y) / height; + d = sqrt(v[0] * v[0] + v[1] * v[1]); + v[2] = cos((M_PI / 2.0) * ((d < 1.0) ? d : 1.0)); + a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + v[0] *= a; + v[1] *= a; + v[2] *= a; +} + +static void +startMotion(int x, int y, int but, int time) +{ + if (but == GLUT_LEFT_BUTTON) { + mode = MoveView; + } else if (but == GLUT_MIDDLE_BUTTON) { + mode = MoveTexture; + } else { + return; + } + + lastTime = time; + ptov(x, y, winWidth, winHeight, lastPos); +} + +static void +animate(void) +{ + glutPostRedisplay(); +} + +static void +vis(int visible) +{ + if (visible == GLUT_VISIBLE) { + if (redrawContinuously) + glutIdleFunc(animate); + } else { + if (redrawContinuously) + glutIdleFunc(NULL); + } +} + +static void +stopMotion(int but, int time) +{ + if ((but == GLUT_LEFT_BUTTON && mode == MoveView) || + (but == GLUT_MIDDLE_BUTTON && mode == MoveTexture)) { + } else { + return; + } + + if (time == lastTime) { + /* redrawContinuously = GL_TRUE;*/ + glutIdleFunc(animate); + } else { + angle = 0.0; + redrawContinuously = GL_FALSE; + glutIdleFunc(0); + } + if (!redrawContinuously) { + mode = MoveNone; + } +} + +static void +trackMotion(int x, int y) +{ + float curPos[3], dx, dy, dz; + + ptov(x, y, winWidth, winHeight, curPos); + + dx = curPos[0] - lastPos[0]; + dy = curPos[1] - lastPos[1]; + dz = curPos[2] - lastPos[2]; + angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz); + + axis[0] = lastPos[1] * curPos[2] - lastPos[2] * curPos[1]; + axis[1] = lastPos[2] * curPos[0] - lastPos[0] * curPos[2]; + axis[2] = lastPos[0] * curPos[1] - lastPos[1] * curPos[0]; + + lastTime = glutGet(GLUT_ELAPSED_TIME); + lastPos[0] = curPos[0]; + lastPos[1] = curPos[1]; + lastPos[2] = curPos[2]; + glutPostRedisplay(); +} + +/*****************************************************************/ + +static void +object(void) +{ + static int object; + + object++; + object %= 3; + switch (object) { + case 0: + drawObject = drawCube; + break; + case 1: + drawObject = drawDodecahedron; + break; + case 2: + drawObject = drawSphere; + break; + default: + break; + } +} + +static void +nop(void) +{ +} + +static void +texture(void) +{ + static int texture = 0; + + texture++; + texture %= 3; + if (texture == 1 && texFilename == NULL) { + /* Skip file texture if not loaded. */ + texture++; + } + switch (texture) { + case 0: + loadTexture = nop; + textureEnabled = GL_FALSE; + break; + case 1: + loadTexture = loadImageTextures; + (*loadTexture) (); + textureEnabled = GL_TRUE; + break; + case 2: + loadTexture = loadSpotlightTexture; + (*loadTexture) (); + textureEnabled = GL_TRUE; + break; + default: + break; + } +} + +static void +help(void) +{ + printf("'h' - help\n"); + printf("'l' - toggle linear/nearest filter\n"); + printf("'s' - toggle projection frustum\n"); + printf("'t' - toggle projected texture\n"); + printf("'o' - toggle object\n"); + printf("'z' - increase zoom factor\n"); + printf("'Z' - decrease zoom factor\n"); + printf("left mouse - move view\n"); + printf("middle mouse - move projection\n"); +} + +/* ARGSUSED1 */ +static void +key(unsigned char key, int x, int y) +{ + switch (key) { + case '\033': + exit(0); + break; + case 'l': + linearFilter = !linearFilter; + (*loadTexture) (); + break; + case 's': + showProjection = !showProjection; + break; + case 't': + texture(); + break; + case 'o': + object(); + break; + case 'z': + zoomFactor += 1.0; + glPixelZoom(zoomFactor, zoomFactor); + glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor); + break; + case 'Z': + zoomFactor -= 1.0; + if (zoomFactor < 1.0) + zoomFactor = 1.0; + glPixelZoom(zoomFactor, zoomFactor); + glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor); + break; + case 'h': + help(); + break; + } + glutPostRedisplay(); +} + +static void +mouse(int button, int state, int x, int y) +{ + if (state == GLUT_DOWN) + startMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME)); + else if (state == GLUT_UP) + stopMotion(button, glutGet(GLUT_ELAPSED_TIME)); + glutPostRedisplay(); +} + +static void +reshape(int w, int h) +{ + winWidth = w; + winHeight = h; + glViewport(0, 0, w / zoomFactor, h / zoomFactor); +} + + +static void +menu(int selection) +{ + if (selection == 666) { + exit(0); + } + key((unsigned char) selection, 0, 0); +} + +int +main(int argc, char **argv) +{ + glutInit(&argc, argv); + + if (argc > 1) { + NumTextures = atoi(argv[1]); + } + assert(NumTextures <= MAX_TEX); + + glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); + glutInitWindowSize(500,500); + (void) glutCreateWindow("projtex"); + glewInit(); + + loadTexture = loadImageTextures; + drawObject = drawCube; + initialize(); + glutDisplayFunc(display); + glutKeyboardFunc(key); + glutReshapeFunc(reshape); + glutMouseFunc(mouse); + glutMotionFunc(trackMotion); + glutVisibilityFunc(vis); + glutCreateMenu(menu); + glutAddMenuEntry("Toggle showing projection", 's'); + glutAddMenuEntry("Switch texture", 't'); + glutAddMenuEntry("Switch object", 'o'); + glutAddMenuEntry("Toggle filtering", 'l'); + glutAddMenuEntry("Quit", 666); + glutAttachMenu(GLUT_RIGHT_BUTTON); + texture(); + glutMainLoop(); + return 0; /* ANSI C requires main to return int. */ +} diff --git a/progs/tests/Makefile b/progs/tests/Makefile index 7dfc65807a3..24275fdc2f1 100644 --- a/progs/tests/Makefile +++ b/progs/tests/Makefile @@ -66,7 +66,6 @@ SOURCES = \ packedpixels.c \ pbo.c \ prog_parameter.c \ - projtex.c \ quads.c \ random.c \ readrate.c \ diff --git a/progs/tests/projtex.c b/progs/tests/projtex.c deleted file mode 100644 index 800d81ecd67..00000000000 --- a/progs/tests/projtex.c +++ /dev/null @@ -1,1030 +0,0 @@ - -/* projtex.c - by David Yu and David Blythe, SGI */ - -/** - ** Demonstrates simple projective texture mapping. - ** - ** Button1 changes view, Button2 moves texture. - ** - ** (See: Segal, Korobkin, van Widenfelt, Foran, and Haeberli - ** "Fast Shadows and Lighting Effects Using Texture Mapping", SIGGRAPH '92) - ** - ** 1994,1995 -- David G Yu - ** - ** cc -o projtex projtex.c texture.c -lglut -lGLU -lGL -lX11 -lm - **/ - -#include -#include -#include -#include -#include -#include -#if 0 -#include "texture.h" -#else -#include "../util/readtex.c" -#endif - - -/* Some files do not define M_PI... */ -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define MAX_TEX 4 -int NumTextures = 1; - -int winWidth, winHeight; - -GLboolean redrawContinuously = GL_FALSE; - -float angle, axis[3]; -enum MoveModes { - MoveNone, MoveView, MoveObject, MoveTexture -}; -enum MoveModes mode = MoveNone; - -GLfloat objectXform[4][4]; -GLfloat textureXform[MAX_TEX][4][4]; - -void (*drawObject) (void); -void (*loadTexture) (void); -GLboolean textureEnabled = GL_TRUE; -GLboolean showProjection = GL_TRUE; -GLboolean linearFilter = GL_TRUE; - -char *texFilename[MAX_TEX] = { - "../images/girl.rgb", - "../images/tile.rgb", - "../images/bw.rgb", - "../images/reflect.rgb" -}; - - -GLfloat zoomFactor = 1.0; - -/*****************************************************************/ - - -void ActiveTexture(int i) -{ - glActiveTextureARB(i); -} - - -/* matrix = identity */ -void -matrixIdentity(GLfloat matrix[16]) -{ - matrix[0] = 1.0; - matrix[1] = 0.0; - matrix[2] = 0.0; - matrix[3] = 0.0; - matrix[4] = 0.0; - matrix[5] = 1.0; - matrix[6] = 0.0; - matrix[7] = 0.0; - matrix[8] = 0.0; - matrix[9] = 0.0; - matrix[10] = 1.0; - matrix[11] = 0.0; - matrix[12] = 0.0; - matrix[13] = 0.0; - matrix[14] = 0.0; - matrix[15] = 1.0; -} - -/* matrix2 = transpose(matrix1) */ -void -matrixTranspose(GLfloat matrix2[16], GLfloat matrix1[16]) -{ - matrix2[0] = matrix1[0]; - matrix2[1] = matrix1[4]; - matrix2[2] = matrix1[8]; - matrix2[3] = matrix1[12]; - - matrix2[4] = matrix1[1]; - matrix2[5] = matrix1[5]; - matrix2[6] = matrix1[9]; - matrix2[7] = matrix1[13]; - - matrix2[8] = matrix1[2]; - matrix2[9] = matrix1[6]; - matrix2[10] = matrix1[10]; - matrix2[11] = matrix1[14]; - - matrix2[12] = matrix1[3]; - matrix2[13] = matrix1[7]; - matrix2[14] = matrix1[14]; - matrix2[15] = matrix1[15]; -} - -/*****************************************************************/ - -/* load SGI .rgb image (pad with a border of the specified width and color) */ -#if 0 -static void -imgLoad(char *filenameIn, int borderIn, GLfloat borderColorIn[4], - int *wOut, int *hOut, GLubyte ** imgOut) -{ - int border = borderIn; - int width, height; - int w, h; - GLubyte *image, *img, *p; - int i, j, components; - - image = (GLubyte *) read_texture(filenameIn, &width, &height, &components); - w = width + 2 * border; - h = height + 2 * border; - img = (GLubyte *) calloc(w * h, 4 * sizeof(unsigned char)); - - p = img; - for (j = -border; j < height + border; ++j) { - for (i = -border; i < width + border; ++i) { - if (0 <= j && j <= height - 1 && 0 <= i && i <= width - 1) { - p[0] = image[4 * (j * width + i) + 0]; - p[1] = image[4 * (j * width + i) + 1]; - p[2] = image[4 * (j * width + i) + 2]; - p[3] = 0xff; - } else { - p[0] = borderColorIn[0] * 0xff; - p[1] = borderColorIn[1] * 0xff; - p[2] = borderColorIn[2] * 0xff; - p[3] = borderColorIn[3] * 0xff; - } - p += 4; - } - } - free(image); - *wOut = w; - *hOut = h; - *imgOut = img; -} -#endif - - -/*****************************************************************/ - -/* Load the image file specified on the command line as the current texture */ -void -loadImageTextures(void) -{ - GLfloat borderColor[4] = - {1.0, 1.0, 1.0, 1.0}; - int tex; - - for (tex = 0; tex < NumTextures; tex++) { - GLubyte *image, *texData3, *texData4; - GLint imgWidth, imgHeight; - GLenum imgFormat; - int i, j; - - printf("loading %s\n", texFilename[tex]); - image = LoadRGBImage(texFilename[tex], &imgWidth, &imgHeight, &imgFormat); - if (!image) { - printf("can't find %s\n", texFilename[tex]); - exit(1); - } - assert(imgFormat == GL_RGB); - - /* scale to 256x256 */ - texData3 = malloc(256 * 256 * 4); - texData4 = malloc(256 * 256 * 4); - assert(texData3); - assert(texData4); - gluScaleImage(imgFormat, imgWidth, imgHeight, GL_UNSIGNED_BYTE, image, - 256, 256, GL_UNSIGNED_BYTE, texData3); - - /* convert to rgba */ - for (i = 0; i < 256 * 256; i++) { - texData4[i*4+0] = texData3[i*3+0]; - texData4[i*4+1] = texData3[i*3+1]; - texData4[i*4+2] = texData3[i*3+2]; - texData4[i*4+3] = 128; - } - - /* put transparent border around image */ - for (i = 0; i < 256; i++) { - texData4[i*4+0] = 255; - texData4[i*4+1] = 255; - texData4[i*4+2] = 255; - texData4[i*4+3] = 0; - } - j = 256 * 255 * 4; - for (i = 0; i < 256; i++) { - texData4[j + i*4+0] = 255; - texData4[j + i*4+1] = 255; - texData4[j + i*4+2] = 255; - texData4[j + i*4+3] = 0; - } - for (i = 0; i < 256; i++) { - j = i * 256 * 4; - texData4[j+0] = 255; - texData4[j+1] = 255; - texData4[j+2] = 255; - texData4[j+3] = 0; - } - for (i = 0; i < 256; i++) { - j = i * 256 * 4 + 255 * 4; - texData4[j+0] = 255; - texData4[j+1] = 255; - texData4[j+2] = 255; - texData4[j+3] = 0; - } - - ActiveTexture(GL_TEXTURE0_ARB + tex); - glBindTexture(GL_TEXTURE_2D, tex + 1); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, - GL_RGBA, GL_UNSIGNED_BYTE, texData4); - - if (linearFilter) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - } -} - -/* Create a simple spotlight pattern and make it the current texture */ -void -loadSpotlightTexture(void) -{ - static int texWidth = 64, texHeight = 64; - static GLubyte *texData; - GLfloat borderColor[4] = - {0.1, 0.1, 0.1, 1.0}; - - if (!texData) { - GLubyte *p; - int i, j; - - texData = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte)); - - p = texData; - for (j = 0; j < texHeight; ++j) { - float dy = (texHeight * 0.5 - j + 0.5) / (texHeight * 0.5); - - for (i = 0; i < texWidth; ++i) { - float dx = (texWidth * 0.5 - i + 0.5) / (texWidth * 0.5); - float r = cos(M_PI / 2.0 * sqrt(dx * dx + dy * dy)); - float c; - - r = (r < 0) ? 0 : r * r; - c = 0xff * (r + borderColor[0]); - p[0] = (c <= 0xff) ? c : 0xff; - c = 0xff * (r + borderColor[1]); - p[1] = (c <= 0xff) ? c : 0xff; - c = 0xff * (r + borderColor[2]); - p[2] = (c <= 0xff) ? c : 0xff; - c = 0xff * (r + borderColor[3]); - p[3] = (c <= 0xff) ? c : 0xff; - p += 4; - } - } - } - if (linearFilter) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight, - GL_RGBA, GL_UNSIGNED_BYTE, texData); -} - -/*****************************************************************/ - -void -checkErrors(void) -{ - GLenum error; - while ((error = glGetError()) != GL_NO_ERROR) { - fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error)); - } -} - -void -drawCube(void) -{ - glBegin(GL_QUADS); - - glNormal3f(-1.0, 0.0, 0.0); - glColor3f(0.80, 0.50, 0.50); - glVertex3f(-0.5, -0.5, -0.5); - glVertex3f(-0.5, -0.5, 0.5); - glVertex3f(-0.5, 0.5, 0.5); - glVertex3f(-0.5, 0.5, -0.5); - - glNormal3f(1.0, 0.0, 0.0); - glColor3f(0.50, 0.80, 0.50); - glVertex3f(0.5, 0.5, 0.5); - glVertex3f(0.5, -0.5, 0.5); - glVertex3f(0.5, -0.5, -0.5); - glVertex3f(0.5, 0.5, -0.5); - - glNormal3f(0.0, -1.0, 0.0); - glColor3f(0.50, 0.50, 0.80); - glVertex3f(-0.5, -0.5, -0.5); - glVertex3f(0.5, -0.5, -0.5); - glVertex3f(0.5, -0.5, 0.5); - glVertex3f(-0.5, -0.5, 0.5); - - glNormal3f(0.0, 1.0, 0.0); - glColor3f(0.50, 0.80, 0.80); - glVertex3f(0.5, 0.5, 0.5); - glVertex3f(0.5, 0.5, -0.5); - glVertex3f(-0.5, 0.5, -0.5); - glVertex3f(-0.5, 0.5, 0.5); - - glNormal3f(0.0, 0.0, -1.0); - glColor3f(0.80, 0.50, 0.80); - glVertex3f(-0.5, -0.5, -0.5); - glVertex3f(-0.5, 0.5, -0.5); - glVertex3f(0.5, 0.5, -0.5); - glVertex3f(0.5, -0.5, -0.5); - - glNormal3f(0.0, 0.0, 1.0); - glColor3f(1.00, 0.80, 0.50); - glVertex3f(0.5, 0.5, 0.5); - glVertex3f(-0.5, 0.5, 0.5); - glVertex3f(-0.5, -0.5, 0.5); - glVertex3f(0.5, -0.5, 0.5); - glEnd(); -} - -void -drawDodecahedron(void) -{ -#define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */ -#define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */ -#define C (0.5 * 1.0) - GLfloat vertexes[20][3] = - { - {-A, 0.0, B}, - {-A, 0.0, -B}, - {A, 0.0, -B}, - {A, 0.0, B}, - {B, -A, 0.0}, - {-B, -A, 0.0}, - {-B, A, 0.0}, - {B, A, 0.0}, - {0.0, B, -A}, - {0.0, -B, -A}, - {0.0, -B, A}, - {0.0, B, A}, - {-C, -C, C}, - {-C, -C, -C}, - {C, -C, -C}, - {C, -C, C}, - {-C, C, C}, - {-C, C, -C}, - {C, C, -C}, - {C, C, C}, - }; -#undef A -#undef B -#undef C - GLint polygons[12][5] = - { - {0, 12, 10, 11, 16}, - {1, 17, 8, 9, 13}, - {2, 14, 9, 8, 18}, - {3, 19, 11, 10, 15}, - {4, 14, 2, 3, 15}, - {5, 12, 0, 1, 13}, - {6, 17, 1, 0, 16}, - {7, 19, 3, 2, 18}, - {8, 17, 6, 7, 18}, - {9, 14, 4, 5, 13}, - {10, 12, 5, 4, 15}, - {11, 19, 7, 6, 16}, - }; - int i; - - glColor3f(0.75, 0.75, 0.75); - for (i = 0; i < 12; ++i) { - GLfloat *p0, *p1, *p2, d; - GLfloat u[3], v[3], n[3]; - - p0 = &vertexes[polygons[i][0]][0]; - p1 = &vertexes[polygons[i][1]][0]; - p2 = &vertexes[polygons[i][2]][0]; - - u[0] = p2[0] - p1[0]; - u[1] = p2[1] - p1[1]; - u[2] = p2[2] - p1[2]; - - v[0] = p0[0] - p1[0]; - v[1] = p0[1] - p1[1]; - v[2] = p0[2] - p1[2]; - - n[0] = u[1] * v[2] - u[2] * v[1]; - n[1] = u[2] * v[0] - u[0] * v[2]; - n[2] = u[0] * v[1] - u[1] * v[0]; - - d = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); - n[0] *= d; - n[1] *= d; - n[2] *= d; - - glBegin(GL_POLYGON); - glNormal3fv(n); - glVertex3fv(p0); - glVertex3fv(p1); - glVertex3fv(p2); - glVertex3fv(vertexes[polygons[i][3]]); - glVertex3fv(vertexes[polygons[i][4]]); - glEnd(); - } -} - -void -drawSphere(void) -{ - int numMajor = 24; - int numMinor = 32; - float radius = 0.8; - double majorStep = (M_PI / numMajor); - double minorStep = (2.0 * M_PI / numMinor); - int i, j; - - glColor3f(0.50, 0.50, 0.50); - for (i = 0; i < numMajor; ++i) { - double a = i * majorStep; - double b = a + majorStep; - double r0 = radius * sin(a); - double r1 = radius * sin(b); - GLfloat z0 = radius * cos(a); - GLfloat z1 = radius * cos(b); - - glBegin(GL_TRIANGLE_STRIP); - for (j = 0; j <= numMinor; ++j) { - double c = j * minorStep; - GLfloat x = cos(c); - GLfloat y = sin(c); - - glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius); - glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor); - glVertex3f(x * r0, y * r0, z0); - - glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius); - glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor); - glVertex3f(x * r1, y * r1, z1); - } - glEnd(); - } -} - -/*****************************************************************/ - -float xmin = -0.035, xmax = 0.035; -float ymin = -0.035, ymax = 0.035; -float nnear = 0.1; -float ffar = 1.9; -float distance = -1.0; - -static void -loadTextureProjection(int texUnit, GLfloat m[16]) -{ - GLfloat mInverse[4][4]; - - /* Should use true inverse, but since m consists only of rotations, we can - just use the transpose. */ - matrixTranspose((GLfloat *) mInverse, m); - - ActiveTexture(GL_TEXTURE0_ARB + texUnit); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glTranslatef(0.5, 0.5, 0.0); - glScalef(0.5, 0.5, 1.0); - glFrustum(xmin, xmax, ymin, ymax, nnear, ffar); - glTranslatef(0.0, 0.0, distance); - glMultMatrixf((GLfloat *) mInverse); - glMatrixMode(GL_MODELVIEW); -} - -static void -drawTextureProjection(void) -{ - float t = ffar / nnear; - GLfloat n[4][3]; - GLfloat f[4][3]; - - n[0][0] = xmin; - n[0][1] = ymin; - n[0][2] = -(nnear + distance); - - n[1][0] = xmax; - n[1][1] = ymin; - n[1][2] = -(nnear + distance); - - n[2][0] = xmax; - n[2][1] = ymax; - n[2][2] = -(nnear + distance); - - n[3][0] = xmin; - n[3][1] = ymax; - n[3][2] = -(nnear + distance); - - f[0][0] = xmin * t; - f[0][1] = ymin * t; - f[0][2] = -(ffar + distance); - - f[1][0] = xmax * t; - f[1][1] = ymin * t; - f[1][2] = -(ffar + distance); - - f[2][0] = xmax * t; - f[2][1] = ymax * t; - f[2][2] = -(ffar + distance); - - f[3][0] = xmin * t; - f[3][1] = ymax * t; - f[3][2] = -(ffar + distance); - - glColor3f(1.0, 1.0, 0.0); - glBegin(GL_LINE_LOOP); - glVertex3fv(n[0]); - glVertex3fv(n[1]); - glVertex3fv(n[2]); - glVertex3fv(n[3]); - glVertex3fv(f[3]); - glVertex3fv(f[2]); - glVertex3fv(f[1]); - glVertex3fv(f[0]); - glVertex3fv(n[0]); - glVertex3fv(n[1]); - glVertex3fv(f[1]); - glVertex3fv(f[0]); - glVertex3fv(f[3]); - glVertex3fv(f[2]); - glVertex3fv(n[2]); - glVertex3fv(n[3]); - glEnd(); -} - -/*****************************************************************/ - -void -initialize(void) -{ - GLfloat light0Pos[4] = - {0.3, 0.3, 0.0, 1.0}; - GLfloat matAmb[4] = - {0.01, 0.01, 0.01, 1.00}; - GLfloat matDiff[4] = - {0.65, 0.65, 0.65, 1.00}; - GLfloat matSpec[4] = - {0.30, 0.30, 0.30, 1.00}; - GLfloat matShine = 10.0; - GLfloat eyePlaneS[] = - {1.0, 0.0, 0.0, 0.0}; - GLfloat eyePlaneT[] = - {0.0, 1.0, 0.0, 0.0}; - GLfloat eyePlaneR[] = - {0.0, 0.0, 1.0, 0.0}; - GLfloat eyePlaneQ[] = - {0.0, 0.0, 0.0, 1.0}; - int i; - - /* Setup Misc. */ - glClearColor(0.41, 0.41, 0.31, 0.0); - - glEnable(GL_DEPTH_TEST); - - /* glLineWidth(2.0);*/ - - glCullFace(GL_FRONT); - glEnable(GL_CULL_FACE); - - glMatrixMode(GL_PROJECTION); - glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3); - glMatrixMode(GL_MODELVIEW); - glTranslatef(0, 0, -2); - - matrixIdentity((GLfloat *) objectXform); - for (i = 0; i < NumTextures; i++) { - matrixIdentity((GLfloat *) textureXform[i]); - } - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, 1, 0, 1, -1, 1); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glRasterPos2i(0, 0); - - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - - /* Setup Lighting */ - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec); - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine); - - glEnable(GL_COLOR_MATERIAL); - - glLightfv(GL_LIGHT0, GL_POSITION, light0Pos); - glEnable(GL_LIGHT0); - - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - glEnable(GL_LIGHTING); - - /* Setup Texture */ - - (*loadTexture) (); - - - for (i = 0; i < NumTextures; i++) { - ActiveTexture(GL_TEXTURE0_ARB + i); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS); - - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT); - - glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR); - - glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ); - } -} - -void -display(void) -{ - int i; - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - if (textureEnabled) { - if (mode == MoveTexture || mode == MoveView) { - /* Have OpenGL compute the new transformation (simple but slow). */ - for (i = 0; i < NumTextures; i++) { - glPushMatrix(); - glLoadIdentity(); -#if 0 - if (i & 1) - glRotatef(angle, axis[0], axis[1], axis[2]); - else -#endif - glRotatef(angle*(i+1), axis[0], axis[1], axis[2]); - - glMultMatrixf((GLfloat *) textureXform[i]); - glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) textureXform[i]); - glPopMatrix(); - } - } - for (i = 0; i < NumTextures; i++) { - loadTextureProjection(i, (GLfloat *) textureXform[i]); - } - - if (showProjection) { - for (i = 0; i < NumTextures; i++) { - ActiveTexture(GL_TEXTURE0_ARB + i); - glPushMatrix(); - glMultMatrixf((GLfloat *) textureXform[i]); - glDisable(GL_LIGHTING); - drawTextureProjection(); - glEnable(GL_LIGHTING); - glPopMatrix(); - } - } - for (i = 0; i < NumTextures; i++) { - ActiveTexture(GL_TEXTURE0_ARB + i); - glEnable(GL_TEXTURE_2D); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glEnable(GL_TEXTURE_GEN_R); - glEnable(GL_TEXTURE_GEN_Q); - } - } - if (mode == MoveObject || mode == MoveView) { - /* Have OpenGL compute the new transformation (simple but slow). */ - glPushMatrix(); - glLoadIdentity(); - glRotatef(angle, axis[0], axis[1], axis[2]); - glMultMatrixf((GLfloat *) objectXform); - glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform); - glPopMatrix(); - } - glPushMatrix(); - glMultMatrixf((GLfloat *) objectXform); - (*drawObject) (); - glPopMatrix(); - - for (i = 0; i < NumTextures; i++) { - ActiveTexture(GL_TEXTURE0_ARB + i); - glDisable(GL_TEXTURE_2D); - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - glDisable(GL_TEXTURE_GEN_R); - glDisable(GL_TEXTURE_GEN_Q); - } - - if (zoomFactor > 1.0) { - glDisable(GL_DEPTH_TEST); - glCopyPixels(0, 0, winWidth / zoomFactor, winHeight / zoomFactor, GL_COLOR); - glEnable(GL_DEPTH_TEST); - } - glFlush(); - glutSwapBuffers(); - checkErrors(); -} - -/*****************************************************************/ - -/* simple trackball-like motion control */ -float lastPos[3]; -int lastTime; - -void -ptov(int x, int y, int width, int height, float v[3]) -{ - float d, a; - - /* project x,y onto a hemi-sphere centered within width, height */ - v[0] = (2.0 * x - width) / width; - v[1] = (height - 2.0 * y) / height; - d = sqrt(v[0] * v[0] + v[1] * v[1]); - v[2] = cos((M_PI / 2.0) * ((d < 1.0) ? d : 1.0)); - a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); - v[0] *= a; - v[1] *= a; - v[2] *= a; -} - -void -startMotion(int x, int y, int but, int time) -{ - if (but == GLUT_LEFT_BUTTON) { - mode = MoveView; - } else if (but == GLUT_MIDDLE_BUTTON) { - mode = MoveTexture; - } else { - return; - } - - lastTime = time; - ptov(x, y, winWidth, winHeight, lastPos); -} - -void -animate(void) -{ - glutPostRedisplay(); -} - -void -vis(int visible) -{ - if (visible == GLUT_VISIBLE) { - if (redrawContinuously) - glutIdleFunc(animate); - } else { - if (redrawContinuously) - glutIdleFunc(NULL); - } -} - -void -stopMotion(int but, int time) -{ - if ((but == GLUT_LEFT_BUTTON && mode == MoveView) || - (but == GLUT_MIDDLE_BUTTON && mode == MoveTexture)) { - } else { - return; - } - - if (time == lastTime) { - /* redrawContinuously = GL_TRUE;*/ - glutIdleFunc(animate); - } else { - angle = 0.0; - redrawContinuously = GL_FALSE; - glutIdleFunc(0); - } - if (!redrawContinuously) { - mode = MoveNone; - } -} - -void -trackMotion(int x, int y) -{ - float curPos[3], dx, dy, dz; - - ptov(x, y, winWidth, winHeight, curPos); - - dx = curPos[0] - lastPos[0]; - dy = curPos[1] - lastPos[1]; - dz = curPos[2] - lastPos[2]; - angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz); - - axis[0] = lastPos[1] * curPos[2] - lastPos[2] * curPos[1]; - axis[1] = lastPos[2] * curPos[0] - lastPos[0] * curPos[2]; - axis[2] = lastPos[0] * curPos[1] - lastPos[1] * curPos[0]; - - lastTime = glutGet(GLUT_ELAPSED_TIME); - lastPos[0] = curPos[0]; - lastPos[1] = curPos[1]; - lastPos[2] = curPos[2]; - glutPostRedisplay(); -} - -/*****************************************************************/ - -void -object(void) -{ - static int object; - - object++; - object %= 3; - switch (object) { - case 0: - drawObject = drawCube; - break; - case 1: - drawObject = drawDodecahedron; - break; - case 2: - drawObject = drawSphere; - break; - default: - break; - } -} - -static void -nop(void) -{ -} - -void -texture(void) -{ - static int texture = 0; - - texture++; - texture %= 3; - if (texture == 1 && texFilename == NULL) { - /* Skip file texture if not loaded. */ - texture++; - } - switch (texture) { - case 0: - loadTexture = nop; - textureEnabled = GL_FALSE; - break; - case 1: - loadTexture = loadImageTextures; - (*loadTexture) (); - textureEnabled = GL_TRUE; - break; - case 2: - loadTexture = loadSpotlightTexture; - (*loadTexture) (); - textureEnabled = GL_TRUE; - break; - default: - break; - } -} - -void -help(void) -{ - printf("'h' - help\n"); - printf("'l' - toggle linear/nearest filter\n"); - printf("'s' - toggle projection frustum\n"); - printf("'t' - toggle projected texture\n"); - printf("'o' - toggle object\n"); - printf("'z' - increase zoom factor\n"); - printf("'Z' - decrease zoom factor\n"); - printf("left mouse - move view\n"); - printf("middle mouse - move projection\n"); -} - -/* ARGSUSED1 */ -void -key(unsigned char key, int x, int y) -{ - switch (key) { - case '\033': - exit(0); - break; - case 'l': - linearFilter = !linearFilter; - (*loadTexture) (); - break; - case 's': - showProjection = !showProjection; - break; - case 't': - texture(); - break; - case 'o': - object(); - break; - case 'z': - zoomFactor += 1.0; - glPixelZoom(zoomFactor, zoomFactor); - glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor); - break; - case 'Z': - zoomFactor -= 1.0; - if (zoomFactor < 1.0) - zoomFactor = 1.0; - glPixelZoom(zoomFactor, zoomFactor); - glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor); - break; - case 'h': - help(); - break; - } - glutPostRedisplay(); -} - -void -mouse(int button, int state, int x, int y) -{ - if (state == GLUT_DOWN) - startMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME)); - else if (state == GLUT_UP) - stopMotion(button, glutGet(GLUT_ELAPSED_TIME)); - glutPostRedisplay(); -} - -void -reshape(int w, int h) -{ - winWidth = w; - winHeight = h; - glViewport(0, 0, w / zoomFactor, h / zoomFactor); -} - - -void -menu(int selection) -{ - if (selection == 666) { - exit(0); - } - key((unsigned char) selection, 0, 0); -} - -int -main(int argc, char **argv) -{ - glutInit(&argc, argv); - - if (argc > 1) { - NumTextures = atoi(argv[1]); - } - assert(NumTextures <= MAX_TEX); - - glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); - (void) glutCreateWindow("projtex"); - glewInit(); - - loadTexture = loadImageTextures; - drawObject = drawCube; - initialize(); - glutDisplayFunc(display); - glutKeyboardFunc(key); - glutReshapeFunc(reshape); - glutMouseFunc(mouse); - glutMotionFunc(trackMotion); - glutVisibilityFunc(vis); - glutCreateMenu(menu); - glutAddMenuEntry("Toggle showing projection", 's'); - glutAddMenuEntry("Switch texture", 't'); - glutAddMenuEntry("Switch object", 'o'); - glutAddMenuEntry("Toggle filtering", 'l'); - glutAddMenuEntry("Quit", 666); - glutAttachMenu(GLUT_RIGHT_BUTTON); - texture(); - glutMainLoop(); - return 0; /* ANSI C requires main to return int. */ -}