Пример #1
0
/**
 * Multiply a matrix by an array of floats with known properties.
 *
 * \param mat pointer to a GLmatrix structure containing the left multiplication
 * matrix, and that will receive the product result.
 * \param m right multiplication matrix array.
 * \param flags flags of the matrix \p m.
 * 
 * Joins both flags and marks the type and inverse as dirty.  Calls matmul34()
 * if both matrices are 3D, or matmul4() otherwise.
 */
static void matrix_multf( GLmatrix *mat, const GLfloat *m, GLuint flags )
{
   mat->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);

   if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
      matmul34( mat->m, mat->m, m );
   else
      matmul4( mat->m, mat->m, m );
}
Пример #2
0
/**
 * Matrix multiplication.
 *
 * \param dest destination matrix.
 * \param a left matrix.
 * \param b right matrix.
 * 
 * Joins both flags and marks the type and inverse as dirty.  Calls matmul34()
 * if both matrices are 3D, or matmul4() otherwise.
 */
void
_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b )
{
   dest->flags = (a->flags |
		  b->flags |
		  MAT_DIRTY_TYPE |
		  MAT_DIRTY_INVERSE);

   if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D))
      matmul34( dest->m, a->m, b->m );
   else
      matmul4( dest->m, a->m, b->m );
}
Пример #3
0
/**
 * 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;
   }
}
Пример #4
0
/*
 * If ctx->NewState is non-zero then this function MUST be called before
 * rendering any primitive.  Basically, function pointers and miscellaneous
 * flags are updated to reflect the current state of the state machine.
 *
 * The above constraint is now maintained largely by the two Exec
 * dispatch tables, which trigger the appropriate flush on transition
 * between State and Geometry modes.
 *
 * Special care is taken with the derived value _NeedEyeCoords.  This
 * is a bitflag which is updated with information from a number of
 * attribute groups (MODELVIEW, LIGHT, TEXTURE).  A lot of derived
 * state references this value, and must be treated with care to
 * ensure that updates are done correctly.  All state dependent on
 * _NeedEyeCoords is calculated from within _mesa_update_tnl_spaces(),
 * and from nowhere else.
 */
void _mesa_update_state( GLcontext *ctx )
{
   const GLuint new_state = ctx->NewState;
   const GLuint oldneedeyecoords = ctx->_NeedEyeCoords;

   if (MESA_VERBOSE & VERBOSE_STATE)
      _mesa_print_state("_mesa_update_state", new_state);

   if (new_state & _NEW_MODELVIEW)
      _math_matrix_analyse( &ctx->ModelView );

   if (new_state & _NEW_PROJECTION)
      update_projection( ctx );

   if (new_state & _NEW_TEXTURE_MATRIX)
      update_texture_matrices( ctx );

   if (new_state & _NEW_COLOR_MATRIX)
      _math_matrix_analyse( &ctx->ColorMatrix );

   /* References ColorMatrix.type (derived above).
    */
   if (new_state & _IMAGE_NEW_TRANSFER_STATE)
      update_image_transfer_state(ctx);

   /* Contributes to NeedEyeCoords, NeedNormals.
    */
   if (new_state & _NEW_TEXTURE)
      update_texture_state( ctx );

   if (new_state & (_NEW_BUFFERS|_NEW_SCISSOR))
      update_drawbuffer( ctx );

   if (new_state & _NEW_POLYGON)
      update_polygon( ctx );

   /* Contributes to NeedEyeCoords, NeedNormals.
    */
   if (new_state & _NEW_LIGHT)
      _mesa_update_lighting( ctx );

   /* We can light in object space if the modelview matrix preserves
    * lengths and relative angles.
    */
   if (new_state & (_NEW_MODELVIEW|_NEW_LIGHT)) {
      ctx->_NeedEyeCoords &= ~NEED_EYE_LIGHT_MODELVIEW;
      if (ctx->Light.Enabled &&
	  !TEST_MAT_FLAGS( &ctx->ModelView, MAT_FLAGS_LENGTH_PRESERVING))
	    ctx->_NeedEyeCoords |= NEED_EYE_LIGHT_MODELVIEW;
   }

   /* Keep ModelviewProject uptodate always to allow tnl
    * implementations that go model->clip even when eye is required.
    */
   if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
      calculate_model_project_matrix(ctx);


   /* ctx->_NeedEyeCoords is now uptodate.
    *
    * If the truth value of this variable has changed, update for the
    * new lighting space and recompute the positions of lights and the
    * normal transform.
    *
    * If the lighting space hasn't changed, may still need to recompute
    * light positions & normal transforms for other reasons.
    */
   if (new_state & (_NEW_MODELVIEW |
		    _NEW_LIGHT |
		    _MESA_NEW_NEED_EYE_COORDS))
      update_tnl_spaces( ctx, oldneedeyecoords );

   /*
    * Here the driver sets up all the ctx->Driver function pointers
    * to it's specific, private functions, and performs any
    * internal state management necessary, including invalidating
    * state of active modules.
    *
    * Set ctx->NewState to zero to avoid recursion if
    * Driver.UpdateState() has to call FLUSH_VERTICES().  (fixed?)
    */
   ctx->NewState = 0;
   ctx->Driver.UpdateState(ctx, new_state);
   ctx->Array.NewState = 0;

   /* At this point we can do some assertions to be sure the required
    * device driver function pointers are all initialized.
    */
   ASSERT(ctx->Driver.GetString);
   ASSERT(ctx->Driver.UpdateState);
   ASSERT(ctx->Driver.Clear);
   ASSERT(ctx->Driver.SetDrawBuffer);
   ASSERT(ctx->Driver.GetBufferSize);
   if (ctx->Visual.accumRedBits > 0) {
      ASSERT(ctx->Driver.Accum);
   }
   ASSERT(ctx->Driver.DrawPixels);
   ASSERT(ctx->Driver.ReadPixels);
   ASSERT(ctx->Driver.CopyPixels);
   ASSERT(ctx->Driver.Bitmap);
   ASSERT(ctx->Driver.ResizeBuffers);
   ASSERT(ctx->Driver.TexImage1D);
   ASSERT(ctx->Driver.TexImage2D);
   ASSERT(ctx->Driver.TexImage3D);
   ASSERT(ctx->Driver.TexSubImage1D);
   ASSERT(ctx->Driver.TexSubImage2D);
   ASSERT(ctx->Driver.TexSubImage3D);
   ASSERT(ctx->Driver.CopyTexImage1D);
   ASSERT(ctx->Driver.CopyTexImage2D);
   ASSERT(ctx->Driver.CopyTexSubImage1D);
   ASSERT(ctx->Driver.CopyTexSubImage2D);
   ASSERT(ctx->Driver.CopyTexSubImage3D);
   if (ctx->Extensions.ARB_texture_compression) {
      ASSERT(ctx->Driver.BaseCompressedTexFormat);
      ASSERT(ctx->Driver.CompressedTextureSize);
      ASSERT(ctx->Driver.GetCompressedTexImage);
#if 0  /* HW drivers need these, but not SW rasterizers */
      ASSERT(ctx->Driver.CompressedTexImage1D);
      ASSERT(ctx->Driver.CompressedTexImage2D);
      ASSERT(ctx->Driver.CompressedTexImage3D);
      ASSERT(ctx->Driver.CompressedTexSubImage1D);
      ASSERT(ctx->Driver.CompressedTexSubImage2D);
      ASSERT(ctx->Driver.CompressedTexSubImage3D);
#endif
   }
}
Пример #5
0
/**
 * 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;
}
Пример #6
0
/**
 * 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);
}