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

GIS编程

开发平台:

Visual C++

  1. /**
  2.  *
  3.  * vox.c : GLUT example for volume rendering
  4.  *
  5.  * Author : Yusuf Attarwala
  6.  *          SGI - Applications
  7.  *
  8.  * Mods by Mark Kilgard.
  9.  *
  10.  * cc vox.c -o vox -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm
  11.  *
  12.  * Voxel Head is a simple volume rendering example using OpenGL 3d textures.
  13.  * This version has limited features (intentional), to keep the code simple.
  14.  *
  15.  * i.e. - there is no control for changing alpha values.
  16.  *      - it just deals with one block of texture (no tiling)
  17.  *      - there are no clipping planes
  18.  *      - it only works with one data set, so it assumes that texture data
  19.  *    is in powers of 2.
  20.  *
  21.  * Some of these features will be implemented in future releases.
  22.  *
  23.  * The technique to create polygonal slices thru voxel space is as
  24.  * follows:
  25.  *
  26.  * Instead of recomputing polygonal slices perpendicular to every
  27.  * viewing vector, it uses the same set of polygonal slices for a
  28.  * range of -45 to 45 degrees. Outside this range, it recomputes
  29.  * another set of slices and so on.
  30.  *
  31.  * These slices are then rendered back to front with 3d texture and
  32.  * blending enabled.
  33.  *
  34.  * It uses GLUT for handling events, windows etc.
  35.  *
  36.  * This program runs with good performance on RealityEngine, VTX,
  37.  * InfiniteReality, or Maximum IMPACT.  In IRIX 6.2, a software
  38.  * implementation of OpenGL's 3D texture mapping extension is
  39.  * available, but performance is very poor.  If you are on a slow
  40.  * machine, you can run "vox -sb" and still get a good feel for how
  41.  * the program performs volume rendering since you can see the 3D
  42.  * slices be rendered back to front with blending.
  43.  * 
  44.  */
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #ifndef _WIN32
  48. #include <unistd.h>
  49. #else
  50. #define R_OK 04  /* Win32 doesn't define this */
  51. /* Win32 defines these, but with a leading _ */
  52. #define pclose _pclose
  53. #define popen _popen
  54. /* Win32 doesn't have a re-entrand rand() */
  55. #define rand_r(x) rand()
  56. #endif
  57. #include <string.h>
  58. #include <math.h>
  59. #include <GL/glut.h>
  60. #define ABS(a)   (((a) >= 0) ? (a) : -(a))
  61. #define _XY    1
  62. #define _YZ    2
  63. #define _ZX    3
  64. #define _MXY   4
  65. #define _MYZ   5
  66. #define _MZX   6
  67. /* pop up menu entries */
  68. #define SPIN_ON   1
  69. #define SPIN_OFF  2
  70. #define MENU_HELP 3
  71. #define MENU_EXIT 4
  72. /* global variables */
  73. int width, height;      /* window width, height */
  74. float left, right, bottom, top, nnear, ffar;  /* ortho, view volume */
  75. float vol_width, vol_height, vol_depth;  /* volume dimensions */
  76. float bminx, bmaxx, bminy, bmaxy, bminz, bmaxz, bdiag;  /* bounding box */
  77. int n_slices;           /* number of slices */
  78. int tex3dSupported = 1;
  79. float slice_poly[3][4][3];
  80. float slice_tcoord[3][4][3];
  81. float anglex, angley, anglez;
  82. unsigned char *voxels;
  83. void
  84. readVoxelData(void)
  85. {
  86.   FILE *file;
  87.   int i, j, k, using_pipe;
  88.   unsigned char *vptr;
  89.   unsigned char *vp, *vx;
  90.   /* see if the hardware supports 3d texture */
  91. #ifdef GL_EXT_texture3D
  92.   if (!glutExtensionSupported("GL_EXT_texture3D")) {
  93.     printf("n==================================================================n");
  94.     printf("This hardware (%s) does not support 3d texture extentionsn",
  95.       (char *) (glGetString(GL_RENDERER)));
  96.     printf("==================================================================n");
  97.     tex3dSupported = 0;
  98.   }
  99. #else
  100.   printf("n==================================================================n");
  101.   printf("Not API support for GL_EXT_texture3D extension when compiled.n");
  102.   printf("==================================================================n");
  103. #endif
  104.   /* open vox.bin data file */
  105.   if ((file = fopen("vox.bin", "r")) == NULL) {
  106. #ifndef _WIN32
  107.     if (!access("vox.bin.gz", R_OK)) {
  108.       if ((file = popen("gzcat vox.bin.gz", "r")) == NULL) {
  109.         fprintf(stderr, "cannot popen input file vox.bin.gz (missing gzcat?)n");
  110.         exit(1);
  111.       }
  112.     } else if (!access("vox.bin.Z", R_OK)) {
  113.       if ((file = popen("zcat vox.bin.Z", "r")) == NULL) {
  114.         fprintf(stderr, "cannot popen input file vox.bin.Z (missing zcat?)n");
  115.         exit(1);
  116.       }
  117.     } else {
  118.       fprintf(stderr, "cannot find vox.bin, vox.bin.gz, or vox.bin.Zn");
  119.       exit(1);
  120.     }
  121.     using_pipe = 1;
  122. #else
  123.     fprintf(stderr, "cannot find vox.binn");
  124.     exit(1);
  125. #endif
  126.   } else {
  127.     using_pipe = 0;
  128.   }
  129.   vol_width = 128;      /* hard coded for demo */
  130.   vol_height = 128;
  131.   vol_depth = 64;
  132.   n_slices = 128;
  133.   if (tex3dSupported) {
  134.     unsigned long size = (unsigned long) (vol_width * vol_height * vol_depth);
  135.     vptr = (unsigned char *) malloc(size);
  136.     fread(vptr, sizeof(char), size, file);
  137.     if (using_pipe) {
  138.       pclose(file);
  139.     } else {
  140.       fclose(file);
  141.     }
  142.     /* size of voxels is twice as the size of vptr, to duplicate alpha value
  143.        = intensity */
  144.     voxels = (unsigned char *) malloc(2 * size);
  145.     /* for now duplicate, alpha value = intensity */
  146.     vx = voxels;
  147.     vp = vptr;
  148.     for (i = 0; i < vol_width; i++)
  149.       for (j = 0; j < vol_height; j++)
  150.         for (k = 0; k < vol_depth; k++) {
  151.           *vx++ = *vp;
  152.           *vx++ = *vp++;
  153.         }
  154.     free(vptr);
  155.   }
  156.   /* compute bounding box extents */
  157.   bminx = -(float) vol_width / 2.0;
  158.   bmaxx = (float) vol_width / 2.0;
  159.   bminy = -(float) vol_height / 2.0;
  160.   bmaxy = (float) vol_height / 2.0;
  161.   bminz = -(float) vol_depth / 2.0;
  162.   bmaxz = (float) vol_depth / 2.0;
  163.   bdiag = sqrt((bmaxx) * (bmaxx) + (bmaxy) * (bmaxy) + (bmaxz) * (bmaxz));
  164.   /* compute view volume extents */
  165.   left = -1.1 * bdiag;
  166.   right = 1.1 * bdiag;
  167.   bottom = -1.1 * bdiag;
  168.   top = 1.1 * bdiag;
  169.   nnear = -1.0 * bdiag;
  170.   ffar = 2 * 1.1 * bdiag;
  171.   /* define the polygon dimensions on which the texture will be mapped */
  172.   /* xy plane */
  173.   slice_poly[0][0][0] = -vol_width / 2.0;
  174.   slice_poly[0][0][1] = -vol_height / 2.0;
  175.   slice_poly[0][0][2] = 0.0;
  176.   slice_poly[0][1][0] = vol_width / 2.0;
  177.   slice_poly[0][1][1] = -vol_height / 2.0;
  178.   slice_poly[0][1][2] = 0.0;
  179.   slice_poly[0][2][0] = vol_width / 2.0;
  180.   slice_poly[0][2][1] = vol_height / 2.0;
  181.   slice_poly[0][2][2] = 0.0;
  182.   slice_poly[0][3][0] = -vol_width / 2.0;
  183.   slice_poly[0][3][1] = vol_height / 2.0;
  184.   slice_poly[0][3][2] = 0.0;
  185.   /* yz plane */
  186.   slice_poly[1][0][0] = 0.0;
  187.   slice_poly[1][0][1] = -vol_height / 2.0;
  188.   slice_poly[1][0][2] = -vol_depth / 2.0;
  189.   slice_poly[1][1][0] = 0.0;
  190.   slice_poly[1][1][1] = vol_height / 2.0;
  191.   slice_poly[1][1][2] = -vol_depth / 2.0;
  192.   slice_poly[1][2][0] = 0.0;
  193.   slice_poly[1][2][1] = vol_height / 2.0;
  194.   slice_poly[1][2][2] = vol_depth / 2.0;
  195.   slice_poly[1][3][0] = 0.0;
  196.   slice_poly[1][3][1] = -vol_height / 2.0;
  197.   slice_poly[1][3][2] = vol_depth / 2.0;
  198.   /* zx plane */
  199.   slice_poly[2][0][0] = -vol_width / 2.0;
  200.   slice_poly[2][0][1] = 0.0;
  201.   slice_poly[2][0][2] = -vol_depth / 2.0;
  202.   slice_poly[2][1][0] = -vol_width / 2.0;
  203.   slice_poly[2][1][1] = 0.0;
  204.   slice_poly[2][1][2] = vol_depth / 2.0;
  205.   slice_poly[2][2][0] = vol_width / 2.0;
  206.   slice_poly[2][2][1] = 0.0;
  207.   slice_poly[2][2][2] = vol_depth / 2.0;
  208.   slice_poly[2][3][0] = vol_width / 2.0;
  209.   slice_poly[2][3][1] = 0.0;
  210.   slice_poly[2][3][2] = -vol_depth / 2.0;
  211.   /* texture coordinates */
  212.   slice_tcoord[0][0][0] = 0.0;
  213.   slice_tcoord[0][0][1] = 0.0;
  214.   slice_tcoord[0][1][0] = 1.0;
  215.   slice_tcoord[0][1][1] = 0.0;
  216.   slice_tcoord[0][2][0] = 1.0;
  217.   slice_tcoord[0][2][1] = 1.0;
  218.   slice_tcoord[0][3][0] = 0.0;
  219.   slice_tcoord[0][3][1] = 1.0;
  220.   slice_tcoord[1][0][1] = 0.0;
  221.   slice_tcoord[1][0][2] = 1.0;
  222.   slice_tcoord[1][1][1] = 1.0;
  223.   slice_tcoord[1][1][2] = 1.0;
  224.   slice_tcoord[1][2][1] = 1.0;
  225.   slice_tcoord[1][2][2] = 0.0;
  226.   slice_tcoord[1][3][1] = 0.0;
  227.   slice_tcoord[1][3][2] = 0.0;
  228.   slice_tcoord[2][0][2] = 0.0;
  229.   slice_tcoord[2][0][0] = 0.0;
  230.   slice_tcoord[2][1][2] = 1.0;
  231.   slice_tcoord[2][1][0] = 0.0;
  232.   slice_tcoord[2][2][2] = 1.0;
  233.   slice_tcoord[2][2][0] = 1.0;
  234.   slice_tcoord[2][3][2] = 0.0;
  235.   slice_tcoord[2][3][0] = 1.0;
  236. }
  237. void
  238. randomTick(void)
  239. {
  240.   static unsigned int seed = 0;
  241.   static int changeSeed = 25;
  242.   float fltran;
  243.   if (changeSeed++ >= 25) {
  244.     seed++;
  245.     if (seed > 256)
  246.       seed = 0;
  247.     changeSeed = 0;
  248.   }
  249.   fltran = (float) (rand_r(&seed) / 30000.0);
  250.   anglex = (anglex > 360.0) ? 0.0 : (anglex + fltran);
  251.   angley = (angley > 360.0) ? 0.0 : (angley + fltran);
  252.   anglez = (anglez > 360.0) ? 0.0 : (anglez + fltran);
  253. }
  254. void
  255. animate(void)
  256. {
  257.   randomTick();
  258.   glutPostRedisplay();
  259. }
  260. void
  261. printCheatSheet(void)
  262. {
  263.   printf("nn-------------------------n");
  264.   printf("OpenGL 3d texture examplenn");
  265.   printf("Keyboard shortcutsn");
  266.   printf("s key   : zoom out (small)n");
  267.   printf("l key   : zoom in  (large)n");
  268.   printf("x key   : rotate about screen xn");
  269.   printf("y key   : rotate about screen yn");
  270.   printf("z key   : rotate about screen zn");
  271.   printf("esc key : quitn");
  272. }
  273. void
  274. menu(int choice)
  275. {
  276.   /* simple GLUT popup menu stuff */
  277.   switch (choice) {
  278.   case SPIN_ON:
  279.     glutChangeToMenuEntry(1, "Random Spin OFF", SPIN_OFF);
  280.     glutIdleFunc(animate);
  281.     break;
  282.   case SPIN_OFF:
  283.     glutChangeToMenuEntry(1, "Random Spin ON", SPIN_ON);
  284.     glutIdleFunc(NULL);
  285.     break;
  286.   case MENU_HELP:
  287.     printCheatSheet();
  288.     break;
  289.   case MENU_EXIT:
  290.     exit(0);
  291.     break;
  292.   }
  293. }
  294. void
  295. setMatrix(void)
  296. {
  297.   /* feel like using ortho projection */
  298.   glMatrixMode(GL_PROJECTION);
  299.   glLoadIdentity();
  300.   glOrtho(left, right, bottom, top, nnear, ffar);
  301.   /* boring view matrix */
  302.   glMatrixMode(GL_MODELVIEW);
  303.   glLoadIdentity();
  304. }
  305. void
  306. load3DTexture(void)
  307. {
  308.   printf("setting up 3d textures...n");
  309.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  310.   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  311. #ifdef GL_EXT_texture3D
  312.   glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  313.   glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  314.   glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S, GL_REPEAT);
  315.   glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T, GL_REPEAT);
  316.   glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_R_EXT, GL_REPEAT);
  317.   glTexImage3DEXT(GL_TEXTURE_3D_EXT, 0, GL_LUMINANCE8_ALPHA8_EXT,
  318.     vol_width, vol_height, vol_depth,
  319.     0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, voxels);
  320. #endif
  321.   if (tex3dSupported) {
  322.     /* enable texturing, blending etc */
  323.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  324.     glEnable(GL_BLEND);
  325.   }
  326.   setMatrix();
  327. }
  328. void
  329. init(void)
  330. {
  331.   /* angle of rotation about coordinate axes */
  332.   anglex = angley = anglez = 0.0;
  333. }
  334. void
  335. invert4d(float from[4][4], float to[4][4])
  336. {
  337.   /* 4x4 matrix inversion routine */
  338.   float wtemp[4][8];
  339.   register float m0, m1, m2, m3, s;
  340.   register float *r0, *r1, *r2, *r3, *rtemp;
  341.   r0 = wtemp[0];
  342.   r1 = wtemp[1];
  343.   r2 = wtemp[2];
  344.   r3 = wtemp[3];
  345.   r0[0] = from[0][0];   /* build up [A][I] */
  346.   r0[1] = from[0][1];
  347.   r0[2] = from[0][2];
  348.   r0[3] = from[0][3];
  349.   r0[4] = 1.0;
  350.   r0[5] = 0.0;
  351.   r0[6] = 0.0;
  352.   r0[7] = 0.0;
  353.   r1[0] = from[1][0];
  354.   r1[1] = from[1][1];
  355.   r1[2] = from[1][2];
  356.   r1[3] = from[1][3];
  357.   r1[4] = 0.0;
  358.   r1[5] = 1.0;
  359.   r1[6] = 0.0;
  360.   r1[7] = 0.0;
  361.   r2[0] = from[2][0];
  362.   r2[1] = from[2][1];
  363.   r2[2] = from[2][2];
  364.   r2[3] = from[2][3];
  365.   r2[4] = 0.0;
  366.   r2[5] = 0.0;
  367.   r2[6] = 1.0;
  368.   r2[7] = 0.0;
  369.   r3[0] = from[3][0];
  370.   r3[1] = from[3][1];
  371.   r3[2] = from[3][2];
  372.   r3[3] = from[3][3];
  373.   r3[4] = 0.0;
  374.   r3[5] = 0.0;
  375.   r3[6] = 0.0;
  376.   r3[7] = 1.0;
  377.   if (r0[0] == 0.0) {   /* swap rows if needed */
  378.     if (r1[0] == 0.0) {
  379.       if (r2[0] == 0.0) {
  380.         if (r3[0] == 0.0)
  381.           goto singular;
  382.         rtemp = r0;
  383.         r0 = r3;
  384.         r3 = rtemp;
  385.       } else {
  386.         rtemp = r0;
  387.         r0 = r2;
  388.         r2 = rtemp;
  389.       }
  390.     } else {
  391.       rtemp = r0;
  392.       r0 = r1;
  393.       r1 = rtemp;
  394.     }
  395.   }
  396.   m1 = r1[0] / r0[0];   /* eliminate first variable */
  397.   m2 = r2[0] / r0[0];
  398.   m3 = r3[0] / r0[0];
  399.   s = r0[1];
  400.   r1[1] = r1[1] - m1 * s;
  401.   r2[1] = r2[1] - m2 * s;
  402.   r3[1] = r3[1] - m3 * s;
  403.   s = r0[2];
  404.   r1[2] = r1[2] - m1 * s;
  405.   r2[2] = r2[2] - m2 * s;
  406.   r3[2] = r3[2] - m3 * s;
  407.   s = r0[3];
  408.   r1[3] = r1[3] - m1 * s;
  409.   r2[3] = r2[3] - m2 * s;
  410.   r3[3] = r3[3] - m3 * s;
  411.   s = r0[4];
  412.   if (s != 0.0) {
  413.     r1[4] = r1[4] - m1 * s;
  414.     r2[4] = r2[4] - m2 * s;
  415.     r3[4] = r3[4] - m3 * s;
  416.   }
  417.   s = r0[5];
  418.   if (s != 0.0) {
  419.     r1[5] = r1[5] - m1 * s;
  420.     r2[5] = r2[5] - m2 * s;
  421.     r3[5] = r3[5] - m3 * s;
  422.   }
  423.   s = r0[6];
  424.   if (s != 0.0) {
  425.     r1[6] = r1[6] - m1 * s;
  426.     r2[6] = r2[6] - m2 * s;
  427.     r3[6] = r3[6] - m3 * s;
  428.   }
  429.   s = r0[7];
  430.   if (s != 0.0) {
  431.     r1[7] = r1[7] - m1 * s;
  432.     r2[7] = r2[7] - m2 * s;
  433.     r3[7] = r3[7] - m3 * s;
  434.   }
  435.   if (r1[1] == 0.0) {   /* swap rows if needed */
  436.     if (r2[1] == 0.0) {
  437.       if (r3[1] == 0.0)
  438.         goto singular;
  439.       rtemp = r1;
  440.       r1 = r3;
  441.       r3 = rtemp;
  442.     } else {
  443.       rtemp = r1;
  444.       r1 = r2;
  445.       r2 = rtemp;
  446.     }
  447.   }
  448.   m2 = r2[1] / r1[1];   /* eliminate second variable */
  449.   m3 = r3[1] / r1[1];
  450.   r2[2] = r2[2] - m2 * r1[2];
  451.   r3[2] = r3[2] - m3 * r1[2];
  452.   r3[3] = r3[3] - m3 * r1[3];
  453.   r2[3] = r2[3] - m2 * r1[3];
  454.   s = r1[4];
  455.   if (s != 0.0) {
  456.     r2[4] = r2[4] - m2 * s;
  457.     r3[4] = r3[4] - m3 * s;
  458.   }
  459.   s = r1[5];
  460.   if (s != 0.0) {
  461.     r2[5] = r2[5] - m2 * s;
  462.     r3[5] = r3[5] - m3 * s;
  463.   }
  464.   s = r1[6];
  465.   if (s != 0.0) {
  466.     r2[6] = r2[6] - m2 * s;
  467.     r3[6] = r3[6] - m3 * s;
  468.   }
  469.   s = r1[7];
  470.   if (s != 0.0) {
  471.     r2[7] = r2[7] - m2 * s;
  472.     r3[7] = r3[7] - m3 * s;
  473.   }
  474.   if (r2[2] == 0.0) {   /* swap last 2 rows if needed */
  475.     if (r3[2] == 0.0)
  476.       goto singular;
  477.     rtemp = r2;
  478.     r2 = r3;
  479.     r3 = rtemp;
  480.   }
  481.   m3 = r3[2] / r2[2];   /* eliminate third variable */
  482.   r3[3] = r3[3] - m3 * r2[3];
  483.   r3[4] = r3[4] - m3 * r2[4];
  484.   r3[5] = r3[5] - m3 * r2[5];
  485.   r3[6] = r3[6] - m3 * r2[6];
  486.   r3[7] = r3[7] - m3 * r2[7];
  487.   if (r3[3] == 0.0)
  488.     goto singular;
  489.   s = 1.0 / r3[3];      /* now back substitute row 3 */
  490.   r3[4] = r3[4] * s;
  491.   r3[5] = r3[5] * s;
  492.   r3[6] = r3[6] * s;
  493.   r3[7] = r3[7] * s;
  494.   m2 = r2[3];           /* now back substitute row 2 */
  495.   s = 1.0 / r2[2];
  496.   r2[4] = s * (r2[4] - r3[4] * m2);
  497.   r2[5] = s * (r2[5] - r3[5] * m2);
  498.   r2[6] = s * (r2[6] - r3[6] * m2);
  499.   r2[7] = s * (r2[7] - r3[7] * m2);
  500.   m1 = r1[3];
  501.   r1[4] = (r1[4] - r3[4] * m1);
  502.   r1[5] = (r1[5] - r3[5] * m1);
  503.   r1[6] = (r1[6] - r3[6] * m1);
  504.   r1[7] = (r1[7] - r3[7] * m1);
  505.   m0 = r0[3];
  506.   r0[4] = (r0[4] - r3[4] * m0);
  507.   r0[5] = (r0[5] - r3[5] * m0);
  508.   r0[6] = (r0[6] - r3[6] * m0);
  509.   r0[7] = (r0[7] - r3[7] * m0);
  510.   m1 = r1[2];           /* now back substitute row 1 */
  511.   s = 1.0 / r1[1];
  512.   r1[4] = s * (r1[4] - r2[4] * m1);
  513.   r1[5] = s * (r1[5] - r2[5] * m1);
  514.   r1[6] = s * (r1[6] - r2[6] * m1);
  515.   r1[7] = s * (r1[7] - r2[7] * m1);
  516.   m0 = r0[2];
  517.   r0[4] = (r0[4] - r2[4] * m0);
  518.   r0[5] = (r0[5] - r2[5] * m0);
  519.   r0[6] = (r0[6] - r2[6] * m0);
  520.   r0[7] = (r0[7] - r2[7] * m0);
  521.   m0 = r0[1];           /* now back substitute row 0 */
  522.   s = 1.0 / r0[0];
  523.   r0[4] = s * (r0[4] - r1[4] * m0);
  524.   r0[5] = s * (r0[5] - r1[5] * m0);
  525.   r0[6] = s * (r0[6] - r1[6] * m0);
  526.   r0[7] = s * (r0[7] - r1[7] * m0);
  527.   to[0][0] = r0[4];     /* copy results back */
  528.   to[0][1] = r0[5];
  529.   to[0][2] = r0[6];
  530.   to[0][3] = r0[7];
  531.   to[1][0] = r1[4];
  532.   to[1][1] = r1[5];
  533.   to[1][2] = r1[6];
  534.   to[1][3] = r1[7];
  535.   to[2][0] = r2[4];
  536.   to[2][1] = r2[5];
  537.   to[2][2] = r2[6];
  538.   to[2][3] = r2[7];
  539.   to[3][0] = r3[4];
  540.   to[3][1] = r3[5];
  541.   to[3][2] = r3[6];
  542.   to[3][3] = r3[7];
  543.   return;
  544. singular:
  545.   printf("ERROR : non_invertable transformn");
  546.   return;
  547. }
  548. void
  549. normalize(float *xn, float *yn, float *zn)
  550. {
  551.   double denom;
  552.   denom = sqrt((double) ((*xn * *xn) + (*yn * *yn) + (*zn * *zn)));
  553.   *xn = *xn / denom;
  554.   *yn = *yn / denom;
  555.   *zn = *zn / denom;
  556. }
  557. int
  558. getViewAxis(void)
  559. {
  560.   float viewDir[3];
  561.   float mat[4][4], vinv[4][4];
  562.   float maxf, xy, yz, zx;
  563.   int im;
  564.   /* out of 3 orthogonal set of planes in world coords,  find out which one
  565.      has maximum angle from the line of  sight.
  566.      we will use these set of planes for creating polygonal slices thru the
  567.      voxel space */
  568.   glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) mat);
  569.   invert4d(mat, vinv);
  570.   viewDir[0] = -vinv[2][0];
  571.   viewDir[1] = -vinv[2][1];
  572.   viewDir[2] = -vinv[2][2];
  573.   normalize(&viewDir[0], &viewDir[1], &viewDir[2]);
  574.   xy = viewDir[2];      /* simplified because 0*xx + 0*yy + 1*zz */
  575.   yz = viewDir[0];
  576.   zx = viewDir[1];
  577.   maxf = ABS(xy);
  578.   im = (xy < 0.0) ? _XY : _MXY;
  579.   if (maxf <= ABS(yz)) {
  580.     maxf = ABS(yz);
  581.     im = (yz < 0.0) ? _YZ : _MYZ;
  582.   }
  583.   if (maxf <= ABS(zx)) {
  584.     maxf = ABS(zx);
  585.     im = (zx < 0.0) ? _ZX : _MZX;
  586.   }
  587.   return (im);
  588. }
  589. #define DRAW_SLICE 
  590.             if (tex3dSupported) {
  591.               glBegin(GL_POLYGON);
  592.       for (p=0;p<4;p++) {
  593. glTexCoord3fv(slice_tcoord[myaxis][p]);
  594. glVertex3fv(slice_poly[myaxis][p]);
  595.       }
  596.       glEnd();
  597.     } 
  598.             else {
  599.               glBegin(GL_LINE_LOOP);
  600.       for (p=0;p<4;p++){
  601. glVertex3fv(slice_poly[myaxis][p]);
  602.       }
  603.       glEnd();
  604.     }
  605. void
  606. drawScene(void)
  607. {
  608.   int i, p;
  609.   float tc;
  610.   int viewAxis, myaxis;
  611.   int sign;
  612.   static int myaxis_lut[] =
  613.   {0, 0, 1, 2, 0, 1, 2};
  614.   /* clear background, z buffer etc */
  615.   glClear(GL_COLOR_BUFFER_BIT);
  616.   glPushMatrix();
  617.   /* apply all the modeling transformations */
  618.   glTranslatef(0.0, 0.0, -bdiag);
  619.   glRotatef(anglex, 1.0, 0.0, 0.0);
  620.   glRotatef(angley, 0.0, 1.0, 0.0);
  621.   glRotatef(anglez, 0.0, 0.0, 1.0);
  622.   /* getViewAxis(), determines which set of polygons need to be used for
  623.      texturing, depending upon the viewing direction */
  624.   viewAxis = getViewAxis();
  625.   myaxis = myaxis_lut[viewAxis];
  626.   glColor3f(1.0, 1.0, 1.0);
  627. #ifdef GL_EXT_texture3D
  628.   if (tex3dSupported)
  629.     glEnable(GL_TEXTURE_3D_EXT);
  630. #endif
  631.   switch (viewAxis) {
  632.   case _XY:
  633.   case _MXY:
  634.     sign = (viewAxis == _XY) ? 1 : -1;
  635.     tc = (viewAxis == _XY) ? 0.0 : 1.0;
  636.     glTranslatef(0.0, 0.0, -sign * vol_depth / 2.0);
  637.     for (i = 0; i < n_slices; i++) {
  638.       slice_tcoord[0][0][2] = slice_tcoord[0][1][2] =
  639.         slice_tcoord[0][2][2] = slice_tcoord[0][3][2] = tc;
  640.       tc += sign * 1.0 / n_slices;
  641.       glTranslatef(0.0, 0.0, sign * vol_depth / (n_slices + 1.0));
  642.       DRAW_SLICE;
  643.     }
  644.     break;
  645.   case _YZ:
  646.   case _MYZ:
  647.     sign = (viewAxis == _YZ) ? 1 : -1;
  648.     tc = (viewAxis == _YZ) ? 0.0 : 1.0;
  649.     glTranslatef(-sign * vol_width / 2.0, 0.0, 0.0);
  650.     for (i = 0; i < n_slices; i++) {
  651.       slice_tcoord[1][0][0] = slice_tcoord[1][1][0] =
  652.         slice_tcoord[1][2][0] = slice_tcoord[1][3][0] = tc;
  653.       tc += sign * 1.0 / n_slices;
  654.       glTranslatef(sign * vol_width / (n_slices + 1.0), 0.0, 0.0);
  655.       DRAW_SLICE;
  656.     }
  657.     break;
  658.   case _ZX:
  659.   case _MZX:
  660.     sign = (viewAxis == _ZX) ? 1 : -1;
  661.     tc = (viewAxis == _ZX) ? 0.0 : 1.0;
  662.     glTranslatef(0.0, -sign * vol_height / 2.0, 0.0);
  663.     for (i = 0; i < n_slices; i++) {
  664.       slice_tcoord[2][0][1] = slice_tcoord[2][1][1] =
  665.         slice_tcoord[2][2][1] = slice_tcoord[2][3][1] = tc;
  666.       tc += sign * 1.0 / n_slices;
  667.       glTranslatef(0.0, sign * vol_height / (n_slices + 1.0), 0.0);
  668.       DRAW_SLICE;
  669.     }
  670.     break;
  671.   }
  672. #ifdef GL_EXT_texture3D
  673.   if (tex3dSupported)
  674.     glDisable(GL_TEXTURE_3D_EXT);
  675. #endif
  676.   glPopMatrix();
  677.   glutSwapBuffers();
  678. }
  679. void
  680. resize(int w, int h)
  681. {
  682.   /* things you do, when the user resizes the window */
  683.   width = w;
  684.   height = h;
  685.   glViewport(0, 0, w, h);
  686.   setMatrix();
  687. }
  688. /* ARGSUSED1 */
  689. void
  690. keyboard(unsigned char c, int x, int y)
  691. {
  692.   /* handle key board input */
  693.   switch (c) {
  694.   case 27:
  695.     exit(0);
  696.     break;
  697.   case 'x':
  698.     anglex += 1.0;
  699.     drawScene();
  700.     break;
  701.   case 'y':
  702.     angley += 1.0;
  703.     drawScene();
  704.     break;
  705.   case 'z':
  706.     anglez += 1.0;
  707.     drawScene();
  708.     break;
  709.   case 'm':
  710.     n_slices++;
  711.     drawScene();
  712.     break;
  713.   case 'e':
  714.     n_slices--;
  715.     if (n_slices < 4)
  716.       n_slices = 4;
  717.     drawScene();
  718.     break;
  719.   case 's':
  720.     if (left < right + 10.0) {
  721.       left -= 1.0;
  722.       right += 1.0;
  723.       bottom -= 1.0;
  724.       top += 1.0;
  725.       setMatrix();
  726.       drawScene();
  727.     }
  728.     break;
  729.   case 'l':
  730.     left += 1.0;
  731.     right -= 1.0;
  732.     bottom += 1.0;
  733.     top -= 1.0;
  734.     setMatrix();
  735.     drawScene();
  736.     break;
  737.   default:
  738.     break;
  739.   }
  740. }
  741. void
  742. main(int argc, char **argv)
  743. {
  744.   int i, mode = GLUT_DOUBLE;
  745.   glutInit(&argc, argv);
  746.   for (i = 1; i < argc; i++) {
  747.     if (!strcmp(argv[i], "-no3Dtex")) {
  748.       tex3dSupported = 0;
  749.     } else if (!strcmp(argv[i], "-sb")) {
  750.       mode = GLUT_SINGLE;
  751.     }
  752.   }
  753.   /* let glut do all the X Stuff */
  754.   glutInitDisplayMode(GLUT_RGB | mode);
  755.   glutCreateWindow("Voxel Head");
  756.   /* init our variables, etc */
  757.   init();
  758.   /* read texture data from a file */
  759.   readVoxelData();
  760.   /* set up OpenGL texturing */
  761.   if (tex3dSupported)
  762.     load3DTexture();
  763.   /* register specific routines to glut */
  764.   glutDisplayFunc(drawScene);
  765.   glutReshapeFunc(resize);
  766.   glutKeyboardFunc(keyboard);
  767.   /* create popup menu for glut */
  768.   glutCreateMenu(menu);
  769.   glutAddMenuEntry("Random Spin ON", SPIN_ON);
  770.   glutAddMenuEntry("Help", MENU_HELP);
  771.   glutAddMenuEntry("Exit", MENU_EXIT);
  772.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  773.   /* loop for ever */
  774.   glutMainLoop();
  775. }