[matrix] Adds cogl_matrix_get_inverse API
This new API takes advantage of the recently imported Mesa code to support inverse matrix calculation. The matrix code keeps track (via internal flags) of the transformations a matrix represents so that it can select an optimized inversion function. Note: although other aspects of the Cogl matrix API have followed a similar style to Cairo's matrix API we haven't added a cogl_matrix_invert API because the inverse of a CoglMatrix is actually cached as part of the CoglMatrix structure meaning a destructive API like cogl_matrix_invert doesn't let users take advantage of this caching design.
This commit is contained in:
parent
8051596e96
commit
0369a1b84d
@ -61,9 +61,6 @@ typedef struct
|
||||
CoglMatrixMode flushed_matrix_mode;
|
||||
GList *texture_units;
|
||||
|
||||
/* Cache of inverse projection matrix */
|
||||
float inverse_projection[16];
|
||||
|
||||
/* Materials */
|
||||
CoglHandle default_material;
|
||||
CoglHandle source_material;
|
||||
|
@ -348,6 +348,17 @@ _cogl_matrix_stack_ortho (CoglMatrixStack *stack,
|
||||
state->is_identity = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
|
||||
CoglMatrix *inverse)
|
||||
{
|
||||
CoglMatrixState *state;
|
||||
|
||||
state = _cogl_matrix_stack_top_mutable (stack, TRUE);
|
||||
|
||||
return cogl_matrix_get_inverse (&state->matrix, inverse);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_matrix_stack_get (CoglMatrixStack *stack,
|
||||
CoglMatrix *matrix)
|
||||
|
@ -71,6 +71,9 @@ void _cogl_matrix_stack_ortho (CoglMatrixStack *stack,
|
||||
float top,
|
||||
float z_near,
|
||||
float z_far);
|
||||
|
||||
gboolean _cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
|
||||
CoglMatrix *inverse);
|
||||
void _cogl_matrix_stack_get (CoglMatrixStack *stack,
|
||||
CoglMatrix *matrix);
|
||||
void _cogl_matrix_stack_set (CoglMatrixStack *stack,
|
||||
|
@ -183,18 +183,6 @@ cogl_matrix_scale (CoglMatrix *matrix,
|
||||
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||
}
|
||||
|
||||
#if 0
|
||||
gboolean
|
||||
cogl_matrix_invert (CoglMatrix *matrix)
|
||||
{
|
||||
/* TODO */
|
||||
/* Note: It might be nice to also use the flag based tricks that mesa does
|
||||
* to alow it to track the type of transformations a matrix represents
|
||||
* so it can use various assumptions to optimise the inversion.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
cogl_matrix_frustum (CoglMatrix *matrix,
|
||||
float left,
|
||||
@ -321,6 +309,27 @@ cogl_matrix_get_array (const CoglMatrix *matrix)
|
||||
return (float *)matrix;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse)
|
||||
{
|
||||
#ifndef USE_MESA_MATRIX_API
|
||||
#warning "cogl_matrix_get_inverse not supported without Mesa matrix API"
|
||||
cogl_matrix_init_identity (inverse);
|
||||
return FALSE;
|
||||
#else
|
||||
if (_math_matrix_update_inverse ((CoglMatrix *)matrix))
|
||||
{
|
||||
cogl_matrix_init_from_array (inverse, matrix->inv);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
cogl_matrix_init_identity (inverse);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
cogl_matrix_transform_point (const CoglMatrix *matrix,
|
||||
float *x,
|
||||
|
@ -266,6 +266,27 @@ void cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array);
|
||||
*/
|
||||
G_CONST_RETURN float *cogl_matrix_get_array (const CoglMatrix *matrix);
|
||||
|
||||
/**
|
||||
* cogl_matrix_get_inverse:
|
||||
* @matrix: A 4x4 transformation matrix
|
||||
* @inverse: The destination for a 4x4 inverse transformation matrix
|
||||
*
|
||||
* This gets the inverse transform of a given matrix and uses it to initialize
|
||||
* a new CoglMatrix.
|
||||
*
|
||||
* Note: that although the first parameter is annotated as const to indicate
|
||||
* that the transform it represents isn't modified this function may
|
||||
* technically save a copy of the inverse transform within the given CoglMatrix
|
||||
* so that subsequent requests for the inverse transform may avoid costly
|
||||
* inversion calculations.
|
||||
*
|
||||
* Returns TRUE if the inverse was successfully calculated or FALSE for
|
||||
* degenerate transformations that can't be inverted (in this case the matrix
|
||||
* will simply be initialized with the identity matrix)
|
||||
*/
|
||||
gboolean
|
||||
cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse);
|
||||
|
||||
/**
|
||||
* cogl_matrix_transform_point:
|
||||
* @matrix: A 4x4 transformation matrix
|
||||
|
@ -368,13 +368,17 @@ set_clip_plane (GLint plane_num,
|
||||
GLdouble plane[4];
|
||||
#endif
|
||||
GLfloat angle;
|
||||
CoglMatrix inverse_projection;
|
||||
CoglHandle draw_buffer = _cogl_get_draw_buffer ();
|
||||
CoglMatrixStack *modelview_stack =
|
||||
_cogl_draw_buffer_get_modelview_stack (draw_buffer);
|
||||
CoglMatrixStack *projection_stack =
|
||||
_cogl_draw_buffer_get_projection_stack (draw_buffer);
|
||||
CoglMatrix inverse_projection;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
_cogl_matrix_stack_get_inverse (projection_stack, &inverse_projection);
|
||||
|
||||
/* Calculate the angle between the axes and the line crossing the
|
||||
two points */
|
||||
angle = atan2f (vertex_b[1] - vertex_a[1],
|
||||
@ -382,13 +386,10 @@ set_clip_plane (GLint plane_num,
|
||||
|
||||
_cogl_matrix_stack_push (modelview_stack);
|
||||
|
||||
/* Load the identity matrix and multiply by the reverse of the
|
||||
projection matrix so we can specify the plane in screen
|
||||
coordinates */
|
||||
_cogl_matrix_stack_load_identity (modelview_stack);
|
||||
cogl_matrix_init_from_array (&inverse_projection,
|
||||
ctx->inverse_projection);
|
||||
_cogl_matrix_stack_multiply (modelview_stack, &inverse_projection);
|
||||
/* Load the inverse of the projection matrix so we can specify the plane
|
||||
* in screen coordinates */
|
||||
_cogl_matrix_stack_set (modelview_stack, &inverse_projection);
|
||||
|
||||
/* Rotate about point a */
|
||||
_cogl_matrix_stack_translate (modelview_stack,
|
||||
vertex_a[0], vertex_a[1], vertex_a[2]);
|
||||
@ -1095,7 +1096,6 @@ cogl_frustum (float left,
|
||||
float z_near,
|
||||
float z_far)
|
||||
{
|
||||
float c, d;
|
||||
CoglMatrixStack *projection_stack =
|
||||
_cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
|
||||
|
||||
@ -1110,22 +1110,6 @@ cogl_frustum (float left,
|
||||
top,
|
||||
z_near,
|
||||
z_far);
|
||||
|
||||
/* Calculate and store the inverse of the matrix */
|
||||
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
|
||||
|
||||
c = - (z_far + z_near) / (z_far - z_near);
|
||||
d = - (2 * (z_far * z_near)) / (z_far - z_near);
|
||||
|
||||
#define M(row,col) ctx->inverse_projection[col*4+row]
|
||||
M(0,0) = (right - left) / (2 * z_near);
|
||||
M(0,3) = (right + left) / (2 * z_near);
|
||||
M(1,1) = (top - bottom) / (2 * z_near);
|
||||
M(1,3) = (top + bottom) / (2 * z_near);
|
||||
M(2,3) = -1.0;
|
||||
M(3,2) = 1.0 / d;
|
||||
M(3,3) = c / d;
|
||||
#undef M
|
||||
}
|
||||
|
||||
void
|
||||
@ -1145,19 +1129,6 @@ cogl_ortho (float left,
|
||||
cogl_matrix_init_identity (&ortho);
|
||||
cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
|
||||
_cogl_matrix_stack_set (projection_stack, &ortho);
|
||||
|
||||
/* Calculate and store the inverse of the matrix */
|
||||
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
|
||||
|
||||
#define M(row,col) ctx->inverse_projection[col*4+row]
|
||||
M(0,0) = 1.0 / ortho.xx;
|
||||
M(0,3) = -ortho.xw;
|
||||
M(1,1) = 1.0 / ortho.yy;
|
||||
M(1,3) = -ortho.yw;
|
||||
M(2,2) = 1.0 / ortho.zz;
|
||||
M(2,3) = -ortho.zw;
|
||||
M(3,3) = 1.0;
|
||||
#undef M
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user