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

📄 m_matrix.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
   if (m[0] == 1.0F) mask |= (1<<16);
   if (m[5] == 1.0F) mask |= (1<<21);
   if (m[10] == 1.0F) mask |= (1<<26);
   if (m[15] == 1.0F) mask |= (1<<31);

   mat->flags &= ~MAT_FLAGS_GEOMETRY;

   /* Check for translation - no-one really cares
    */
   if ((mask & MASK_NO_TRX) != MASK_NO_TRX)
      mat->flags |= MAT_FLAG_TRANSLATION;

   /* Do the real work
    */
   if (mask == (GLuint) MASK_IDENTITY) {
      mat->type = MATRIX_IDENTITY;
   }
   else if ((mask & MASK_2D_NO_ROT) == (GLuint) MASK_2D_NO_ROT) {
      mat->type = MATRIX_2D_NO_ROT;

      if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE)
	 mat->flags |= MAT_FLAG_GENERAL_SCALE;
   }
   else if ((mask & MASK_2D) == (GLuint) MASK_2D) {
      GLfloat mm = DOT2(m, m);
      GLfloat m4m4 = DOT2(m+4,m+4);
      GLfloat mm4 = DOT2(m,m+4);

      mat->type = MATRIX_2D;

      /* Check for scale */
      if (SQ(mm-1) > SQ(1e-6) ||
	  SQ(m4m4-1) > SQ(1e-6))
	 mat->flags |= MAT_FLAG_GENERAL_SCALE;

      /* Check for rotation */
      if (SQ(mm4) > SQ(1e-6))
	 mat->flags |= MAT_FLAG_GENERAL_3D;
      else
	 mat->flags |= MAT_FLAG_ROTATION;

   }
   else if ((mask & MASK_3D_NO_ROT) == (GLuint) MASK_3D_NO_ROT) {
      mat->type = MATRIX_3D_NO_ROT;

      /* Check for scale */
      if (SQ(m[0]-m[5]) < SQ(1e-6) &&
	  SQ(m[0]-m[10]) < SQ(1e-6)) {
	 if (SQ(m[0]-1.0) > SQ(1e-6)) {
	    mat->flags |= MAT_FLAG_UNIFORM_SCALE;
         }
      }
      else {
	 mat->flags |= MAT_FLAG_GENERAL_SCALE;
      }
   }
   else if ((mask & MASK_3D) == (GLuint) MASK_3D) {
      GLfloat c1 = DOT3(m,m);
      GLfloat c2 = DOT3(m+4,m+4);
      GLfloat c3 = DOT3(m+8,m+8);
      GLfloat d1 = DOT3(m, m+4);
      GLfloat cp[3];

      mat->type = MATRIX_3D;

      /* Check for scale */
      if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) {
	 if (SQ(c1-1.0) > SQ(1e-6))
	    mat->flags |= MAT_FLAG_UNIFORM_SCALE;
	 /* else no scale at all */
      }
      else {
	 mat->flags |= MAT_FLAG_GENERAL_SCALE;
      }

      /* Check for rotation */
      if (SQ(d1) < SQ(1e-6)) {
	 CROSS3( cp, m, m+4 );
	 SUB_3V( cp, cp, (m+8) );
	 if (LEN_SQUARED_3FV(cp) < SQ(1e-6))
	    mat->flags |= MAT_FLAG_ROTATION;
	 else
	    mat->flags |= MAT_FLAG_GENERAL_3D;
      }
      else {
	 mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */
      }
   }
   else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) {
      mat->type = MATRIX_PERSPECTIVE;
      mat->flags |= MAT_FLAG_GENERAL;
   }
   else {
      mat->type = MATRIX_GENERAL;
      mat->flags |= MAT_FLAG_GENERAL;
   }
}

/**
 * Analyze a matrix given that its flags are accurate.
 * 
 * This is the more common operation, hopefully.
 */
static void analyse_from_flags( GLmatrix *mat )
{
   const GLfloat *m = mat->m;

   if (TEST_MAT_FLAGS(mat, 0)) {
      mat->type = MATRIX_IDENTITY;
   }
   else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION |
				 MAT_FLAG_UNIFORM_SCALE |
				 MAT_FLAG_GENERAL_SCALE))) {
      if ( m[10]==1.0F && m[14]==0.0F ) {
	 mat->type = MATRIX_2D_NO_ROT;
      }
      else {
	 mat->type = MATRIX_3D_NO_ROT;
      }
   }
   else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) {
      if (                                 m[ 8]==0.0F
            &&                             m[ 9]==0.0F
            && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F) {
	 mat->type = MATRIX_2D;
      }
      else {
	 mat->type = MATRIX_3D;
      }
   }
   else if (                 m[4]==0.0F                 && m[12]==0.0F
            && m[1]==0.0F                               && m[13]==0.0F
            && m[2]==0.0F && m[6]==0.0F
            && m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) {
      mat->type = MATRIX_PERSPECTIVE;
   }
   else {
      mat->type = MATRIX_GENERAL;
   }
}

/**
 * Analyze and update a matrix.
 *
 * \param mat matrix.
 *
 * If the matrix type is dirty then calls either analyse_from_scratch() or
 * analyse_from_flags() to determine its type, according to whether the flags
 * are dirty or not, respectively. If the matrix has an inverse and it's dirty
 * then calls matrix_invert(). Finally clears the dirty flags.
 */
void
_math_matrix_analyse( GLmatrix *mat )
{
   if (mat->flags & MAT_DIRTY_TYPE) {
      if (mat->flags & MAT_DIRTY_FLAGS)
	 analyse_from_scratch( mat );
      else
	 analyse_from_flags( mat );
   }

   if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) {
      matrix_invert( mat );
   }

   mat->flags &= ~(MAT_DIRTY_FLAGS|
		   MAT_DIRTY_TYPE|
		   MAT_DIRTY_INVERSE);
}

/*@}*/


/**
 * Test if the given matrix preserves vector lengths.
 */
GLboolean
_math_matrix_is_length_preserving( const GLmatrix *m )
{
   return TEST_MAT_FLAGS( m, MAT_FLAGS_LENGTH_PRESERVING);
}


/**
 * Test if the given matrix does any rotation.
 * (or perhaps if the upper-left 3x3 is non-identity)
 */
GLboolean
_math_matrix_has_rotation( const GLmatrix *m )
{
   if (m->flags & (MAT_FLAG_GENERAL |
                   MAT_FLAG_ROTATION |
                   MAT_FLAG_GENERAL_3D |
                   MAT_FLAG_PERSPECTIVE))
      return GL_TRUE;
   else
      return GL_FALSE;
}


GLboolean
_math_matrix_is_general_scale( const GLmatrix *m )
{
   return (m->flags & MAT_FLAG_GENERAL_SCALE) ? GL_TRUE : GL_FALSE;
}


GLboolean
_math_matrix_is_dirty( const GLmatrix *m )
{
   return (m->flags & MAT_DIRTY) ? GL_TRUE : GL_FALSE;
}


/**********************************************************************/
/** \name Matrix setup */
/*@{*/

/**
 * Copy a matrix.
 *
 * \param to destination matrix.
 * \param from source matrix.
 *
 * Copies all fields in GLmatrix, creating an inverse array if necessary.
 */
void
_math_matrix_copy( GLmatrix *to, const GLmatrix *from )
{
   MEMCPY( to->m, from->m, sizeof(Identity) );
   to->flags = from->flags;
   to->type = from->type;

   if (to->inv != 0) {
      if (from->inv == 0) {
	 matrix_invert( to );
      }
      else {
	 MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16);
      }
   }
}

/**
 * Loads a matrix array into GLmatrix.
 * 
 * \param m matrix array.
 * \param mat matrix.
 *
 * Copies \p m into GLmatrix::m and marks the MAT_FLAG_GENERAL and MAT_DIRTY
 * flags.
 */
void
_math_matrix_loadf( GLmatrix *mat, const GLfloat *m )
{
   MEMCPY( mat->m, m, 16*sizeof(GLfloat) );
   mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY);
}

/**
 * Matrix constructor.
 *
 * \param m matrix.
 *
 * Initialize the GLmatrix fields.
 */
void
_math_matrix_ctr( GLmatrix *m )
{
   m->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
   if (m->m)
      MEMCPY( m->m, Identity, sizeof(Identity) );
   m->inv = NULL;
   m->type = MATRIX_IDENTITY;
   m->flags = 0;
}

/**
 * Matrix destructor.
 *
 * \param m matrix.
 *
 * Frees the data in a GLmatrix.
 */
void
_math_matrix_dtr( GLmatrix *m )
{
   if (m->m) {
      ALIGN_FREE( m->m );
      m->m = NULL;
   }
   if (m->inv) {
      ALIGN_FREE( m->inv );
      m->inv = NULL;
   }
}

/**
 * Allocate a matrix inverse.
 *
 * \param m matrix.
 *
 * Allocates the matrix inverse, GLmatrix::inv, and sets it to Identity.
 */
void
_math_matrix_alloc_inv( GLmatrix *m )
{
   if (!m->inv) {
      m->inv = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
      if (m->inv)
         MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) );
   }
}

/*@}*/


/**********************************************************************/
/** \name Matrix transpose */
/*@{*/

/**
 * Transpose a GLfloat matrix.
 *
 * \param to destination array.
 * \param from source array.
 */
void
_math_transposef( GLfloat to[16], const GLfloat from[16] )
{
   to[0] = from[0];
   to[1] = from[4];
   to[2] = from[8];
   to[3] = from[12];
   to[4] = from[1];
   to[5] = from[5];
   to[6] = from[9];
   to[7] = from[13];
   to[8] = from[2];
   to[9] = from[6];
   to[10] = from[10];
   to[11] = from[14];
   to[12] = from[3];
   to[13] = from[7];
   to[14] = from[11];
   to[15] = from[15];
}

/**
 * Transpose a GLdouble matrix.
 *
 * \param to destination array.
 * \param from source array.
 */
void
_math_transposed( GLdouble to[16], const GLdouble from[16] )
{
   to[0] = from[0];
   to[1] = from[4];
   to[2] = from[8];
   to[3] = from[12];
   to[4] = from[1];
   to[5] = from[5];
   to[6] = from[9];
   to[7] = from[13];
   to[8] = from[2];
   to[9] = from[6];
   to[10] = from[10];
   to[11] = from[14];
   to[12] = from[3];
   to[13] = from[7];
   to[14] = from[11];
   to[15] = from[15];
}

/**
 * Transpose a GLdouble matrix and convert to GLfloat.
 *
 * \param to destination array.
 * \param from source array.
 */
void
_math_transposefd( GLfloat to[16], const GLdouble from[16] )
{
   to[0] = (GLfloat) from[0];
   to[1] = (GLfloat) from[4];
   to[2] = (GLfloat) from[8];
   to[3] = (GLfloat) from[12];
   to[4] = (GLfloat) from[1];
   to[5] = (GLfloat) from[5];
   to[6] = (GLfloat) from[9];
   to[7] = (GLfloat) from[13];
   to[8] = (GLfloat) from[2];
   to[9] = (GLfloat) from[6];
   to[10] = (GLfloat) from[10];
   to[11] = (GLfloat) from[14];
   to[12] = (GLfloat) from[3];
   to[13] = (GLfloat) from[7];
   to[14] = (GLfloat) from[11];
   to[15] = (GLfloat) from[15];
}

/*@}*/

⌨️ 快捷键说明

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