home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / xform.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  29KB  |  1,116 lines

  1. /* $Id: xform.c,v 1.32 1996/04/25 20:42:13 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995-1996  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Log: xform.c,v $
  26.  * Revision 1.32  1996/04/25  20:42:13  brianp
  27.  * replaced gl_alloc_depth_buffer() call with DD.alloc_depth_buffer()
  28.  *
  29.  * Revision 1.31  1996/04/18  14:55:31  brianp
  30.  * fixed a few erroneous error messages
  31.  *
  32.  * Revision 1.30  1996/04/11  20:03:16  brianp
  33.  * fixed CC.IdentityTexMat bug, cleaned up glTranslate() and glScale() code
  34.  *
  35.  * Revision 1.29  1996/03/22  20:54:08  brianp
  36.  * removed CC.ClipSpans stuff
  37.  *
  38.  * Revision 1.28  1996/02/23  17:10:40  brianp
  39.  * optimized matmul() and gl_transform_vector() per Jean-Luc Daems
  40.  *
  41.  * Revision 1.27  1996/02/19  21:50:00  brianp
  42.  * added support for software alpha buffering
  43.  *
  44.  * Revision 1.26  1996/02/15  16:52:29  brianp
  45.  * renamed a few transformation functions and added gl_xform_points_3fv()
  46.  *
  47.  * Revision 1.25  1995/12/30  17:19:58  brianp
  48.  * new, faster glTranslate and glScale functions
  49.  *
  50.  * Revision 1.24  1995/12/19  17:07:49  brianp
  51.  * new implementation of glMatrixMode
  52.  *
  53.  * Revision 1.23  1995/12/12  21:47:15  brianp
  54.  * optimized gl_transform_vertices() by checking for common matrix values
  55.  *
  56.  * Revision 1.22  1995/10/31  19:40:35  brianp
  57.  * removed INLINE macro, more trouble than it was worth
  58.  *
  59.  * Revision 1.21  1995/10/16  15:26:56  brianp
  60.  * replaced dd_buffer_info with DD.buffer_size call
  61.  *
  62.  * Revision 1.20  1995/09/30  15:35:13  brianp
  63.  * added test for identity texture matrix in gl_mult_matrix
  64.  *
  65.  * Revision 1.19  1995/09/27  18:31:40  brianp
  66.  * added gl_transform_normals
  67.  *
  68.  * Revision 1.18  1995/09/26  16:05:26  brianp
  69.  * removed gl_transform_point, gl_transform_normal
  70.  * added gl_transform_points
  71.  *
  72.  * Revision 1.17  1995/09/13  14:42:23  brianp
  73.  * added logic to test for identity texture matrix
  74.  *
  75.  * Revision 1.16  1995/07/24  20:35:20  brianp
  76.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  77.  *
  78.  * Revision 1.15  1995/07/24  18:58:28  brianp
  79.  * correct gl_viewport() semantics, introduced CC.ClipSpans flag
  80.  *
  81.  * Revision 1.14  1995/06/21  15:11:08  brianp
  82.  * better allocation policy for depth, stencil buffer in gl_viewport
  83.  *
  84.  * Revision 1.13  1995/06/20  16:26:32  brianp
  85.  * removed fudge value from viewport transformation scale and translation
  86.  *
  87.  * Revision 1.12  1995/05/22  21:02:41  brianp
  88.  * Release 1.2
  89.  *
  90.  * Revision 1.11  1995/05/12  16:57:22  brianp
  91.  * replaced CC.Mode!=0 with INSIDE_BEGIN_END
  92.  *
  93.  * Revision 1.10  1995/04/19  13:48:18  brianp
  94.  * renamed occurances of near and far for SCO x86 Unix
  95.  *
  96.  * Revision 1.9  1995/04/01  16:17:47  brianp
  97.  * fixed mult_matrix bug in glTranslatef and glScalef
  98.  *
  99.  * Revision 1.8  1995/03/28  16:10:33  brianp
  100.  * removed singular matrix error message
  101.  *
  102.  * Revision 1.7  1995/03/22  21:37:47  brianp
  103.  * removed mode from dd_buffer_info()
  104.  *
  105.  * Revision 1.6  1995/03/10  17:13:20  brianp
  106.  * new matmul and invert_matrix functions from Thomas Malik
  107.  *
  108.  * Revision 1.5  1995/03/10  15:19:43  brianp
  109.  * added divide by zero check to gl_transform_normal
  110.  *
  111.  * Revision 1.4  1995/03/09  21:42:30  brianp
  112.  * new ModelViewInv matrix logic
  113.  *
  114.  * Revision 1.3  1995/03/09  20:08:48  brianp
  115.  * changed order of arguments to gl_transform_ functions to be more logical
  116.  *
  117.  * Revision 1.2  1995/03/04  19:29:44  brianp
  118.  * 1.1 beta revision
  119.  *
  120.  * Revision 1.1  1995/02/24  14:28:31  brianp
  121.  * Initial revision
  122.  *
  123.  */
  124.  
  125.  
  126. /*
  127.  * Geometry Transformation.
  128.  *
  129.  *
  130.  * NOTES:
  131.  * 1. 4x4 transformation matrices are stored in memory in column major order.
  132.  * 2. Points/vertices are to be thought of as column vectors.
  133.  * 3. Transformation of a point p by a matrix M is: p' = M * p
  134.  *
  135.  */
  136.  
  137.  
  138.  
  139. #include <math.h>
  140. #include <stdio.h>
  141. #include <stdlib.h>
  142. #include <string.h>
  143. #include "alphabuf.h"
  144. #include "context.h"
  145. #include "depth.h"
  146. #include "dd.h"
  147. #include "list.h"
  148. #include "macros.h"
  149. #include "stencil.h"
  150.  
  151.  
  152.  
  153. #ifndef M_PI
  154. #  define M_PI (3.1415926)
  155. #endif
  156.  
  157.  
  158.  
  159. static GLfloat Identity[16] = {
  160.    1.0, 0.0, 0.0, 0.0,
  161.    0.0, 1.0, 0.0, 0.0,
  162.    0.0, 0.0, 1.0, 0.0,
  163.    0.0, 0.0, 0.0, 1.0
  164. };
  165.  
  166.  
  167.  
  168.  
  169. #ifdef DEBUG
  170. static void print_matrix( const GLfloat m[16] )
  171. {
  172.    int i;
  173.  
  174.    for (i=0;i<4;i++) {
  175.       printf("%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] );
  176.    }
  177. }
  178. #endif
  179.  
  180.  
  181.  
  182. /*
  183.  * Perform a 4x4 matrix multiplication  (product = a x b).
  184.  * Input:  a, b - matrices to multiply
  185.  * Output:  product - product of a and b
  186.  */
  187. static void
  188. matmul( GLfloat *product, const GLfloat *a, const GLfloat *b )
  189. {
  190.    /* This matmul was contributed by Thomas Malik */
  191.    GLfloat temp[16];
  192.    GLint i;
  193.  
  194. #define A(row,col)  a[(col<<2)+row]
  195. #define B(row,col)  b[(col<<2)+row]
  196. #define T(row,col)  temp[(col<<2)+row]
  197.  
  198.    /* i-te Zeile */
  199.    for (i = 0; i < 4; i++) {
  200.       GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
  201.       T(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
  202.       T(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
  203.       T(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
  204.       T(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
  205.    }
  206.  
  207. #undef A
  208. #undef B
  209. #undef T
  210.    MEMCPY( product, temp, 16*sizeof(GLfloat) );
  211. }
  212.  
  213.  
  214.  
  215. /*
  216.  * Find the inverse of the 4 by 4 matrix b using gausian elimination
  217.  * and return it in a.
  218.  *
  219.  * This function was contributed by Thomas Malik (malik@rhrk.uni-kl.de).
  220.  * Thanks Thomas!
  221.  */
  222. static void invert_matrix(const GLfloat *b,GLfloat * a)
  223. {
  224. #define MAT(m,r,c) ((m)[(c)*4+(r)])
  225.  
  226.   GLfloat val, val2;
  227.   GLint   i, j, k, ind;
  228.   GLfloat tmp[16];
  229.  
  230.   MEMCPY(a,Identity,sizeof(float)*16);
  231.   MEMCPY(tmp, b,sizeof(float)*16);
  232.  
  233.   for (i = 0; i != 4; i++) {
  234.  
  235.     val = MAT(tmp,i,i);            /* find pivot */
  236.     ind = i;
  237.     for (j = i + 1; j != 4; j++) {
  238.       if (fabs(MAT(tmp,j,i)) > fabs(val)) {
  239.     ind = j;
  240.     val = MAT(tmp,j,i);
  241.       }
  242.     }
  243.  
  244.     if (ind != i) {            /* swap columns */
  245.       for (j = 0; j != 4; j++) {
  246.     val2 = MAT(a,i,j);
  247.     MAT(a,i,j) = MAT(a,ind,j);
  248.     MAT(a,ind,j) = val2;
  249.     val2 = MAT(tmp,i,j);
  250.     MAT(tmp,i,j) = MAT(tmp,ind,j);
  251.     MAT(tmp,ind,j) = val2;
  252.       }
  253.     }
  254.  
  255.     if (val == 0.0F) {    
  256.        /* The matrix is singular (has no inverse).  This isn't really
  257.     * an error since singular matrices can be used for projecting
  258.     * shadows, etc.  We let the inverse be the identity matrix.
  259.     */
  260.        /*fprintf(stderr,"Singular matrix, no inverse!\n");*/
  261.        MEMCPY( a, Identity, 16*sizeof(GLfloat) );
  262.        return;
  263.     }
  264.  
  265.     for (j = 0; j != 4; j++) {
  266.       MAT(tmp,i,j) /= val;
  267.       MAT(a,i,j) /= val;
  268.     }
  269.  
  270.     for (j = 0; j != 4; j++) {        /* eliminate column */
  271.       if (j == i)
  272.     continue;
  273.       val = MAT(tmp,j,i);
  274.       for (k = 0; k != 4; k++) {
  275.     MAT(tmp,j,k) -= MAT(tmp,i,k) * val;
  276.     MAT(a,j,k) -= MAT(a,i,k) * val;
  277.       }
  278.     }
  279.   }
  280. #undef MAT
  281. }
  282.  
  283.  
  284.  
  285.  
  286. /*
  287.  * Compute the inverse of the current ModelViewMatrix.
  288.  */
  289. void gl_compute_modelview_inverse( void )
  290. {
  291.    invert_matrix( CC.ModelViewMatrix, CC.ModelViewInv );
  292.    CC.ModelViewInvValid = GL_TRUE;
  293. }
  294.  
  295.  
  296.  
  297. /*
  298.  * Apply a transformation matrix to an array of [X Y Z W] coordinates:
  299.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  300.  * where p[i] and q[i] are 4-element column vectors and m is a 16-element
  301.  * transformation matrix.
  302.  */
  303. void gl_xform_points_4fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
  304.                           GLfloat p[][4] )
  305. {
  306.    /* This function has been carefully crafted to maximize register usage
  307.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  308.     * will like this code too.
  309.     */
  310.    {
  311.       GLuint i;
  312.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  313.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  314.       if (m12==0.0F && m13==0.0F) {
  315.          /* common case */
  316.          for (i=0;i<n;i++) {
  317.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  318.             q[i][0] = m0 * p0 + m4  * p1 + m8 * p2;
  319.             q[i][1] = m1 * p0 + m5  * p1 + m9 * p2;
  320.          }
  321.       }
  322.       else {
  323.          /* general case */
  324.          for (i=0;i<n;i++) {
  325.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  326.             q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12 * p3;
  327.             q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13 * p3;
  328.          }
  329.       }
  330.    }
  331.    {
  332.       GLuint i;
  333.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  334.       GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  335.       if (m3==0.0F && m7==0.0F && m11==0.0F && m15==1.0F) {
  336.          /* common case */
  337.          for (i=0;i<n;i++) {
  338.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  339.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  340.             q[i][3] = p3;
  341.          }
  342.       }
  343.       else {
  344.          /* general case */
  345.          for (i=0;i<n;i++) {
  346.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  347.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  348.             q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15 * p3;
  349.          }
  350.       }
  351.    }
  352. }
  353.  
  354.  
  355.  
  356. /*
  357.  * Apply a transformation matrix to an array of [X Y Z] coordinates:
  358.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  359.  */
  360. void gl_xform_points_3fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
  361.                           GLfloat p[][3] )
  362. {
  363.    /* This function has been carefully crafted to maximize register usage
  364.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  365.     * will like this code too.
  366.     */
  367.    {
  368.       GLuint i;
  369.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  370.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  371.       for (i=0;i<n;i++) {
  372.          GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  373.          q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12;
  374.          q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13;
  375.       }
  376.    }
  377.    {
  378.       GLuint i;
  379.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  380.       GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  381.       if (m3==0.0F && m7==0.0F && m11==0.0F && m15==1.0F) {
  382.          /* common case */
  383.          for (i=0;i<n;i++) {
  384.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  385.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14;
  386.             q[i][3] = 1.0F;
  387.          }
  388.       }
  389.       else {
  390.          /* general case */
  391.          for (i=0;i<n;i++) {
  392.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  393.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14;
  394.             q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15;
  395.          }
  396.       }
  397.    }
  398. }
  399.  
  400.  
  401.  
  402. /*
  403.  * Apply a transformation matrix to an array of normal vectors:
  404.  *   for i in 0 to n-1 do  v[i] = u[i] * m
  405.  * where u[i] and v[i] are 3-element row vectors and m is a 16-element
  406.  * transformation matrix.
  407.  * If the normalize flag is true the normals will be scaled to length 1.
  408.  */
  409. void gl_xform_normals_3fv( GLuint n, GLfloat v[][3], const GLfloat m[16],
  410.                            GLfloat u[][3], GLboolean normalize )
  411. {
  412.    if (normalize) {
  413.       /* Transform normals and scale to unit length */
  414.       GLuint i;
  415.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  416.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  417.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  418.       for (i=0;i<n;i++) {
  419.          GLdouble tx, ty, tz;
  420.          {
  421.             GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  422.             tx = ux * m0 + uy * m1 + uz * m2;
  423.             ty = ux * m4 + uy * m5 + uz * m6;
  424.             tz = ux * m8 + uy * m9 + uz * m10;
  425.          }
  426.          {
  427.             GLdouble len, scale;
  428.             len = sqrt( tx*tx + ty*ty + tz*tz );
  429.             scale = (len>0.00001) ? (1.0 / len) : 1.0;
  430.             v[i][0] = tx * scale;
  431.             v[i][1] = ty * scale;
  432.             v[i][2] = tz * scale;
  433.          }
  434.       }
  435.    }
  436.    else {
  437.       /* Just transform normals, don't scale */
  438.       GLuint i;
  439.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  440.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  441.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  442.       for (i=0;i<n;i++) {
  443.          GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  444.          v[i][0] = ux * m0 + uy * m1 + uz * m2;
  445.          v[i][1] = ux * m4 + uy * m5 + uz * m6;
  446.          v[i][2] = ux * m8 + uy * m9 + uz * m10;
  447.       }
  448.    }
  449. }
  450.  
  451.  
  452.  
  453. /*
  454.  * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix.  This
  455.  * function is used for transforming clipping plane equations and spotlight
  456.  * directions.
  457.  * Mathematically,  u = v * m.
  458.  * Input:  v - input vector
  459.  *         m - transformation matrix
  460.  * Output:  u - transformed vector
  461.  */
  462. void gl_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
  463. {
  464.    GLfloat v0=v[0], v1=v[1], v2=v[2], v3=v[3];
  465. #define M(row,col)  m[col*4+row]
  466.    u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
  467.    u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
  468.    u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
  469.    u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
  470. #undef M
  471. }
  472.  
  473.  
  474.  
  475. void glMatrixMode( GLenum mode )
  476. {
  477.    if (CC.CompileFlag) {
  478.       gl_save_matrixmode( mode );
  479.    }
  480.    if (CC.ExecuteFlag) {
  481.       if (INSIDE_BEGIN_END) {
  482.          gl_error( GL_INVALID_OPERATION, "glMatrixMode" );
  483.          return;
  484.       }
  485.       switch (mode) {
  486.          case GL_MODELVIEW:
  487.          case GL_PROJECTION:
  488.          case GL_TEXTURE:
  489.             CC.Transform.MatrixMode = mode;
  490.             break;
  491.          default:
  492.             gl_error( GL_INVALID_ENUM, "glMatrixMode" );
  493.       }
  494.    }
  495. }
  496.  
  497.  
  498.  
  499. void glOrtho( GLdouble left, GLdouble right,
  500.           GLdouble bottom, GLdouble top,
  501.           GLdouble nearval, GLdouble farval )
  502. {
  503.    GLfloat x, y, z;
  504.    GLfloat tx, ty, tz;
  505.    GLfloat m[16];
  506.  
  507.    x = 2.0 / (right-left);
  508.    y = 2.0 / (top-bottom);
  509.    z = -2.0 / (farval-nearval);
  510.    tx = -(right+left) / (right-left);
  511.    ty = -(top+bottom) / (top-bottom);
  512.    tz = -(farval+nearval) / (farval-nearval);
  513.  
  514. #define M(row,col)  m[col*4+row]
  515.    M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = 0.0F;  M(0,3) = tx;
  516.    M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = 0.0F;  M(1,3) = ty;
  517.    M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = z;     M(2,3) = tz;
  518.    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = 0.0F;  M(3,3) = 1.0F;
  519. #undef M
  520.  
  521.    glMultMatrixf( m );
  522. }
  523.  
  524.  
  525.  
  526. void glFrustum( GLdouble left, GLdouble right,
  527.         GLdouble bottom, GLdouble top,
  528.         GLdouble nearval, GLdouble farval )
  529. {
  530.    GLfloat x, y, a, b, c, d;
  531.    GLfloat m[16];
  532.  
  533.    if (nearval<=0.0 || farval<=0.0) {
  534.       gl_error( GL_INVALID_VALUE, "glFrustum(near or far)" );
  535.    }
  536.  
  537.    x = (2.0*nearval) / (right-left);
  538.    y = (2.0*nearval) / (top-bottom);
  539.    a = (right+left) / (right-left);
  540.    b = (top+bottom) / (top-bottom);
  541.    c = -(farval+nearval) / ( farval-nearval);
  542.    d = -(2.0*farval*nearval) / (farval-nearval);  /* error? */
  543.  
  544. #define M(row,col)  m[col*4+row]
  545.    M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = a;      M(0,3) = 0.0F;
  546.    M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = b;      M(1,3) = 0.0F;
  547.    M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = c;      M(2,3) = d;
  548.    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;
  549. #undef M
  550.  
  551.    glMultMatrixf( m );
  552. }
  553.  
  554.  
  555.  
  556. /*
  557.  * Define a new viewport and reallocate auxillary buffers if the size of
  558.  * the window (color buffer) has changed.
  559.  */
  560. void gl_viewport( GLint x, GLint y, GLsizei width, GLsizei height )
  561. {
  562.    GLint newsize;
  563.    GLuint buf_width, buf_height, buf_depth;
  564.  
  565.    if (width<0 || height<0) {
  566.       gl_error( GL_INVALID_VALUE, "glViewport" );
  567.       return;
  568.    }
  569.    if (INSIDE_BEGIN_END) {
  570.       gl_error( GL_INVALID_OPERATION, "glViewport" );
  571.       return;
  572.    }
  573.  
  574. #ifdef LEAVEOUT
  575.    /* clamp x, y, width, and height to implementation dependent range */
  576.    x = CLAMP( x, 0, MAX_WIDTH-1 );
  577.    y = CLAMP( y, 0, MAX_HEIGHT-1 );
  578.    if (width<1) {
  579.       width = 1;
  580.    }
  581.    if (height<1) {
  582.       height = 1;
  583.    }
  584.    if (x+width>MAX_WIDTH) {
  585.       width = MAX_WIDTH - x;
  586.    }
  587.    if (y+height>MAX_HEIGHT) {
  588.       height = MAX_HEIGHT - y;
  589.    }
  590. #endif
  591.  
  592.    /* ask device driver for size of output buffer */
  593.    (*DD.buffer_size)( &buf_width, &buf_height, &buf_depth );
  594.  
  595.    /* see if size of device driver buffer has changed */
  596.    newsize = CC.BufferWidth!=buf_width || CC.BufferHeight!=buf_height;
  597.  
  598.    /* save buffer size */
  599.    CC.BufferWidth = buf_width;
  600.    CC.BufferHeight = buf_height;
  601.  
  602.    /* Save viewport */
  603.    CC.Viewport.X = x;
  604.    CC.Viewport.Width = width;
  605.    CC.Viewport.Y = y;
  606.    CC.Viewport.Height = height;
  607.  
  608.    /* compute scale and bias values */
  609.    CC.Viewport.Sx = (GLfloat) width / 2.0F;
  610.    CC.Viewport.Tx = CC.Viewport.Sx + x;
  611.    CC.Viewport.Sy = (GLfloat) height / 2.0F;
  612.    CC.Viewport.Ty = CC.Viewport.Sy + y;
  613.  
  614.    /* Reallocate other buffers if needed. */
  615.    if (newsize && CC.DepthBuffer) {
  616.       /* reallocate depth buffer, if there is one */
  617.       (*DD.alloc_depth_buffer)();
  618.    }
  619.    if (newsize && CC.StencilBuffer) {
  620.       /* reallocate stencil buffer, if there is one */
  621.       gl_alloc_stencil_buffer();
  622.    }
  623.    if (newsize && CC.AccumBuffer) {
  624.       /* Deallocate the accumulation buffer.  A new one will be allocated */
  625.       /* if/when glAccum() is called again. */
  626.       free( CC.AccumBuffer );
  627.       CC.AccumBuffer = NULL;
  628.    }
  629.    if (newsize && (CC.FrontAlphaEnabled || CC.BackAlphaEnabled)) {
  630.       gl_alloc_alpha_buffers();
  631.    }
  632.  
  633.    CC.NewState = GL_TRUE;
  634. }
  635.  
  636.  
  637.  
  638. void glViewport( GLint x, GLint y, GLsizei width, GLsizei height )
  639. {
  640.    if (CC.ExecuteFlag) {
  641.       gl_viewport( x, y, width, height );
  642.    }
  643.    if (CC.CompileFlag) {
  644.       gl_save_viewport( x, y, width, height );
  645.    }
  646. }
  647.  
  648.  
  649.  
  650.  
  651. /*
  652.  * Determine if the given matrix is the identity matrix.
  653.  */
  654. static GLboolean is_identity( const GLfloat m[16] )
  655. {
  656.    if (   m[0]==1.0F && m[4]==0.0F && m[ 8]==0.0F && m[12]==0.0F
  657.        && m[1]==0.0F && m[5]==1.0F && m[ 9]==0.0F && m[13]==0.0F
  658.        && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F
  659.        && m[3]==0.0F && m[7]==0.0F && m[11]==0.0F && m[15]==1.0F) {
  660.       return GL_TRUE;
  661.    }
  662.    else {
  663.       return GL_FALSE;
  664.    }
  665. }
  666.  
  667.  
  668.  
  669.  
  670. void glPushMatrix( void )
  671. {
  672.    if (CC.CompileFlag) {
  673.       gl_save_pushmatrix();
  674.    }
  675.    if (CC.ExecuteFlag) {
  676.       if (INSIDE_BEGIN_END) {
  677.      gl_error( GL_INVALID_OPERATION, "glPushMatrix" );
  678.      return;
  679.       }
  680.       switch (CC.Transform.MatrixMode) {
  681.      case GL_MODELVIEW:
  682.         if (CC.ModelViewStackDepth>=MAX_MODELVIEW_STACK_DEPTH-1) {
  683.            gl_error( GL_STACK_OVERFLOW, "glPushMatrix");
  684.            return;
  685.         }
  686.         MEMCPY( CC.ModelViewStack[CC.ModelViewStackDepth],
  687.             CC.ModelViewMatrix,
  688.             16*sizeof(GLfloat) );
  689.         CC.ModelViewStackDepth++;
  690.         break;
  691.      case GL_PROJECTION:
  692.         if (CC.ProjectionStackDepth>=MAX_PROJECTION_STACK_DEPTH) {
  693.            gl_error( GL_STACK_OVERFLOW, "glPushMatrix");
  694.            return;
  695.         }
  696.         MEMCPY( CC.ProjectionStack[CC.ProjectionStackDepth],
  697.             CC.ProjectionMatrix,
  698.             16*sizeof(GLfloat) );
  699.         CC.ProjectionStackDepth++;
  700.         break;
  701.      case GL_TEXTURE:
  702.         if (CC.TextureStackDepth>=MAX_TEXTURE_STACK_DEPTH) {
  703.            gl_error( GL_STACK_OVERFLOW, "glPushMatrix");
  704.            return;
  705.         }
  706.         MEMCPY( CC.TextureStack[CC.TextureStackDepth],
  707.             CC.TextureMatrix,
  708.             16*sizeof(GLfloat) );
  709.         CC.TextureStackDepth++;
  710.         break;
  711.       }
  712.    }
  713. }
  714.  
  715.  
  716.  
  717. void glPopMatrix( void )
  718. {
  719.    if (CC.CompileFlag) {
  720.       gl_save_popmatrix();
  721.    }
  722.    if (CC.ExecuteFlag) {
  723.       if (INSIDE_BEGIN_END) {
  724.      gl_error( GL_INVALID_OPERATION, "glPopMatrix" );
  725.      return;
  726.       }
  727.       switch (CC.Transform.MatrixMode) {
  728.      case GL_MODELVIEW:
  729.         if (CC.ModelViewStackDepth==0) {
  730.            gl_error( GL_STACK_UNDERFLOW, "glPopMatrix");
  731.            return;
  732.         }
  733.         CC.ModelViewStackDepth--;
  734.         MEMCPY( CC.ModelViewMatrix,
  735.             CC.ModelViewStack[CC.ModelViewStackDepth],
  736.             16*sizeof(GLfloat) );
  737.         CC.ModelViewInvValid = GL_FALSE;
  738.         break;
  739.      case GL_PROJECTION:
  740.         if (CC.ProjectionStackDepth==0) {
  741.            gl_error( GL_STACK_UNDERFLOW, "glPopMatrix");
  742.            return;
  743.         }
  744.         CC.ProjectionStackDepth--;
  745.         MEMCPY( CC.ProjectionMatrix,
  746.             CC.ProjectionStack[CC.ProjectionStackDepth],
  747.             16*sizeof(GLfloat) );
  748.         break;
  749.      case GL_TEXTURE:
  750.         if (CC.TextureStackDepth==0) {
  751.            gl_error( GL_STACK_UNDERFLOW, "glPopMatrix");
  752.            return;
  753.         }
  754.         CC.TextureStackDepth--;
  755.         MEMCPY( CC.TextureMatrix,
  756.             CC.TextureStack[CC.TextureStackDepth],
  757.             16*sizeof(GLfloat) );
  758.             CC.IdentityTexMat = is_identity( CC.TextureMatrix );
  759.         break;
  760.       }
  761.    }
  762. }
  763.  
  764.  
  765.  
  766. void gl_load_matrix( const GLfloat *m )
  767. {
  768.    if (INSIDE_BEGIN_END) {
  769.       gl_error( GL_INVALID_OPERATION, "glLoadMatrix" );
  770.       return;
  771.    }
  772.    switch (CC.Transform.MatrixMode) {
  773.       case GL_MODELVIEW:
  774.          MEMCPY( CC.ModelViewMatrix, m, 16*sizeof(GLfloat) );
  775.      CC.ModelViewInvValid = GL_FALSE;
  776.      break;
  777.       case GL_PROJECTION:
  778.      MEMCPY( CC.ProjectionMatrix, m, 16*sizeof(GLfloat) );
  779.      break;
  780.       case GL_TEXTURE:
  781.      MEMCPY( CC.TextureMatrix, m, 16*sizeof(GLfloat) );
  782.          CC.IdentityTexMat = is_identity( CC.TextureMatrix );
  783.      break;
  784.    }
  785. }
  786.  
  787.  
  788.  
  789. void glLoadMatrixd( const GLdouble *m )
  790. {
  791.    GLfloat fm[16];
  792.    GLuint i;
  793.  
  794.    for (i=0;i<16;i++) {
  795.       fm[i] = (GLfloat) m[i];
  796.    }
  797.  
  798.    glLoadMatrixf( fm );
  799. }
  800.  
  801.  
  802.  
  803. void glLoadMatrixf( const GLfloat *m )
  804. {
  805.    if (CC.CompileFlag) {
  806.       gl_save_loadmatrix( m );
  807.    }
  808.    if (CC.ExecuteFlag) {
  809.       gl_load_matrix( m );
  810.    }
  811. }
  812.  
  813.  
  814.  
  815. void glLoadIdentity( void )
  816. {
  817.    if (CC.CompileFlag) {
  818.       gl_save_loadmatrix( Identity );
  819.    }
  820.    if (CC.ExecuteFlag) {
  821.       gl_load_matrix( Identity );
  822.    }
  823. }
  824.  
  825.  
  826.  
  827. void gl_mult_matrix( const GLfloat *m )
  828. {
  829.    if (INSIDE_BEGIN_END) {
  830.       gl_error( GL_INVALID_OPERATION, "glMultMatrix" );
  831.       return;
  832.    }
  833.    switch (CC.Transform.MatrixMode) {
  834.       case GL_MODELVIEW:
  835.          matmul( CC.ModelViewMatrix, CC.ModelViewMatrix, m );
  836.      CC.ModelViewInvValid = GL_FALSE;
  837.      break;
  838.       case GL_PROJECTION:
  839.      matmul( CC.ProjectionMatrix, CC.ProjectionMatrix, m );
  840.      break;
  841.       case GL_TEXTURE:
  842.      matmul( CC.TextureMatrix, CC.TextureMatrix, m );
  843.          CC.IdentityTexMat = is_identity( CC.TextureMatrix );
  844.      break;
  845.    }
  846. }
  847.  
  848.  
  849.  
  850. void glMultMatrixd( const GLdouble *m )
  851. {
  852.    GLfloat fm[16];
  853.    GLuint i;
  854.  
  855.    for (i=0;i<16;i++) {
  856.       fm[i] = (GLfloat) m[i];
  857.    }
  858.  
  859.    glMultMatrixf( fm );
  860. }
  861.  
  862.  
  863.  
  864. void glMultMatrixf( const GLfloat *m )
  865. {
  866.    if (CC.CompileFlag) {
  867.       gl_save_multmatrix( m );
  868.    }
  869.    if (CC.ExecuteFlag) {
  870.       gl_mult_matrix( m );
  871.    }
  872. }
  873.  
  874.  
  875.  
  876. void glRotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
  877. {
  878.    glRotatef( (GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z );
  879. }
  880.  
  881.  
  882.  
  883. void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
  884. {
  885.    /* This function contributed by Erich Boleyn (erich@uruk.org) */
  886.  
  887.    GLfloat m[16];
  888.    GLfloat mag, s, c;
  889.    GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
  890.  
  891.    s = sin( angle * (M_PI / 180.0) );
  892.    c = cos( angle * (M_PI / 180.0) );
  893.  
  894.    mag = sqrt( x*x + y*y + z*z );
  895.  
  896.    if (mag == 0.0)
  897.      return;
  898.  
  899.    x /= mag;
  900.    y /= mag;
  901.    z /= mag;
  902.  
  903. #define M(row,col)  m[col*4+row]
  904.  
  905.    /*
  906.     *     Arbitrary axis rotation matrix.
  907.     *
  908.     *  This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
  909.     *  like so:  Rz * Ry * T * Ry' * Rz'.  T is the final rotation
  910.     *  (which is about the X-axis), and the two composite transforms
  911.     *  Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
  912.     *  from the arbitrary axis to the X-axis then back.  They are
  913.     *  all elementary rotations.
  914.     *
  915.     *  Rz' is a rotation about the Z-axis, to bring the axis vector
  916.     *  into the x-z plane.  Then Ry' is applied, rotating about the
  917.     *  Y-axis to bring the axis vector parallel with the X-axis.  The
  918.     *  rotation about the X-axis is then performed.  Ry and Rz are
  919.     *  simply the respective inverse transforms to bring the arbitrary
  920.     *  axis back to it's original orientation.  The first transforms
  921.     *  Rz' and Ry' are considered inverses, since the data from the
  922.     *  arbitrary axis gives you info on how to get to it, not how
  923.     *  to get away from it, and an inverse must be applied.
  924.     *
  925.     *  The basic calculation used is to recognize that the arbitrary
  926.     *  axis vector (x, y, z), since it is of unit length, actually
  927.     *  represents the sines and cosines of the angles to rotate the
  928.     *  X-axis to the same orientation, with theta being the angle about
  929.     *  Z and phi the angle about Y (in the order described above)
  930.     *  as follows:
  931.     *
  932.     *  cos ( theta ) = x / sqrt ( 1 - z^2 )
  933.     *  sin ( theta ) = y / sqrt ( 1 - z^2 )
  934.     *
  935.     *  cos ( phi ) = sqrt ( 1 - z^2 )
  936.     *  sin ( phi ) = z
  937.     *
  938.     *  Note that cos ( phi ) can further be inserted to the above
  939.     *  formulas:
  940.     *
  941.     *  cos ( theta ) = x / cos ( phi )
  942.     *  sin ( theta ) = y / sin ( phi )
  943.     *
  944.     *  ...etc.  Because of those relations and the standard trigonometric
  945.     *  relations, it is pssible to reduce the transforms down to what
  946.     *  is used below.  It may be that any primary axis chosen will give the
  947.     *  same results (modulo a sign convention) using thie method.
  948.     *
  949.     *  Particularly nice is to notice that all divisions that might
  950.     *  have caused trouble when parallel to certain planes or
  951.     *  axis go away with care paid to reducing the expressions.
  952.     *  After checking, it does perform correctly under all cases, since
  953.     *  in all the cases of division where the denominator would have
  954.     *  been zero, the numerator would have been zero as well, giving
  955.     *  the expected result.
  956.     */
  957.  
  958.    xx = x * x;
  959.    yy = y * y;
  960.    zz = z * z;
  961.    xy = x * y;
  962.    yz = y * z;
  963.    zx = z * x;
  964.    xs = x * s;
  965.    ys = y * s;
  966.    zs = z * s;
  967.    one_c = 1.0F - c;
  968.  
  969.    M(0,0) = (one_c * xx) + c;
  970.    M(0,1) = (one_c * xy) - zs;
  971.    M(0,2) = (one_c * zx) + ys;
  972.    M(0,3) = 0.0F;
  973.  
  974.    M(1,0) = (one_c * xy) + zs;
  975.    M(1,1) = (one_c * yy) + c;
  976.    M(1,2) = (one_c * yz) - xs;
  977.    M(1,3) = 0.0F;
  978.  
  979.    M(2,0) = (one_c * zx) - ys;
  980.    M(2,1) = (one_c * yz) + xs;
  981.    M(2,2) = (one_c * zz) + c;
  982.    M(2,3) = 0.0F;
  983.  
  984.    M(3,0) = 0.0F;
  985.    M(3,1) = 0.0F;
  986.    M(3,2) = 0.0F;
  987.    M(3,3) = 1.0F;
  988.  
  989. #undef M
  990.  
  991.    if (CC.CompileFlag) {
  992.       gl_save_multmatrix( m );
  993.    }
  994.    if (CC.ExecuteFlag) {
  995.       gl_mult_matrix( m );
  996.    }
  997. }
  998.  
  999.  
  1000.  
  1001. /*
  1002.  * Execute a glScale call
  1003.  */
  1004. void gl_scale( GLfloat x, GLfloat y, GLfloat z )
  1005. {
  1006.    GLfloat *m;
  1007.  
  1008.    if (INSIDE_BEGIN_END) {
  1009.       gl_error( GL_INVALID_OPERATION, "glScale" );
  1010.       return;
  1011.    }
  1012.    switch (CC.Transform.MatrixMode) {
  1013.       case GL_MODELVIEW:
  1014.          m = CC.ModelViewMatrix;
  1015.      CC.ModelViewInvValid = GL_FALSE;
  1016.      break;
  1017.       case GL_PROJECTION:
  1018.          m = CC.ProjectionMatrix;
  1019.      break;
  1020.       case GL_TEXTURE:
  1021.          m = CC.TextureMatrix;
  1022.      break;
  1023.    }
  1024.    m[0] *= x;   m[4] *= y;   m[8]  *= z;
  1025.    m[1] *= x;   m[5] *= y;   m[9]  *= z;
  1026.    m[2] *= x;   m[6] *= y;   m[10] *= z;
  1027.    m[3] *= x;   m[7] *= y;   m[11] *= z;
  1028.  
  1029.    if (CC.Transform.MatrixMode==GL_TEXTURE) {
  1030.       CC.IdentityTexMat = is_identity( CC.TextureMatrix );
  1031.    }
  1032. }
  1033.  
  1034.  
  1035.  
  1036. void glScaled( GLdouble x, GLdouble y, GLdouble z )
  1037. {
  1038.    if (CC.CompileFlag) {
  1039.       gl_save_scale( (GLfloat) x, (GLfloat) y, (GLfloat) z );
  1040.    }
  1041.    if (CC.ExecuteFlag) {
  1042.       gl_scale( (GLfloat) x, (GLfloat) y, (GLfloat) z );
  1043.    }
  1044. }
  1045.  
  1046.  
  1047.  
  1048. void glScalef( GLfloat x, GLfloat y, GLfloat z )
  1049. {
  1050.    if (CC.CompileFlag) {
  1051.       gl_save_scale( x, y, z );
  1052.    }
  1053.    if (CC.ExecuteFlag) {
  1054.       gl_scale( x, y, z );
  1055.    }
  1056. }
  1057.  
  1058.  
  1059.  
  1060. /*
  1061.  * Execute a glTranslate call
  1062.  */
  1063. void gl_translate( GLfloat x, GLfloat y, GLfloat z )
  1064. {
  1065.    GLfloat *m;
  1066.    if (INSIDE_BEGIN_END) {
  1067.       gl_error( GL_INVALID_OPERATION, "glTranslate" );
  1068.       return;
  1069.    }
  1070.    switch (CC.Transform.MatrixMode) {
  1071.       case GL_MODELVIEW:
  1072.          m = CC.ModelViewMatrix;
  1073.      CC.ModelViewInvValid = GL_FALSE;
  1074.      break;
  1075.       case GL_PROJECTION:
  1076.          m = CC.ProjectionMatrix;
  1077.      break;
  1078.       case GL_TEXTURE:
  1079.          m = CC.TextureMatrix;
  1080.      break;
  1081.    }
  1082.  
  1083.    m[12] = m[0] * x + m[4] * y + m[8]  * z + m[12];
  1084.    m[13] = m[1] * x + m[5] * y + m[9]  * z + m[13];
  1085.    m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
  1086.    m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
  1087.  
  1088.    if (CC.Transform.MatrixMode==GL_TEXTURE) {
  1089.       CC.IdentityTexMat = is_identity( CC.TextureMatrix );
  1090.    }
  1091. }
  1092.  
  1093.  
  1094.  
  1095. void glTranslated( GLdouble x, GLdouble y, GLdouble z )
  1096. {
  1097.    if (CC.CompileFlag) {
  1098.       gl_save_translate( (GLfloat) x, (GLfloat) y, (GLfloat) z );
  1099.    }
  1100.    if (CC.ExecuteFlag) {
  1101.       gl_translate( (GLfloat) x, (GLfloat) y, (GLfloat) z );
  1102.    }
  1103. }
  1104.  
  1105.  
  1106.  
  1107. void glTranslatef( GLfloat x, GLfloat y, GLfloat z )
  1108. {
  1109.    if (CC.CompileFlag) {
  1110.       gl_save_translate( x, y, z );
  1111.    }
  1112.    if (CC.ExecuteFlag) {
  1113.       gl_translate( x, y, z );
  1114.    }
  1115. }
  1116.