2e986ed3e8
CoglMatrix doesn't have a 1:1 mapping of graphene functions, and sometimes it's just not worth adding wrappers over it. It is easier to expose the internal graphene_matrix_t and let callers use it directly. Add new cogl_matrix_get_graphene_matrix() helper function, and simplify Clutter's matrix progress function. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1439
819 lines
23 KiB
C
819 lines
23 KiB
C
/*
|
|
* Cogl
|
|
*
|
|
* A Low Level GPU Graphics and Utilities API
|
|
*
|
|
* Copyright (C) 2009,2010,2011 Intel Corporation.
|
|
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
* Authors:
|
|
* Robert Bragg <robert@linux.intel.com>
|
|
* Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
*/
|
|
|
|
#include "cogl-config.h"
|
|
|
|
#include <cogl-util.h>
|
|
#include <cogl-debug.h>
|
|
#include <cogl-matrix.h>
|
|
#include <cogl-matrix-private.h>
|
|
|
|
#include <glib.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
#include <cogl-gtype-private.h>
|
|
COGL_GTYPE_DEFINE_BOXED (Matrix, matrix,
|
|
cogl_matrix_copy,
|
|
cogl_matrix_free);
|
|
|
|
enum CoglMatrixFlags
|
|
{
|
|
COGL_MATRIX_FLAG_NONE = 0,
|
|
COGL_MATRIX_FLAG_SINGULAR = 1 << 0,
|
|
COGL_MATRIX_FLAG_DIRTY_INVERSE = 1 << 1,
|
|
};
|
|
|
|
void
|
|
cogl_matrix_multiply (CoglMatrix *result,
|
|
const CoglMatrix *a,
|
|
const CoglMatrix *b)
|
|
{
|
|
graphene_matrix_multiply (&b->m, &a->m, &result->m);
|
|
result->flags = a->flags | b->flags | COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
|
|
_COGL_MATRIX_DEBUG_PRINT (result);
|
|
}
|
|
|
|
void
|
|
_cogl_matrix_prefix_print (const char *prefix, const CoglMatrix *matrix)
|
|
{
|
|
graphene_matrix_print (&matrix->m);
|
|
g_print ("%sInverse: \n", prefix);
|
|
if (!(matrix->flags & COGL_MATRIX_FLAG_DIRTY_INVERSE))
|
|
graphene_matrix_print (&matrix->inv);
|
|
else
|
|
g_print ("%s - not available\n", prefix);
|
|
}
|
|
|
|
/*
|
|
* Dumps the contents of a CoglMatrix structure.
|
|
*/
|
|
void
|
|
cogl_debug_matrix_print (const CoglMatrix *matrix)
|
|
{
|
|
_cogl_matrix_prefix_print ("", matrix);
|
|
}
|
|
|
|
/*
|
|
* Compute inverse of a transformation matrix.
|
|
*
|
|
* @mat pointer to a CoglMatrix structure. The matrix inverse will be
|
|
* stored in the CoglMatrix::inv attribute.
|
|
*
|
|
* Returns: %TRUE for success, %FALSE for failure (\p singular matrix).
|
|
*
|
|
* Calls the matrix inversion function in inv_mat_tab corresponding to the
|
|
* given matrix type. In case of failure, updates the MAT_FLAG_SINGULAR flag,
|
|
* and copies the identity matrix into CoglMatrix::inv.
|
|
*/
|
|
|
|
static inline gboolean
|
|
calculate_inverse (CoglMatrix *matrix)
|
|
{
|
|
graphene_matrix_t scaled;
|
|
graphene_matrix_t m;
|
|
gboolean invertible;
|
|
float pivot = G_MAXFLOAT;
|
|
float v[16];
|
|
float scale;
|
|
|
|
graphene_matrix_init_from_matrix (&m, &matrix->m);
|
|
graphene_matrix_to_float (&m, v);
|
|
|
|
pivot = MIN (pivot, v[0]);
|
|
pivot = MIN (pivot, v[5]);
|
|
pivot = MIN (pivot, v[10]);
|
|
pivot = MIN (pivot, v[15]);
|
|
scale = 1.f / pivot;
|
|
|
|
graphene_matrix_init_scale (&scaled, scale, scale, scale);
|
|
|
|
/* Float precision is a limiting factor */
|
|
graphene_matrix_multiply (&m, &scaled, &m);
|
|
|
|
invertible = graphene_matrix_inverse (&m, &matrix->inv);
|
|
|
|
if (invertible)
|
|
graphene_matrix_multiply (&scaled, &matrix->inv, &matrix->inv);
|
|
else
|
|
graphene_matrix_init_identity (&matrix->inv);
|
|
|
|
return invertible;
|
|
}
|
|
|
|
static gboolean
|
|
_cogl_matrix_update_inverse (CoglMatrix *matrix)
|
|
{
|
|
if (matrix->flags & COGL_MATRIX_FLAG_DIRTY_INVERSE)
|
|
{
|
|
if (calculate_inverse (matrix))
|
|
matrix->flags &= ~COGL_MATRIX_FLAG_SINGULAR;
|
|
else
|
|
matrix->flags |= COGL_MATRIX_FLAG_SINGULAR;
|
|
|
|
matrix->flags &= ~COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
}
|
|
|
|
if (matrix->flags & COGL_MATRIX_FLAG_SINGULAR)
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse)
|
|
{
|
|
if (_cogl_matrix_update_inverse ((CoglMatrix *)matrix))
|
|
{
|
|
graphene_matrix_init_from_matrix (&inverse->m, &matrix->inv);
|
|
graphene_matrix_init_from_matrix (&inverse->inv, &matrix->m);
|
|
inverse->flags = COGL_MATRIX_FLAG_NONE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
cogl_matrix_init_identity (inverse);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void
|
|
cogl_matrix_rotate (CoglMatrix *matrix,
|
|
float angle,
|
|
float x,
|
|
float y,
|
|
float z)
|
|
{
|
|
graphene_matrix_t rotation;
|
|
graphene_vec3_t axis;
|
|
unsigned long flags;
|
|
|
|
flags = matrix->flags;
|
|
|
|
graphene_vec3_init (&axis, x, y, z);
|
|
graphene_matrix_init_rotate (&rotation, angle, &axis);
|
|
graphene_matrix_multiply (&rotation, &matrix->m, &matrix->m);
|
|
|
|
matrix->flags = flags |= COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_rotate_euler (CoglMatrix *matrix,
|
|
const graphene_euler_t *euler)
|
|
{
|
|
CoglMatrix rotation_transform;
|
|
|
|
cogl_matrix_init_from_euler (&rotation_transform, euler);
|
|
cogl_matrix_multiply (matrix, matrix, &rotation_transform);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_frustum (CoglMatrix *matrix,
|
|
float left,
|
|
float right,
|
|
float bottom,
|
|
float top,
|
|
float z_near,
|
|
float z_far)
|
|
{
|
|
graphene_matrix_t frustum;
|
|
unsigned long flags;
|
|
|
|
flags = matrix->flags;
|
|
|
|
graphene_matrix_init_frustum (&frustum,
|
|
left, right,
|
|
bottom, top,
|
|
z_near, z_far);
|
|
graphene_matrix_multiply (&frustum, &matrix->m, &matrix->m);
|
|
|
|
flags |= COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
matrix->flags = flags;
|
|
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_perspective (CoglMatrix *matrix,
|
|
float fov_y,
|
|
float aspect,
|
|
float z_near,
|
|
float z_far)
|
|
{
|
|
float ymax = z_near * tan (fov_y * G_PI / 360.0);
|
|
|
|
cogl_matrix_frustum (matrix,
|
|
-ymax * aspect, /* left */
|
|
ymax * aspect, /* right */
|
|
-ymax, /* bottom */
|
|
ymax, /* top */
|
|
z_near,
|
|
z_far);
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_orthographic (CoglMatrix *matrix,
|
|
float left,
|
|
float bottom,
|
|
float right,
|
|
float top,
|
|
float near,
|
|
float far)
|
|
{
|
|
graphene_matrix_t ortho;
|
|
unsigned long flags;
|
|
|
|
flags = matrix->flags;
|
|
|
|
graphene_matrix_init_ortho (&ortho,
|
|
left, right,
|
|
top, bottom,
|
|
near, far);
|
|
graphene_matrix_multiply (&ortho, &matrix->m, &matrix->m);
|
|
|
|
matrix->flags = flags | COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_scale (CoglMatrix *matrix,
|
|
float sx,
|
|
float sy,
|
|
float sz)
|
|
{
|
|
graphene_matrix_t scale;
|
|
unsigned long flags;
|
|
|
|
flags = matrix->flags;
|
|
|
|
graphene_matrix_init_scale (&scale, sx, sy, sz);
|
|
graphene_matrix_multiply (&scale, &matrix->m, &matrix->m);
|
|
|
|
matrix->flags = flags | COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_translate (CoglMatrix *matrix,
|
|
float x,
|
|
float y,
|
|
float z)
|
|
{
|
|
graphene_matrix_t translation;
|
|
|
|
graphene_matrix_init_translate (&translation,
|
|
&GRAPHENE_POINT3D_INIT (x, y, z));
|
|
graphene_matrix_multiply (&translation, &matrix->m, &matrix->m);
|
|
matrix->flags |= COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_init_identity (CoglMatrix *matrix)
|
|
{
|
|
graphene_matrix_init_identity (&matrix->m);
|
|
matrix->flags = COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_init_translation (CoglMatrix *matrix,
|
|
float tx,
|
|
float ty,
|
|
float tz)
|
|
{
|
|
graphene_matrix_init_translate (&matrix->m, &GRAPHENE_POINT3D_INIT (tx, ty, tz));
|
|
matrix->flags = COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
/*
|
|
* Loads a matrix array into CoglMatrix.
|
|
*
|
|
* @m matrix array.
|
|
* @mat matrix.
|
|
*
|
|
* Copies \p m into CoglMatrix::m and marks the MAT_FLAG_GENERAL and
|
|
* MAT_DIRTY_ALL
|
|
* flags.
|
|
*/
|
|
static void
|
|
_cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array)
|
|
{
|
|
graphene_matrix_init_from_float (&matrix->m, array);
|
|
matrix->flags = COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
}
|
|
|
|
void
|
|
cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array)
|
|
{
|
|
_cogl_matrix_init_from_array (matrix, array);
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_init_from_matrix (CoglMatrix *matrix,
|
|
const CoglMatrix *source)
|
|
{
|
|
memcpy (matrix, source, sizeof (CoglMatrix));
|
|
}
|
|
|
|
void
|
|
_cogl_matrix_init_from_matrix_without_inverse (CoglMatrix *matrix,
|
|
const CoglMatrix *src)
|
|
{
|
|
graphene_matrix_init_from_matrix (&matrix->m, &src->m);
|
|
matrix->flags = src->flags | COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
}
|
|
|
|
void
|
|
cogl_matrix_init_from_euler (CoglMatrix *matrix,
|
|
const graphene_euler_t *euler)
|
|
{
|
|
graphene_matrix_init_identity (&matrix->m);
|
|
graphene_matrix_rotate_euler (&matrix->m, euler);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_view_2d_in_frustum (CoglMatrix *matrix,
|
|
float left,
|
|
float right,
|
|
float bottom,
|
|
float top,
|
|
float z_near,
|
|
float z_2d,
|
|
float width_2d,
|
|
float height_2d)
|
|
{
|
|
float left_2d_plane = left / z_near * z_2d;
|
|
float right_2d_plane = right / z_near * z_2d;
|
|
float bottom_2d_plane = bottom / z_near * z_2d;
|
|
float top_2d_plane = top / z_near * z_2d;
|
|
|
|
float width_2d_start = right_2d_plane - left_2d_plane;
|
|
float height_2d_start = top_2d_plane - bottom_2d_plane;
|
|
|
|
/* Factors to scale from framebuffer geometry to frustum
|
|
* cross-section geometry. */
|
|
float width_scale = width_2d_start / width_2d;
|
|
float height_scale = height_2d_start / height_2d;
|
|
|
|
cogl_matrix_translate (matrix,
|
|
left_2d_plane, top_2d_plane, -z_2d);
|
|
|
|
cogl_matrix_scale (matrix, width_scale, -height_scale, width_scale);
|
|
}
|
|
|
|
/* Assuming a symmetric perspective matrix is being used for your
|
|
* projective transform this convenience function lets you compose a
|
|
* view transform such that geometry on the z=0 plane will map to
|
|
* screen coordinates with a top left origin of (0,0) and with the
|
|
* given width and height.
|
|
*/
|
|
void
|
|
cogl_matrix_view_2d_in_perspective (CoglMatrix *matrix,
|
|
float fov_y,
|
|
float aspect,
|
|
float z_near,
|
|
float z_2d,
|
|
float width_2d,
|
|
float height_2d)
|
|
{
|
|
float top = z_near * tan (fov_y * G_PI / 360.0);
|
|
cogl_matrix_view_2d_in_frustum (matrix,
|
|
-top * aspect,
|
|
top * aspect,
|
|
-top,
|
|
top,
|
|
z_near,
|
|
z_2d,
|
|
width_2d,
|
|
height_2d);
|
|
}
|
|
|
|
gboolean
|
|
cogl_matrix_equal (const void *v1, const void *v2)
|
|
{
|
|
const CoglMatrix *a = v1;
|
|
const CoglMatrix *b = v2;
|
|
|
|
g_return_val_if_fail (v1 != NULL, FALSE);
|
|
g_return_val_if_fail (v2 != NULL, FALSE);
|
|
|
|
return graphene_matrix_equal_fast (&a->m, &b->m);
|
|
}
|
|
|
|
CoglMatrix *
|
|
cogl_matrix_copy (const CoglMatrix *matrix)
|
|
{
|
|
if (G_LIKELY (matrix))
|
|
return g_slice_dup (CoglMatrix, matrix);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
cogl_matrix_free (CoglMatrix *matrix)
|
|
{
|
|
g_slice_free (CoglMatrix, matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_to_float (const CoglMatrix *matrix,
|
|
float *out_array)
|
|
{
|
|
graphene_matrix_to_float (&matrix->m, out_array);
|
|
}
|
|
|
|
float
|
|
cogl_matrix_get_value (const CoglMatrix *matrix,
|
|
unsigned int row,
|
|
unsigned int column)
|
|
{
|
|
return graphene_matrix_get_value (&matrix->m, column, row);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_transform_point (const CoglMatrix *matrix,
|
|
float *x,
|
|
float *y,
|
|
float *z,
|
|
float *w)
|
|
{
|
|
graphene_vec4_t p;
|
|
|
|
graphene_vec4_init (&p, *x, *y, *z, *w);
|
|
graphene_matrix_transform_vec4 (&matrix->m, &p, &p);
|
|
|
|
*x = graphene_vec4_get_x (&p);
|
|
*y = graphene_vec4_get_y (&p);
|
|
*z = graphene_vec4_get_z (&p);
|
|
*w = graphene_vec4_get_w (&p);
|
|
}
|
|
|
|
typedef struct _Point2f
|
|
{
|
|
float x;
|
|
float y;
|
|
} Point2f;
|
|
|
|
typedef struct _Point3f
|
|
{
|
|
float x;
|
|
float y;
|
|
float z;
|
|
} Point3f;
|
|
|
|
typedef struct _Point4f
|
|
{
|
|
float x;
|
|
float y;
|
|
float z;
|
|
float w;
|
|
} Point4f;
|
|
|
|
static void
|
|
init_matrix_rows (const CoglMatrix *matrix,
|
|
unsigned int n_rows,
|
|
graphene_vec4_t *rows)
|
|
{
|
|
graphene_matrix_t m;
|
|
unsigned int i;
|
|
|
|
graphene_matrix_transpose (&matrix->m, &m);
|
|
|
|
for (i = 0; i < n_rows; i++)
|
|
graphene_matrix_get_row (&m, i, &rows[i]);
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_transform_points_f2 (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
const void *points_in,
|
|
size_t stride_out,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
graphene_vec4_t rows[3];
|
|
int i;
|
|
|
|
init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point2f p = *(Point2f *)((uint8_t *)points_in + i * stride_in);
|
|
Point3f *o = (Point3f *)((uint8_t *)points_out + i * stride_out);
|
|
graphene_vec4_t point;
|
|
|
|
graphene_vec4_init (&point, p.x, p.y, 0.f, 1.f);
|
|
|
|
o->x = graphene_vec4_dot (&rows[0], &point);
|
|
o->y = graphene_vec4_dot (&rows[1], &point);
|
|
o->z = graphene_vec4_dot (&rows[2], &point);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_project_points_f2 (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
const void *points_in,
|
|
size_t stride_out,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
graphene_vec4_t rows[4];
|
|
int i;
|
|
|
|
init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point2f p = *(Point2f *)((uint8_t *)points_in + i * stride_in);
|
|
Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out);
|
|
graphene_vec4_t point;
|
|
|
|
graphene_vec4_init (&point, p.x, p.y, 0.f, 1.f);
|
|
|
|
o->x = graphene_vec4_dot (&rows[0], &point);
|
|
o->y = graphene_vec4_dot (&rows[1], &point);
|
|
o->z = graphene_vec4_dot (&rows[2], &point);
|
|
o->w = graphene_vec4_dot (&rows[3], &point);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_transform_points_f3 (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
const void *points_in,
|
|
size_t stride_out,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
graphene_vec4_t rows[3];
|
|
int i;
|
|
|
|
init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point3f p = *(Point3f *)((uint8_t *)points_in + i * stride_in);
|
|
Point3f *o = (Point3f *)((uint8_t *)points_out + i * stride_out);
|
|
graphene_vec4_t point;
|
|
|
|
graphene_vec4_init (&point, p.x, p.y, p.z, 1.f);
|
|
|
|
o->x = graphene_vec4_dot (&rows[0], &point);
|
|
o->y = graphene_vec4_dot (&rows[1], &point);
|
|
o->z = graphene_vec4_dot (&rows[2], &point);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_project_points_f3 (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
const void *points_in,
|
|
size_t stride_out,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
graphene_vec4_t rows[4];
|
|
int i;
|
|
|
|
init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point3f p = *(Point3f *)((uint8_t *)points_in + i * stride_in);
|
|
Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out);
|
|
graphene_vec4_t point;
|
|
|
|
graphene_vec4_init (&point, p.x, p.y, p.z, 1.f);
|
|
|
|
o->x = graphene_vec4_dot (&rows[0], &point);
|
|
o->y = graphene_vec4_dot (&rows[1], &point);
|
|
o->z = graphene_vec4_dot (&rows[2], &point);
|
|
o->w = graphene_vec4_dot (&rows[3], &point);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_project_points_f4 (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
const void *points_in,
|
|
size_t stride_out,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
graphene_vec4_t rows[4];
|
|
int i;
|
|
|
|
init_matrix_rows (matrix, G_N_ELEMENTS (rows), rows);
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point4f p = *(Point4f *)((uint8_t *)points_in + i * stride_in);
|
|
Point4f *o = (Point4f *)((uint8_t *)points_out + i * stride_out);
|
|
graphene_vec4_t point;
|
|
|
|
graphene_vec4_init (&point, p.x, p.y, p.z, p.w);
|
|
|
|
o->x = graphene_vec4_dot (&rows[0], &point);
|
|
o->y = graphene_vec4_dot (&rows[1], &point);
|
|
o->z = graphene_vec4_dot (&rows[2], &point);
|
|
o->w = graphene_vec4_dot (&rows[3], &point);
|
|
}
|
|
}
|
|
|
|
void
|
|
cogl_matrix_transform_points (const CoglMatrix *matrix,
|
|
int n_components,
|
|
size_t stride_in,
|
|
const void *points_in,
|
|
size_t stride_out,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
/* The results of transforming always have three components... */
|
|
g_return_if_fail (stride_out >= sizeof (Point3f));
|
|
|
|
if (n_components == 2)
|
|
_cogl_matrix_transform_points_f2 (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
else
|
|
{
|
|
g_return_if_fail (n_components == 3);
|
|
|
|
_cogl_matrix_transform_points_f3 (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
}
|
|
}
|
|
|
|
void
|
|
cogl_matrix_project_points (const CoglMatrix *matrix,
|
|
int n_components,
|
|
size_t stride_in,
|
|
const void *points_in,
|
|
size_t stride_out,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
if (n_components == 2)
|
|
_cogl_matrix_project_points_f2 (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
else if (n_components == 3)
|
|
_cogl_matrix_project_points_f3 (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
else
|
|
{
|
|
g_return_if_fail (n_components == 4);
|
|
|
|
_cogl_matrix_project_points_f4 (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
cogl_matrix_is_identity (const CoglMatrix *matrix)
|
|
{
|
|
return graphene_matrix_is_identity (&matrix->m);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_look_at (CoglMatrix *matrix,
|
|
float eye_position_x,
|
|
float eye_position_y,
|
|
float eye_position_z,
|
|
float object_x,
|
|
float object_y,
|
|
float object_z,
|
|
float world_up_x,
|
|
float world_up_y,
|
|
float world_up_z)
|
|
{
|
|
graphene_vec3_t eye;
|
|
graphene_vec3_t center;
|
|
graphene_vec3_t up;
|
|
CoglMatrix look_at;
|
|
|
|
graphene_vec3_init (&eye, eye_position_x, eye_position_y, eye_position_z);
|
|
graphene_vec3_init (¢er, object_x, object_y, object_z);
|
|
graphene_vec3_init (&up, world_up_x, world_up_y, world_up_z);
|
|
|
|
graphene_matrix_init_look_at (&look_at.m, &eye, ¢er, &up);
|
|
look_at.flags = COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
|
|
cogl_matrix_multiply (matrix, matrix, &look_at);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_transpose (CoglMatrix *matrix)
|
|
{
|
|
/* We don't need to do anything if the matrix is the identity matrix */
|
|
if (graphene_matrix_is_identity (&matrix->m))
|
|
return;
|
|
|
|
graphene_matrix_transpose (&matrix->m, &matrix->m);
|
|
}
|
|
|
|
GType
|
|
cogl_gtype_matrix_get_type (void)
|
|
{
|
|
return cogl_matrix_get_gtype ();
|
|
}
|
|
|
|
void
|
|
cogl_matrix_skew_xy (CoglMatrix *matrix,
|
|
float factor)
|
|
{
|
|
graphene_matrix_t skew;
|
|
|
|
graphene_matrix_init_identity (&skew);
|
|
graphene_matrix_skew_xy (&skew, factor);
|
|
graphene_matrix_multiply (&skew, &matrix->m, &matrix->m);
|
|
|
|
matrix->flags |= COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_skew_xz (CoglMatrix *matrix,
|
|
float factor)
|
|
{
|
|
graphene_matrix_t skew;
|
|
|
|
graphene_matrix_init_identity (&skew);
|
|
graphene_matrix_skew_xz (&skew, factor);
|
|
graphene_matrix_multiply (&skew, &matrix->m, &matrix->m);
|
|
|
|
matrix->flags |= COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_skew_yz (CoglMatrix *matrix,
|
|
float factor)
|
|
{
|
|
graphene_matrix_t skew;
|
|
|
|
graphene_matrix_init_identity (&skew);
|
|
graphene_matrix_skew_yz (&skew, factor);
|
|
graphene_matrix_multiply (&skew, &matrix->m, &matrix->m);
|
|
|
|
matrix->flags |= COGL_MATRIX_FLAG_DIRTY_INVERSE;
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
const graphene_matrix_t *
|
|
cogl_matrix_get_graphene_matrix (const CoglMatrix *matrix)
|
|
{
|
|
return &matrix->m;
|
|
}
|