projtex.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:22k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /* projtex.c - by David Yu and David Blythe, SGI */
  2. /**
  3.  ** Demonstrates simple projective texture mapping.
  4.  **
  5.  ** Button1 changes view, Button2 moves texture.
  6.  **
  7.  ** (See: Segal, Korobkin, van Widenfelt, Foran, and Haeberli
  8.  **  "Fast Shadows and Lighting Effects Using Texture Mapping", SIGGRAPH '92)
  9.  **
  10.  ** 1994,1995 -- David G Yu
  11.  **
  12.  ** cc -o projtex projtex.c texture.c -lglut -lGLU -lGL -lX11 -lm
  13.  **/
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <math.h>
  17. #include <GL/glut.h>
  18. #include "texture.h"
  19. /* Some <math.h> files do not define M_PI... */
  20. #ifndef M_PI
  21. #define M_PI 3.14159265358979323846
  22. #endif
  23. int winWidth, winHeight;
  24. GLboolean redrawContinuously = GL_FALSE;
  25. float angle, axis[3];
  26. enum MoveModes {
  27.   MoveNone, MoveView, MoveObject, MoveTexture
  28. };
  29. enum MoveModes mode = MoveNone;
  30. GLfloat objectXform[4][4];
  31. GLfloat textureXform[4][4];
  32. void (*drawObject) (void);
  33. void (*loadTexture) (void);
  34. GLboolean textureEnabled = GL_TRUE;
  35. GLboolean showProjection = GL_TRUE;
  36. GLboolean linearFilter = GL_TRUE;
  37. char *texFilename = NULL;
  38. GLfloat zoomFactor = 1.0;
  39. /*****************************************************************/
  40. /* matrix = identity */
  41. void
  42. matrixIdentity(GLfloat matrix[16])
  43. {
  44.   matrix[0] = 1.0;
  45.   matrix[1] = 0.0;
  46.   matrix[2] = 0.0;
  47.   matrix[3] = 0.0;
  48.   matrix[4] = 0.0;
  49.   matrix[5] = 1.0;
  50.   matrix[6] = 0.0;
  51.   matrix[7] = 0.0;
  52.   matrix[8] = 0.0;
  53.   matrix[9] = 0.0;
  54.   matrix[10] = 1.0;
  55.   matrix[11] = 0.0;
  56.   matrix[12] = 0.0;
  57.   matrix[13] = 0.0;
  58.   matrix[14] = 0.0;
  59.   matrix[15] = 1.0;
  60. }
  61. /* matrix2 = transpose(matrix1) */
  62. void
  63. matrixTranspose(GLfloat matrix2[16], GLfloat matrix1[16])
  64. {
  65.   matrix2[0] = matrix1[0];
  66.   matrix2[1] = matrix1[4];
  67.   matrix2[2] = matrix1[8];
  68.   matrix2[3] = matrix1[12];
  69.   matrix2[4] = matrix1[1];
  70.   matrix2[5] = matrix1[5];
  71.   matrix2[6] = matrix1[9];
  72.   matrix2[7] = matrix1[13];
  73.   matrix2[8] = matrix1[2];
  74.   matrix2[9] = matrix1[6];
  75.   matrix2[10] = matrix1[10];
  76.   matrix2[11] = matrix1[14];
  77.   matrix2[12] = matrix1[3];
  78.   matrix2[13] = matrix1[7];
  79.   matrix2[14] = matrix1[14];
  80.   matrix2[15] = matrix1[15];
  81. }
  82. /*****************************************************************/
  83. /* load SGI .rgb image (pad with a border of the specified width and color) */
  84. static void
  85. imgLoad(char *filenameIn, int borderIn, GLfloat borderColorIn[4],
  86.   int *wOut, int *hOut, GLubyte ** imgOut)
  87. {
  88.   int border = borderIn;
  89.   int width, height;
  90.   int w, h;
  91.   GLubyte *image, *img, *p;
  92.   int i, j, components;
  93.   image = (GLubyte *) read_texture(filenameIn, &width, &height, &components);
  94.   w = width + 2 * border;
  95.   h = height + 2 * border;
  96.   img = (GLubyte *) calloc(w * h, 4 * sizeof(unsigned char));
  97.   p = img;
  98.   for (j = -border; j < height + border; ++j) {
  99.     for (i = -border; i < width + border; ++i) {
  100.       if (0 <= j && j <= height - 1 && 0 <= i && i <= width - 1) {
  101.         p[0] = image[4 * (j * width + i) + 0];
  102.         p[1] = image[4 * (j * width + i) + 1];
  103.         p[2] = image[4 * (j * width + i) + 2];
  104.         p[3] = 0xff;
  105.       } else {
  106.         p[0] = borderColorIn[0] * 0xff;
  107.         p[1] = borderColorIn[1] * 0xff;
  108.         p[2] = borderColorIn[2] * 0xff;
  109.         p[3] = borderColorIn[3] * 0xff;
  110.       }
  111.       p += 4;
  112.     }
  113.   }
  114.   free(image);
  115.   *wOut = w;
  116.   *hOut = h;
  117.   *imgOut = img;
  118. }
  119. /*****************************************************************/
  120. /* Load the image file specified on the command line as the current texture */
  121. void
  122. loadImageTexture(void)
  123. {
  124.   static int texWidth, texHeight;
  125.   static GLubyte *texData;
  126.   GLfloat borderColor[4] =
  127.   {1.0, 1.0, 1.0, 1.0};
  128.   if (!texData && texFilename) {
  129.     imgLoad(texFilename, 2, borderColor, &texWidth, &texHeight, &texData);
  130.   }
  131.   if (linearFilter) {
  132.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  133.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  134.   } else {
  135.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  136.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  137.   }
  138.   glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
  139.   gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
  140.     GL_RGBA, GL_UNSIGNED_BYTE, texData);
  141. }
  142. /* Create a simple spotlight pattern and make it the current texture */
  143. void
  144. loadSpotlightTexture(void)
  145. {
  146.   static int texWidth = 64, texHeight = 64;
  147.   static GLubyte *texData;
  148.   GLfloat borderColor[4] =
  149.   {0.1, 0.1, 0.1, 1.0};
  150.   if (!texData) {
  151.     GLubyte *p;
  152.     int i, j;
  153.     texData = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
  154.     p = texData;
  155.     for (j = 0; j < texHeight; ++j) {
  156.       float dy = (texHeight * 0.5 - j + 0.5) / (texHeight * 0.5);
  157.       for (i = 0; i < texWidth; ++i) {
  158.         float dx = (texWidth * 0.5 - i + 0.5) / (texWidth * 0.5);
  159.         float r = cos(M_PI / 2.0 * sqrt(dx * dx + dy * dy));
  160.         float c;
  161.         r = (r < 0) ? 0 : r * r;
  162.         c = 0xff * (r + borderColor[0]);
  163.         p[0] = (c <= 0xff) ? c : 0xff;
  164.         c = 0xff * (r + borderColor[1]);
  165.         p[1] = (c <= 0xff) ? c : 0xff;
  166.         c = 0xff * (r + borderColor[2]);
  167.         p[2] = (c <= 0xff) ? c : 0xff;
  168.         c = 0xff * (r + borderColor[3]);
  169.         p[3] = (c <= 0xff) ? c : 0xff;
  170.         p += 4;
  171.       }
  172.     }
  173.   }
  174.   if (linearFilter) {
  175.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  176.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  177.   } else {
  178.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  179.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  180.   }
  181.   glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
  182.   gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
  183.     GL_RGBA, GL_UNSIGNED_BYTE, texData);
  184. }
  185. /*****************************************************************/
  186. void
  187. checkErrors(void)
  188. {
  189.   GLenum error;
  190.   while ((error = glGetError()) != GL_NO_ERROR) {
  191.     fprintf(stderr, "Error: %sn", (char *) gluErrorString(error));
  192.   }
  193. }
  194. void
  195. drawCube(void)
  196. {
  197.   glBegin(GL_QUADS);
  198.   glNormal3f(-1.0, 0.0, 0.0);
  199.   glColor3f(0.80, 0.50, 0.50);
  200.   glVertex3f(-0.5, -0.5, -0.5);
  201.   glVertex3f(-0.5, -0.5, 0.5);
  202.   glVertex3f(-0.5, 0.5, 0.5);
  203.   glVertex3f(-0.5, 0.5, -0.5);
  204.   glNormal3f(1.0, 0.0, 0.0);
  205.   glColor3f(0.50, 0.80, 0.50);
  206.   glVertex3f(0.5, 0.5, 0.5);
  207.   glVertex3f(0.5, -0.5, 0.5);
  208.   glVertex3f(0.5, -0.5, -0.5);
  209.   glVertex3f(0.5, 0.5, -0.5);
  210.   glNormal3f(0.0, -1.0, 0.0);
  211.   glColor3f(0.50, 0.50, 0.80);
  212.   glVertex3f(-0.5, -0.5, -0.5);
  213.   glVertex3f(0.5, -0.5, -0.5);
  214.   glVertex3f(0.5, -0.5, 0.5);
  215.   glVertex3f(-0.5, -0.5, 0.5);
  216.   glNormal3f(0.0, 1.0, 0.0);
  217.   glColor3f(0.50, 0.80, 0.80);
  218.   glVertex3f(0.5, 0.5, 0.5);
  219.   glVertex3f(0.5, 0.5, -0.5);
  220.   glVertex3f(-0.5, 0.5, -0.5);
  221.   glVertex3f(-0.5, 0.5, 0.5);
  222.   glNormal3f(0.0, 0.0, -1.0);
  223.   glColor3f(0.80, 0.50, 0.80);
  224.   glVertex3f(-0.5, -0.5, -0.5);
  225.   glVertex3f(-0.5, 0.5, -0.5);
  226.   glVertex3f(0.5, 0.5, -0.5);
  227.   glVertex3f(0.5, -0.5, -0.5);
  228.   glNormal3f(0.0, 0.0, 1.0);
  229.   glColor3f(1.00, 0.80, 0.50);
  230.   glVertex3f(0.5, 0.5, 0.5);
  231.   glVertex3f(-0.5, 0.5, 0.5);
  232.   glVertex3f(-0.5, -0.5, 0.5);
  233.   glVertex3f(0.5, -0.5, 0.5);
  234.   glEnd();
  235. }
  236. void
  237. drawDodecahedron(void)
  238. {
  239. #define A (0.5 * 1.61803)  /* (sqrt(5) + 1) / 2 */
  240. #define B (0.5 * 0.61803)  /* (sqrt(5) - 1) / 2 */
  241. #define C (0.5 * 1.0)
  242.   GLfloat vertexes[20][3] =
  243.   {
  244.     {-A, 0.0, B},
  245.     {-A, 0.0, -B},
  246.     {A, 0.0, -B},
  247.     {A, 0.0, B},
  248.     {B, -A, 0.0},
  249.     {-B, -A, 0.0},
  250.     {-B, A, 0.0},
  251.     {B, A, 0.0},
  252.     {0.0, B, -A},
  253.     {0.0, -B, -A},
  254.     {0.0, -B, A},
  255.     {0.0, B, A},
  256.     {-C, -C, C},
  257.     {-C, -C, -C},
  258.     {C, -C, -C},
  259.     {C, -C, C},
  260.     {-C, C, C},
  261.     {-C, C, -C},
  262.     {C, C, -C},
  263.     {C, C, C},
  264.   };
  265. #undef A
  266. #undef B
  267. #undef C
  268.   GLint polygons[12][5] =
  269.   {
  270.     {0, 12, 10, 11, 16},
  271.     {1, 17, 8, 9, 13},
  272.     {2, 14, 9, 8, 18},
  273.     {3, 19, 11, 10, 15},
  274.     {4, 14, 2, 3, 15},
  275.     {5, 12, 0, 1, 13},
  276.     {6, 17, 1, 0, 16},
  277.     {7, 19, 3, 2, 18},
  278.     {8, 17, 6, 7, 18},
  279.     {9, 14, 4, 5, 13},
  280.     {10, 12, 5, 4, 15},
  281.     {11, 19, 7, 6, 16},
  282.   };
  283.   int i;
  284.   glColor3f(0.75, 0.75, 0.75);
  285.   for (i = 0; i < 12; ++i) {
  286.     GLfloat *p0, *p1, *p2, d;
  287.     GLfloat u[3], v[3], n[3];
  288.     p0 = &vertexes[polygons[i][0]][0];
  289.     p1 = &vertexes[polygons[i][1]][0];
  290.     p2 = &vertexes[polygons[i][2]][0];
  291.     u[0] = p2[0] - p1[0];
  292.     u[1] = p2[1] - p1[1];
  293.     u[2] = p2[2] - p1[2];
  294.     v[0] = p0[0] - p1[0];
  295.     v[1] = p0[1] - p1[1];
  296.     v[2] = p0[2] - p1[2];
  297.     n[0] = u[1] * v[2] - u[2] * v[1];
  298.     n[1] = u[2] * v[0] - u[0] * v[2];
  299.     n[2] = u[0] * v[1] - u[1] * v[0];
  300.     d = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
  301.     n[0] *= d;
  302.     n[1] *= d;
  303.     n[2] *= d;
  304.     glBegin(GL_POLYGON);
  305.     glNormal3fv(n);
  306.     glVertex3fv(p0);
  307.     glVertex3fv(p1);
  308.     glVertex3fv(p2);
  309.     glVertex3fv(vertexes[polygons[i][3]]);
  310.     glVertex3fv(vertexes[polygons[i][4]]);
  311.     glEnd();
  312.   }
  313. }
  314. void
  315. drawSphere(void)
  316. {
  317.   int numMajor = 24;
  318.   int numMinor = 32;
  319.   float radius = 0.8;
  320.   double majorStep = (M_PI / numMajor);
  321.   double minorStep = (2.0 * M_PI / numMinor);
  322.   int i, j;
  323.   glColor3f(0.50, 0.50, 0.50);
  324.   for (i = 0; i < numMajor; ++i) {
  325.     double a = i * majorStep;
  326.     double b = a + majorStep;
  327.     double r0 = radius * sin(a);
  328.     double r1 = radius * sin(b);
  329.     GLfloat z0 = radius * cos(a);
  330.     GLfloat z1 = radius * cos(b);
  331.     glBegin(GL_TRIANGLE_STRIP);
  332.     for (j = 0; j <= numMinor; ++j) {
  333.       double c = j * minorStep;
  334.       GLfloat x = cos(c);
  335.       GLfloat y = sin(c);
  336.       glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
  337.       glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
  338.       glVertex3f(x * r0, y * r0, z0);
  339.       glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
  340.       glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
  341.       glVertex3f(x * r1, y * r1, z1);
  342.     }
  343.     glEnd();
  344.   }
  345. }
  346. /*****************************************************************/
  347. float xmin = -0.035, xmax = 0.035;
  348. float ymin = -0.035, ymax = 0.035;
  349. float nnear = 0.1;
  350. float ffar = 1.9;
  351. float distance = -1.0;
  352. static void
  353. loadTextureProjection(GLfloat m[16])
  354. {
  355.   GLfloat mInverse[4][4];
  356.   /* Should use true inverse, but since m consists only of rotations, we can
  357.      just use the transpose. */
  358.   matrixTranspose((GLfloat *) mInverse, m);
  359.   glMatrixMode(GL_TEXTURE);
  360.   glLoadIdentity();
  361.   glTranslatef(0.5, 0.5, 0.0);
  362.   glScalef(0.5, 0.5, 1.0);
  363.   glFrustum(xmin, xmax, ymin, ymax, nnear, ffar);
  364.   glTranslatef(0.0, 0.0, distance);
  365.   glMultMatrixf((GLfloat *) mInverse);
  366.   glMatrixMode(GL_MODELVIEW);
  367. }
  368. static void
  369. drawTextureProjection(void)
  370. {
  371.   float t = ffar / nnear;
  372.   GLfloat n[4][3];
  373.   GLfloat f[4][3];
  374.   n[0][0] = xmin;
  375.   n[0][1] = ymin;
  376.   n[0][2] = -(nnear + distance);
  377.   n[1][0] = xmax;
  378.   n[1][1] = ymin;
  379.   n[1][2] = -(nnear + distance);
  380.   n[2][0] = xmax;
  381.   n[2][1] = ymax;
  382.   n[2][2] = -(nnear + distance);
  383.   n[3][0] = xmin;
  384.   n[3][1] = ymax;
  385.   n[3][2] = -(nnear + distance);
  386.   f[0][0] = xmin * t;
  387.   f[0][1] = ymin * t;
  388.   f[0][2] = -(ffar + distance);
  389.   f[1][0] = xmax * t;
  390.   f[1][1] = ymin * t;
  391.   f[1][2] = -(ffar + distance);
  392.   f[2][0] = xmax * t;
  393.   f[2][1] = ymax * t;
  394.   f[2][2] = -(ffar + distance);
  395.   f[3][0] = xmin * t;
  396.   f[3][1] = ymax * t;
  397.   f[3][2] = -(ffar + distance);
  398.   glColor3f(1.0, 1.0, 0.0);
  399.   glBegin(GL_LINE_LOOP);
  400.   glVertex3fv(n[0]);
  401.   glVertex3fv(n[1]);
  402.   glVertex3fv(n[2]);
  403.   glVertex3fv(n[3]);
  404.   glVertex3fv(f[3]);
  405.   glVertex3fv(f[2]);
  406.   glVertex3fv(f[1]);
  407.   glVertex3fv(f[0]);
  408.   glVertex3fv(n[0]);
  409.   glVertex3fv(n[1]);
  410.   glVertex3fv(f[1]);
  411.   glVertex3fv(f[0]);
  412.   glVertex3fv(f[3]);
  413.   glVertex3fv(f[2]);
  414.   glVertex3fv(n[2]);
  415.   glVertex3fv(n[3]);
  416.   glEnd();
  417. }
  418. /*****************************************************************/
  419. void
  420. initialize(void)
  421. {
  422.   GLfloat light0Pos[4] =
  423.   {0.3, 0.3, 0.0, 1.0};
  424.   GLfloat matAmb[4] =
  425.   {0.01, 0.01, 0.01, 1.00};
  426.   GLfloat matDiff[4] =
  427.   {0.65, 0.65, 0.65, 1.00};
  428.   GLfloat matSpec[4] =
  429.   {0.30, 0.30, 0.30, 1.00};
  430.   GLfloat matShine = 10.0;
  431.   GLfloat eyePlaneS[] =
  432.   {1.0, 0.0, 0.0, 0.0};
  433.   GLfloat eyePlaneT[] =
  434.   {0.0, 1.0, 0.0, 0.0};
  435.   GLfloat eyePlaneR[] =
  436.   {0.0, 0.0, 1.0, 0.0};
  437.   GLfloat eyePlaneQ[] =
  438.   {0.0, 0.0, 0.0, 1.0};
  439.   /* Setup Misc.  */
  440.   glClearColor(0.41, 0.41, 0.31, 0.0);
  441.   glEnable(GL_DEPTH_TEST);
  442.   glLineWidth(2.0);
  443.   glCullFace(GL_FRONT);
  444.   glEnable(GL_CULL_FACE);
  445.   glMatrixMode(GL_PROJECTION);
  446.   glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
  447.   glMatrixMode(GL_MODELVIEW);
  448.   glTranslatef(0, 0, -2);
  449.   matrixIdentity((GLfloat *) objectXform);
  450.   matrixIdentity((GLfloat *) textureXform);
  451.   glMatrixMode(GL_PROJECTION);
  452.   glPushMatrix();
  453.   glLoadIdentity();
  454.   glOrtho(0, 1, 0, 1, -1, 1);
  455.   glMatrixMode(GL_MODELVIEW);
  456.   glPushMatrix();
  457.   glLoadIdentity();
  458.   glRasterPos2i(0, 0);
  459.   glPopMatrix();
  460.   glMatrixMode(GL_PROJECTION);
  461.   glPopMatrix();
  462.   glMatrixMode(GL_MODELVIEW);
  463.   /* Setup Lighting */
  464.   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb);
  465.   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
  466.   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
  467.   glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
  468.   glEnable(GL_COLOR_MATERIAL);
  469.   glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  470.   glEnable(GL_LIGHT0);
  471.   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  472.   glEnable(GL_LIGHTING);
  473.   /* Setup Texture */
  474.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  475.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  476.   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  477.   (*loadTexture) ();
  478.   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  479.   glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS);
  480.   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  481.   glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT);
  482.   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  483.   glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR);
  484.   glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  485.   glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ);
  486. }
  487. void
  488. display(void)
  489. {
  490.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  491.   if (textureEnabled) {
  492.     if (mode == MoveTexture || mode == MoveView) {
  493.       /* Have OpenGL compute the new transformation (simple but slow). */
  494.       glPushMatrix();
  495.       glLoadIdentity();
  496.       glRotatef(angle, axis[0], axis[1], axis[2]);
  497.       glMultMatrixf((GLfloat *) textureXform);
  498.       glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) textureXform);
  499.       glPopMatrix();
  500.     }
  501.     loadTextureProjection((GLfloat *) textureXform);
  502.     if (showProjection) {
  503.       glPushMatrix();
  504.       glMultMatrixf((GLfloat *) textureXform);
  505.       glDisable(GL_LIGHTING);
  506.       drawTextureProjection();
  507.       glEnable(GL_LIGHTING);
  508.       glPopMatrix();
  509.     }
  510.     glEnable(GL_TEXTURE_2D);
  511.     glEnable(GL_TEXTURE_GEN_S);
  512.     glEnable(GL_TEXTURE_GEN_T);
  513.     glEnable(GL_TEXTURE_GEN_R);
  514.     glEnable(GL_TEXTURE_GEN_Q);
  515.   }
  516.   if (mode == MoveObject || mode == MoveView) {
  517.     /* Have OpenGL compute the new transformation (simple but slow). */
  518.     glPushMatrix();
  519.     glLoadIdentity();
  520.     glRotatef(angle, axis[0], axis[1], axis[2]);
  521.     glMultMatrixf((GLfloat *) objectXform);
  522.     glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
  523.     glPopMatrix();
  524.   }
  525.   glPushMatrix();
  526.   glMultMatrixf((GLfloat *) objectXform);
  527.   (*drawObject) ();
  528.   glPopMatrix();
  529.   glDisable(GL_TEXTURE_2D);
  530.   glDisable(GL_TEXTURE_GEN_S);
  531.   glDisable(GL_TEXTURE_GEN_T);
  532.   glDisable(GL_TEXTURE_GEN_R);
  533.   glDisable(GL_TEXTURE_GEN_Q);
  534.   if (zoomFactor > 1.0) {
  535.     glDisable(GL_DEPTH_TEST);
  536.     glCopyPixels(0, 0, winWidth / zoomFactor, winHeight / zoomFactor, GL_COLOR);
  537.     glEnable(GL_DEPTH_TEST);
  538.   }
  539.   glFlush();
  540.   glutSwapBuffers();
  541.   checkErrors();
  542. }
  543. /*****************************************************************/
  544. /* simple trackball-like motion control */
  545. float lastPos[3];
  546. int lastTime;
  547. void
  548. ptov(int x, int y, int width, int height, float v[3])
  549. {
  550.   float d, a;
  551.   /* project x,y onto a hemi-sphere centered within width, height */
  552.   v[0] = (2.0 * x - width) / width;
  553.   v[1] = (height - 2.0 * y) / height;
  554.   d = sqrt(v[0] * v[0] + v[1] * v[1]);
  555.   v[2] = cos((M_PI / 2.0) * ((d < 1.0) ? d : 1.0));
  556.   a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  557.   v[0] *= a;
  558.   v[1] *= a;
  559.   v[2] *= a;
  560. }
  561. void
  562. startMotion(int x, int y, int but, int time)
  563. {
  564.   if (but == GLUT_LEFT_BUTTON) {
  565.     mode = MoveView;
  566.   } else if (but == GLUT_MIDDLE_BUTTON) {
  567.     mode = MoveTexture;
  568.   } else {
  569.     return;
  570.   }
  571.   lastTime = time;
  572.   ptov(x, y, winWidth, winHeight, lastPos);
  573. }
  574. void
  575. animate(void)
  576. {
  577.   glutPostRedisplay();
  578. }
  579. void
  580. vis(int visible)
  581. {
  582.   if (visible == GLUT_VISIBLE) {
  583.     if (redrawContinuously)
  584.       glutIdleFunc(animate);
  585.   } else {
  586.     if (redrawContinuously)
  587.       glutIdleFunc(NULL);
  588.   }
  589. }
  590. void
  591. stopMotion(int but, int time)
  592. {
  593.   if ((but == GLUT_LEFT_BUTTON && mode == MoveView) ||
  594.     (but == GLUT_MIDDLE_BUTTON && mode == MoveTexture)) {
  595.   } else {
  596.     return;
  597.   }
  598.   if (time == lastTime) {
  599.     redrawContinuously = GL_TRUE;
  600.     glutIdleFunc(animate);
  601.   } else {
  602.     angle = 0.0;
  603.     redrawContinuously = GL_FALSE;
  604.     glutIdleFunc(0);
  605.   }
  606.   if (!redrawContinuously) {
  607.     mode = MoveNone;
  608.   }
  609. }
  610. void
  611. trackMotion(int x, int y)
  612. {
  613.   float curPos[3], dx, dy, dz;
  614.   ptov(x, y, winWidth, winHeight, curPos);
  615.   dx = curPos[0] - lastPos[0];
  616.   dy = curPos[1] - lastPos[1];
  617.   dz = curPos[2] - lastPos[2];
  618.   angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
  619.   axis[0] = lastPos[1] * curPos[2] - lastPos[2] * curPos[1];
  620.   axis[1] = lastPos[2] * curPos[0] - lastPos[0] * curPos[2];
  621.   axis[2] = lastPos[0] * curPos[1] - lastPos[1] * curPos[0];
  622.   lastTime = glutGet(GLUT_ELAPSED_TIME);
  623.   lastPos[0] = curPos[0];
  624.   lastPos[1] = curPos[1];
  625.   lastPos[2] = curPos[2];
  626.   glutPostRedisplay();
  627. }
  628. /*****************************************************************/
  629. void
  630. object(void)
  631. {
  632.   static int object;
  633.   object++;
  634.   object %= 3;
  635.   switch (object) {
  636.   case 0:
  637.     drawObject = drawCube;
  638.     break;
  639.   case 1:
  640.     drawObject = drawDodecahedron;
  641.     break;
  642.   case 2:
  643.     drawObject = drawSphere;
  644.     break;
  645.   default:
  646.     break;
  647.   }
  648. }
  649. static void
  650. nop(void)
  651. {
  652. }
  653. void
  654. texture(void)
  655. {
  656.   static int texture = 0;
  657.   texture++;
  658.   texture %= 3;
  659.   if (texture == 1 && texFilename == NULL) {
  660.     /* Skip file texture if not loaded. */
  661.     texture++;
  662.   }
  663.   switch (texture) {
  664.   case 0:
  665.     loadTexture = nop;
  666.     textureEnabled = GL_FALSE;
  667.     break;
  668.   case 1:
  669.     loadTexture = loadImageTexture;
  670.     (*loadTexture) ();
  671.     textureEnabled = GL_TRUE;
  672.     break;
  673.   case 2:
  674.     loadTexture = loadSpotlightTexture;
  675.     (*loadTexture) ();
  676.     textureEnabled = GL_TRUE;
  677.     break;
  678.   default:
  679.     break;
  680.   }
  681. }
  682. void
  683. help(void)
  684. {
  685.   printf("'h'   - helpn");
  686.   printf("'l'   - toggle linear/nearest filtern");
  687.   printf("'s'   - toggle projection frustumn");
  688.   printf("'t'   - toggle projected texturen");
  689.   printf("'o'   - toggle objectn");
  690.   printf("'z'   - increase zoom factorn");
  691.   printf("'Z'   - decrease zoom factorn");
  692.   printf("left mouse     - move viewn");
  693.   printf("middle mouse   - move projectionn");
  694. }
  695. /* ARGSUSED1 */
  696. void
  697. key(unsigned char key, int x, int y)
  698. {
  699.   switch (key) {
  700.   case '33':
  701.     exit(0);
  702.     break;
  703.   case 'l':
  704.     linearFilter = !linearFilter;
  705.     (*loadTexture) ();
  706.     break;
  707.   case 's':
  708.     showProjection = !showProjection;
  709.     break;
  710.   case 't':
  711.     texture();
  712.     break;
  713.   case 'o':
  714.     object();
  715.     break;
  716.   case 'z':
  717.     zoomFactor += 1.0;
  718.     glPixelZoom(zoomFactor, zoomFactor);
  719.     glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
  720.     break;
  721.   case 'Z':
  722.     zoomFactor -= 1.0;
  723.     if (zoomFactor < 1.0)
  724.       zoomFactor = 1.0;
  725.     glPixelZoom(zoomFactor, zoomFactor);
  726.     glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
  727.     break;
  728.   case 'h':
  729.     help();
  730.     break;
  731.   }
  732.   glutPostRedisplay();
  733. }
  734. void
  735. mouse(int button, int state, int x, int y)
  736. {
  737.   if (state == GLUT_DOWN)
  738.     startMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME));
  739.   else if (state == GLUT_UP)
  740.     stopMotion(button, glutGet(GLUT_ELAPSED_TIME));
  741.   glutPostRedisplay();
  742. }
  743. void
  744. reshape(int w, int h)
  745. {
  746.   winWidth = w;
  747.   winHeight = h;
  748.   glViewport(0, 0, w / zoomFactor, h / zoomFactor);
  749. }
  750. void
  751. usage(char *name)
  752. {
  753.   fprintf(stderr, "usage: %s <image-filename>n", name);
  754.   fprintf(stderr, "n");
  755. }
  756. void
  757. menu(int selection)
  758. {
  759.   if (selection == 666) {
  760.     exit(0);
  761.   }
  762.   key((unsigned char) selection, 0, 0);
  763. }
  764. int
  765. main(int argc, char **argv)
  766. {
  767.   glutInit(&argc, argv);
  768.   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
  769.   (void) glutCreateWindow("projtex");
  770.   if (argc > 2) {
  771.     usage(argv[0]);
  772.     exit(1);
  773.   }
  774.   if (argc > 1) {
  775.     texFilename = argv[1];
  776.   }
  777.   loadTexture = loadImageTexture;
  778.   drawObject = drawCube;
  779.   initialize();
  780.   glutDisplayFunc(display);
  781.   glutKeyboardFunc(key);
  782.   glutReshapeFunc(reshape);
  783.   glutMouseFunc(mouse);
  784.   glutMotionFunc(trackMotion);
  785.   glutVisibilityFunc(vis);
  786.   glutCreateMenu(menu);
  787.   glutAddMenuEntry("Toggle showing projection", 's');
  788.   glutAddMenuEntry("Switch texture", 't');
  789.   glutAddMenuEntry("Switch object", 'o');
  790.   glutAddMenuEntry("Toggle filtering", 'l');
  791.   glutAddMenuEntry("Quit", 666);
  792.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  793.   texture();
  794.   glutMainLoop();
  795.   return 0;             /* ANSI C requires main to return int. */
  796. }