xref: /aosp_15_r20/external/mesa3d/src/mesa/math/m_matrix.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Mesa 3-D graphics library
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
8*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
9*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
11*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
12*61046927SAndroid Build Coastguard Worker  *
13*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
14*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
15*61046927SAndroid Build Coastguard Worker  *
16*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22*61046927SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
23*61046927SAndroid Build Coastguard Worker  */
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker /**
27*61046927SAndroid Build Coastguard Worker  * \file m_matrix.c
28*61046927SAndroid Build Coastguard Worker  * Matrix operations.
29*61046927SAndroid Build Coastguard Worker  *
30*61046927SAndroid Build Coastguard Worker  * \note
31*61046927SAndroid Build Coastguard Worker  * -# 4x4 transformation matrices are stored in memory in column major order.
32*61046927SAndroid Build Coastguard Worker  * -# Points/vertices are to be thought of as column vectors.
33*61046927SAndroid Build Coastguard Worker  * -# Transformation of a point p by a matrix M is: p' = M * p
34*61046927SAndroid Build Coastguard Worker  */
35*61046927SAndroid Build Coastguard Worker 
36*61046927SAndroid Build Coastguard Worker #include <stddef.h>
37*61046927SAndroid Build Coastguard Worker #include <math.h>
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker #include "main/errors.h"
40*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
41*61046927SAndroid Build Coastguard Worker #include "main/macros.h"
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker #include "m_matrix.h"
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker /**
49*61046927SAndroid Build Coastguard Worker  * \defgroup MatFlags MAT_FLAG_XXX-flags
50*61046927SAndroid Build Coastguard Worker  *
51*61046927SAndroid Build Coastguard Worker  * Bitmasks to indicate different kinds of 4x4 matrices in GLmatrix::flags
52*61046927SAndroid Build Coastguard Worker  */
53*61046927SAndroid Build Coastguard Worker /*@{*/
54*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_IDENTITY       0     /**< is an identity matrix flag.
55*61046927SAndroid Build Coastguard Worker                                        *   (Not actually used - the identity
56*61046927SAndroid Build Coastguard Worker                                        *   matrix is identified by the absence
57*61046927SAndroid Build Coastguard Worker                                        *   of all other flags.)
58*61046927SAndroid Build Coastguard Worker                                        */
59*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_GENERAL        0x1   /**< is a general matrix flag */
60*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_ROTATION       0x2   /**< is a rotation matrix flag */
61*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_TRANSLATION    0x4   /**< is a translation matrix flag */
62*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_UNIFORM_SCALE  0x8   /**< is an uniform scaling matrix flag */
63*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_GENERAL_SCALE  0x10  /**< is a general scaling matrix flag */
64*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_GENERAL_3D     0x20  /**< general 3D matrix flag */
65*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_PERSPECTIVE    0x40  /**< is a perspective proj matrix flag */
66*61046927SAndroid Build Coastguard Worker #define MAT_FLAG_SINGULAR       0x80  /**< is a singular matrix flag */
67*61046927SAndroid Build Coastguard Worker #define MAT_DIRTY_TYPE          0x100  /**< matrix type is dirty */
68*61046927SAndroid Build Coastguard Worker #define MAT_DIRTY_FLAGS         0x200  /**< matrix flags are dirty */
69*61046927SAndroid Build Coastguard Worker #define MAT_DIRTY_INVERSE       0x400  /**< matrix inverse is dirty */
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker /** angle preserving matrix flags mask */
72*61046927SAndroid Build Coastguard Worker #define MAT_FLAGS_ANGLE_PRESERVING (MAT_FLAG_ROTATION | \
73*61046927SAndroid Build Coastguard Worker                                     MAT_FLAG_TRANSLATION | \
74*61046927SAndroid Build Coastguard Worker                                     MAT_FLAG_UNIFORM_SCALE)
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker /** geometry related matrix flags mask */
77*61046927SAndroid Build Coastguard Worker #define MAT_FLAGS_GEOMETRY (MAT_FLAG_GENERAL | \
78*61046927SAndroid Build Coastguard Worker                             MAT_FLAG_ROTATION | \
79*61046927SAndroid Build Coastguard Worker                             MAT_FLAG_TRANSLATION | \
80*61046927SAndroid Build Coastguard Worker                             MAT_FLAG_UNIFORM_SCALE | \
81*61046927SAndroid Build Coastguard Worker                             MAT_FLAG_GENERAL_SCALE | \
82*61046927SAndroid Build Coastguard Worker                             MAT_FLAG_GENERAL_3D | \
83*61046927SAndroid Build Coastguard Worker                             MAT_FLAG_PERSPECTIVE | \
84*61046927SAndroid Build Coastguard Worker                             MAT_FLAG_SINGULAR)
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker /** length preserving matrix flags mask */
87*61046927SAndroid Build Coastguard Worker #define MAT_FLAGS_LENGTH_PRESERVING (MAT_FLAG_ROTATION | \
88*61046927SAndroid Build Coastguard Worker                                      MAT_FLAG_TRANSLATION)
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker /** 3D (non-perspective) matrix flags mask */
92*61046927SAndroid Build Coastguard Worker #define MAT_FLAGS_3D (MAT_FLAG_ROTATION | \
93*61046927SAndroid Build Coastguard Worker                       MAT_FLAG_TRANSLATION | \
94*61046927SAndroid Build Coastguard Worker                       MAT_FLAG_UNIFORM_SCALE | \
95*61046927SAndroid Build Coastguard Worker                       MAT_FLAG_GENERAL_SCALE | \
96*61046927SAndroid Build Coastguard Worker                       MAT_FLAG_GENERAL_3D)
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker /** dirty matrix flags mask */
99*61046927SAndroid Build Coastguard Worker #define MAT_DIRTY          (MAT_DIRTY_TYPE | \
100*61046927SAndroid Build Coastguard Worker                             MAT_DIRTY_FLAGS | \
101*61046927SAndroid Build Coastguard Worker                             MAT_DIRTY_INVERSE)
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker /*@}*/
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker /**
107*61046927SAndroid Build Coastguard Worker  * Test geometry related matrix flags.
108*61046927SAndroid Build Coastguard Worker  *
109*61046927SAndroid Build Coastguard Worker  * \param mat a pointer to a GLmatrix structure.
110*61046927SAndroid Build Coastguard Worker  * \param a flags mask.
111*61046927SAndroid Build Coastguard Worker  *
112*61046927SAndroid Build Coastguard Worker  * \returns non-zero if all geometry related matrix flags are contained within
113*61046927SAndroid Build Coastguard Worker  * the mask, or zero otherwise.
114*61046927SAndroid Build Coastguard Worker  */
115*61046927SAndroid Build Coastguard Worker #define TEST_MAT_FLAGS(mat, a)  \
116*61046927SAndroid Build Coastguard Worker     ((MAT_FLAGS_GEOMETRY & (~(a)) & ((mat)->flags) ) == 0)
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker /**********************************************************************/
120*61046927SAndroid Build Coastguard Worker /** \name Matrix multiplication */
121*61046927SAndroid Build Coastguard Worker /*@{*/
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker #define A(row,col)  a[(col<<2)+row]
124*61046927SAndroid Build Coastguard Worker #define B(row,col)  b[(col<<2)+row]
125*61046927SAndroid Build Coastguard Worker #define P(row,col)  product[(col<<2)+row]
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker /**
128*61046927SAndroid Build Coastguard Worker  * Perform a full 4x4 matrix multiplication.
129*61046927SAndroid Build Coastguard Worker  *
130*61046927SAndroid Build Coastguard Worker  * \param a matrix.
131*61046927SAndroid Build Coastguard Worker  * \param b matrix.
132*61046927SAndroid Build Coastguard Worker  * \param product will receive the product of \p a and \p b.
133*61046927SAndroid Build Coastguard Worker  *
134*61046927SAndroid Build Coastguard Worker  * \warning Is assumed that \p product != \p b. \p product == \p a is allowed.
135*61046927SAndroid Build Coastguard Worker  *
136*61046927SAndroid Build Coastguard Worker  * \note KW: 4*16 = 64 multiplications
137*61046927SAndroid Build Coastguard Worker  *
138*61046927SAndroid Build Coastguard Worker  * \author This \c matmul was contributed by Thomas Malik
139*61046927SAndroid Build Coastguard Worker  */
matmul4(GLfloat * product,const GLfloat * a,const GLfloat * b)140*61046927SAndroid Build Coastguard Worker static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b )
141*61046927SAndroid Build Coastguard Worker {
142*61046927SAndroid Build Coastguard Worker    GLint i;
143*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 4; i++) {
144*61046927SAndroid Build Coastguard Worker       const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
145*61046927SAndroid Build Coastguard Worker       P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
146*61046927SAndroid Build Coastguard Worker       P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
147*61046927SAndroid Build Coastguard Worker       P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
148*61046927SAndroid Build Coastguard Worker       P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
149*61046927SAndroid Build Coastguard Worker    }
150*61046927SAndroid Build Coastguard Worker }
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker /**
153*61046927SAndroid Build Coastguard Worker  * Multiply two matrices known to occupy only the top three rows, such
154*61046927SAndroid Build Coastguard Worker  * as typical model matrices, and orthogonal matrices.
155*61046927SAndroid Build Coastguard Worker  *
156*61046927SAndroid Build Coastguard Worker  * \param a matrix.
157*61046927SAndroid Build Coastguard Worker  * \param b matrix.
158*61046927SAndroid Build Coastguard Worker  * \param product will receive the product of \p a and \p b.
159*61046927SAndroid Build Coastguard Worker  */
matmul34(GLfloat * product,const GLfloat * a,const GLfloat * b)160*61046927SAndroid Build Coastguard Worker static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b )
161*61046927SAndroid Build Coastguard Worker {
162*61046927SAndroid Build Coastguard Worker    GLint i;
163*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 3; i++) {
164*61046927SAndroid Build Coastguard Worker       const GLfloat ai0=A(i,0),  ai1=A(i,1),  ai2=A(i,2),  ai3=A(i,3);
165*61046927SAndroid Build Coastguard Worker       P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0);
166*61046927SAndroid Build Coastguard Worker       P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1);
167*61046927SAndroid Build Coastguard Worker       P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2);
168*61046927SAndroid Build Coastguard Worker       P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3;
169*61046927SAndroid Build Coastguard Worker    }
170*61046927SAndroid Build Coastguard Worker    P(3,0) = 0;
171*61046927SAndroid Build Coastguard Worker    P(3,1) = 0;
172*61046927SAndroid Build Coastguard Worker    P(3,2) = 0;
173*61046927SAndroid Build Coastguard Worker    P(3,3) = 1;
174*61046927SAndroid Build Coastguard Worker }
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker #undef A
177*61046927SAndroid Build Coastguard Worker #undef B
178*61046927SAndroid Build Coastguard Worker #undef P
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker /* "m" must be a 4x4 matrix. Set it to the identity matrix. */
181*61046927SAndroid Build Coastguard Worker static void
matrix_set_identity(GLfloat * m)182*61046927SAndroid Build Coastguard Worker matrix_set_identity(GLfloat *m)
183*61046927SAndroid Build Coastguard Worker {
184*61046927SAndroid Build Coastguard Worker    m[0] = m[5] = m[10] = m[15] = 1;
185*61046927SAndroid Build Coastguard Worker    m[1] = m[2] = m[3] = m[4] = m[6] = m[7] = 0;
186*61046927SAndroid Build Coastguard Worker    m[8] = m[9] = m[11] = m[12] = m[13] = m[14] = 0;
187*61046927SAndroid Build Coastguard Worker }
188*61046927SAndroid Build Coastguard Worker 
189*61046927SAndroid Build Coastguard Worker /**
190*61046927SAndroid Build Coastguard Worker  * Multiply a matrix by an array of floats with known properties.
191*61046927SAndroid Build Coastguard Worker  *
192*61046927SAndroid Build Coastguard Worker  * \param mat pointer to a GLmatrix structure containing the left multiplication
193*61046927SAndroid Build Coastguard Worker  * matrix, and that will receive the product result.
194*61046927SAndroid Build Coastguard Worker  * \param m right multiplication matrix array.
195*61046927SAndroid Build Coastguard Worker  * \param flags flags of the matrix \p m.
196*61046927SAndroid Build Coastguard Worker  *
197*61046927SAndroid Build Coastguard Worker  * Joins both flags and marks the type and inverse as dirty.  Calls matmul34()
198*61046927SAndroid Build Coastguard Worker  * if both matrices are 3D, or matmul4() otherwise.
199*61046927SAndroid Build Coastguard Worker  */
matrix_multf(GLmatrix * mat,const GLfloat * m,GLuint flags)200*61046927SAndroid Build Coastguard Worker static void matrix_multf( GLmatrix *mat, const GLfloat *m, GLuint flags )
201*61046927SAndroid Build Coastguard Worker {
202*61046927SAndroid Build Coastguard Worker    mat->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
205*61046927SAndroid Build Coastguard Worker       matmul34( mat->m, mat->m, m );
206*61046927SAndroid Build Coastguard Worker    else
207*61046927SAndroid Build Coastguard Worker       matmul4( mat->m, mat->m, m );
208*61046927SAndroid Build Coastguard Worker }
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker /**
211*61046927SAndroid Build Coastguard Worker  * Matrix multiplication.
212*61046927SAndroid Build Coastguard Worker  *
213*61046927SAndroid Build Coastguard Worker  * \param dest destination matrix.
214*61046927SAndroid Build Coastguard Worker  * \param a left matrix.
215*61046927SAndroid Build Coastguard Worker  * \param b right matrix.
216*61046927SAndroid Build Coastguard Worker  *
217*61046927SAndroid Build Coastguard Worker  * Joins both flags and marks the type and inverse as dirty.  Calls matmul34()
218*61046927SAndroid Build Coastguard Worker  * if both matrices are 3D, or matmul4() otherwise.
219*61046927SAndroid Build Coastguard Worker  */
220*61046927SAndroid Build Coastguard Worker void
_math_matrix_mul_matrix(GLmatrix * dest,const GLmatrix * a,const GLmatrix * b)221*61046927SAndroid Build Coastguard Worker _math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b )
222*61046927SAndroid Build Coastguard Worker {
223*61046927SAndroid Build Coastguard Worker    dest->flags = (a->flags |
224*61046927SAndroid Build Coastguard Worker                   b->flags |
225*61046927SAndroid Build Coastguard Worker                   MAT_DIRTY_TYPE |
226*61046927SAndroid Build Coastguard Worker                   MAT_DIRTY_INVERSE);
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D))
229*61046927SAndroid Build Coastguard Worker       matmul34( dest->m, a->m, b->m );
230*61046927SAndroid Build Coastguard Worker    else
231*61046927SAndroid Build Coastguard Worker       matmul4( dest->m, a->m, b->m );
232*61046927SAndroid Build Coastguard Worker }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker /**
235*61046927SAndroid Build Coastguard Worker  * Matrix multiplication.
236*61046927SAndroid Build Coastguard Worker  *
237*61046927SAndroid Build Coastguard Worker  * \param dest left and destination matrix.
238*61046927SAndroid Build Coastguard Worker  * \param m right matrix array.
239*61046927SAndroid Build Coastguard Worker  *
240*61046927SAndroid Build Coastguard Worker  * Marks the matrix flags with general flag, and type and inverse dirty flags.
241*61046927SAndroid Build Coastguard Worker  * Calls matmul4() for the multiplication.
242*61046927SAndroid Build Coastguard Worker  */
243*61046927SAndroid Build Coastguard Worker void
_math_matrix_mul_floats(GLmatrix * dest,const GLfloat * m)244*61046927SAndroid Build Coastguard Worker _math_matrix_mul_floats( GLmatrix *dest, const GLfloat *m )
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker    dest->flags |= (MAT_FLAG_GENERAL |
247*61046927SAndroid Build Coastguard Worker                    MAT_DIRTY_TYPE |
248*61046927SAndroid Build Coastguard Worker                    MAT_DIRTY_INVERSE |
249*61046927SAndroid Build Coastguard Worker                    MAT_DIRTY_FLAGS);
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    matmul4( dest->m, dest->m, m );
252*61046927SAndroid Build Coastguard Worker }
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker /*@}*/
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker /**
257*61046927SAndroid Build Coastguard Worker  * References an element of 4x4 matrix.
258*61046927SAndroid Build Coastguard Worker  *
259*61046927SAndroid Build Coastguard Worker  * \param m matrix array.
260*61046927SAndroid Build Coastguard Worker  * \param c column of the desired element.
261*61046927SAndroid Build Coastguard Worker  * \param r row of the desired element.
262*61046927SAndroid Build Coastguard Worker  *
263*61046927SAndroid Build Coastguard Worker  * \return value of the desired element.
264*61046927SAndroid Build Coastguard Worker  *
265*61046927SAndroid Build Coastguard Worker  * Calculate the linear storage index of the element and references it.
266*61046927SAndroid Build Coastguard Worker  */
267*61046927SAndroid Build Coastguard Worker #define MAT(m,r,c) (m)[(c)*4+(r)]
268*61046927SAndroid Build Coastguard Worker 
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker /**********************************************************************/
271*61046927SAndroid Build Coastguard Worker /** \name Matrix inversion */
272*61046927SAndroid Build Coastguard Worker /*@{*/
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker /**
275*61046927SAndroid Build Coastguard Worker  * Compute inverse of 4x4 transformation matrix.
276*61046927SAndroid Build Coastguard Worker  *
277*61046927SAndroid Build Coastguard Worker  * \param mat pointer to a GLmatrix structure. The matrix inverse will be
278*61046927SAndroid Build Coastguard Worker  * stored in the GLmatrix::inv attribute.
279*61046927SAndroid Build Coastguard Worker  *
280*61046927SAndroid Build Coastguard Worker  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
281*61046927SAndroid Build Coastguard Worker  *
282*61046927SAndroid Build Coastguard Worker  * \author
283*61046927SAndroid Build Coastguard Worker  * Code contributed by Jacques Leroy [email protected]
284*61046927SAndroid Build Coastguard Worker  *
285*61046927SAndroid Build Coastguard Worker  * Calculates the inverse matrix by performing the gaussian matrix reduction
286*61046927SAndroid Build Coastguard Worker  * with partial pivoting followed by back/substitution with the loops manually
287*61046927SAndroid Build Coastguard Worker  * unrolled.
288*61046927SAndroid Build Coastguard Worker  */
invert_matrix_general(GLmatrix * mat)289*61046927SAndroid Build Coastguard Worker static GLboolean invert_matrix_general( GLmatrix *mat )
290*61046927SAndroid Build Coastguard Worker {
291*61046927SAndroid Build Coastguard Worker    return util_invert_mat4x4(mat->inv, mat->m);
292*61046927SAndroid Build Coastguard Worker }
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker /**
295*61046927SAndroid Build Coastguard Worker  * Compute inverse of a general 3d transformation matrix.
296*61046927SAndroid Build Coastguard Worker  *
297*61046927SAndroid Build Coastguard Worker  * \param mat pointer to a GLmatrix structure. The matrix inverse will be
298*61046927SAndroid Build Coastguard Worker  * stored in the GLmatrix::inv attribute.
299*61046927SAndroid Build Coastguard Worker  *
300*61046927SAndroid Build Coastguard Worker  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
301*61046927SAndroid Build Coastguard Worker  *
302*61046927SAndroid Build Coastguard Worker  * \author Adapted from graphics gems II.
303*61046927SAndroid Build Coastguard Worker  *
304*61046927SAndroid Build Coastguard Worker  * Calculates the inverse of the upper left by first calculating its
305*61046927SAndroid Build Coastguard Worker  * determinant and multiplying it to the symmetric adjust matrix of each
306*61046927SAndroid Build Coastguard Worker  * element. Finally deals with the translation part by transforming the
307*61046927SAndroid Build Coastguard Worker  * original translation vector using by the calculated submatrix inverse.
308*61046927SAndroid Build Coastguard Worker  */
invert_matrix_3d_general(GLmatrix * mat)309*61046927SAndroid Build Coastguard Worker static GLboolean invert_matrix_3d_general( GLmatrix *mat )
310*61046927SAndroid Build Coastguard Worker {
311*61046927SAndroid Build Coastguard Worker    const GLfloat *in = mat->m;
312*61046927SAndroid Build Coastguard Worker    GLfloat *out = mat->inv;
313*61046927SAndroid Build Coastguard Worker    GLfloat pos, neg, t;
314*61046927SAndroid Build Coastguard Worker    GLfloat det;
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker    /* Calculate the determinant of upper left 3x3 submatrix and
317*61046927SAndroid Build Coastguard Worker     * determine if the matrix is singular.
318*61046927SAndroid Build Coastguard Worker     */
319*61046927SAndroid Build Coastguard Worker    pos = neg = 0.0;
320*61046927SAndroid Build Coastguard Worker    t =  MAT(in,0,0) * MAT(in,1,1) * MAT(in,2,2);
321*61046927SAndroid Build Coastguard Worker    if (t >= 0.0F) pos += t; else neg += t;
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    t =  MAT(in,1,0) * MAT(in,2,1) * MAT(in,0,2);
324*61046927SAndroid Build Coastguard Worker    if (t >= 0.0F) pos += t; else neg += t;
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker    t =  MAT(in,2,0) * MAT(in,0,1) * MAT(in,1,2);
327*61046927SAndroid Build Coastguard Worker    if (t >= 0.0F) pos += t; else neg += t;
328*61046927SAndroid Build Coastguard Worker 
329*61046927SAndroid Build Coastguard Worker    t = -MAT(in,2,0) * MAT(in,1,1) * MAT(in,0,2);
330*61046927SAndroid Build Coastguard Worker    if (t >= 0.0F) pos += t; else neg += t;
331*61046927SAndroid Build Coastguard Worker 
332*61046927SAndroid Build Coastguard Worker    t = -MAT(in,1,0) * MAT(in,0,1) * MAT(in,2,2);
333*61046927SAndroid Build Coastguard Worker    if (t >= 0.0F) pos += t; else neg += t;
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker    t = -MAT(in,0,0) * MAT(in,2,1) * MAT(in,1,2);
336*61046927SAndroid Build Coastguard Worker    if (t >= 0.0F) pos += t; else neg += t;
337*61046927SAndroid Build Coastguard Worker 
338*61046927SAndroid Build Coastguard Worker    det = pos + neg;
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker    if (fabsf(det) < 1e-25F)
341*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
342*61046927SAndroid Build Coastguard Worker 
343*61046927SAndroid Build Coastguard Worker    det = 1.0F / det;
344*61046927SAndroid Build Coastguard Worker    MAT(out,0,0) = (  (MAT(in,1,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,1,2) )*det);
345*61046927SAndroid Build Coastguard Worker    MAT(out,0,1) = (- (MAT(in,0,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,0,2) )*det);
346*61046927SAndroid Build Coastguard Worker    MAT(out,0,2) = (  (MAT(in,0,1)*MAT(in,1,2) - MAT(in,1,1)*MAT(in,0,2) )*det);
347*61046927SAndroid Build Coastguard Worker    MAT(out,1,0) = (- (MAT(in,1,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,1,2) )*det);
348*61046927SAndroid Build Coastguard Worker    MAT(out,1,1) = (  (MAT(in,0,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,0,2) )*det);
349*61046927SAndroid Build Coastguard Worker    MAT(out,1,2) = (- (MAT(in,0,0)*MAT(in,1,2) - MAT(in,1,0)*MAT(in,0,2) )*det);
350*61046927SAndroid Build Coastguard Worker    MAT(out,2,0) = (  (MAT(in,1,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,1,1) )*det);
351*61046927SAndroid Build Coastguard Worker    MAT(out,2,1) = (- (MAT(in,0,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,0,1) )*det);
352*61046927SAndroid Build Coastguard Worker    MAT(out,2,2) = (  (MAT(in,0,0)*MAT(in,1,1) - MAT(in,1,0)*MAT(in,0,1) )*det);
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker    /* Do the translation part */
355*61046927SAndroid Build Coastguard Worker    MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
356*61046927SAndroid Build Coastguard Worker                      MAT(in,1,3) * MAT(out,0,1) +
357*61046927SAndroid Build Coastguard Worker                      MAT(in,2,3) * MAT(out,0,2) );
358*61046927SAndroid Build Coastguard Worker    MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +
359*61046927SAndroid Build Coastguard Worker                      MAT(in,1,3) * MAT(out,1,1) +
360*61046927SAndroid Build Coastguard Worker                      MAT(in,2,3) * MAT(out,1,2) );
361*61046927SAndroid Build Coastguard Worker    MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +
362*61046927SAndroid Build Coastguard Worker                      MAT(in,1,3) * MAT(out,2,1) +
363*61046927SAndroid Build Coastguard Worker                      MAT(in,2,3) * MAT(out,2,2) );
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
366*61046927SAndroid Build Coastguard Worker }
367*61046927SAndroid Build Coastguard Worker 
368*61046927SAndroid Build Coastguard Worker /**
369*61046927SAndroid Build Coastguard Worker  * Compute inverse of a 3d transformation matrix.
370*61046927SAndroid Build Coastguard Worker  *
371*61046927SAndroid Build Coastguard Worker  * \param mat pointer to a GLmatrix structure. The matrix inverse will be
372*61046927SAndroid Build Coastguard Worker  * stored in the GLmatrix::inv attribute.
373*61046927SAndroid Build Coastguard Worker  *
374*61046927SAndroid Build Coastguard Worker  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
375*61046927SAndroid Build Coastguard Worker  *
376*61046927SAndroid Build Coastguard Worker  * If the matrix is not an angle preserving matrix then calls
377*61046927SAndroid Build Coastguard Worker  * invert_matrix_3d_general for the actual calculation. Otherwise calculates
378*61046927SAndroid Build Coastguard Worker  * the inverse matrix analyzing and inverting each of the scaling, rotation and
379*61046927SAndroid Build Coastguard Worker  * translation parts.
380*61046927SAndroid Build Coastguard Worker  */
invert_matrix_3d(GLmatrix * mat)381*61046927SAndroid Build Coastguard Worker static GLboolean invert_matrix_3d( GLmatrix *mat )
382*61046927SAndroid Build Coastguard Worker {
383*61046927SAndroid Build Coastguard Worker    const GLfloat *in = mat->m;
384*61046927SAndroid Build Coastguard Worker    GLfloat *out = mat->inv;
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING)) {
387*61046927SAndroid Build Coastguard Worker       return invert_matrix_3d_general( mat );
388*61046927SAndroid Build Coastguard Worker    }
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker    if (mat->flags & MAT_FLAG_UNIFORM_SCALE) {
391*61046927SAndroid Build Coastguard Worker       GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) +
392*61046927SAndroid Build Coastguard Worker                        MAT(in,0,1) * MAT(in,0,1) +
393*61046927SAndroid Build Coastguard Worker                        MAT(in,0,2) * MAT(in,0,2));
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker       if (scale == 0.0F)
396*61046927SAndroid Build Coastguard Worker          return GL_FALSE;
397*61046927SAndroid Build Coastguard Worker 
398*61046927SAndroid Build Coastguard Worker       scale = 1.0F / scale;
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker       /* Transpose and scale the 3 by 3 upper-left submatrix. */
401*61046927SAndroid Build Coastguard Worker       MAT(out,0,0) = scale * MAT(in,0,0);
402*61046927SAndroid Build Coastguard Worker       MAT(out,1,0) = scale * MAT(in,0,1);
403*61046927SAndroid Build Coastguard Worker       MAT(out,2,0) = scale * MAT(in,0,2);
404*61046927SAndroid Build Coastguard Worker       MAT(out,0,1) = scale * MAT(in,1,0);
405*61046927SAndroid Build Coastguard Worker       MAT(out,1,1) = scale * MAT(in,1,1);
406*61046927SAndroid Build Coastguard Worker       MAT(out,2,1) = scale * MAT(in,1,2);
407*61046927SAndroid Build Coastguard Worker       MAT(out,0,2) = scale * MAT(in,2,0);
408*61046927SAndroid Build Coastguard Worker       MAT(out,1,2) = scale * MAT(in,2,1);
409*61046927SAndroid Build Coastguard Worker       MAT(out,2,2) = scale * MAT(in,2,2);
410*61046927SAndroid Build Coastguard Worker    }
411*61046927SAndroid Build Coastguard Worker    else if (mat->flags & MAT_FLAG_ROTATION) {
412*61046927SAndroid Build Coastguard Worker       /* Transpose the 3 by 3 upper-left submatrix. */
413*61046927SAndroid Build Coastguard Worker       MAT(out,0,0) = MAT(in,0,0);
414*61046927SAndroid Build Coastguard Worker       MAT(out,1,0) = MAT(in,0,1);
415*61046927SAndroid Build Coastguard Worker       MAT(out,2,0) = MAT(in,0,2);
416*61046927SAndroid Build Coastguard Worker       MAT(out,0,1) = MAT(in,1,0);
417*61046927SAndroid Build Coastguard Worker       MAT(out,1,1) = MAT(in,1,1);
418*61046927SAndroid Build Coastguard Worker       MAT(out,2,1) = MAT(in,1,2);
419*61046927SAndroid Build Coastguard Worker       MAT(out,0,2) = MAT(in,2,0);
420*61046927SAndroid Build Coastguard Worker       MAT(out,1,2) = MAT(in,2,1);
421*61046927SAndroid Build Coastguard Worker       MAT(out,2,2) = MAT(in,2,2);
422*61046927SAndroid Build Coastguard Worker    }
423*61046927SAndroid Build Coastguard Worker    else {
424*61046927SAndroid Build Coastguard Worker       /* pure translation */
425*61046927SAndroid Build Coastguard Worker       matrix_set_identity(out);
426*61046927SAndroid Build Coastguard Worker       MAT(out,0,3) = - MAT(in,0,3);
427*61046927SAndroid Build Coastguard Worker       MAT(out,1,3) = - MAT(in,1,3);
428*61046927SAndroid Build Coastguard Worker       MAT(out,2,3) = - MAT(in,2,3);
429*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
430*61046927SAndroid Build Coastguard Worker    }
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker    if (mat->flags & MAT_FLAG_TRANSLATION) {
433*61046927SAndroid Build Coastguard Worker       /* Do the translation part */
434*61046927SAndroid Build Coastguard Worker       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
435*61046927SAndroid Build Coastguard Worker                         MAT(in,1,3) * MAT(out,0,1) +
436*61046927SAndroid Build Coastguard Worker                         MAT(in,2,3) * MAT(out,0,2) );
437*61046927SAndroid Build Coastguard Worker       MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +
438*61046927SAndroid Build Coastguard Worker                         MAT(in,1,3) * MAT(out,1,1) +
439*61046927SAndroid Build Coastguard Worker                         MAT(in,2,3) * MAT(out,1,2) );
440*61046927SAndroid Build Coastguard Worker       MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +
441*61046927SAndroid Build Coastguard Worker                         MAT(in,1,3) * MAT(out,2,1) +
442*61046927SAndroid Build Coastguard Worker                         MAT(in,2,3) * MAT(out,2,2) );
443*61046927SAndroid Build Coastguard Worker    }
444*61046927SAndroid Build Coastguard Worker    else {
445*61046927SAndroid Build Coastguard Worker       MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0;
446*61046927SAndroid Build Coastguard Worker    }
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
449*61046927SAndroid Build Coastguard Worker }
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker /**
452*61046927SAndroid Build Coastguard Worker  * Compute inverse of an identity transformation matrix.
453*61046927SAndroid Build Coastguard Worker  *
454*61046927SAndroid Build Coastguard Worker  * \param mat pointer to a GLmatrix structure. The matrix inverse will be
455*61046927SAndroid Build Coastguard Worker  * stored in the GLmatrix::inv attribute.
456*61046927SAndroid Build Coastguard Worker  *
457*61046927SAndroid Build Coastguard Worker  * \return always GL_TRUE.
458*61046927SAndroid Build Coastguard Worker  *
459*61046927SAndroid Build Coastguard Worker  * Simply copies Identity into GLmatrix::inv.
460*61046927SAndroid Build Coastguard Worker  */
invert_matrix_identity(GLmatrix * mat)461*61046927SAndroid Build Coastguard Worker static GLboolean invert_matrix_identity( GLmatrix *mat )
462*61046927SAndroid Build Coastguard Worker {
463*61046927SAndroid Build Coastguard Worker    matrix_set_identity(mat->inv);
464*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
465*61046927SAndroid Build Coastguard Worker }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker /**
468*61046927SAndroid Build Coastguard Worker  * Compute inverse of a no-rotation 3d transformation matrix.
469*61046927SAndroid Build Coastguard Worker  *
470*61046927SAndroid Build Coastguard Worker  * \param mat pointer to a GLmatrix structure. The matrix inverse will be
471*61046927SAndroid Build Coastguard Worker  * stored in the GLmatrix::inv attribute.
472*61046927SAndroid Build Coastguard Worker  *
473*61046927SAndroid Build Coastguard Worker  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
474*61046927SAndroid Build Coastguard Worker  *
475*61046927SAndroid Build Coastguard Worker  * Calculates the
476*61046927SAndroid Build Coastguard Worker  */
invert_matrix_3d_no_rot(GLmatrix * mat)477*61046927SAndroid Build Coastguard Worker static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat )
478*61046927SAndroid Build Coastguard Worker {
479*61046927SAndroid Build Coastguard Worker    const GLfloat *in = mat->m;
480*61046927SAndroid Build Coastguard Worker    GLfloat *out = mat->inv;
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker    if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0 || MAT(in,2,2) == 0 )
483*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker    matrix_set_identity(out);
486*61046927SAndroid Build Coastguard Worker    MAT(out,0,0) = 1.0F / MAT(in,0,0);
487*61046927SAndroid Build Coastguard Worker    MAT(out,1,1) = 1.0F / MAT(in,1,1);
488*61046927SAndroid Build Coastguard Worker    MAT(out,2,2) = 1.0F / MAT(in,2,2);
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker    if (mat->flags & MAT_FLAG_TRANSLATION) {
491*61046927SAndroid Build Coastguard Worker       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
492*61046927SAndroid Build Coastguard Worker       MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
493*61046927SAndroid Build Coastguard Worker       MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2));
494*61046927SAndroid Build Coastguard Worker    }
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
497*61046927SAndroid Build Coastguard Worker }
498*61046927SAndroid Build Coastguard Worker 
499*61046927SAndroid Build Coastguard Worker /**
500*61046927SAndroid Build Coastguard Worker  * Compute inverse of a no-rotation 2d transformation matrix.
501*61046927SAndroid Build Coastguard Worker  *
502*61046927SAndroid Build Coastguard Worker  * \param mat pointer to a GLmatrix structure. The matrix inverse will be
503*61046927SAndroid Build Coastguard Worker  * stored in the GLmatrix::inv attribute.
504*61046927SAndroid Build Coastguard Worker  *
505*61046927SAndroid Build Coastguard Worker  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
506*61046927SAndroid Build Coastguard Worker  *
507*61046927SAndroid Build Coastguard Worker  * Calculates the inverse matrix by applying the inverse scaling and
508*61046927SAndroid Build Coastguard Worker  * translation to the identity matrix.
509*61046927SAndroid Build Coastguard Worker  */
invert_matrix_2d_no_rot(GLmatrix * mat)510*61046927SAndroid Build Coastguard Worker static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat )
511*61046927SAndroid Build Coastguard Worker {
512*61046927SAndroid Build Coastguard Worker    const GLfloat *in = mat->m;
513*61046927SAndroid Build Coastguard Worker    GLfloat *out = mat->inv;
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0)
516*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
517*61046927SAndroid Build Coastguard Worker 
518*61046927SAndroid Build Coastguard Worker    matrix_set_identity(out);
519*61046927SAndroid Build Coastguard Worker    MAT(out,0,0) = 1.0F / MAT(in,0,0);
520*61046927SAndroid Build Coastguard Worker    MAT(out,1,1) = 1.0F / MAT(in,1,1);
521*61046927SAndroid Build Coastguard Worker 
522*61046927SAndroid Build Coastguard Worker    if (mat->flags & MAT_FLAG_TRANSLATION) {
523*61046927SAndroid Build Coastguard Worker       MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
524*61046927SAndroid Build Coastguard Worker       MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
525*61046927SAndroid Build Coastguard Worker    }
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
528*61046927SAndroid Build Coastguard Worker }
529*61046927SAndroid Build Coastguard Worker 
530*61046927SAndroid Build Coastguard Worker /**
531*61046927SAndroid Build Coastguard Worker  * Matrix inversion function pointer type.
532*61046927SAndroid Build Coastguard Worker  */
533*61046927SAndroid Build Coastguard Worker typedef GLboolean (*inv_mat_func)( GLmatrix *mat );
534*61046927SAndroid Build Coastguard Worker 
535*61046927SAndroid Build Coastguard Worker /**
536*61046927SAndroid Build Coastguard Worker  * Table of the matrix inversion functions according to the matrix type.
537*61046927SAndroid Build Coastguard Worker  */
538*61046927SAndroid Build Coastguard Worker static inv_mat_func inv_mat_tab[7] = {
539*61046927SAndroid Build Coastguard Worker    invert_matrix_general,
540*61046927SAndroid Build Coastguard Worker    invert_matrix_identity,
541*61046927SAndroid Build Coastguard Worker    invert_matrix_3d_no_rot,
542*61046927SAndroid Build Coastguard Worker    invert_matrix_general,
543*61046927SAndroid Build Coastguard Worker    invert_matrix_3d,        /* lazy! */
544*61046927SAndroid Build Coastguard Worker    invert_matrix_2d_no_rot,
545*61046927SAndroid Build Coastguard Worker    invert_matrix_3d
546*61046927SAndroid Build Coastguard Worker };
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker /**
549*61046927SAndroid Build Coastguard Worker  * Compute inverse of a transformation matrix.
550*61046927SAndroid Build Coastguard Worker  *
551*61046927SAndroid Build Coastguard Worker  * \param mat pointer to a GLmatrix structure. The matrix inverse will be
552*61046927SAndroid Build Coastguard Worker  * stored in the GLmatrix::inv attribute.
553*61046927SAndroid Build Coastguard Worker  *
554*61046927SAndroid Build Coastguard Worker  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
555*61046927SAndroid Build Coastguard Worker  *
556*61046927SAndroid Build Coastguard Worker  * Calls the matrix inversion function in inv_mat_tab corresponding to the
557*61046927SAndroid Build Coastguard Worker  * given matrix type.  In case of failure, updates the MAT_FLAG_SINGULAR flag,
558*61046927SAndroid Build Coastguard Worker  * and copies the identity matrix into GLmatrix::inv.
559*61046927SAndroid Build Coastguard Worker  */
matrix_invert(GLmatrix * mat)560*61046927SAndroid Build Coastguard Worker static GLboolean matrix_invert( GLmatrix *mat )
561*61046927SAndroid Build Coastguard Worker {
562*61046927SAndroid Build Coastguard Worker    if (inv_mat_tab[mat->type](mat)) {
563*61046927SAndroid Build Coastguard Worker       mat->flags &= ~MAT_FLAG_SINGULAR;
564*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
565*61046927SAndroid Build Coastguard Worker    } else {
566*61046927SAndroid Build Coastguard Worker       mat->flags |= MAT_FLAG_SINGULAR;
567*61046927SAndroid Build Coastguard Worker       matrix_set_identity(mat->inv);
568*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
569*61046927SAndroid Build Coastguard Worker    }
570*61046927SAndroid Build Coastguard Worker }
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker /*@}*/
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker /**********************************************************************/
576*61046927SAndroid Build Coastguard Worker /** \name Matrix generation */
577*61046927SAndroid Build Coastguard Worker /*@{*/
578*61046927SAndroid Build Coastguard Worker 
579*61046927SAndroid Build Coastguard Worker /**
580*61046927SAndroid Build Coastguard Worker  * Generate a 4x4 transformation matrix from glRotate parameters, and
581*61046927SAndroid Build Coastguard Worker  * post-multiply the input matrix by it.
582*61046927SAndroid Build Coastguard Worker  *
583*61046927SAndroid Build Coastguard Worker  * \author
584*61046927SAndroid Build Coastguard Worker  * This function was contributed by Erich Boleyn ([email protected]).
585*61046927SAndroid Build Coastguard Worker  * Optimizations contributed by Rudolf Opalla ([email protected]).
586*61046927SAndroid Build Coastguard Worker  */
587*61046927SAndroid Build Coastguard Worker void
_math_matrix_rotate(GLmatrix * mat,GLfloat angle,GLfloat x,GLfloat y,GLfloat z)588*61046927SAndroid Build Coastguard Worker _math_matrix_rotate( GLmatrix *mat,
589*61046927SAndroid Build Coastguard Worker                      GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
590*61046927SAndroid Build Coastguard Worker {
591*61046927SAndroid Build Coastguard Worker    GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
592*61046927SAndroid Build Coastguard Worker    GLfloat m[16];
593*61046927SAndroid Build Coastguard Worker    GLboolean optimized;
594*61046927SAndroid Build Coastguard Worker 
595*61046927SAndroid Build Coastguard Worker    s = sinf( angle * M_PI / 180.0 );
596*61046927SAndroid Build Coastguard Worker    c = cosf( angle * M_PI / 180.0 );
597*61046927SAndroid Build Coastguard Worker 
598*61046927SAndroid Build Coastguard Worker    matrix_set_identity(m);
599*61046927SAndroid Build Coastguard Worker    optimized = GL_FALSE;
600*61046927SAndroid Build Coastguard Worker 
601*61046927SAndroid Build Coastguard Worker #define M(row,col)  m[col*4+row]
602*61046927SAndroid Build Coastguard Worker 
603*61046927SAndroid Build Coastguard Worker    if (x == 0.0F) {
604*61046927SAndroid Build Coastguard Worker       if (y == 0.0F) {
605*61046927SAndroid Build Coastguard Worker          if (z != 0.0F) {
606*61046927SAndroid Build Coastguard Worker             optimized = GL_TRUE;
607*61046927SAndroid Build Coastguard Worker             /* rotate only around z-axis */
608*61046927SAndroid Build Coastguard Worker             M(0,0) = c;
609*61046927SAndroid Build Coastguard Worker             M(1,1) = c;
610*61046927SAndroid Build Coastguard Worker             if (z < 0.0F) {
611*61046927SAndroid Build Coastguard Worker                M(0,1) = s;
612*61046927SAndroid Build Coastguard Worker                M(1,0) = -s;
613*61046927SAndroid Build Coastguard Worker             }
614*61046927SAndroid Build Coastguard Worker             else {
615*61046927SAndroid Build Coastguard Worker                M(0,1) = -s;
616*61046927SAndroid Build Coastguard Worker                M(1,0) = s;
617*61046927SAndroid Build Coastguard Worker             }
618*61046927SAndroid Build Coastguard Worker          }
619*61046927SAndroid Build Coastguard Worker       }
620*61046927SAndroid Build Coastguard Worker       else if (z == 0.0F) {
621*61046927SAndroid Build Coastguard Worker          optimized = GL_TRUE;
622*61046927SAndroid Build Coastguard Worker          /* rotate only around y-axis */
623*61046927SAndroid Build Coastguard Worker          M(0,0) = c;
624*61046927SAndroid Build Coastguard Worker          M(2,2) = c;
625*61046927SAndroid Build Coastguard Worker          if (y < 0.0F) {
626*61046927SAndroid Build Coastguard Worker             M(0,2) = -s;
627*61046927SAndroid Build Coastguard Worker             M(2,0) = s;
628*61046927SAndroid Build Coastguard Worker          }
629*61046927SAndroid Build Coastguard Worker          else {
630*61046927SAndroid Build Coastguard Worker             M(0,2) = s;
631*61046927SAndroid Build Coastguard Worker             M(2,0) = -s;
632*61046927SAndroid Build Coastguard Worker          }
633*61046927SAndroid Build Coastguard Worker       }
634*61046927SAndroid Build Coastguard Worker    }
635*61046927SAndroid Build Coastguard Worker    else if (y == 0.0F) {
636*61046927SAndroid Build Coastguard Worker       if (z == 0.0F) {
637*61046927SAndroid Build Coastguard Worker          optimized = GL_TRUE;
638*61046927SAndroid Build Coastguard Worker          /* rotate only around x-axis */
639*61046927SAndroid Build Coastguard Worker          M(1,1) = c;
640*61046927SAndroid Build Coastguard Worker          M(2,2) = c;
641*61046927SAndroid Build Coastguard Worker          if (x < 0.0F) {
642*61046927SAndroid Build Coastguard Worker             M(1,2) = s;
643*61046927SAndroid Build Coastguard Worker             M(2,1) = -s;
644*61046927SAndroid Build Coastguard Worker          }
645*61046927SAndroid Build Coastguard Worker          else {
646*61046927SAndroid Build Coastguard Worker             M(1,2) = -s;
647*61046927SAndroid Build Coastguard Worker             M(2,1) = s;
648*61046927SAndroid Build Coastguard Worker          }
649*61046927SAndroid Build Coastguard Worker       }
650*61046927SAndroid Build Coastguard Worker    }
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker    if (!optimized) {
653*61046927SAndroid Build Coastguard Worker       const GLfloat mag = sqrtf(x * x + y * y + z * z);
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker       if (mag <= 1.0e-4F) {
656*61046927SAndroid Build Coastguard Worker          /* no rotation, leave mat as-is */
657*61046927SAndroid Build Coastguard Worker          return;
658*61046927SAndroid Build Coastguard Worker       }
659*61046927SAndroid Build Coastguard Worker 
660*61046927SAndroid Build Coastguard Worker       x /= mag;
661*61046927SAndroid Build Coastguard Worker       y /= mag;
662*61046927SAndroid Build Coastguard Worker       z /= mag;
663*61046927SAndroid Build Coastguard Worker 
664*61046927SAndroid Build Coastguard Worker 
665*61046927SAndroid Build Coastguard Worker       /*
666*61046927SAndroid Build Coastguard Worker        *     Arbitrary axis rotation matrix.
667*61046927SAndroid Build Coastguard Worker        *
668*61046927SAndroid Build Coastguard Worker        *  This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
669*61046927SAndroid Build Coastguard Worker        *  like so:  Rz * Ry * T * Ry' * Rz'.  T is the final rotation
670*61046927SAndroid Build Coastguard Worker        *  (which is about the X-axis), and the two composite transforms
671*61046927SAndroid Build Coastguard Worker        *  Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
672*61046927SAndroid Build Coastguard Worker        *  from the arbitrary axis to the X-axis then back.  They are
673*61046927SAndroid Build Coastguard Worker        *  all elementary rotations.
674*61046927SAndroid Build Coastguard Worker        *
675*61046927SAndroid Build Coastguard Worker        *  Rz' is a rotation about the Z-axis, to bring the axis vector
676*61046927SAndroid Build Coastguard Worker        *  into the x-z plane.  Then Ry' is applied, rotating about the
677*61046927SAndroid Build Coastguard Worker        *  Y-axis to bring the axis vector parallel with the X-axis.  The
678*61046927SAndroid Build Coastguard Worker        *  rotation about the X-axis is then performed.  Ry and Rz are
679*61046927SAndroid Build Coastguard Worker        *  simply the respective inverse transforms to bring the arbitrary
680*61046927SAndroid Build Coastguard Worker        *  axis back to its original orientation.  The first transforms
681*61046927SAndroid Build Coastguard Worker        *  Rz' and Ry' are considered inverses, since the data from the
682*61046927SAndroid Build Coastguard Worker        *  arbitrary axis gives you info on how to get to it, not how
683*61046927SAndroid Build Coastguard Worker        *  to get away from it, and an inverse must be applied.
684*61046927SAndroid Build Coastguard Worker        *
685*61046927SAndroid Build Coastguard Worker        *  The basic calculation used is to recognize that the arbitrary
686*61046927SAndroid Build Coastguard Worker        *  axis vector (x, y, z), since it is of unit length, actually
687*61046927SAndroid Build Coastguard Worker        *  represents the sines and cosines of the angles to rotate the
688*61046927SAndroid Build Coastguard Worker        *  X-axis to the same orientation, with theta being the angle about
689*61046927SAndroid Build Coastguard Worker        *  Z and phi the angle about Y (in the order described above)
690*61046927SAndroid Build Coastguard Worker        *  as follows:
691*61046927SAndroid Build Coastguard Worker        *
692*61046927SAndroid Build Coastguard Worker        *  cos ( theta ) = x / sqrt ( 1 - z^2 )
693*61046927SAndroid Build Coastguard Worker        *  sin ( theta ) = y / sqrt ( 1 - z^2 )
694*61046927SAndroid Build Coastguard Worker        *
695*61046927SAndroid Build Coastguard Worker        *  cos ( phi ) = sqrt ( 1 - z^2 )
696*61046927SAndroid Build Coastguard Worker        *  sin ( phi ) = z
697*61046927SAndroid Build Coastguard Worker        *
698*61046927SAndroid Build Coastguard Worker        *  Note that cos ( phi ) can further be inserted to the above
699*61046927SAndroid Build Coastguard Worker        *  formulas:
700*61046927SAndroid Build Coastguard Worker        *
701*61046927SAndroid Build Coastguard Worker        *  cos ( theta ) = x / cos ( phi )
702*61046927SAndroid Build Coastguard Worker        *  sin ( theta ) = y / sin ( phi )
703*61046927SAndroid Build Coastguard Worker        *
704*61046927SAndroid Build Coastguard Worker        *  ...etc.  Because of those relations and the standard trigonometric
705*61046927SAndroid Build Coastguard Worker        *  relations, it is pssible to reduce the transforms down to what
706*61046927SAndroid Build Coastguard Worker        *  is used below.  It may be that any primary axis chosen will give the
707*61046927SAndroid Build Coastguard Worker        *  same results (modulo a sign convention) using thie method.
708*61046927SAndroid Build Coastguard Worker        *
709*61046927SAndroid Build Coastguard Worker        *  Particularly nice is to notice that all divisions that might
710*61046927SAndroid Build Coastguard Worker        *  have caused trouble when parallel to certain planes or
711*61046927SAndroid Build Coastguard Worker        *  axis go away with care paid to reducing the expressions.
712*61046927SAndroid Build Coastguard Worker        *  After checking, it does perform correctly under all cases, since
713*61046927SAndroid Build Coastguard Worker        *  in all the cases of division where the denominator would have
714*61046927SAndroid Build Coastguard Worker        *  been zero, the numerator would have been zero as well, giving
715*61046927SAndroid Build Coastguard Worker        *  the expected result.
716*61046927SAndroid Build Coastguard Worker        */
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker       xx = x * x;
719*61046927SAndroid Build Coastguard Worker       yy = y * y;
720*61046927SAndroid Build Coastguard Worker       zz = z * z;
721*61046927SAndroid Build Coastguard Worker       xy = x * y;
722*61046927SAndroid Build Coastguard Worker       yz = y * z;
723*61046927SAndroid Build Coastguard Worker       zx = z * x;
724*61046927SAndroid Build Coastguard Worker       xs = x * s;
725*61046927SAndroid Build Coastguard Worker       ys = y * s;
726*61046927SAndroid Build Coastguard Worker       zs = z * s;
727*61046927SAndroid Build Coastguard Worker       one_c = 1.0F - c;
728*61046927SAndroid Build Coastguard Worker 
729*61046927SAndroid Build Coastguard Worker       /* We already hold the identity-matrix so we can skip some statements */
730*61046927SAndroid Build Coastguard Worker       M(0,0) = (one_c * xx) + c;
731*61046927SAndroid Build Coastguard Worker       M(0,1) = (one_c * xy) - zs;
732*61046927SAndroid Build Coastguard Worker       M(0,2) = (one_c * zx) + ys;
733*61046927SAndroid Build Coastguard Worker /*    M(0,3) = 0.0F; */
734*61046927SAndroid Build Coastguard Worker 
735*61046927SAndroid Build Coastguard Worker       M(1,0) = (one_c * xy) + zs;
736*61046927SAndroid Build Coastguard Worker       M(1,1) = (one_c * yy) + c;
737*61046927SAndroid Build Coastguard Worker       M(1,2) = (one_c * yz) - xs;
738*61046927SAndroid Build Coastguard Worker /*    M(1,3) = 0.0F; */
739*61046927SAndroid Build Coastguard Worker 
740*61046927SAndroid Build Coastguard Worker       M(2,0) = (one_c * zx) - ys;
741*61046927SAndroid Build Coastguard Worker       M(2,1) = (one_c * yz) + xs;
742*61046927SAndroid Build Coastguard Worker       M(2,2) = (one_c * zz) + c;
743*61046927SAndroid Build Coastguard Worker /*    M(2,3) = 0.0F; */
744*61046927SAndroid Build Coastguard Worker 
745*61046927SAndroid Build Coastguard Worker /*
746*61046927SAndroid Build Coastguard Worker       M(3,0) = 0.0F;
747*61046927SAndroid Build Coastguard Worker       M(3,1) = 0.0F;
748*61046927SAndroid Build Coastguard Worker       M(3,2) = 0.0F;
749*61046927SAndroid Build Coastguard Worker       M(3,3) = 1.0F;
750*61046927SAndroid Build Coastguard Worker */
751*61046927SAndroid Build Coastguard Worker    }
752*61046927SAndroid Build Coastguard Worker #undef M
753*61046927SAndroid Build Coastguard Worker 
754*61046927SAndroid Build Coastguard Worker    matrix_multf( mat, m, MAT_FLAG_ROTATION );
755*61046927SAndroid Build Coastguard Worker }
756*61046927SAndroid Build Coastguard Worker 
757*61046927SAndroid Build Coastguard Worker /**
758*61046927SAndroid Build Coastguard Worker  * Apply a perspective projection matrix.
759*61046927SAndroid Build Coastguard Worker  *
760*61046927SAndroid Build Coastguard Worker  * \param mat matrix to apply the projection.
761*61046927SAndroid Build Coastguard Worker  * \param left left clipping plane coordinate.
762*61046927SAndroid Build Coastguard Worker  * \param right right clipping plane coordinate.
763*61046927SAndroid Build Coastguard Worker  * \param bottom bottom clipping plane coordinate.
764*61046927SAndroid Build Coastguard Worker  * \param top top clipping plane coordinate.
765*61046927SAndroid Build Coastguard Worker  * \param nearval distance to the near clipping plane.
766*61046927SAndroid Build Coastguard Worker  * \param farval distance to the far clipping plane.
767*61046927SAndroid Build Coastguard Worker  *
768*61046927SAndroid Build Coastguard Worker  * Creates the projection matrix and multiplies it with \p mat, marking the
769*61046927SAndroid Build Coastguard Worker  * MAT_FLAG_PERSPECTIVE flag.
770*61046927SAndroid Build Coastguard Worker  */
771*61046927SAndroid Build Coastguard Worker void
_math_matrix_frustum(GLmatrix * mat,GLfloat left,GLfloat right,GLfloat bottom,GLfloat top,GLfloat nearval,GLfloat farval)772*61046927SAndroid Build Coastguard Worker _math_matrix_frustum( GLmatrix *mat,
773*61046927SAndroid Build Coastguard Worker                       GLfloat left, GLfloat right,
774*61046927SAndroid Build Coastguard Worker                       GLfloat bottom, GLfloat top,
775*61046927SAndroid Build Coastguard Worker                       GLfloat nearval, GLfloat farval )
776*61046927SAndroid Build Coastguard Worker {
777*61046927SAndroid Build Coastguard Worker    GLfloat x, y, a, b, c, d;
778*61046927SAndroid Build Coastguard Worker    GLfloat m[16];
779*61046927SAndroid Build Coastguard Worker 
780*61046927SAndroid Build Coastguard Worker    x = (2.0F*nearval) / (right-left);
781*61046927SAndroid Build Coastguard Worker    y = (2.0F*nearval) / (top-bottom);
782*61046927SAndroid Build Coastguard Worker    a = (right+left) / (right-left);
783*61046927SAndroid Build Coastguard Worker    b = (top+bottom) / (top-bottom);
784*61046927SAndroid Build Coastguard Worker    c = -(farval+nearval) / ( farval-nearval);
785*61046927SAndroid Build Coastguard Worker    d = -(2.0F*farval*nearval) / (farval-nearval);  /* error? */
786*61046927SAndroid Build Coastguard Worker 
787*61046927SAndroid Build Coastguard Worker #define M(row,col)  m[col*4+row]
788*61046927SAndroid Build Coastguard Worker    M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = a;      M(0,3) = 0.0F;
789*61046927SAndroid Build Coastguard Worker    M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = b;      M(1,3) = 0.0F;
790*61046927SAndroid Build Coastguard Worker    M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = c;      M(2,3) = d;
791*61046927SAndroid Build Coastguard Worker    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;
792*61046927SAndroid Build Coastguard Worker #undef M
793*61046927SAndroid Build Coastguard Worker 
794*61046927SAndroid Build Coastguard Worker    matrix_multf( mat, m, MAT_FLAG_PERSPECTIVE );
795*61046927SAndroid Build Coastguard Worker }
796*61046927SAndroid Build Coastguard Worker 
797*61046927SAndroid Build Coastguard Worker /**
798*61046927SAndroid Build Coastguard Worker  * Create an orthographic projection matrix.
799*61046927SAndroid Build Coastguard Worker  *
800*61046927SAndroid Build Coastguard Worker  * \param m float array in which to store the project matrix
801*61046927SAndroid Build Coastguard Worker  * \param left left clipping plane coordinate.
802*61046927SAndroid Build Coastguard Worker  * \param right right clipping plane coordinate.
803*61046927SAndroid Build Coastguard Worker  * \param bottom bottom clipping plane coordinate.
804*61046927SAndroid Build Coastguard Worker  * \param top top clipping plane coordinate.
805*61046927SAndroid Build Coastguard Worker  * \param nearval distance to the near clipping plane.
806*61046927SAndroid Build Coastguard Worker  * \param farval distance to the far clipping plane.
807*61046927SAndroid Build Coastguard Worker  *
808*61046927SAndroid Build Coastguard Worker  * Creates the projection matrix and stored the values in \p m.  As with other
809*61046927SAndroid Build Coastguard Worker  * OpenGL matrices, the data is stored in column-major ordering.
810*61046927SAndroid Build Coastguard Worker  */
811*61046927SAndroid Build Coastguard Worker void
_math_float_ortho(float * m,float left,float right,float bottom,float top,float nearval,float farval)812*61046927SAndroid Build Coastguard Worker _math_float_ortho(float *m,
813*61046927SAndroid Build Coastguard Worker                   float left, float right,
814*61046927SAndroid Build Coastguard Worker                   float bottom, float top,
815*61046927SAndroid Build Coastguard Worker                   float nearval, float farval)
816*61046927SAndroid Build Coastguard Worker {
817*61046927SAndroid Build Coastguard Worker #define M(row,col)  m[col*4+row]
818*61046927SAndroid Build Coastguard Worker    M(0,0) = 2.0F / (right-left);
819*61046927SAndroid Build Coastguard Worker    M(0,1) = 0.0F;
820*61046927SAndroid Build Coastguard Worker    M(0,2) = 0.0F;
821*61046927SAndroid Build Coastguard Worker    M(0,3) = -(right+left) / (right-left);
822*61046927SAndroid Build Coastguard Worker 
823*61046927SAndroid Build Coastguard Worker    M(1,0) = 0.0F;
824*61046927SAndroid Build Coastguard Worker    M(1,1) = 2.0F / (top-bottom);
825*61046927SAndroid Build Coastguard Worker    M(1,2) = 0.0F;
826*61046927SAndroid Build Coastguard Worker    M(1,3) = -(top+bottom) / (top-bottom);
827*61046927SAndroid Build Coastguard Worker 
828*61046927SAndroid Build Coastguard Worker    M(2,0) = 0.0F;
829*61046927SAndroid Build Coastguard Worker    M(2,1) = 0.0F;
830*61046927SAndroid Build Coastguard Worker    M(2,2) = -2.0F / (farval-nearval);
831*61046927SAndroid Build Coastguard Worker    M(2,3) = -(farval+nearval) / (farval-nearval);
832*61046927SAndroid Build Coastguard Worker 
833*61046927SAndroid Build Coastguard Worker    M(3,0) = 0.0F;
834*61046927SAndroid Build Coastguard Worker    M(3,1) = 0.0F;
835*61046927SAndroid Build Coastguard Worker    M(3,2) = 0.0F;
836*61046927SAndroid Build Coastguard Worker    M(3,3) = 1.0F;
837*61046927SAndroid Build Coastguard Worker #undef M
838*61046927SAndroid Build Coastguard Worker }
839*61046927SAndroid Build Coastguard Worker 
840*61046927SAndroid Build Coastguard Worker /**
841*61046927SAndroid Build Coastguard Worker  * Apply an orthographic projection matrix.
842*61046927SAndroid Build Coastguard Worker  *
843*61046927SAndroid Build Coastguard Worker  * \param mat matrix to apply the projection.
844*61046927SAndroid Build Coastguard Worker  * \param left left clipping plane coordinate.
845*61046927SAndroid Build Coastguard Worker  * \param right right clipping plane coordinate.
846*61046927SAndroid Build Coastguard Worker  * \param bottom bottom clipping plane coordinate.
847*61046927SAndroid Build Coastguard Worker  * \param top top clipping plane coordinate.
848*61046927SAndroid Build Coastguard Worker  * \param nearval distance to the near clipping plane.
849*61046927SAndroid Build Coastguard Worker  * \param farval distance to the far clipping plane.
850*61046927SAndroid Build Coastguard Worker  *
851*61046927SAndroid Build Coastguard Worker  * Creates the projection matrix and multiplies it with \p mat, marking the
852*61046927SAndroid Build Coastguard Worker  * MAT_FLAG_GENERAL_SCALE and MAT_FLAG_TRANSLATION flags.
853*61046927SAndroid Build Coastguard Worker  */
854*61046927SAndroid Build Coastguard Worker void
_math_matrix_ortho(GLmatrix * mat,GLfloat left,GLfloat right,GLfloat bottom,GLfloat top,GLfloat nearval,GLfloat farval)855*61046927SAndroid Build Coastguard Worker _math_matrix_ortho( GLmatrix *mat,
856*61046927SAndroid Build Coastguard Worker                     GLfloat left, GLfloat right,
857*61046927SAndroid Build Coastguard Worker                     GLfloat bottom, GLfloat top,
858*61046927SAndroid Build Coastguard Worker                     GLfloat nearval, GLfloat farval )
859*61046927SAndroid Build Coastguard Worker {
860*61046927SAndroid Build Coastguard Worker    GLfloat m[16];
861*61046927SAndroid Build Coastguard Worker 
862*61046927SAndroid Build Coastguard Worker    _math_float_ortho(m, left, right, bottom, top, nearval, farval);
863*61046927SAndroid Build Coastguard Worker    matrix_multf( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));
864*61046927SAndroid Build Coastguard Worker }
865*61046927SAndroid Build Coastguard Worker 
866*61046927SAndroid Build Coastguard Worker /**
867*61046927SAndroid Build Coastguard Worker  * Multiply a matrix with a general scaling matrix.
868*61046927SAndroid Build Coastguard Worker  *
869*61046927SAndroid Build Coastguard Worker  * \param mat matrix.
870*61046927SAndroid Build Coastguard Worker  * \param x x axis scale factor.
871*61046927SAndroid Build Coastguard Worker  * \param y y axis scale factor.
872*61046927SAndroid Build Coastguard Worker  * \param z z axis scale factor.
873*61046927SAndroid Build Coastguard Worker  *
874*61046927SAndroid Build Coastguard Worker  * Multiplies in-place the elements of \p mat by the scale factors. Checks if
875*61046927SAndroid Build Coastguard Worker  * the scales factors are roughly the same, marking the MAT_FLAG_UNIFORM_SCALE
876*61046927SAndroid Build Coastguard Worker  * flag, or MAT_FLAG_GENERAL_SCALE. Marks the MAT_DIRTY_TYPE and
877*61046927SAndroid Build Coastguard Worker  * MAT_DIRTY_INVERSE dirty flags.
878*61046927SAndroid Build Coastguard Worker  */
879*61046927SAndroid Build Coastguard Worker void
_math_matrix_scale(GLmatrix * mat,GLfloat x,GLfloat y,GLfloat z)880*61046927SAndroid Build Coastguard Worker _math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z )
881*61046927SAndroid Build Coastguard Worker {
882*61046927SAndroid Build Coastguard Worker    GLfloat *m = mat->m;
883*61046927SAndroid Build Coastguard Worker    m[0] *= x;   m[4] *= y;   m[8]  *= z;
884*61046927SAndroid Build Coastguard Worker    m[1] *= x;   m[5] *= y;   m[9]  *= z;
885*61046927SAndroid Build Coastguard Worker    m[2] *= x;   m[6] *= y;   m[10] *= z;
886*61046927SAndroid Build Coastguard Worker    m[3] *= x;   m[7] *= y;   m[11] *= z;
887*61046927SAndroid Build Coastguard Worker 
888*61046927SAndroid Build Coastguard Worker    if (fabsf(x - y) < 1e-8F && fabsf(x - z) < 1e-8F)
889*61046927SAndroid Build Coastguard Worker       mat->flags |= MAT_FLAG_UNIFORM_SCALE;
890*61046927SAndroid Build Coastguard Worker    else
891*61046927SAndroid Build Coastguard Worker       mat->flags |= MAT_FLAG_GENERAL_SCALE;
892*61046927SAndroid Build Coastguard Worker 
893*61046927SAndroid Build Coastguard Worker    mat->flags |= (MAT_DIRTY_TYPE |
894*61046927SAndroid Build Coastguard Worker                   MAT_DIRTY_INVERSE);
895*61046927SAndroid Build Coastguard Worker }
896*61046927SAndroid Build Coastguard Worker 
897*61046927SAndroid Build Coastguard Worker /**
898*61046927SAndroid Build Coastguard Worker  * Multiply a matrix with a translation matrix.
899*61046927SAndroid Build Coastguard Worker  *
900*61046927SAndroid Build Coastguard Worker  * \param mat matrix.
901*61046927SAndroid Build Coastguard Worker  * \param x translation vector x coordinate.
902*61046927SAndroid Build Coastguard Worker  * \param y translation vector y coordinate.
903*61046927SAndroid Build Coastguard Worker  * \param z translation vector z coordinate.
904*61046927SAndroid Build Coastguard Worker  *
905*61046927SAndroid Build Coastguard Worker  * Adds the translation coordinates to the elements of \p mat in-place.  Marks
906*61046927SAndroid Build Coastguard Worker  * the MAT_FLAG_TRANSLATION flag, and the MAT_DIRTY_TYPE and MAT_DIRTY_INVERSE
907*61046927SAndroid Build Coastguard Worker  * dirty flags.
908*61046927SAndroid Build Coastguard Worker  */
909*61046927SAndroid Build Coastguard Worker void
_math_matrix_translate(GLmatrix * mat,GLfloat x,GLfloat y,GLfloat z)910*61046927SAndroid Build Coastguard Worker _math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z )
911*61046927SAndroid Build Coastguard Worker {
912*61046927SAndroid Build Coastguard Worker    GLfloat *m = mat->m;
913*61046927SAndroid Build Coastguard Worker    m[12] = m[0] * x + m[4] * y + m[8]  * z + m[12];
914*61046927SAndroid Build Coastguard Worker    m[13] = m[1] * x + m[5] * y + m[9]  * z + m[13];
915*61046927SAndroid Build Coastguard Worker    m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
916*61046927SAndroid Build Coastguard Worker    m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
917*61046927SAndroid Build Coastguard Worker 
918*61046927SAndroid Build Coastguard Worker    mat->flags |= (MAT_FLAG_TRANSLATION |
919*61046927SAndroid Build Coastguard Worker                   MAT_DIRTY_TYPE |
920*61046927SAndroid Build Coastguard Worker                   MAT_DIRTY_INVERSE);
921*61046927SAndroid Build Coastguard Worker }
922*61046927SAndroid Build Coastguard Worker 
923*61046927SAndroid Build Coastguard Worker 
924*61046927SAndroid Build Coastguard Worker /**
925*61046927SAndroid Build Coastguard Worker  * Set matrix to do viewport and depthrange mapping.
926*61046927SAndroid Build Coastguard Worker  * Transforms Normalized Device Coords to window/Z values.
927*61046927SAndroid Build Coastguard Worker  */
928*61046927SAndroid Build Coastguard Worker void
_math_matrix_viewport(GLmatrix * m,const float scale[3],const float translate[3],double depthMax)929*61046927SAndroid Build Coastguard Worker _math_matrix_viewport(GLmatrix *m, const float scale[3],
930*61046927SAndroid Build Coastguard Worker                       const float translate[3], double depthMax)
931*61046927SAndroid Build Coastguard Worker {
932*61046927SAndroid Build Coastguard Worker    m->m[0] = scale[0];
933*61046927SAndroid Build Coastguard Worker    m->m[5] = scale[1];
934*61046927SAndroid Build Coastguard Worker    m->m[10] = depthMax*scale[2];
935*61046927SAndroid Build Coastguard Worker    m->m[12] = translate[0];
936*61046927SAndroid Build Coastguard Worker    m->m[13] = translate[1];
937*61046927SAndroid Build Coastguard Worker    m->m[14] = depthMax*translate[2];
938*61046927SAndroid Build Coastguard Worker    m->flags = MAT_FLAG_GENERAL_SCALE | MAT_FLAG_TRANSLATION;
939*61046927SAndroid Build Coastguard Worker    m->type = MATRIX_3D_NO_ROT;
940*61046927SAndroid Build Coastguard Worker }
941*61046927SAndroid Build Coastguard Worker 
942*61046927SAndroid Build Coastguard Worker 
943*61046927SAndroid Build Coastguard Worker /**
944*61046927SAndroid Build Coastguard Worker  * Set a matrix to the identity matrix.
945*61046927SAndroid Build Coastguard Worker  *
946*61046927SAndroid Build Coastguard Worker  * \param mat matrix.
947*61046927SAndroid Build Coastguard Worker  *
948*61046927SAndroid Build Coastguard Worker  * Copies ::Identity into \p GLmatrix::m, and into GLmatrix::inv if not NULL.
949*61046927SAndroid Build Coastguard Worker  * Sets the matrix type to identity, and clear the dirty flags.
950*61046927SAndroid Build Coastguard Worker  */
951*61046927SAndroid Build Coastguard Worker void
_math_matrix_set_identity(GLmatrix * mat)952*61046927SAndroid Build Coastguard Worker _math_matrix_set_identity( GLmatrix *mat )
953*61046927SAndroid Build Coastguard Worker {
954*61046927SAndroid Build Coastguard Worker    matrix_set_identity(mat->m);
955*61046927SAndroid Build Coastguard Worker    matrix_set_identity(mat->inv);
956*61046927SAndroid Build Coastguard Worker 
957*61046927SAndroid Build Coastguard Worker    mat->type = MATRIX_IDENTITY;
958*61046927SAndroid Build Coastguard Worker    mat->flags &= ~(MAT_DIRTY_FLAGS|
959*61046927SAndroid Build Coastguard Worker                    MAT_DIRTY_TYPE|
960*61046927SAndroid Build Coastguard Worker                    MAT_DIRTY_INVERSE);
961*61046927SAndroid Build Coastguard Worker }
962*61046927SAndroid Build Coastguard Worker 
963*61046927SAndroid Build Coastguard Worker /*@}*/
964*61046927SAndroid Build Coastguard Worker 
965*61046927SAndroid Build Coastguard Worker 
966*61046927SAndroid Build Coastguard Worker /**********************************************************************/
967*61046927SAndroid Build Coastguard Worker /** \name Matrix analysis */
968*61046927SAndroid Build Coastguard Worker /*@{*/
969*61046927SAndroid Build Coastguard Worker 
970*61046927SAndroid Build Coastguard Worker #define ZERO(x) (1<<x)
971*61046927SAndroid Build Coastguard Worker #define ONE(x)  (1<<(x+16))
972*61046927SAndroid Build Coastguard Worker 
973*61046927SAndroid Build Coastguard Worker #define MASK_NO_TRX      (ZERO(12) | ZERO(13) | ZERO(14))
974*61046927SAndroid Build Coastguard Worker #define MASK_NO_2D_SCALE ( ONE(0)  | ONE(5))
975*61046927SAndroid Build Coastguard Worker 
976*61046927SAndroid Build Coastguard Worker #define MASK_IDENTITY    ( ONE(0)  | ZERO(4)  | ZERO(8)  | ZERO(12) |\
977*61046927SAndroid Build Coastguard Worker                           ZERO(1)  |  ONE(5)  | ZERO(9)  | ZERO(13) |\
978*61046927SAndroid Build Coastguard Worker                           ZERO(2)  | ZERO(6)  |  ONE(10) | ZERO(14) |\
979*61046927SAndroid Build Coastguard Worker                           ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
980*61046927SAndroid Build Coastguard Worker 
981*61046927SAndroid Build Coastguard Worker #define MASK_2D_NO_ROT   (           ZERO(4)  | ZERO(8)  |           \
982*61046927SAndroid Build Coastguard Worker                           ZERO(1)  |            ZERO(9)  |           \
983*61046927SAndroid Build Coastguard Worker                           ZERO(2)  | ZERO(6)  |  ONE(10) | ZERO(14) |\
984*61046927SAndroid Build Coastguard Worker                           ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
985*61046927SAndroid Build Coastguard Worker 
986*61046927SAndroid Build Coastguard Worker #define MASK_2D          (                      ZERO(8)  |           \
987*61046927SAndroid Build Coastguard Worker                                                 ZERO(9)  |           \
988*61046927SAndroid Build Coastguard Worker                           ZERO(2)  | ZERO(6)  |  ONE(10) | ZERO(14) |\
989*61046927SAndroid Build Coastguard Worker                           ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
990*61046927SAndroid Build Coastguard Worker 
991*61046927SAndroid Build Coastguard Worker 
992*61046927SAndroid Build Coastguard Worker #define MASK_3D_NO_ROT   (           ZERO(4)  | ZERO(8)  |           \
993*61046927SAndroid Build Coastguard Worker                           ZERO(1)  |            ZERO(9)  |           \
994*61046927SAndroid Build Coastguard Worker                           ZERO(2)  | ZERO(6)  |                      \
995*61046927SAndroid Build Coastguard Worker                           ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
996*61046927SAndroid Build Coastguard Worker 
997*61046927SAndroid Build Coastguard Worker #define MASK_3D          (                                           \
998*61046927SAndroid Build Coastguard Worker                                                                      \
999*61046927SAndroid Build Coastguard Worker                                                                      \
1000*61046927SAndroid Build Coastguard Worker                           ZERO(3)  | ZERO(7)  | ZERO(11) |  ONE(15) )
1001*61046927SAndroid Build Coastguard Worker 
1002*61046927SAndroid Build Coastguard Worker 
1003*61046927SAndroid Build Coastguard Worker #define MASK_PERSPECTIVE (           ZERO(4)  |            ZERO(12) |\
1004*61046927SAndroid Build Coastguard Worker                           ZERO(1)  |                       ZERO(13) |\
1005*61046927SAndroid Build Coastguard Worker                           ZERO(2)  | ZERO(6)  |                      \
1006*61046927SAndroid Build Coastguard Worker                           ZERO(3)  | ZERO(7)  |            ZERO(15) )
1007*61046927SAndroid Build Coastguard Worker 
1008*61046927SAndroid Build Coastguard Worker #define SQ(x) ((x)*(x))
1009*61046927SAndroid Build Coastguard Worker 
1010*61046927SAndroid Build Coastguard Worker /**
1011*61046927SAndroid Build Coastguard Worker  * Determine type and flags from scratch.
1012*61046927SAndroid Build Coastguard Worker  *
1013*61046927SAndroid Build Coastguard Worker  * \param mat matrix.
1014*61046927SAndroid Build Coastguard Worker  *
1015*61046927SAndroid Build Coastguard Worker  * This is expensive enough to only want to do it once.
1016*61046927SAndroid Build Coastguard Worker  */
analyse_from_scratch(GLmatrix * mat)1017*61046927SAndroid Build Coastguard Worker static void analyse_from_scratch( GLmatrix *mat )
1018*61046927SAndroid Build Coastguard Worker {
1019*61046927SAndroid Build Coastguard Worker    const GLfloat *m = mat->m;
1020*61046927SAndroid Build Coastguard Worker    GLuint mask = 0;
1021*61046927SAndroid Build Coastguard Worker    GLuint i;
1022*61046927SAndroid Build Coastguard Worker 
1023*61046927SAndroid Build Coastguard Worker    for (i = 0 ; i < 16 ; i++) {
1024*61046927SAndroid Build Coastguard Worker       if (m[i] == 0.0F) mask |= (1<<i);
1025*61046927SAndroid Build Coastguard Worker    }
1026*61046927SAndroid Build Coastguard Worker 
1027*61046927SAndroid Build Coastguard Worker    if (m[0] == 1.0F) mask |= (1<<16);
1028*61046927SAndroid Build Coastguard Worker    if (m[5] == 1.0F) mask |= (1<<21);
1029*61046927SAndroid Build Coastguard Worker    if (m[10] == 1.0F) mask |= (1<<26);
1030*61046927SAndroid Build Coastguard Worker    if (m[15] == 1.0F) mask |= (1<<31);
1031*61046927SAndroid Build Coastguard Worker 
1032*61046927SAndroid Build Coastguard Worker    mat->flags &= ~MAT_FLAGS_GEOMETRY;
1033*61046927SAndroid Build Coastguard Worker 
1034*61046927SAndroid Build Coastguard Worker    /* Check for translation - no-one really cares
1035*61046927SAndroid Build Coastguard Worker     */
1036*61046927SAndroid Build Coastguard Worker    if ((mask & MASK_NO_TRX) != MASK_NO_TRX)
1037*61046927SAndroid Build Coastguard Worker       mat->flags |= MAT_FLAG_TRANSLATION;
1038*61046927SAndroid Build Coastguard Worker 
1039*61046927SAndroid Build Coastguard Worker    /* Do the real work
1040*61046927SAndroid Build Coastguard Worker     */
1041*61046927SAndroid Build Coastguard Worker    if (mask == (GLuint) MASK_IDENTITY) {
1042*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_IDENTITY;
1043*61046927SAndroid Build Coastguard Worker    }
1044*61046927SAndroid Build Coastguard Worker    else if ((mask & MASK_2D_NO_ROT) == (GLuint) MASK_2D_NO_ROT) {
1045*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_2D_NO_ROT;
1046*61046927SAndroid Build Coastguard Worker 
1047*61046927SAndroid Build Coastguard Worker       if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE)
1048*61046927SAndroid Build Coastguard Worker          mat->flags |= MAT_FLAG_GENERAL_SCALE;
1049*61046927SAndroid Build Coastguard Worker    }
1050*61046927SAndroid Build Coastguard Worker    else if ((mask & MASK_2D) == (GLuint) MASK_2D) {
1051*61046927SAndroid Build Coastguard Worker       GLfloat mm = DOT2(m, m);
1052*61046927SAndroid Build Coastguard Worker       GLfloat m4m4 = DOT2(m+4,m+4);
1053*61046927SAndroid Build Coastguard Worker       GLfloat mm4 = DOT2(m,m+4);
1054*61046927SAndroid Build Coastguard Worker 
1055*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_2D;
1056*61046927SAndroid Build Coastguard Worker 
1057*61046927SAndroid Build Coastguard Worker       /* Check for scale */
1058*61046927SAndroid Build Coastguard Worker       if (SQ(mm-1) > SQ(1e-6F) ||
1059*61046927SAndroid Build Coastguard Worker           SQ(m4m4-1) > SQ(1e-6F))
1060*61046927SAndroid Build Coastguard Worker          mat->flags |= MAT_FLAG_GENERAL_SCALE;
1061*61046927SAndroid Build Coastguard Worker 
1062*61046927SAndroid Build Coastguard Worker       /* Check for rotation */
1063*61046927SAndroid Build Coastguard Worker       if (SQ(mm4) > SQ(1e-6F))
1064*61046927SAndroid Build Coastguard Worker          mat->flags |= MAT_FLAG_GENERAL_3D;
1065*61046927SAndroid Build Coastguard Worker       else
1066*61046927SAndroid Build Coastguard Worker          mat->flags |= MAT_FLAG_ROTATION;
1067*61046927SAndroid Build Coastguard Worker 
1068*61046927SAndroid Build Coastguard Worker    }
1069*61046927SAndroid Build Coastguard Worker    else if ((mask & MASK_3D_NO_ROT) == (GLuint) MASK_3D_NO_ROT) {
1070*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_3D_NO_ROT;
1071*61046927SAndroid Build Coastguard Worker 
1072*61046927SAndroid Build Coastguard Worker       /* Check for scale */
1073*61046927SAndroid Build Coastguard Worker       if (SQ(m[0]-m[5]) < SQ(1e-6F) &&
1074*61046927SAndroid Build Coastguard Worker           SQ(m[0]-m[10]) < SQ(1e-6F)) {
1075*61046927SAndroid Build Coastguard Worker          if (SQ(m[0]-1.0F) > SQ(1e-6F)) {
1076*61046927SAndroid Build Coastguard Worker             mat->flags |= MAT_FLAG_UNIFORM_SCALE;
1077*61046927SAndroid Build Coastguard Worker          }
1078*61046927SAndroid Build Coastguard Worker       }
1079*61046927SAndroid Build Coastguard Worker       else {
1080*61046927SAndroid Build Coastguard Worker          mat->flags |= MAT_FLAG_GENERAL_SCALE;
1081*61046927SAndroid Build Coastguard Worker       }
1082*61046927SAndroid Build Coastguard Worker    }
1083*61046927SAndroid Build Coastguard Worker    else if ((mask & MASK_3D) == (GLuint) MASK_3D) {
1084*61046927SAndroid Build Coastguard Worker       GLfloat c1 = DOT3(m,m);
1085*61046927SAndroid Build Coastguard Worker       GLfloat c2 = DOT3(m+4,m+4);
1086*61046927SAndroid Build Coastguard Worker       GLfloat c3 = DOT3(m+8,m+8);
1087*61046927SAndroid Build Coastguard Worker       GLfloat d1 = DOT3(m, m+4);
1088*61046927SAndroid Build Coastguard Worker       GLfloat cp[3];
1089*61046927SAndroid Build Coastguard Worker 
1090*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_3D;
1091*61046927SAndroid Build Coastguard Worker 
1092*61046927SAndroid Build Coastguard Worker       /* Check for scale */
1093*61046927SAndroid Build Coastguard Worker       if (SQ(c1-c2) < SQ(1e-6F) && SQ(c1-c3) < SQ(1e-6F)) {
1094*61046927SAndroid Build Coastguard Worker          if (SQ(c1-1.0F) > SQ(1e-6F))
1095*61046927SAndroid Build Coastguard Worker             mat->flags |= MAT_FLAG_UNIFORM_SCALE;
1096*61046927SAndroid Build Coastguard Worker          /* else no scale at all */
1097*61046927SAndroid Build Coastguard Worker       }
1098*61046927SAndroid Build Coastguard Worker       else {
1099*61046927SAndroid Build Coastguard Worker          mat->flags |= MAT_FLAG_GENERAL_SCALE;
1100*61046927SAndroid Build Coastguard Worker       }
1101*61046927SAndroid Build Coastguard Worker 
1102*61046927SAndroid Build Coastguard Worker       /* Check for rotation */
1103*61046927SAndroid Build Coastguard Worker       if (SQ(d1) < SQ(1e-6F)) {
1104*61046927SAndroid Build Coastguard Worker          CROSS3( cp, m, m+4 );
1105*61046927SAndroid Build Coastguard Worker          SUB_3V( cp, cp, (m+8) );
1106*61046927SAndroid Build Coastguard Worker          if (LEN_SQUARED_3FV(cp) < SQ(1e-6F))
1107*61046927SAndroid Build Coastguard Worker             mat->flags |= MAT_FLAG_ROTATION;
1108*61046927SAndroid Build Coastguard Worker          else
1109*61046927SAndroid Build Coastguard Worker             mat->flags |= MAT_FLAG_GENERAL_3D;
1110*61046927SAndroid Build Coastguard Worker       }
1111*61046927SAndroid Build Coastguard Worker       else {
1112*61046927SAndroid Build Coastguard Worker          mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */
1113*61046927SAndroid Build Coastguard Worker       }
1114*61046927SAndroid Build Coastguard Worker    }
1115*61046927SAndroid Build Coastguard Worker    else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) {
1116*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_PERSPECTIVE;
1117*61046927SAndroid Build Coastguard Worker       mat->flags |= MAT_FLAG_GENERAL;
1118*61046927SAndroid Build Coastguard Worker    }
1119*61046927SAndroid Build Coastguard Worker    else {
1120*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_GENERAL;
1121*61046927SAndroid Build Coastguard Worker       mat->flags |= MAT_FLAG_GENERAL;
1122*61046927SAndroid Build Coastguard Worker    }
1123*61046927SAndroid Build Coastguard Worker }
1124*61046927SAndroid Build Coastguard Worker 
1125*61046927SAndroid Build Coastguard Worker /**
1126*61046927SAndroid Build Coastguard Worker  * Analyze a matrix given that its flags are accurate.
1127*61046927SAndroid Build Coastguard Worker  *
1128*61046927SAndroid Build Coastguard Worker  * This is the more common operation, hopefully.
1129*61046927SAndroid Build Coastguard Worker  */
analyse_from_flags(GLmatrix * mat)1130*61046927SAndroid Build Coastguard Worker static void analyse_from_flags( GLmatrix *mat )
1131*61046927SAndroid Build Coastguard Worker {
1132*61046927SAndroid Build Coastguard Worker    const GLfloat *m = mat->m;
1133*61046927SAndroid Build Coastguard Worker 
1134*61046927SAndroid Build Coastguard Worker    if (TEST_MAT_FLAGS(mat, 0)) {
1135*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_IDENTITY;
1136*61046927SAndroid Build Coastguard Worker    }
1137*61046927SAndroid Build Coastguard Worker    else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION |
1138*61046927SAndroid Build Coastguard Worker                                  MAT_FLAG_UNIFORM_SCALE |
1139*61046927SAndroid Build Coastguard Worker                                  MAT_FLAG_GENERAL_SCALE))) {
1140*61046927SAndroid Build Coastguard Worker       if ( m[10]==1.0F && m[14]==0.0F ) {
1141*61046927SAndroid Build Coastguard Worker          mat->type = MATRIX_2D_NO_ROT;
1142*61046927SAndroid Build Coastguard Worker       }
1143*61046927SAndroid Build Coastguard Worker       else {
1144*61046927SAndroid Build Coastguard Worker          mat->type = MATRIX_3D_NO_ROT;
1145*61046927SAndroid Build Coastguard Worker       }
1146*61046927SAndroid Build Coastguard Worker    }
1147*61046927SAndroid Build Coastguard Worker    else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) {
1148*61046927SAndroid Build Coastguard Worker       if (                                 m[ 8]==0.0F
1149*61046927SAndroid Build Coastguard Worker             &&                             m[ 9]==0.0F
1150*61046927SAndroid Build Coastguard Worker             && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F) {
1151*61046927SAndroid Build Coastguard Worker          mat->type = MATRIX_2D;
1152*61046927SAndroid Build Coastguard Worker       }
1153*61046927SAndroid Build Coastguard Worker       else {
1154*61046927SAndroid Build Coastguard Worker          mat->type = MATRIX_3D;
1155*61046927SAndroid Build Coastguard Worker       }
1156*61046927SAndroid Build Coastguard Worker    }
1157*61046927SAndroid Build Coastguard Worker    else if (                 m[4]==0.0F                 && m[12]==0.0F
1158*61046927SAndroid Build Coastguard Worker             && m[1]==0.0F                               && m[13]==0.0F
1159*61046927SAndroid Build Coastguard Worker             && m[2]==0.0F && m[6]==0.0F
1160*61046927SAndroid Build Coastguard Worker             && m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) {
1161*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_PERSPECTIVE;
1162*61046927SAndroid Build Coastguard Worker    }
1163*61046927SAndroid Build Coastguard Worker    else {
1164*61046927SAndroid Build Coastguard Worker       mat->type = MATRIX_GENERAL;
1165*61046927SAndroid Build Coastguard Worker    }
1166*61046927SAndroid Build Coastguard Worker }
1167*61046927SAndroid Build Coastguard Worker 
1168*61046927SAndroid Build Coastguard Worker /**
1169*61046927SAndroid Build Coastguard Worker  * Analyze and update a matrix.
1170*61046927SAndroid Build Coastguard Worker  *
1171*61046927SAndroid Build Coastguard Worker  * \param mat matrix.
1172*61046927SAndroid Build Coastguard Worker  *
1173*61046927SAndroid Build Coastguard Worker  * If the matrix type is dirty then calls either analyse_from_scratch() or
1174*61046927SAndroid Build Coastguard Worker  * analyse_from_flags() to determine its type, according to whether the flags
1175*61046927SAndroid Build Coastguard Worker  * are dirty or not, respectively. If the matrix has an inverse and it's dirty
1176*61046927SAndroid Build Coastguard Worker  * then calls matrix_invert(). Finally clears the dirty flags.
1177*61046927SAndroid Build Coastguard Worker  */
1178*61046927SAndroid Build Coastguard Worker void
_math_matrix_analyse(GLmatrix * mat)1179*61046927SAndroid Build Coastguard Worker _math_matrix_analyse( GLmatrix *mat )
1180*61046927SAndroid Build Coastguard Worker {
1181*61046927SAndroid Build Coastguard Worker    if (mat->flags & MAT_DIRTY_TYPE) {
1182*61046927SAndroid Build Coastguard Worker       if (mat->flags & MAT_DIRTY_FLAGS)
1183*61046927SAndroid Build Coastguard Worker          analyse_from_scratch( mat );
1184*61046927SAndroid Build Coastguard Worker       else
1185*61046927SAndroid Build Coastguard Worker          analyse_from_flags( mat );
1186*61046927SAndroid Build Coastguard Worker    }
1187*61046927SAndroid Build Coastguard Worker 
1188*61046927SAndroid Build Coastguard Worker    if (mat->flags & MAT_DIRTY_INVERSE) {
1189*61046927SAndroid Build Coastguard Worker       matrix_invert( mat );
1190*61046927SAndroid Build Coastguard Worker       mat->flags &= ~MAT_DIRTY_INVERSE;
1191*61046927SAndroid Build Coastguard Worker    }
1192*61046927SAndroid Build Coastguard Worker 
1193*61046927SAndroid Build Coastguard Worker    mat->flags &= ~(MAT_DIRTY_FLAGS | MAT_DIRTY_TYPE);
1194*61046927SAndroid Build Coastguard Worker }
1195*61046927SAndroid Build Coastguard Worker 
1196*61046927SAndroid Build Coastguard Worker /*@}*/
1197*61046927SAndroid Build Coastguard Worker 
1198*61046927SAndroid Build Coastguard Worker 
1199*61046927SAndroid Build Coastguard Worker /**
1200*61046927SAndroid Build Coastguard Worker  * Test if the given matrix preserves vector lengths.
1201*61046927SAndroid Build Coastguard Worker  */
1202*61046927SAndroid Build Coastguard Worker GLboolean
_math_matrix_is_length_preserving(const GLmatrix * m)1203*61046927SAndroid Build Coastguard Worker _math_matrix_is_length_preserving( const GLmatrix *m )
1204*61046927SAndroid Build Coastguard Worker {
1205*61046927SAndroid Build Coastguard Worker    return TEST_MAT_FLAGS( m, MAT_FLAGS_LENGTH_PRESERVING);
1206*61046927SAndroid Build Coastguard Worker }
1207*61046927SAndroid Build Coastguard Worker 
1208*61046927SAndroid Build Coastguard Worker GLboolean
_math_matrix_is_dirty(const GLmatrix * m)1209*61046927SAndroid Build Coastguard Worker _math_matrix_is_dirty( const GLmatrix *m )
1210*61046927SAndroid Build Coastguard Worker {
1211*61046927SAndroid Build Coastguard Worker    return (m->flags & MAT_DIRTY) ? GL_TRUE : GL_FALSE;
1212*61046927SAndroid Build Coastguard Worker }
1213*61046927SAndroid Build Coastguard Worker 
1214*61046927SAndroid Build Coastguard Worker 
1215*61046927SAndroid Build Coastguard Worker /**********************************************************************/
1216*61046927SAndroid Build Coastguard Worker /** \name Matrix setup */
1217*61046927SAndroid Build Coastguard Worker /*@{*/
1218*61046927SAndroid Build Coastguard Worker 
1219*61046927SAndroid Build Coastguard Worker /**
1220*61046927SAndroid Build Coastguard Worker  * Copy a matrix.
1221*61046927SAndroid Build Coastguard Worker  *
1222*61046927SAndroid Build Coastguard Worker  * \param to destination matrix.
1223*61046927SAndroid Build Coastguard Worker  * \param from source matrix.
1224*61046927SAndroid Build Coastguard Worker  *
1225*61046927SAndroid Build Coastguard Worker  * Copies all fields in GLmatrix, creating an inverse array if necessary.
1226*61046927SAndroid Build Coastguard Worker  */
1227*61046927SAndroid Build Coastguard Worker void
_math_matrix_copy(GLmatrix * to,const GLmatrix * from)1228*61046927SAndroid Build Coastguard Worker _math_matrix_copy( GLmatrix *to, const GLmatrix *from )
1229*61046927SAndroid Build Coastguard Worker {
1230*61046927SAndroid Build Coastguard Worker    memcpy(to->m, from->m, 16 * sizeof(GLfloat));
1231*61046927SAndroid Build Coastguard Worker    memcpy(to->inv, from->inv, 16 * sizeof(GLfloat));
1232*61046927SAndroid Build Coastguard Worker    to->flags = from->flags;
1233*61046927SAndroid Build Coastguard Worker    to->type = from->type;
1234*61046927SAndroid Build Coastguard Worker }
1235*61046927SAndroid Build Coastguard Worker 
1236*61046927SAndroid Build Coastguard Worker /**
1237*61046927SAndroid Build Coastguard Worker  * Copy a matrix as part of glPushMatrix.
1238*61046927SAndroid Build Coastguard Worker  *
1239*61046927SAndroid Build Coastguard Worker  * The makes the source matrix canonical (inverse and flags are up-to-date),
1240*61046927SAndroid Build Coastguard Worker  * so that later glPopMatrix is evaluated as a no-op if there is no state
1241*61046927SAndroid Build Coastguard Worker  * change.
1242*61046927SAndroid Build Coastguard Worker  *
1243*61046927SAndroid Build Coastguard Worker  * It this wasn't done, a draw call would canonicalize the matrix, which
1244*61046927SAndroid Build Coastguard Worker  * would make it different from the pushed one and so glPopMatrix wouldn't be
1245*61046927SAndroid Build Coastguard Worker  * recognized as a no-op.
1246*61046927SAndroid Build Coastguard Worker  */
1247*61046927SAndroid Build Coastguard Worker void
_math_matrix_push_copy(GLmatrix * to,GLmatrix * from)1248*61046927SAndroid Build Coastguard Worker _math_matrix_push_copy(GLmatrix *to, GLmatrix *from)
1249*61046927SAndroid Build Coastguard Worker {
1250*61046927SAndroid Build Coastguard Worker    if (from->flags & MAT_DIRTY)
1251*61046927SAndroid Build Coastguard Worker       _math_matrix_analyse(from);
1252*61046927SAndroid Build Coastguard Worker 
1253*61046927SAndroid Build Coastguard Worker    _math_matrix_copy(to, from);
1254*61046927SAndroid Build Coastguard Worker }
1255*61046927SAndroid Build Coastguard Worker 
1256*61046927SAndroid Build Coastguard Worker /**
1257*61046927SAndroid Build Coastguard Worker  * Loads a matrix array into GLmatrix.
1258*61046927SAndroid Build Coastguard Worker  *
1259*61046927SAndroid Build Coastguard Worker  * \param m matrix array.
1260*61046927SAndroid Build Coastguard Worker  * \param mat matrix.
1261*61046927SAndroid Build Coastguard Worker  *
1262*61046927SAndroid Build Coastguard Worker  * Copies \p m into GLmatrix::m and marks the MAT_FLAG_GENERAL and MAT_DIRTY
1263*61046927SAndroid Build Coastguard Worker  * flags.
1264*61046927SAndroid Build Coastguard Worker  */
1265*61046927SAndroid Build Coastguard Worker void
_math_matrix_loadf(GLmatrix * mat,const GLfloat * m)1266*61046927SAndroid Build Coastguard Worker _math_matrix_loadf( GLmatrix *mat, const GLfloat *m )
1267*61046927SAndroid Build Coastguard Worker {
1268*61046927SAndroid Build Coastguard Worker    memcpy( mat->m, m, 16*sizeof(GLfloat) );
1269*61046927SAndroid Build Coastguard Worker    mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY);
1270*61046927SAndroid Build Coastguard Worker }
1271*61046927SAndroid Build Coastguard Worker 
1272*61046927SAndroid Build Coastguard Worker /**
1273*61046927SAndroid Build Coastguard Worker  * Matrix constructor.
1274*61046927SAndroid Build Coastguard Worker  *
1275*61046927SAndroid Build Coastguard Worker  * \param m matrix.
1276*61046927SAndroid Build Coastguard Worker  *
1277*61046927SAndroid Build Coastguard Worker  * Initialize the GLmatrix fields.
1278*61046927SAndroid Build Coastguard Worker  */
1279*61046927SAndroid Build Coastguard Worker void
_math_matrix_ctr(GLmatrix * m)1280*61046927SAndroid Build Coastguard Worker _math_matrix_ctr( GLmatrix *m )
1281*61046927SAndroid Build Coastguard Worker {
1282*61046927SAndroid Build Coastguard Worker    memset(m, 0, sizeof(*m));
1283*61046927SAndroid Build Coastguard Worker    matrix_set_identity(m->m);
1284*61046927SAndroid Build Coastguard Worker    matrix_set_identity(m->inv);
1285*61046927SAndroid Build Coastguard Worker    m->type = MATRIX_IDENTITY;
1286*61046927SAndroid Build Coastguard Worker    m->flags = 0;
1287*61046927SAndroid Build Coastguard Worker }
1288*61046927SAndroid Build Coastguard Worker 
1289*61046927SAndroid Build Coastguard Worker /*@}*/
1290*61046927SAndroid Build Coastguard Worker 
1291*61046927SAndroid Build Coastguard Worker 
1292*61046927SAndroid Build Coastguard Worker /**********************************************************************/
1293*61046927SAndroid Build Coastguard Worker /** \name Matrix transpose */
1294*61046927SAndroid Build Coastguard Worker /*@{*/
1295*61046927SAndroid Build Coastguard Worker 
1296*61046927SAndroid Build Coastguard Worker /**
1297*61046927SAndroid Build Coastguard Worker  * Transpose a GLfloat matrix.
1298*61046927SAndroid Build Coastguard Worker  *
1299*61046927SAndroid Build Coastguard Worker  * \param to destination array.
1300*61046927SAndroid Build Coastguard Worker  * \param from source array.
1301*61046927SAndroid Build Coastguard Worker  */
1302*61046927SAndroid Build Coastguard Worker void
_math_transposef(GLfloat to[16],const GLfloat from[16])1303*61046927SAndroid Build Coastguard Worker _math_transposef( GLfloat to[16], const GLfloat from[16] )
1304*61046927SAndroid Build Coastguard Worker {
1305*61046927SAndroid Build Coastguard Worker    to[0] = from[0];
1306*61046927SAndroid Build Coastguard Worker    to[1] = from[4];
1307*61046927SAndroid Build Coastguard Worker    to[2] = from[8];
1308*61046927SAndroid Build Coastguard Worker    to[3] = from[12];
1309*61046927SAndroid Build Coastguard Worker    to[4] = from[1];
1310*61046927SAndroid Build Coastguard Worker    to[5] = from[5];
1311*61046927SAndroid Build Coastguard Worker    to[6] = from[9];
1312*61046927SAndroid Build Coastguard Worker    to[7] = from[13];
1313*61046927SAndroid Build Coastguard Worker    to[8] = from[2];
1314*61046927SAndroid Build Coastguard Worker    to[9] = from[6];
1315*61046927SAndroid Build Coastguard Worker    to[10] = from[10];
1316*61046927SAndroid Build Coastguard Worker    to[11] = from[14];
1317*61046927SAndroid Build Coastguard Worker    to[12] = from[3];
1318*61046927SAndroid Build Coastguard Worker    to[13] = from[7];
1319*61046927SAndroid Build Coastguard Worker    to[14] = from[11];
1320*61046927SAndroid Build Coastguard Worker    to[15] = from[15];
1321*61046927SAndroid Build Coastguard Worker }
1322*61046927SAndroid Build Coastguard Worker 
1323*61046927SAndroid Build Coastguard Worker /**
1324*61046927SAndroid Build Coastguard Worker  * Transpose a GLdouble matrix.
1325*61046927SAndroid Build Coastguard Worker  *
1326*61046927SAndroid Build Coastguard Worker  * \param to destination array.
1327*61046927SAndroid Build Coastguard Worker  * \param from source array.
1328*61046927SAndroid Build Coastguard Worker  */
1329*61046927SAndroid Build Coastguard Worker void
_math_transposed(GLdouble to[16],const GLdouble from[16])1330*61046927SAndroid Build Coastguard Worker _math_transposed( GLdouble to[16], const GLdouble from[16] )
1331*61046927SAndroid Build Coastguard Worker {
1332*61046927SAndroid Build Coastguard Worker    to[0] = from[0];
1333*61046927SAndroid Build Coastguard Worker    to[1] = from[4];
1334*61046927SAndroid Build Coastguard Worker    to[2] = from[8];
1335*61046927SAndroid Build Coastguard Worker    to[3] = from[12];
1336*61046927SAndroid Build Coastguard Worker    to[4] = from[1];
1337*61046927SAndroid Build Coastguard Worker    to[5] = from[5];
1338*61046927SAndroid Build Coastguard Worker    to[6] = from[9];
1339*61046927SAndroid Build Coastguard Worker    to[7] = from[13];
1340*61046927SAndroid Build Coastguard Worker    to[8] = from[2];
1341*61046927SAndroid Build Coastguard Worker    to[9] = from[6];
1342*61046927SAndroid Build Coastguard Worker    to[10] = from[10];
1343*61046927SAndroid Build Coastguard Worker    to[11] = from[14];
1344*61046927SAndroid Build Coastguard Worker    to[12] = from[3];
1345*61046927SAndroid Build Coastguard Worker    to[13] = from[7];
1346*61046927SAndroid Build Coastguard Worker    to[14] = from[11];
1347*61046927SAndroid Build Coastguard Worker    to[15] = from[15];
1348*61046927SAndroid Build Coastguard Worker }
1349*61046927SAndroid Build Coastguard Worker 
1350*61046927SAndroid Build Coastguard Worker /**
1351*61046927SAndroid Build Coastguard Worker  * Transpose a GLdouble matrix and convert to GLfloat.
1352*61046927SAndroid Build Coastguard Worker  *
1353*61046927SAndroid Build Coastguard Worker  * \param to destination array.
1354*61046927SAndroid Build Coastguard Worker  * \param from source array.
1355*61046927SAndroid Build Coastguard Worker  */
1356*61046927SAndroid Build Coastguard Worker void
_math_transposefd(GLfloat to[16],const GLdouble from[16])1357*61046927SAndroid Build Coastguard Worker _math_transposefd( GLfloat to[16], const GLdouble from[16] )
1358*61046927SAndroid Build Coastguard Worker {
1359*61046927SAndroid Build Coastguard Worker    to[0] = (GLfloat) from[0];
1360*61046927SAndroid Build Coastguard Worker    to[1] = (GLfloat) from[4];
1361*61046927SAndroid Build Coastguard Worker    to[2] = (GLfloat) from[8];
1362*61046927SAndroid Build Coastguard Worker    to[3] = (GLfloat) from[12];
1363*61046927SAndroid Build Coastguard Worker    to[4] = (GLfloat) from[1];
1364*61046927SAndroid Build Coastguard Worker    to[5] = (GLfloat) from[5];
1365*61046927SAndroid Build Coastguard Worker    to[6] = (GLfloat) from[9];
1366*61046927SAndroid Build Coastguard Worker    to[7] = (GLfloat) from[13];
1367*61046927SAndroid Build Coastguard Worker    to[8] = (GLfloat) from[2];
1368*61046927SAndroid Build Coastguard Worker    to[9] = (GLfloat) from[6];
1369*61046927SAndroid Build Coastguard Worker    to[10] = (GLfloat) from[10];
1370*61046927SAndroid Build Coastguard Worker    to[11] = (GLfloat) from[14];
1371*61046927SAndroid Build Coastguard Worker    to[12] = (GLfloat) from[3];
1372*61046927SAndroid Build Coastguard Worker    to[13] = (GLfloat) from[7];
1373*61046927SAndroid Build Coastguard Worker    to[14] = (GLfloat) from[11];
1374*61046927SAndroid Build Coastguard Worker    to[15] = (GLfloat) from[15];
1375*61046927SAndroid Build Coastguard Worker }
1376*61046927SAndroid Build Coastguard Worker 
1377*61046927SAndroid Build Coastguard Worker /*@}*/
1378*61046927SAndroid Build Coastguard Worker 
1379*61046927SAndroid Build Coastguard Worker 
1380*61046927SAndroid Build Coastguard Worker /**
1381*61046927SAndroid Build Coastguard Worker  * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix.  This
1382*61046927SAndroid Build Coastguard Worker  * function is used for transforming clipping plane equations and spotlight
1383*61046927SAndroid Build Coastguard Worker  * directions.
1384*61046927SAndroid Build Coastguard Worker  * Mathematically,  u = v * m.
1385*61046927SAndroid Build Coastguard Worker  * Input:  v - input vector
1386*61046927SAndroid Build Coastguard Worker  *         m - transformation matrix
1387*61046927SAndroid Build Coastguard Worker  * Output:  u - transformed vector
1388*61046927SAndroid Build Coastguard Worker  */
1389*61046927SAndroid Build Coastguard Worker void
_mesa_transform_vector(GLfloat u[4],const GLfloat v[4],const GLfloat m[16])1390*61046927SAndroid Build Coastguard Worker _mesa_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
1391*61046927SAndroid Build Coastguard Worker {
1392*61046927SAndroid Build Coastguard Worker    const GLfloat v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
1393*61046927SAndroid Build Coastguard Worker #define M(row,col)  m[row + col*4]
1394*61046927SAndroid Build Coastguard Worker    u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
1395*61046927SAndroid Build Coastguard Worker    u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
1396*61046927SAndroid Build Coastguard Worker    u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
1397*61046927SAndroid Build Coastguard Worker    u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
1398*61046927SAndroid Build Coastguard Worker #undef M
1399*61046927SAndroid Build Coastguard Worker }
1400