ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

m_matrix.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  6.3
00004  *
00005  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 
00037 #include "main/glheader.h"
00038 #include "main/imports.h"
00039 #include "main/macros.h"
00040 #include "main/imports.h"
00041 
00042 #include "m_matrix.h"
00043 
00044 
00052 #define MAT_FLAG_IDENTITY       0     
00057 #define MAT_FLAG_GENERAL        0x1   
00058 #define MAT_FLAG_ROTATION       0x2   
00059 #define MAT_FLAG_TRANSLATION    0x4   
00060 #define MAT_FLAG_UNIFORM_SCALE  0x8   
00061 #define MAT_FLAG_GENERAL_SCALE  0x10  
00062 #define MAT_FLAG_GENERAL_3D     0x20  
00063 #define MAT_FLAG_PERSPECTIVE    0x40  
00064 #define MAT_FLAG_SINGULAR       0x80  
00065 #define MAT_DIRTY_TYPE          0x100  
00066 #define MAT_DIRTY_FLAGS         0x200  
00067 #define MAT_DIRTY_INVERSE       0x400  
00070 #define MAT_FLAGS_ANGLE_PRESERVING (MAT_FLAG_ROTATION | \
00071                     MAT_FLAG_TRANSLATION | \
00072                     MAT_FLAG_UNIFORM_SCALE)
00073 
00075 #define MAT_FLAGS_GEOMETRY (MAT_FLAG_GENERAL | \
00076                 MAT_FLAG_ROTATION | \
00077                 MAT_FLAG_TRANSLATION | \
00078                 MAT_FLAG_UNIFORM_SCALE | \
00079                 MAT_FLAG_GENERAL_SCALE | \
00080                 MAT_FLAG_GENERAL_3D | \
00081                 MAT_FLAG_PERSPECTIVE | \
00082                         MAT_FLAG_SINGULAR)
00083 
00085 #define MAT_FLAGS_LENGTH_PRESERVING (MAT_FLAG_ROTATION | \
00086                      MAT_FLAG_TRANSLATION)
00087 
00088 
00090 #define MAT_FLAGS_3D (MAT_FLAG_ROTATION | \
00091               MAT_FLAG_TRANSLATION | \
00092               MAT_FLAG_UNIFORM_SCALE | \
00093               MAT_FLAG_GENERAL_SCALE | \
00094               MAT_FLAG_GENERAL_3D)
00095 
00097 #define MAT_DIRTY          (MAT_DIRTY_TYPE | \
00098                 MAT_DIRTY_FLAGS | \
00099                 MAT_DIRTY_INVERSE)
00100 
00113 #define TEST_MAT_FLAGS(mat, a)  \
00114     ((MAT_FLAGS_GEOMETRY & (~(a)) & ((mat)->flags) ) == 0)
00115 
00116 
00117 
00121 static const char *types[] = {
00122    "MATRIX_GENERAL",
00123    "MATRIX_IDENTITY",
00124    "MATRIX_3D_NO_ROT",
00125    "MATRIX_PERSPECTIVE",
00126    "MATRIX_2D",
00127    "MATRIX_2D_NO_ROT",
00128    "MATRIX_3D"
00129 };
00130 
00131 
00135 static GLfloat Identity[16] = {
00136    1.0, 0.0, 0.0, 0.0,
00137    0.0, 1.0, 0.0, 0.0,
00138    0.0, 0.0, 1.0, 0.0,
00139    0.0, 0.0, 0.0, 1.0
00140 };
00141 
00142 
00143 
00144 /**********************************************************************/
00147 
00148 #define A(row,col)  a[(col<<2)+row]
00149 #define B(row,col)  b[(col<<2)+row]
00150 #define P(row,col)  product[(col<<2)+row]
00151 
00165 static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b )
00166 {
00167    GLint i;
00168    for (i = 0; i < 4; i++) {
00169       const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
00170       P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
00171       P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
00172       P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
00173       P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
00174    }
00175 }
00176 
00185 static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b )
00186 {
00187    GLint i;
00188    for (i = 0; i < 3; i++) {
00189       const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
00190       P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0);
00191       P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1);
00192       P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2);
00193       P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3;
00194    }
00195    P(3,0) = 0;
00196    P(3,1) = 0;
00197    P(3,2) = 0;
00198    P(3,3) = 1;
00199 }
00200 
00201 #undef A
00202 #undef B
00203 #undef P
00204 
00216 static void matrix_multf( GLmatrix *mat, const GLfloat *m, GLuint flags )
00217 {
00218    mat->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);
00219 
00220    if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
00221       matmul34( mat->m, mat->m, m );
00222    else
00223       matmul4( mat->m, mat->m, m );
00224 }
00225 
00236 void
00237 _math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b )
00238 {
00239    dest->flags = (a->flags |
00240           b->flags |
00241           MAT_DIRTY_TYPE |
00242           MAT_DIRTY_INVERSE);
00243 
00244    if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D))
00245       matmul34( dest->m, a->m, b->m );
00246    else
00247       matmul4( dest->m, a->m, b->m );
00248 }
00249 
00259 void
00260 _math_matrix_mul_floats( GLmatrix *dest, const GLfloat *m )
00261 {
00262    dest->flags |= (MAT_FLAG_GENERAL |
00263            MAT_DIRTY_TYPE |
00264            MAT_DIRTY_INVERSE |
00265                    MAT_DIRTY_FLAGS);
00266 
00267    matmul4( dest->m, dest->m, m );
00268 }
00269 
00273 /**********************************************************************/
00276 
00284 static void print_matrix_floats( const GLfloat m[16] )
00285 {
00286    int i;
00287    for (i=0;i<4;i++) {
00288       _mesa_debug(NULL,"\t%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] );
00289    }
00290 }
00291 
00297 void
00298 _math_matrix_print( const GLmatrix *m )
00299 {
00300    _mesa_debug(NULL, "Matrix type: %s, flags: %x\n", types[m->type], m->flags);
00301    print_matrix_floats(m->m);
00302    _mesa_debug(NULL, "Inverse: \n");
00303    if (m->inv) {
00304       GLfloat prod[16];
00305       print_matrix_floats(m->inv);
00306       matmul4(prod, m->m, m->inv);
00307       _mesa_debug(NULL, "Mat * Inverse:\n");
00308       print_matrix_floats(prod);
00309    }
00310    else {
00311       _mesa_debug(NULL, "  - not available\n");
00312    }
00313 }
00314 
00329 #define MAT(m,r,c) (m)[(c)*4+(r)]
00330 
00331 
00332 /**********************************************************************/
00335 
00341 #define SWAP_ROWS(a, b) { GLfloat *_tmp = a; (a)=(b); (b)=_tmp; }
00342 
00358 static GLboolean invert_matrix_general( GLmatrix *mat )
00359 {
00360    const GLfloat *m = mat->m;
00361    GLfloat *out = mat->inv;
00362    GLfloat wtmp[4][8];
00363    GLfloat m0, m1, m2, m3, s;
00364    GLfloat *r0, *r1, *r2, *r3;
00365 
00366    r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
00367 
00368    r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1),
00369    r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3),
00370    r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,
00371 
00372    r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1),
00373    r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3),
00374    r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,
00375 
00376    r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1),
00377    r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3),
00378    r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,
00379 
00380    r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1),
00381    r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3),
00382    r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;
00383 
00384    /* choose pivot - or die */
00385    if (FABSF(r3[0])>FABSF(r2[0])) SWAP_ROWS(r3, r2);
00386    if (FABSF(r2[0])>FABSF(r1[0])) SWAP_ROWS(r2, r1);
00387    if (FABSF(r1[0])>FABSF(r0[0])) SWAP_ROWS(r1, r0);
00388    if (0.0 == r0[0])  return GL_FALSE;
00389 
00390    /* eliminate first variable     */
00391    m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0];
00392    s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s;
00393    s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s;
00394    s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s;
00395    s = r0[4];
00396    if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; }
00397    s = r0[5];
00398    if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; }
00399    s = r0[6];
00400    if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; }
00401    s = r0[7];
00402    if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; }
00403 
00404    /* choose pivot - or die */
00405    if (FABSF(r3[1])>FABSF(r2[1])) SWAP_ROWS(r3, r2);
00406    if (FABSF(r2[1])>FABSF(r1[1])) SWAP_ROWS(r2, r1);
00407    if (0.0 == r1[1])  return GL_FALSE;
00408 
00409    /* eliminate second variable */
00410    m2 = r2[1]/r1[1]; m3 = r3[1]/r1[1];
00411    r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2];
00412    r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3];
00413    s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; }
00414    s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; }
00415    s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; }
00416    s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; }
00417 
00418    /* choose pivot - or die */
00419    if (FABSF(r3[2])>FABSF(r2[2])) SWAP_ROWS(r3, r2);
00420    if (0.0 == r2[2])  return GL_FALSE;
00421 
00422    /* eliminate third variable */
00423    m3 = r3[2]/r2[2];
00424    r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
00425    r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6],
00426    r3[7] -= m3 * r2[7];
00427 
00428    /* last check */
00429    if (0.0 == r3[3]) return GL_FALSE;
00430 
00431    s = 1.0F/r3[3];             /* now back substitute row 3 */
00432    r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s;
00433 
00434    m2 = r2[3];                 /* now back substitute row 2 */
00435    s  = 1.0F/r2[2];
00436    r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
00437    r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
00438    m1 = r1[3];
00439    r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
00440    r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
00441    m0 = r0[3];
00442    r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
00443    r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
00444 
00445    m1 = r1[2];                 /* now back substitute row 1 */
00446    s  = 1.0F/r1[1];
00447    r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
00448    r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
00449    m0 = r0[2];
00450    r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
00451    r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
00452 
00453    m0 = r0[1];                 /* now back substitute row 0 */
00454    s  = 1.0F/r0[0];
00455    r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
00456    r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
00457 
00458    MAT(out,0,0) = r0[4]; MAT(out,0,1) = r0[5],
00459    MAT(out,0,2) = r0[6]; MAT(out,0,3) = r0[7],
00460    MAT(out,1,0) = r1[4]; MAT(out,1,1) = r1[5],
00461    MAT(out,1,2) = r1[6]; MAT(out,1,3) = r1[7],
00462    MAT(out,2,0) = r2[4]; MAT(out,2,1) = r2[5],
00463    MAT(out,2,2) = r2[6]; MAT(out,2,3) = r2[7],
00464    MAT(out,3,0) = r3[4]; MAT(out,3,1) = r3[5],
00465    MAT(out,3,2) = r3[6]; MAT(out,3,3) = r3[7];
00466 
00467    return GL_TRUE;
00468 }
00469 #undef SWAP_ROWS
00470 
00486 static GLboolean invert_matrix_3d_general( GLmatrix *mat )
00487 {
00488    const GLfloat *in = mat->m;
00489    GLfloat *out = mat->inv;
00490    GLfloat pos, neg, t;
00491    GLfloat det;
00492 
00493    /* Calculate the determinant of upper left 3x3 submatrix and
00494     * determine if the matrix is singular.
00495     */
00496    pos = neg = 0.0;
00497    t =  MAT(in,0,0) * MAT(in,1,1) * MAT(in,2,2);
00498    if (t >= 0.0) pos += t; else neg += t;
00499 
00500    t =  MAT(in,1,0) * MAT(in,2,1) * MAT(in,0,2);
00501    if (t >= 0.0) pos += t; else neg += t;
00502 
00503    t =  MAT(in,2,0) * MAT(in,0,1) * MAT(in,1,2);
00504    if (t >= 0.0) pos += t; else neg += t;
00505 
00506    t = -MAT(in,2,0) * MAT(in,1,1) * MAT(in,0,2);
00507    if (t >= 0.0) pos += t; else neg += t;
00508 
00509    t = -MAT(in,1,0) * MAT(in,0,1) * MAT(in,2,2);
00510    if (t >= 0.0) pos += t; else neg += t;
00511 
00512    t = -MAT(in,0,0) * MAT(in,2,1) * MAT(in,1,2);
00513    if (t >= 0.0) pos += t; else neg += t;
00514 
00515    det = pos + neg;
00516 
00517    if (det*det < 1e-25)
00518       return GL_FALSE;
00519 
00520    det = 1.0F / det;
00521    MAT(out,0,0) = (  (MAT(in,1,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,1,2) )*det);
00522    MAT(out,0,1) = (- (MAT(in,0,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,0,2) )*det);
00523    MAT(out,0,2) = (  (MAT(in,0,1)*MAT(in,1,2) - MAT(in,1,1)*MAT(in,0,2) )*det);
00524    MAT(out,1,0) = (- (MAT(in,1,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,1,2) )*det);
00525    MAT(out,1,1) = (  (MAT(in,0,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,0,2) )*det);
00526    MAT(out,1,2) = (- (MAT(in,0,0)*MAT(in,1,2) - MAT(in,1,0)*MAT(in,0,2) )*det);
00527    MAT(out,2,0) = (  (MAT(in,1,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,1,1) )*det);
00528    MAT(out,2,1) = (- (MAT(in,0,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,0,1) )*det);
00529    MAT(out,2,2) = (  (MAT(in,0,0)*MAT(in,1,1) - MAT(in,1,0)*MAT(in,0,1) )*det);
00530 
00531    /* Do the translation part */
00532    MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
00533              MAT(in,1,3) * MAT(out,0,1) +
00534              MAT(in,2,3) * MAT(out,0,2) );
00535    MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +
00536              MAT(in,1,3) * MAT(out,1,1) +
00537              MAT(in,2,3) * MAT(out,1,2) );
00538    MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +
00539              MAT(in,1,3) * MAT(out,2,1) +
00540              MAT(in,2,3) * MAT(out,2,2) );
00541 
00542    return GL_TRUE;
00543 }
00544 
00558 static GLboolean invert_matrix_3d( GLmatrix *mat )
00559 {
00560    const GLfloat *in = mat->m;
00561    GLfloat *out = mat->inv;
00562 
00563    if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING)) {
00564       return invert_matrix_3d_general( mat );
00565    }
00566 
00567    if (mat->flags & MAT_FLAG_UNIFORM_SCALE) {
00568       GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) +
00569                        MAT(in,0,1) * MAT(in,0,1) +
00570                        MAT(in,0,2) * MAT(in,0,2));
00571 
00572       if (scale == 0.0)
00573          return GL_FALSE;
00574 
00575       scale = 1.0F / scale;
00576 
00577       /* Transpose and scale the 3 by 3 upper-left submatrix. */
00578       MAT(out,0,0) = scale * MAT(in,0,0);
00579       MAT(out,1,0) = scale * MAT(in,0,1);
00580       MAT(out,2,0) = scale * MAT(in,0,2);
00581       MAT(out,0,1) = scale * MAT(in,1,0);
00582       MAT(out,1,1) = scale * MAT(in,1,1);
00583       MAT(out,2,1) = scale * MAT(in,1,2);
00584       MAT(out,0,2) = scale * MAT(in,2,0);
00585       MAT(out,1,2) = scale * MAT(in,2,1);
00586       MAT(out,2,2) = scale * MAT(in,2,2);
00587    }
00588    else if (mat->flags & MAT_FLAG_ROTATION) {
00589       /* Transpose the 3 by 3 upper-left submatrix. */
00590       MAT(out,0,0) = MAT(in,0,0);
00591       MAT(out,1,0) = MAT(in,0,1);
00592       MAT(out,2,0) = MAT(in,0,2);
00593       MAT(out,0,1) = MAT(in,1,0);
00594       MAT(out,1,1) = MAT(in,1,1);
00595       MAT(out,2,1) = MAT(in,1,2);
00596       MAT(out,0,2) = MAT(in,2,0);
00597       MAT(out,1,2) = MAT(in,2,1);
00598       MAT(out,2,2) = MAT(in,2,2);
00599    }
00600    else {
00601       /* pure translation */
00602       MEMCPY( out, Identity, sizeof(Identity) );
00603       MAT(out,0,3) = - MAT(in,0,3);
00604       MAT(out,1,3) = - MAT(in,1,3);
00605       MAT(out,2,3) = - MAT(in,2,3);
00606       return GL_TRUE;
00607    }
00608 
00609    if (mat->flags & MAT_FLAG_TRANSLATION) {
00610       /* Do the translation part */
00611       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
00612             MAT(in,1,3) * MAT(out,0,1) +
00613             MAT(in,2,3) * MAT(out,0,2) );
00614       MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +
00615             MAT(in,1,3) * MAT(out,1,1) +
00616             MAT(in,2,3) * MAT(out,1,2) );
00617       MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +
00618             MAT(in,1,3) * MAT(out,2,1) +
00619             MAT(in,2,3) * MAT(out,2,2) );
00620    }
00621    else {
00622       MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0;
00623    }
00624 
00625    return GL_TRUE;
00626 }
00627 
00638 static GLboolean invert_matrix_identity( GLmatrix *mat )
00639 {
00640    MEMCPY( mat->inv, Identity, sizeof(Identity) );
00641    return GL_TRUE;
00642 }
00643 
00654 static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat )
00655 {
00656    const GLfloat *in = mat->m;
00657    GLfloat *out = mat->inv;
00658 
00659    if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0 || MAT(in,2,2) == 0 )
00660       return GL_FALSE;
00661 
00662    MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
00663    MAT(out,0,0) = 1.0F / MAT(in,0,0);
00664    MAT(out,1,1) = 1.0F / MAT(in,1,1);
00665    MAT(out,2,2) = 1.0F / MAT(in,2,2);
00666 
00667    if (mat->flags & MAT_FLAG_TRANSLATION) {
00668       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
00669       MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
00670       MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2));
00671    }
00672 
00673    return GL_TRUE;
00674 }
00675 
00687 static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat )
00688 {
00689    const GLfloat *in = mat->m;
00690    GLfloat *out = mat->inv;
00691 
00692    if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0)
00693       return GL_FALSE;
00694 
00695    MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
00696    MAT(out,0,0) = 1.0F / MAT(in,0,0);
00697    MAT(out,1,1) = 1.0F / MAT(in,1,1);
00698 
00699    if (mat->flags & MAT_FLAG_TRANSLATION) {
00700       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
00701       MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
00702    }
00703 
00704    return GL_TRUE;
00705 }
00706 
00707 #if 0
00708 /* broken */
00709 static GLboolean invert_matrix_perspective( GLmatrix *mat )
00710 {
00711    const GLfloat *in = mat->m;
00712    GLfloat *out = mat->inv;
00713 
00714    if (MAT(in,2,3) == 0)
00715       return GL_FALSE;
00716 
00717    MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
00718 
00719    MAT(out,0,0) = 1.0F / MAT(in,0,0);
00720    MAT(out,1,1) = 1.0F / MAT(in,1,1);
00721 
00722    MAT(out,0,3) = MAT(in,0,2);
00723    MAT(out,1,3) = MAT(in,1,2);
00724 
00725    MAT(out,2,2) = 0;
00726    MAT(out,2,3) = -1;
00727 
00728    MAT(out,3,2) = 1.0F / MAT(in,2,3);
00729    MAT(out,3,3) = MAT(in,2,2) * MAT(out,3,2);
00730 
00731    return GL_TRUE;
00732 }
00733 #endif
00734 
00738 typedef GLboolean (*inv_mat_func)( GLmatrix *mat );
00739 
00743 static inv_mat_func inv_mat_tab[7] = {
00744    invert_matrix_general,
00745    invert_matrix_identity,
00746    invert_matrix_3d_no_rot,
00747 #if 0
00748    /* Don't use this function for now - it fails when the projection matrix
00749     * is premultiplied by a translation (ala Chromium's tilesort SPU).
00750     */
00751    invert_matrix_perspective,
00752 #else
00753    invert_matrix_general,
00754 #endif
00755    invert_matrix_3d,        /* lazy! */
00756    invert_matrix_2d_no_rot,
00757    invert_matrix_3d
00758 };
00759 
00772 static GLboolean matrix_invert( GLmatrix *mat )
00773 {
00774    if (inv_mat_tab[mat->type](mat)) {
00775       mat->flags &= ~MAT_FLAG_SINGULAR;
00776       return GL_TRUE;
00777    } else {
00778       mat->flags |= MAT_FLAG_SINGULAR;
00779       MEMCPY( mat->inv, Identity, sizeof(Identity) );
00780       return GL_FALSE;
00781    }
00782 }
00783 
00787 /**********************************************************************/
00790 
00799 void
00800 _math_matrix_rotate( GLmatrix *mat,
00801              GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
00802 {
00803    GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
00804    GLfloat m[16];
00805    GLboolean optimized;
00806 
00807    s = (GLfloat) _mesa_sin( angle * DEG2RAD );
00808    c = (GLfloat) _mesa_cos( angle * DEG2RAD );
00809 
00810    MEMCPY(m, Identity, sizeof(GLfloat)*16);
00811    optimized = GL_FALSE;
00812 
00813 #define M(row,col)  m[col*4+row]
00814 
00815    if (x == 0.0F) {
00816       if (y == 0.0F) {
00817          if (z != 0.0F) {
00818             optimized = GL_TRUE;
00819             /* rotate only around z-axis */
00820             M(0,0) = c;
00821             M(1,1) = c;
00822             if (z < 0.0F) {
00823                M(0,1) = s;
00824                M(1,0) = -s;
00825             }
00826             else {
00827                M(0,1) = -s;
00828                M(1,0) = s;
00829             }
00830          }
00831       }
00832       else if (z == 0.0F) {
00833          optimized = GL_TRUE;
00834          /* rotate only around y-axis */
00835          M(0,0) = c;
00836          M(2,2) = c;
00837          if (y < 0.0F) {
00838             M(0,2) = -s;
00839             M(2,0) = s;
00840          }
00841          else {
00842             M(0,2) = s;
00843             M(2,0) = -s;
00844          }
00845       }
00846    }
00847    else if (y == 0.0F) {
00848       if (z == 0.0F) {
00849          optimized = GL_TRUE;
00850          /* rotate only around x-axis */
00851          M(1,1) = c;
00852          M(2,2) = c;
00853          if (x < 0.0F) {
00854             M(1,2) = s;
00855             M(2,1) = -s;
00856          }
00857          else {
00858             M(1,2) = -s;
00859             M(2,1) = s;
00860          }
00861       }
00862    }
00863 
00864    if (!optimized) {
00865       const GLfloat mag = SQRTF(x * x + y * y + z * z);
00866 
00867       if (mag <= 1.0e-4) {
00868          /* no rotation, leave mat as-is */
00869          return;
00870       }
00871 
00872       x /= mag;
00873       y /= mag;
00874       z /= mag;
00875 
00876 
00877       /*
00878        *     Arbitrary axis rotation matrix.
00879        *
00880        *  This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
00881        *  like so:  Rz * Ry * T * Ry' * Rz'.  T is the final rotation
00882        *  (which is about the X-axis), and the two composite transforms
00883        *  Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
00884        *  from the arbitrary axis to the X-axis then back.  They are
00885        *  all elementary rotations.
00886        *
00887        *  Rz' is a rotation about the Z-axis, to bring the axis vector
00888        *  into the x-z plane.  Then Ry' is applied, rotating about the
00889        *  Y-axis to bring the axis vector parallel with the X-axis.  The
00890        *  rotation about the X-axis is then performed.  Ry and Rz are
00891        *  simply the respective inverse transforms to bring the arbitrary
00892        *  axis back to it's original orientation.  The first transforms
00893        *  Rz' and Ry' are considered inverses, since the data from the
00894        *  arbitrary axis gives you info on how to get to it, not how
00895        *  to get away from it, and an inverse must be applied.
00896        *
00897        *  The basic calculation used is to recognize that the arbitrary
00898        *  axis vector (x, y, z), since it is of unit length, actually
00899        *  represents the sines and cosines of the angles to rotate the
00900        *  X-axis to the same orientation, with theta being the angle about
00901        *  Z and phi the angle about Y (in the order described above)
00902        *  as follows:
00903        *
00904        *  cos ( theta ) = x / sqrt ( 1 - z^2 )
00905        *  sin ( theta ) = y / sqrt ( 1 - z^2 )
00906        *
00907        *  cos ( phi ) = sqrt ( 1 - z^2 )
00908        *  sin ( phi ) = z
00909        *
00910        *  Note that cos ( phi ) can further be inserted to the above
00911        *  formulas:
00912        *
00913        *  cos ( theta ) = x / cos ( phi )
00914        *  sin ( theta ) = y / sin ( phi )
00915        *
00916        *  ...etc.  Because of those relations and the standard trigonometric
00917        *  relations, it is pssible to reduce the transforms down to what
00918        *  is used below.  It may be that any primary axis chosen will give the
00919        *  same results (modulo a sign convention) using thie method.
00920        *
00921        *  Particularly nice is to notice that all divisions that might
00922        *  have caused trouble when parallel to certain planes or
00923        *  axis go away with care paid to reducing the expressions.
00924        *  After checking, it does perform correctly under all cases, since
00925        *  in all the cases of division where the denominator would have
00926        *  been zero, the numerator would have been zero as well, giving
00927        *  the expected result.
00928        */
00929 
00930       xx = x * x;
00931       yy = y * y;
00932       zz = z * z;
00933       xy = x * y;
00934       yz = y * z;
00935       zx = z * x;
00936       xs = x * s;
00937       ys = y * s;
00938       zs = z * s;
00939       one_c = 1.0F - c;
00940 
00941       /* We already hold the identity-matrix so we can skip some statements */
00942       M(0,0) = (one_c * xx) + c;
00943       M(0,1) = (one_c * xy) - zs;
00944       M(0,2) = (one_c * zx) + ys;
00945 /*    M(0,3) = 0.0F; */
00946 
00947       M(1,0) = (one_c * xy) + zs;
00948       M(1,1) = (one_c * yy) + c;
00949       M(1,2) = (one_c * yz) - xs;
00950 /*    M(1,3) = 0.0F; */
00951 
00952       M(2,0) = (one_c * zx) - ys;
00953       M(2,1) = (one_c * yz) + xs;
00954       M(2,2) = (one_c * zz) + c;
00955 /*    M(2,3) = 0.0F; */
00956 
00957 /*
00958       M(3,0) = 0.0F;
00959       M(3,1) = 0.0F;
00960       M(3,2) = 0.0F;
00961       M(3,3) = 1.0F;
00962 */
00963    }
00964 #undef M
00965 
00966    matrix_multf( mat, m, MAT_FLAG_ROTATION );
00967 }
00968 
00983 void
00984 _math_matrix_frustum( GLmatrix *mat,
00985               GLfloat left, GLfloat right,
00986               GLfloat bottom, GLfloat top,
00987               GLfloat nearval, GLfloat farval )
00988 {
00989    GLfloat x, y, a, b, c, d;
00990    GLfloat m[16];
00991 
00992    x = (2.0F*nearval) / (right-left);
00993    y = (2.0F*nearval) / (top-bottom);
00994    a = (right+left) / (right-left);
00995    b = (top+bottom) / (top-bottom);
00996    c = -(farval+nearval) / ( farval-nearval);
00997    d = -(2.0F*farval*nearval) / (farval-nearval);  /* error? */
00998 
00999 #define M(row,col)  m[col*4+row]
01000    M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = a;      M(0,3) = 0.0F;
01001    M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = b;      M(1,3) = 0.0F;
01002    M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = c;      M(2,3) = d;
01003    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;
01004 #undef M
01005 
01006    matrix_multf( mat, m, MAT_FLAG_PERSPECTIVE );
01007 }
01008 
01023 void
01024 _math_matrix_ortho( GLmatrix *mat,
01025             GLfloat left, GLfloat right,
01026             GLfloat bottom, GLfloat top,
01027             GLfloat nearval, GLfloat farval )
01028 {
01029    GLfloat m[16];
01030 
01031 #define M(row,col)  m[col*4+row]
01032    M(0,0) = 2.0F / (right-left);
01033    M(0,1) = 0.0F;
01034    M(0,2) = 0.0F;
01035    M(0,3) = -(right+left) / (right-left);
01036 
01037    M(1,0) = 0.0F;
01038    M(1,1) = 2.0F / (top-bottom);
01039    M(1,2) = 0.0F;
01040    M(1,3) = -(top+bottom) / (top-bottom);
01041 
01042    M(2,0) = 0.0F;
01043    M(2,1) = 0.0F;
01044    M(2,2) = -2.0F / (farval-nearval);
01045    M(2,3) = -(farval+nearval) / (farval-nearval);
01046 
01047    M(3,0) = 0.0F;
01048    M(3,1) = 0.0F;
01049    M(3,2) = 0.0F;
01050    M(3,3) = 1.0F;
01051 #undef M
01052 
01053    matrix_multf( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));
01054 }
01055 
01069 void
01070 _math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z )
01071 {
01072    GLfloat *m = mat->m;
01073    m[0] *= x;   m[4] *= y;   m[8]  *= z;
01074    m[1] *= x;   m[5] *= y;   m[9]  *= z;
01075    m[2] *= x;   m[6] *= y;   m[10] *= z;
01076    m[3] *= x;   m[7] *= y;   m[11] *= z;
01077 
01078    if (FABSF(x - y) < 1e-8 && FABSF(x - z) < 1e-8)
01079       mat->flags |= MAT_FLAG_UNIFORM_SCALE;
01080    else
01081       mat->flags |= MAT_FLAG_GENERAL_SCALE;
01082 
01083    mat->flags |= (MAT_DIRTY_TYPE |
01084           MAT_DIRTY_INVERSE);
01085 }
01086 
01099 void
01100 _math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z )
01101 {
01102    GLfloat *m = mat->m;
01103    m[12] = m[0] * x + m[4] * y + m[8]  * z + m[12];
01104    m[13] = m[1] * x + m[5] * y + m[9]  * z + m[13];
01105    m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
01106    m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
01107 
01108    mat->flags |= (MAT_FLAG_TRANSLATION |
01109           MAT_DIRTY_TYPE |
01110           MAT_DIRTY_INVERSE);
01111 }
01112 
01113 
01118 void
01119 _math_matrix_viewport(GLmatrix *m, GLint x, GLint y, GLint width, GLint height,
01120                       GLfloat zNear, GLfloat zFar, GLfloat depthMax)
01121 {
01122    m->m[MAT_SX] = (GLfloat) width / 2.0F;
01123    m->m[MAT_TX] = m->m[MAT_SX] + x;
01124    m->m[MAT_SY] = (GLfloat) height / 2.0F;
01125    m->m[MAT_TY] = m->m[MAT_SY] + y;
01126    m->m[MAT_SZ] = depthMax * ((zFar - zNear) / 2.0F);
01127    m->m[MAT_TZ] = depthMax * ((zFar - zNear) / 2.0F + zNear);
01128    m->flags = MAT_FLAG_GENERAL_SCALE | MAT_FLAG_TRANSLATION;
01129    m->type = MATRIX_3D_NO_ROT;
01130 }
01131 
01132 
01141 void
01142 _math_matrix_set_identity( GLmatrix *mat )
01143 {
01144    MEMCPY( mat->m, Identity, 16*sizeof(GLfloat) );
01145 
01146    if (mat->inv)
01147       MEMCPY( mat->inv, Identity, 16*sizeof(GLfloat) );
01148 
01149    mat->type = MATRIX_IDENTITY;
01150    mat->flags &= ~(MAT_DIRTY_FLAGS|
01151            MAT_DIRTY_TYPE|
01152            MAT_DIRTY_INVERSE);
01153 }
01154 
01158 /**********************************************************************/
01161 
01162 #define ZERO(x) (1<<x)
01163 #define ONE(x)  (1<<(x+16))
01164 
01165 #define MASK_NO_TRX      (ZERO(12) | ZERO(13) | ZERO(14))
01166 #define MASK_NO_2D_SCALE ( ONE(0)  | ONE(5))
01167 
01168 #define MASK_IDENTITY    ( ONE(0)  | ZERO(4)  | ZERO(8)  | ZERO(12) |\
01169               ZERO(1)  |  ONE(5)  | ZERO(9)  | ZERO(13) |\
01170               ZERO(2)  | ZERO(6)  |  ONE(10) | ZERO(14) |\
01171               ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
01172 
01173 #define MASK_2D_NO_ROT   (           ZERO(4)  | ZERO(8)  |           \
01174               ZERO(1)  |            ZERO(9)  |           \
01175               ZERO(2)  | ZERO(6)  |  ONE(10) | ZERO(14) |\
01176               ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
01177 
01178 #define MASK_2D          (                      ZERO(8)  |           \
01179                                     ZERO(9)  |           \
01180               ZERO(2)  | ZERO(6)  |  ONE(10) | ZERO(14) |\
01181               ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
01182 
01183 
01184 #define MASK_3D_NO_ROT   (           ZERO(4)  | ZERO(8)  |           \
01185               ZERO(1)  |            ZERO(9)  |           \
01186               ZERO(2)  | ZERO(6)  |                      \
01187               ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
01188 
01189 #define MASK_3D          (                                           \
01190                                                          \
01191                                                          \
01192               ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
01193 
01194 
01195 #define MASK_PERSPECTIVE (           ZERO(4)  |            ZERO(12) |\
01196               ZERO(1)  |                       ZERO(13) |\
01197               ZERO(2)  | ZERO(6)  |                      \
01198               ZERO(3)  | ZERO(7)  |            ZERO(15) )
01199 
01200 #define SQ(x) ((x)*(x))
01201 
01209 static void analyse_from_scratch( GLmatrix *mat )
01210 {
01211    const GLfloat *m = mat->m;
01212    GLuint mask = 0;
01213    GLuint i;
01214 
01215    for (i = 0 ; i < 16 ; i++) {
01216       if (m[i] == 0.0) mask |= (1<<i);
01217    }
01218 
01219    if (m[0] == 1.0F) mask |= (1<<16);
01220    if (m[5] == 1.0F) mask |= (1<<21);
01221    if (m[10] == 1.0F) mask |= (1<<26);
01222    if (m[15] == 1.0F) mask |= (1<<31);
01223 
01224    mat->flags &= ~MAT_FLAGS_GEOMETRY;
01225 
01226    /* Check for translation - no-one really cares
01227     */
01228    if ((mask & MASK_NO_TRX) != MASK_NO_TRX)
01229       mat->flags |= MAT_FLAG_TRANSLATION;
01230 
01231    /* Do the real work
01232     */
01233    if (mask == (GLuint) MASK_IDENTITY) {
01234       mat->type = MATRIX_IDENTITY;
01235    }
01236    else if ((mask & MASK_2D_NO_ROT) == (GLuint) MASK_2D_NO_ROT) {
01237       mat->type = MATRIX_2D_NO_ROT;
01238 
01239       if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE)
01240      mat->flags |= MAT_FLAG_GENERAL_SCALE;
01241    }
01242    else if ((mask & MASK_2D) == (GLuint) MASK_2D) {
01243       GLfloat mm = DOT2(m, m);
01244       GLfloat m4m4 = DOT2(m+4,m+4);
01245       GLfloat mm4 = DOT2(m,m+4);
01246 
01247       mat->type = MATRIX_2D;
01248 
01249       /* Check for scale */
01250       if (SQ(mm-1) > SQ(1e-6) ||
01251       SQ(m4m4-1) > SQ(1e-6))
01252      mat->flags |= MAT_FLAG_GENERAL_SCALE;
01253 
01254       /* Check for rotation */
01255       if (SQ(mm4) > SQ(1e-6))
01256      mat->flags |= MAT_FLAG_GENERAL_3D;
01257       else
01258      mat->flags |= MAT_FLAG_ROTATION;
01259 
01260    }
01261    else if ((mask & MASK_3D_NO_ROT) == (GLuint) MASK_3D_NO_ROT) {
01262       mat->type = MATRIX_3D_NO_ROT;
01263 
01264       /* Check for scale */
01265       if (SQ(m[0]-m[5]) < SQ(1e-6) &&
01266       SQ(m[0]-m[10]) < SQ(1e-6)) {
01267      if (SQ(m[0]-1.0) > SQ(1e-6)) {
01268         mat->flags |= MAT_FLAG_UNIFORM_SCALE;
01269          }
01270       }
01271       else {
01272      mat->flags |= MAT_FLAG_GENERAL_SCALE;
01273       }
01274    }
01275    else if ((mask & MASK_3D) == (GLuint) MASK_3D) {
01276       GLfloat c1 = DOT3(m,m);
01277       GLfloat c2 = DOT3(m+4,m+4);
01278       GLfloat c3 = DOT3(m+8,m+8);
01279       GLfloat d1 = DOT3(m, m+4);
01280       GLfloat cp[3];
01281 
01282       mat->type = MATRIX_3D;
01283 
01284       /* Check for scale */
01285       if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) {
01286      if (SQ(c1-1.0) > SQ(1e-6))
01287         mat->flags |= MAT_FLAG_UNIFORM_SCALE;
01288      /* else no scale at all */
01289       }
01290       else {
01291      mat->flags |= MAT_FLAG_GENERAL_SCALE;
01292       }
01293 
01294       /* Check for rotation */
01295       if (SQ(d1) < SQ(1e-6)) {
01296      CROSS3( cp, m, m+4 );
01297      SUB_3V( cp, cp, (m+8) );
01298      if (LEN_SQUARED_3FV(cp) < SQ(1e-6))
01299         mat->flags |= MAT_FLAG_ROTATION;
01300      else
01301         mat->flags |= MAT_FLAG_GENERAL_3D;
01302       }
01303       else {
01304      mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */
01305       }
01306    }
01307    else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) {
01308       mat->type = MATRIX_PERSPECTIVE;
01309       mat->flags |= MAT_FLAG_GENERAL;
01310    }
01311    else {
01312       mat->type = MATRIX_GENERAL;
01313       mat->flags |= MAT_FLAG_GENERAL;
01314    }
01315 }
01316 
01322 static void analyse_from_flags( GLmatrix *mat )
01323 {
01324    const GLfloat *m = mat->m;
01325 
01326    if (TEST_MAT_FLAGS(mat, 0)) {
01327       mat->type = MATRIX_IDENTITY;
01328    }
01329    else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION |
01330                  MAT_FLAG_UNIFORM_SCALE |
01331                  MAT_FLAG_GENERAL_SCALE))) {
01332       if ( m[10]==1.0F && m[14]==0.0F ) {
01333      mat->type = MATRIX_2D_NO_ROT;
01334       }
01335       else {
01336      mat->type = MATRIX_3D_NO_ROT;
01337       }
01338    }
01339    else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) {
01340       if (                                 m[ 8]==0.0F
01341             &&                             m[ 9]==0.0F
01342             && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F) {
01343      mat->type = MATRIX_2D;
01344       }
01345       else {
01346      mat->type = MATRIX_3D;
01347       }
01348    }
01349    else if (                 m[4]==0.0F                 && m[12]==0.0F
01350             && m[1]==0.0F                               && m[13]==0.0F
01351             && m[2]==0.0F && m[6]==0.0F
01352             && m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) {
01353       mat->type = MATRIX_PERSPECTIVE;
01354    }
01355    else {
01356       mat->type = MATRIX_GENERAL;
01357    }
01358 }
01359 
01370 void
01371 _math_matrix_analyse( GLmatrix *mat )
01372 {
01373    if (mat->flags & MAT_DIRTY_TYPE) {
01374       if (mat->flags & MAT_DIRTY_FLAGS)
01375      analyse_from_scratch( mat );
01376       else
01377      analyse_from_flags( mat );
01378    }
01379 
01380    if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) {
01381       matrix_invert( mat );
01382    }
01383 
01384    mat->flags &= ~(MAT_DIRTY_FLAGS|
01385            MAT_DIRTY_TYPE|
01386            MAT_DIRTY_INVERSE);
01387 }
01388 
01395 GLboolean
01396 _math_matrix_is_length_preserving( const GLmatrix *m )
01397 {
01398    return TEST_MAT_FLAGS( m, MAT_FLAGS_LENGTH_PRESERVING);
01399 }
01400 
01401 
01406 GLboolean
01407 _math_matrix_has_rotation( const GLmatrix *m )
01408 {
01409    if (m->flags & (MAT_FLAG_GENERAL |
01410                    MAT_FLAG_ROTATION |
01411                    MAT_FLAG_GENERAL_3D |
01412                    MAT_FLAG_PERSPECTIVE))
01413       return GL_TRUE;
01414    else
01415       return GL_FALSE;
01416 }
01417 
01418 
01419 GLboolean
01420 _math_matrix_is_general_scale( const GLmatrix *m )
01421 {
01422    return (m->flags & MAT_FLAG_GENERAL_SCALE) ? GL_TRUE : GL_FALSE;
01423 }
01424 
01425 
01426 GLboolean
01427 _math_matrix_is_dirty( const GLmatrix *m )
01428 {
01429    return (m->flags & MAT_DIRTY) ? GL_TRUE : GL_FALSE;
01430 }
01431 
01432 
01433 /**********************************************************************/
01436 
01445 void
01446 _math_matrix_copy( GLmatrix *to, const GLmatrix *from )
01447 {
01448    MEMCPY( to->m, from->m, sizeof(Identity) );
01449    to->flags = from->flags;
01450    to->type = from->type;
01451 
01452    if (to->inv != 0) {
01453       if (from->inv == 0) {
01454      matrix_invert( to );
01455       }
01456       else {
01457      MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16);
01458       }
01459    }
01460 }
01461 
01471 void
01472 _math_matrix_loadf( GLmatrix *mat, const GLfloat *m )
01473 {
01474    MEMCPY( mat->m, m, 16*sizeof(GLfloat) );
01475    mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY);
01476 }
01477 
01485 void
01486 _math_matrix_ctr( GLmatrix *m )
01487 {
01488    m->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
01489    if (m->m)
01490       MEMCPY( m->m, Identity, sizeof(Identity) );
01491    m->inv = NULL;
01492    m->type = MATRIX_IDENTITY;
01493    m->flags = 0;
01494 }
01495 
01503 void
01504 _math_matrix_dtr( GLmatrix *m )
01505 {
01506    if (m->m) {
01507       ALIGN_FREE( m->m );
01508       m->m = NULL;
01509    }
01510    if (m->inv) {
01511       ALIGN_FREE( m->inv );
01512       m->inv = NULL;
01513    }
01514 }
01515 
01523 void
01524 _math_matrix_alloc_inv( GLmatrix *m )
01525 {
01526    if (!m->inv) {
01527       m->inv = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
01528       if (m->inv)
01529          MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) );
01530    }
01531 }
01532 
01536 /**********************************************************************/
01539 
01546 void
01547 _math_transposef( GLfloat to[16], const GLfloat from[16] )
01548 {
01549    to[0] = from[0];
01550    to[1] = from[4];
01551    to[2] = from[8];
01552    to[3] = from[12];
01553    to[4] = from[1];
01554    to[5] = from[5];
01555    to[6] = from[9];
01556    to[7] = from[13];
01557    to[8] = from[2];
01558    to[9] = from[6];
01559    to[10] = from[10];
01560    to[11] = from[14];
01561    to[12] = from[3];
01562    to[13] = from[7];
01563    to[14] = from[11];
01564    to[15] = from[15];
01565 }
01566 
01573 void
01574 _math_transposed( GLdouble to[16], const GLdouble from[16] )
01575 {
01576    to[0] = from[0];
01577    to[1] = from[4];
01578    to[2] = from[8];
01579    to[3] = from[12];
01580    to[4] = from[1];
01581    to[5] = from[5];
01582    to[6] = from[9];
01583    to[7] = from[13];
01584    to[8] = from[2];
01585    to[9] = from[6];
01586    to[10] = from[10];
01587    to[11] = from[14];
01588    to[12] = from[3];
01589    to[13] = from[7];
01590    to[14] = from[11];
01591    to[15] = from[15];
01592 }
01593 
01600 void
01601 _math_transposefd( GLfloat to[16], const GLdouble from[16] )
01602 {
01603    to[0] = (GLfloat) from[0];
01604    to[1] = (GLfloat) from[4];
01605    to[2] = (GLfloat) from[8];
01606    to[3] = (GLfloat) from[12];
01607    to[4] = (GLfloat) from[1];
01608    to[5] = (GLfloat) from[5];
01609    to[6] = (GLfloat) from[9];
01610    to[7] = (GLfloat) from[13];
01611    to[8] = (GLfloat) from[2];
01612    to[9] = (GLfloat) from[6];
01613    to[10] = (GLfloat) from[10];
01614    to[11] = (GLfloat) from[14];
01615    to[12] = (GLfloat) from[3];
01616    to[13] = (GLfloat) from[7];
01617    to[14] = (GLfloat) from[11];
01618    to[15] = (GLfloat) from[15];
01619 }
01620 

Generated on Mon May 28 2012 04:20:15 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.