⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m_matrix.c

📁 mesa-6.5-minigui源码
💻 C
📖 第 1 页 / 共 3 页
字号:
   return GL_TRUE;}/** * Compute inverse of a 3d transformation matrix. *  * \param mat pointer to a GLmatrix structure. The matrix inverse will be * stored in the GLmatrix::inv attribute. *  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). * * If the matrix is not an angle preserving matrix then calls * invert_matrix_3d_general for the actual calculation. Otherwise calculates * the inverse matrix analyzing and inverting each of the scaling, rotation and * translation parts. */static GLboolean invert_matrix_3d( GLmatrix *mat ){   const GLfloat *in = mat->m;   GLfloat *out = mat->inv;   if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING)) {      return invert_matrix_3d_general( mat );   }   if (mat->flags & MAT_FLAG_UNIFORM_SCALE) {      GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) +                       MAT(in,0,1) * MAT(in,0,1) +                       MAT(in,0,2) * MAT(in,0,2));      if (scale == 0.0)         return GL_FALSE;      scale = 1.0F / scale;      /* Transpose and scale the 3 by 3 upper-left submatrix. */      MAT(out,0,0) = scale * MAT(in,0,0);      MAT(out,1,0) = scale * MAT(in,0,1);      MAT(out,2,0) = scale * MAT(in,0,2);      MAT(out,0,1) = scale * MAT(in,1,0);      MAT(out,1,1) = scale * MAT(in,1,1);      MAT(out,2,1) = scale * MAT(in,1,2);      MAT(out,0,2) = scale * MAT(in,2,0);      MAT(out,1,2) = scale * MAT(in,2,1);      MAT(out,2,2) = scale * MAT(in,2,2);   }   else if (mat->flags & MAT_FLAG_ROTATION) {      /* Transpose the 3 by 3 upper-left submatrix. */      MAT(out,0,0) = MAT(in,0,0);      MAT(out,1,0) = MAT(in,0,1);      MAT(out,2,0) = MAT(in,0,2);      MAT(out,0,1) = MAT(in,1,0);      MAT(out,1,1) = MAT(in,1,1);      MAT(out,2,1) = MAT(in,1,2);      MAT(out,0,2) = MAT(in,2,0);      MAT(out,1,2) = MAT(in,2,1);      MAT(out,2,2) = MAT(in,2,2);   }   else {      /* pure translation */      MEMCPY( out, Identity, sizeof(Identity) );      MAT(out,0,3) = - MAT(in,0,3);      MAT(out,1,3) = - MAT(in,1,3);      MAT(out,2,3) = - MAT(in,2,3);      return GL_TRUE;   }   if (mat->flags & MAT_FLAG_TRANSLATION) {      /* Do the translation part */      MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +			MAT(in,1,3) * MAT(out,0,1) +			MAT(in,2,3) * MAT(out,0,2) );      MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +			MAT(in,1,3) * MAT(out,1,1) +			MAT(in,2,3) * MAT(out,1,2) );      MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +			MAT(in,1,3) * MAT(out,2,1) +			MAT(in,2,3) * MAT(out,2,2) );   }   else {      MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0;   }   return GL_TRUE;}/** * Compute inverse of an identity transformation matrix. *  * \param mat pointer to a GLmatrix structure. The matrix inverse will be * stored in the GLmatrix::inv attribute. *  * \return always GL_TRUE. * * Simply copies Identity into GLmatrix::inv. */static GLboolean invert_matrix_identity( GLmatrix *mat ){   MEMCPY( mat->inv, Identity, sizeof(Identity) );   return GL_TRUE;}/** * Compute inverse of a no-rotation 3d transformation matrix. *  * \param mat pointer to a GLmatrix structure. The matrix inverse will be * stored in the GLmatrix::inv attribute. *  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). * * Calculates the  */static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat ){   const GLfloat *in = mat->m;   GLfloat *out = mat->inv;   if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0 || MAT(in,2,2) == 0 )      return GL_FALSE;   MEMCPY( out, Identity, 16 * sizeof(GLfloat) );   MAT(out,0,0) = 1.0F / MAT(in,0,0);   MAT(out,1,1) = 1.0F / MAT(in,1,1);   MAT(out,2,2) = 1.0F / MAT(in,2,2);   if (mat->flags & MAT_FLAG_TRANSLATION) {      MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));      MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));      MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2));   }   return GL_TRUE;}/** * Compute inverse of a no-rotation 2d transformation matrix. *  * \param mat pointer to a GLmatrix structure. The matrix inverse will be * stored in the GLmatrix::inv attribute. *  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). * * Calculates the inverse matrix by applying the inverse scaling and * translation to the identity matrix. */static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat ){   const GLfloat *in = mat->m;   GLfloat *out = mat->inv;   if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0)      return GL_FALSE;   MEMCPY( out, Identity, 16 * sizeof(GLfloat) );   MAT(out,0,0) = 1.0F / MAT(in,0,0);   MAT(out,1,1) = 1.0F / MAT(in,1,1);   if (mat->flags & MAT_FLAG_TRANSLATION) {      MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));      MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));   }   return GL_TRUE;}#if 0/* broken */static GLboolean invert_matrix_perspective( GLmatrix *mat ){   const GLfloat *in = mat->m;   GLfloat *out = mat->inv;   if (MAT(in,2,3) == 0)      return GL_FALSE;   MEMCPY( out, Identity, 16 * sizeof(GLfloat) );   MAT(out,0,0) = 1.0F / MAT(in,0,0);   MAT(out,1,1) = 1.0F / MAT(in,1,1);   MAT(out,0,3) = MAT(in,0,2);   MAT(out,1,3) = MAT(in,1,2);   MAT(out,2,2) = 0;   MAT(out,2,3) = -1;   MAT(out,3,2) = 1.0F / MAT(in,2,3);   MAT(out,3,3) = MAT(in,2,2) * MAT(out,3,2);   return GL_TRUE;}#endif/** * Matrix inversion function pointer type. */typedef GLboolean (*inv_mat_func)( GLmatrix *mat );/** * Table of the matrix inversion functions according to the matrix type. */static inv_mat_func inv_mat_tab[7] = {   invert_matrix_general,   invert_matrix_identity,   invert_matrix_3d_no_rot,#if 0   /* Don't use this function for now - it fails when the projection matrix    * is premultiplied by a translation (ala Chromium's tilesort SPU).    */   invert_matrix_perspective,#else   invert_matrix_general,#endif   invert_matrix_3d,		/* lazy! */   invert_matrix_2d_no_rot,   invert_matrix_3d};/** * Compute inverse of a transformation matrix. *  * \param mat pointer to a GLmatrix structure. The matrix inverse will be * stored in the GLmatrix::inv attribute. *  * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). * * Calls the matrix inversion function in inv_mat_tab corresponding to the * given matrix type.  In case of failure, updates the MAT_FLAG_SINGULAR flag, * and copies the identity matrix into GLmatrix::inv. */static GLboolean matrix_invert( GLmatrix *mat ){   if (inv_mat_tab[mat->type](mat)) {      mat->flags &= ~MAT_FLAG_SINGULAR;      return GL_TRUE;   } else {      mat->flags |= MAT_FLAG_SINGULAR;      MEMCPY( mat->inv, Identity, sizeof(Identity) );      return GL_FALSE;   }}/*@}*//**********************************************************************//** \name Matrix generation *//*@{*//** * Generate a 4x4 transformation matrix from glRotate parameters, and * post-multiply the input matrix by it. * * \author * This function was contributed by Erich Boleyn (erich@uruk.org). * Optimizations contributed by Rudolf Opalla (rudi@khm.de). */void_math_matrix_rotate( GLmatrix *mat,		     GLfloat angle, GLfloat x, GLfloat y, GLfloat z ){   GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;   GLfloat m[16];   GLboolean optimized;   s = (GLfloat) _mesa_sin( angle * DEG2RAD );   c = (GLfloat) _mesa_cos( angle * DEG2RAD );   MEMCPY(m, Identity, sizeof(GLfloat)*16);   optimized = GL_FALSE;#define M(row,col)  m[col*4+row]   if (x == 0.0F) {      if (y == 0.0F) {         if (z != 0.0F) {            optimized = GL_TRUE;            /* rotate only around z-axis */            M(0,0) = c;            M(1,1) = c;            if (z < 0.0F) {               M(0,1) = s;               M(1,0) = -s;            }            else {               M(0,1) = -s;               M(1,0) = s;            }         }      }      else if (z == 0.0F) {         optimized = GL_TRUE;         /* rotate only around y-axis */         M(0,0) = c;         M(2,2) = c;         if (y < 0.0F) {            M(0,2) = -s;            M(2,0) = s;         }         else {            M(0,2) = s;            M(2,0) = -s;         }      }   }   else if (y == 0.0F) {      if (z == 0.0F) {         optimized = GL_TRUE;         /* rotate only around x-axis */         M(1,1) = c;         M(2,2) = c;         if (x < 0.0F) {            M(1,2) = s;            M(2,1) = -s;         }         else {            M(1,2) = -s;            M(2,1) = s;         }      }   }   if (!optimized) {      const GLfloat mag = SQRTF(x * x + y * y + z * z);      if (mag <= 1.0e-4) {         /* no rotation, leave mat as-is */         return;      }      x /= mag;      y /= mag;      z /= mag;      /*       *     Arbitrary axis rotation matrix.       *       *  This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied       *  like so:  Rz * Ry * T * Ry' * Rz'.  T is the final rotation       *  (which is about the X-axis), and the two composite transforms       *  Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary       *  from the arbitrary axis to the X-axis then back.  They are       *  all elementary rotations.       *       *  Rz' is a rotation about the Z-axis, to bring the axis vector       *  into the x-z plane.  Then Ry' is applied, rotating about the       *  Y-axis to bring the axis vector parallel with the X-axis.  The       *  rotation about the X-axis is then performed.  Ry and Rz are       *  simply the respective inverse transforms to bring the arbitrary       *  axis back to it's original orientation.  The first transforms       *  Rz' and Ry' are considered inverses, since the data from the       *  arbitrary axis gives you info on how to get to it, not how       *  to get away from it, and an inverse must be applied.       *       *  The basic calculation used is to recognize that the arbitrary       *  axis vector (x, y, z), since it is of unit length, actually       *  represents the sines and cosines of the angles to rotate the       *  X-axis to the same orientation, with theta being the angle about       *  Z and phi the angle about Y (in the order described above)       *  as follows:       *       *  cos ( theta ) = x / sqrt ( 1 - z^2 )       *  sin ( theta ) = y / sqrt ( 1 - z^2 )       *       *  cos ( phi ) = sqrt ( 1 - z^2 )       *  sin ( phi ) = z       *       *  Note that cos ( phi ) can further be inserted to the above       *  formulas:       *       *  cos ( theta ) = x / cos ( phi )       *  sin ( theta ) = y / sin ( phi )       *       *  ...etc.  Because of those relations and the standard trigonometric       *  relations, it is pssible to reduce the transforms down to what       *  is used below.  It may be that any primary axis chosen will give the       *  same results (modulo a sign convention) using thie method.       *       *  Particularly nice is to notice that all divisions that might       *  have caused trouble when parallel to certain planes or       *  axis go away with care paid to reducing the expressions.       *  After checking, it does perform correctly under all cases, since       *  in all the cases of division where the denominator would have       *  been zero, the numerator would have been zero as well, giving       *  the expected result.       */      xx = x * x;      yy = y * y;      zz = z * z;      xy = x * y;      yz = y * z;      zx = z * x;      xs = x * s;      ys = y * s;      zs = z * s;      one_c = 1.0F - c;      /* We already hold the identity-matrix so we can skip some statements */      M(0,0) = (one_c * xx) + c;      M(0,1) = (one_c * xy) - zs;      M(0,2) = (one_c * zx) + ys;/*    M(0,3) = 0.0F; */      M(1,0) = (one_c * xy) + zs;      M(1,1) = (one_c * yy) + c;      M(1,2) = (one_c * yz) - xs;/*    M(1,3) = 0.0F; */      M(2,0) = (one_c * zx) - ys;      M(2,1) = (one_c * yz) + xs;      M(2,2) = (one_c * zz) + c;/*    M(2,3) = 0.0F; *//*      M(3,0) = 0.0F;      M(3,1) = 0.0F;      M(3,2) = 0.0F;      M(3,3) = 1.0F;*/   }#undef M   matrix_multf( mat, m, MAT_FLAG_ROTATION );}/** * Apply a perspective projection matrix. * * \param mat matrix to apply the projection. * \param left left clipping plane coordinate. * \param right right clipping plane coordinate. * \param bottom bottom clipping plane coordinate. * \param top top clipping plane coordinate. * \param nearval distance to the near clipping plane. * \param farval distance to the far clipping plane. * * Creates the projection matrix and multiplies it with \p mat, marking the * MAT_FLAG_PERSPECTIVE flag. */void_math_matrix_frustum( GLmatrix *mat,		      GLfloat left, GLfloat right,		      GLfloat bottom, GLfloat top,		      GLfloat nearval, GLfloat farval ){   GLfloat x, y, a, b, c, d;   GLfloat m[16];   x = (2.0F*nearval) / (right-left);   y = (2.0F*nearval) / (top-bottom);   a = (right+left) / (right-left);   b = (top+bottom) / (top-bottom);   c = -(farval+nearval) / ( farval-nearval);   d = -(2.0F*farval*nearval) / (farval-nearval);  /* error? */#define M(row,col)  m[col*4+row]   M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = a;      M(0,3) = 0.0F;   M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = b;      M(1,3) = 0.0F;   M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = c;      M(2,3) = d;   M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;#undef M   matrix_multf( mat, m, MAT_FLAG_PERSPECTIVE );}/** * Apply an orthographic projection matrix. * * \param mat matrix to apply the projection. * \param left left clipping plane coordinate. * \param right right clipping plane coordinate. * \param bottom bottom clipping plane coordinate. * \param top top clipping plane coordinate. * \param nearval distance to the near clipping plane. * \param farval distance to the far clipping plane. * * Creates the projection matrix and multiplies it with \p mat, marking the * MAT_FLAG_GENERAL_SCALE and MAT_FLAG_TRANSLATION flags. */void_math_matrix_ortho( GLmatrix *mat,		    GLfloat left, GLfloat right,		    GLfloat bottom, GLfloat top,		    GLfloat nearval, GLfloat farval ){   GLfloat m[16];#define M(row,col)  m[col*4+row]   M(0,0) = 2.0F / (right-left);   M(0,1) = 0.0F;   M(0,2) = 0.0F;   M(0,3) = -(right+left) / (right-left);   M(1,0) = 0.0F;   M(1,1) = 2.0F / (top-bottom);   M(1,2) = 0.0F;   M(1,3) = -(top+bottom) / (top-bottom);   M(2,0) = 0.0F;   M(2,1) = 0.0F;   M(2,2) = -2.0F / (farval-nearval);   M(2,3) = -(farval+nearval) / (farval-nearval);   M(3,0) = 0.0F;   M(3,1) = 0.0F;   M(3,2) = 0.0F;   M(3,3) = 1.0F;#undef M   matrix_multf( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));}/** * Multiply a matrix with a general scaling matrix. * * \param mat matrix. * \param x x axis scale factor. * \param y y axis scale factor. * \param z z axis scale factor. * * Multiplies in-place the elements of \p mat by the scale factors. Checks if * the scales factors are roughly the same, marking the MAT_FLAG_UNIFORM_SCALE * flag, or MAT_FLAG_GENERAL_SCALE. Marks the MAT_DIRTY_TYPE and * MAT_DIRTY_INVERSE dirty flags. */void_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ){   GLfloat *m = mat->m;   m[0] *= x;   m[4] *= y;   m[8]  *= z;   m[1] *= x;   m[5] *= y;   m[9]  *= z;   m[2] *= x;   m[6] *= y;   m[10] *= z;   m[3] *= x;   m[7] *= y;   m[11] *= z;   if (FABSF(x - y) < 1e-8 && FABSF(x - z) < 1e-8)      mat->flags |= MAT_FLAG_UNIFORM_SCALE;   else      mat->flags |= MAT_FLAG_GENERAL_SCALE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -