[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
2126bf60fd
commit
28c7e940bf
@ -61,9 +61,6 @@ typedef struct
|
|||||||
CoglMatrixMode flushed_matrix_mode;
|
CoglMatrixMode flushed_matrix_mode;
|
||||||
GList *texture_units;
|
GList *texture_units;
|
||||||
|
|
||||||
/* Cache of inverse projection matrix */
|
|
||||||
float inverse_projection[16];
|
|
||||||
|
|
||||||
/* Materials */
|
/* Materials */
|
||||||
CoglHandle default_material;
|
CoglHandle default_material;
|
||||||
CoglHandle source_material;
|
CoglHandle source_material;
|
||||||
|
@ -348,6 +348,17 @@ _cogl_matrix_stack_ortho (CoglMatrixStack *stack,
|
|||||||
state->is_identity = FALSE;
|
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
|
void
|
||||||
_cogl_matrix_stack_get (CoglMatrixStack *stack,
|
_cogl_matrix_stack_get (CoglMatrixStack *stack,
|
||||||
CoglMatrix *matrix)
|
CoglMatrix *matrix)
|
||||||
|
@ -71,6 +71,9 @@ void _cogl_matrix_stack_ortho (CoglMatrixStack *stack,
|
|||||||
float top,
|
float top,
|
||||||
float z_near,
|
float z_near,
|
||||||
float z_far);
|
float z_far);
|
||||||
|
|
||||||
|
gboolean _cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
|
||||||
|
CoglMatrix *inverse);
|
||||||
void _cogl_matrix_stack_get (CoglMatrixStack *stack,
|
void _cogl_matrix_stack_get (CoglMatrixStack *stack,
|
||||||
CoglMatrix *matrix);
|
CoglMatrix *matrix);
|
||||||
void _cogl_matrix_stack_set (CoglMatrixStack *stack,
|
void _cogl_matrix_stack_set (CoglMatrixStack *stack,
|
||||||
|
@ -183,18 +183,6 @@ cogl_matrix_scale (CoglMatrix *matrix,
|
|||||||
_COGL_MATRIX_DEBUG_PRINT (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
|
void
|
||||||
cogl_matrix_frustum (CoglMatrix *matrix,
|
cogl_matrix_frustum (CoglMatrix *matrix,
|
||||||
float left,
|
float left,
|
||||||
@ -321,6 +309,27 @@ cogl_matrix_get_array (const CoglMatrix *matrix)
|
|||||||
return (float *)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
|
void
|
||||||
cogl_matrix_transform_point (const CoglMatrix *matrix,
|
cogl_matrix_transform_point (const CoglMatrix *matrix,
|
||||||
float *x,
|
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);
|
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:
|
* cogl_matrix_transform_point:
|
||||||
* @matrix: A 4x4 transformation matrix
|
* @matrix: A 4x4 transformation matrix
|
||||||
|
47
cogl/cogl.c
47
cogl/cogl.c
@ -368,13 +368,17 @@ set_clip_plane (GLint plane_num,
|
|||||||
GLdouble plane[4];
|
GLdouble plane[4];
|
||||||
#endif
|
#endif
|
||||||
GLfloat angle;
|
GLfloat angle;
|
||||||
CoglMatrix inverse_projection;
|
|
||||||
CoglHandle draw_buffer = _cogl_get_draw_buffer ();
|
CoglHandle draw_buffer = _cogl_get_draw_buffer ();
|
||||||
CoglMatrixStack *modelview_stack =
|
CoglMatrixStack *modelview_stack =
|
||||||
_cogl_draw_buffer_get_modelview_stack (draw_buffer);
|
_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_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
|
/* Calculate the angle between the axes and the line crossing the
|
||||||
two points */
|
two points */
|
||||||
angle = atan2f (vertex_b[1] - vertex_a[1],
|
angle = atan2f (vertex_b[1] - vertex_a[1],
|
||||||
@ -382,13 +386,10 @@ set_clip_plane (GLint plane_num,
|
|||||||
|
|
||||||
_cogl_matrix_stack_push (modelview_stack);
|
_cogl_matrix_stack_push (modelview_stack);
|
||||||
|
|
||||||
/* Load the identity matrix and multiply by the reverse of the
|
/* Load the inverse of the projection matrix so we can specify the plane
|
||||||
projection matrix so we can specify the plane in screen
|
* in screen coordinates */
|
||||||
coordinates */
|
_cogl_matrix_stack_set (modelview_stack, &inverse_projection);
|
||||||
_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);
|
|
||||||
/* Rotate about point a */
|
/* Rotate about point a */
|
||||||
_cogl_matrix_stack_translate (modelview_stack,
|
_cogl_matrix_stack_translate (modelview_stack,
|
||||||
vertex_a[0], vertex_a[1], vertex_a[2]);
|
vertex_a[0], vertex_a[1], vertex_a[2]);
|
||||||
@ -1095,7 +1096,6 @@ cogl_frustum (float left,
|
|||||||
float z_near,
|
float z_near,
|
||||||
float z_far)
|
float z_far)
|
||||||
{
|
{
|
||||||
float c, d;
|
|
||||||
CoglMatrixStack *projection_stack =
|
CoglMatrixStack *projection_stack =
|
||||||
_cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
|
_cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
|
||||||
|
|
||||||
@ -1110,22 +1110,6 @@ cogl_frustum (float left,
|
|||||||
top,
|
top,
|
||||||
z_near,
|
z_near,
|
||||||
z_far);
|
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
|
void
|
||||||
@ -1145,19 +1129,6 @@ cogl_ortho (float left,
|
|||||||
cogl_matrix_init_identity (&ortho);
|
cogl_matrix_init_identity (&ortho);
|
||||||
cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
|
cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
|
||||||
_cogl_matrix_stack_set (projection_stack, &ortho);
|
_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
|
void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user