📄 m_matrix.c
字号:
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 + -