Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenm_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
1.7.6.1
|