d1434d1c33
This adds an experimental quaternion utility API. It's not yet fully documented but it's complete enough that people can start to experiment with using it. It adds the following functions: cogl_quaternion_init_identity cogl_quaternion_init cogl_quaternion_init_from_angle_vector cogl_quaternion_init_from_array cogl_quaternion_init_from_x_rotation cogl_quaternion_init_from_y_rotation cogl_quaternion_init_from_z_rotation cogl_quaternion_equal cogl_quaternion_copy cogl_quaternion_free cogl_quaternion_get_rotation_angle cogl_quaternion_get_rotation_axis cogl_quaternion_normalize cogl_quaternion_dot_product cogl_quaternion_invert cogl_quaternion_multiply cogl_quaternion_pow cogl_quaternion_slerp cogl_quaternion_nlerp cogl_quaternion_squad cogl_get_static_identity_quaternion cogl_get_static_zero_quaternion Since it's experimental API you'll need to define COGL_ENABLE_EXPERIMENTAL_API before including cogl.h.
683 lines
20 KiB
C
683 lines
20 KiB
C
/*
|
|
* Cogl
|
|
*
|
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
|
*
|
|
* Copyright (C) 2008,2009 Intel Corporation.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*
|
|
*
|
|
* Authors:
|
|
* Robert Bragg <robert@linux.intel.com>
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#define USE_MESA_MATRIX_API
|
|
|
|
#include <cogl.h>
|
|
#include "cogl-debug.h"
|
|
#include <cogl-quaternion.h>
|
|
#include <cogl-quaternion-private.h>
|
|
#include <cogl-matrix.h>
|
|
#include <cogl-matrix-private.h>
|
|
#ifdef USE_MESA_MATRIX_API
|
|
#include <cogl-matrix-mesa.h>
|
|
#endif
|
|
|
|
#include <glib.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
#ifdef _COGL_SUPPORTS_GTYPE_INTEGRATION
|
|
#include <cogl-gtype-private.h>
|
|
COGL_GTYPE_DEFINE_BOXED ("Matrix", matrix,
|
|
cogl_matrix_copy,
|
|
cogl_matrix_free);
|
|
#endif
|
|
|
|
void
|
|
_cogl_matrix_print (CoglMatrix *matrix)
|
|
{
|
|
float *m = (float *)matrix;
|
|
int y;
|
|
|
|
for (y = 0; y < 4; y++)
|
|
g_print ("\t%6.4f %6.4f %6.4f %6.4f\n", m[y], m[4+y], m[8+y], m[12+y]);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_init_identity (CoglMatrix *matrix)
|
|
{
|
|
#ifndef USE_MESA_MATRIX_API
|
|
matrix->xx = 1; matrix->xy = 0; matrix->xz = 0; matrix->xw = 0;
|
|
matrix->yx = 0; matrix->yy = 1; matrix->yz = 0; matrix->yw = 0;
|
|
matrix->zx = 0; matrix->zy = 0; matrix->zz = 1; matrix->zw = 0;
|
|
matrix->wx = 0; matrix->wy = 0; matrix->wz = 0; matrix->ww = 1;
|
|
#else
|
|
_math_matrix_init_identity (matrix);
|
|
#endif
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_init_from_quaternion (CoglMatrix *matrix,
|
|
CoglQuaternion *quaternion)
|
|
{
|
|
_math_matrix_init_from_quaternion (matrix, quaternion);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_multiply (CoglMatrix *result,
|
|
const CoglMatrix *a,
|
|
const CoglMatrix *b)
|
|
{
|
|
#ifndef USE_MESA_MATRIX_API
|
|
CoglMatrix r;
|
|
|
|
/* row 0 */
|
|
r.xx = a->xx * b->xx + a->xy * b->yx + a->xz * b->zx + a->xw * b->wx;
|
|
r.xy = a->xx * b->xy + a->xy * b->yy + a->xz * b->zy + a->xw * b->wy;
|
|
r.xz = a->xx * b->xz + a->xy * b->yz + a->xz * b->zz + a->xw * b->wz;
|
|
r.xw = a->xx * b->xw + a->xy * b->yw + a->xz * b->zw + a->xw * b->ww;
|
|
|
|
/* row 1 */
|
|
r.yx = a->yx * b->xx + a->yy * b->yx + a->yz * b->zx + a->yw * b->wx;
|
|
r.yy = a->yx * b->xy + a->yy * b->yy + a->yz * b->zy + a->yw * b->wy;
|
|
r.yz = a->yx * b->xz + a->yy * b->yz + a->yz * b->zz + a->yw * b->wz;
|
|
r.yw = a->yx * b->xw + a->yy * b->yw + a->yz * b->zw + a->yw * b->ww;
|
|
|
|
/* row 2 */
|
|
r.zx = a->zx * b->xx + a->zy * b->yx + a->zz * b->zx + a->zw * b->wx;
|
|
r.zy = a->zx * b->xy + a->zy * b->yy + a->zz * b->zy + a->zw * b->wy;
|
|
r.zz = a->zx * b->xz + a->zy * b->yz + a->zz * b->zz + a->zw * b->wz;
|
|
r.zw = a->zx * b->xw + a->zy * b->yw + a->zz * b->zw + a->zw * b->ww;
|
|
|
|
/* row 3 */
|
|
r.wx = a->wx * b->xx + a->wy * b->yx + a->wz * b->zx + a->ww * b->wx;
|
|
r.wy = a->wx * b->xy + a->wy * b->yy + a->wz * b->zy + a->ww * b->wy;
|
|
r.wz = a->wx * b->xz + a->wy * b->yz + a->wz * b->zz + a->ww * b->wz;
|
|
r.ww = a->wx * b->xw + a->wy * b->yw + a->wz * b->zw + a->ww * b->ww;
|
|
|
|
/* The idea was that having this unrolled; it might be easier for the
|
|
* compiler to vectorize, but that's probably not true. Mesa does it
|
|
* using a single for (i=0; i<4; i++) approach, maybe that's better...
|
|
*/
|
|
|
|
*result = r;
|
|
#else
|
|
_math_matrix_multiply (result, a, b);
|
|
#endif
|
|
_COGL_MATRIX_DEBUG_PRINT (result);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_rotate (CoglMatrix *matrix,
|
|
float angle,
|
|
float x,
|
|
float y,
|
|
float z)
|
|
{
|
|
#ifndef USE_MESA_MATRIX_API
|
|
CoglMatrix rotation;
|
|
CoglMatrix result;
|
|
float c, s;
|
|
|
|
angle *= G_PI / 180.0f;
|
|
c = cosf (angle);
|
|
s = sinf (angle);
|
|
|
|
rotation.xx = x * x * (1.0f - c) + c;
|
|
rotation.yx = y * x * (1.0f - c) + z * s;
|
|
rotation.zx = x * z * (1.0f - c) - y * s;
|
|
rotation.wx = 0.0f;
|
|
|
|
rotation.xy = x * y * (1.0f - c) - z * s;
|
|
rotation.yy = y * y * (1.0f - c) + c;
|
|
rotation.zy = y * z * (1.0f - c) + x * s;
|
|
rotation.wy = 0.0f;
|
|
|
|
rotation.xz = x * z * (1.0f - c) + y * s;
|
|
rotation.yz = y * z * (1.0f - c) - x * s;
|
|
rotation.zz = z * z * (1.0f - c) + c;
|
|
rotation.wz = 0.0f;
|
|
|
|
rotation.xw = 0.0f;
|
|
rotation.yw = 0.0f;
|
|
rotation.zw = 0.0f;
|
|
rotation.ww = 1.0f;
|
|
|
|
cogl_matrix_multiply (&result, matrix, &rotation);
|
|
*matrix = result;
|
|
#else
|
|
_math_matrix_rotate (matrix, angle, x, y, z);
|
|
#endif
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_translate (CoglMatrix *matrix,
|
|
float x,
|
|
float y,
|
|
float z)
|
|
{
|
|
#ifndef USE_MESA_MATRIX_API
|
|
matrix->xw = matrix->xx * x + matrix->xy * y + matrix->xz * z + matrix->xw;
|
|
matrix->yw = matrix->yx * x + matrix->yy * y + matrix->yz * z + matrix->yw;
|
|
matrix->zw = matrix->zx * x + matrix->zy * y + matrix->zz * z + matrix->zw;
|
|
matrix->ww = matrix->wx * x + matrix->wy * y + matrix->wz * z + matrix->ww;
|
|
#else
|
|
_math_matrix_translate (matrix, x, y, z);
|
|
#endif
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_scale (CoglMatrix *matrix,
|
|
float sx,
|
|
float sy,
|
|
float sz)
|
|
{
|
|
#ifndef USE_MESA_MATRIX_API
|
|
matrix->xx *= sx; matrix->xy *= sy; matrix->xz *= sz;
|
|
matrix->yx *= sx; matrix->yy *= sy; matrix->yz *= sz;
|
|
matrix->zx *= sx; matrix->zy *= sy; matrix->zz *= sz;
|
|
matrix->wx *= sx; matrix->wy *= sy; matrix->wz *= sz;
|
|
#else
|
|
_math_matrix_scale (matrix, sx, sy, sz);
|
|
#endif
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_frustum (CoglMatrix *matrix,
|
|
float left,
|
|
float right,
|
|
float bottom,
|
|
float top,
|
|
float z_near,
|
|
float z_far)
|
|
{
|
|
#ifndef USE_MESA_MATRIX_API
|
|
float x, y, a, b, c, d;
|
|
CoglMatrix frustum;
|
|
|
|
x = (2.0f * z_near) / (right - left);
|
|
y = (2.0f * z_near) / (top - bottom);
|
|
a = (right + left) / (right - left);
|
|
b = (top + bottom) / (top - bottom);
|
|
c = -(z_far + z_near) / ( z_far - z_near);
|
|
d = -(2.0f * z_far* z_near) / (z_far - z_near);
|
|
|
|
frustum.xx = x;
|
|
frustum.yx = 0.0f;
|
|
frustum.zx = 0.0f;
|
|
frustum.wx = 0.0f;
|
|
|
|
frustum.xy = 0.0f;
|
|
frustum.yy = y;
|
|
frustum.zy = 0.0f;
|
|
frustum.wy = 0.0f;
|
|
|
|
frustum.xz = a;
|
|
frustum.yz = b;
|
|
frustum.zz = c;
|
|
frustum.wz = -1.0f;
|
|
|
|
frustum.xw = 0.0f;
|
|
frustum.yw = 0.0f;
|
|
frustum.zw = d;
|
|
frustum.ww = 0.0f;
|
|
|
|
cogl_matrix_multiply (matrix, matrix, &frustum);
|
|
#else
|
|
_math_matrix_frustum (matrix, left, right, bottom, top, z_near, z_far);
|
|
#endif
|
|
_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_ortho (CoglMatrix *matrix,
|
|
float left,
|
|
float right,
|
|
float bottom,
|
|
float top,
|
|
float near_val,
|
|
float far_val)
|
|
{
|
|
#ifndef USE_MESA_MATRIX_API
|
|
CoglMatrix ortho;
|
|
|
|
/* column 0 */
|
|
ortho.xx = 2.0 / (right - left);
|
|
ortho.yx = 0.0;
|
|
ortho.zx = 0.0;
|
|
ortho.wx = 0.0;
|
|
|
|
/* column 1 */
|
|
ortho.xy = 0.0;
|
|
ortho.yy = 2.0 / (top - bottom);
|
|
ortho.zy = 0.0;
|
|
ortho.wy = 0.0;
|
|
|
|
/* column 2 */
|
|
ortho.xz = 0.0;
|
|
ortho.yz = 0.0;
|
|
ortho.zz = -2.0 / (far_val - near_val);
|
|
ortho.wz = 0.0;
|
|
|
|
/* column 3 */
|
|
ortho.xw = -(right + left) / (right - left);
|
|
ortho.yw = -(top + bottom) / (top - bottom);
|
|
ortho.zw = -(far_val + near_val) / (far_val - near_val);
|
|
ortho.ww = 1.0;
|
|
|
|
cogl_matrix_multiply (matrix, matrix, &ortho);
|
|
#else
|
|
_math_matrix_ortho (matrix, left, right, bottom, top, near_val, far_val);
|
|
#endif
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void
|
|
cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array)
|
|
{
|
|
#ifndef USE_MESA_MATRIX_API
|
|
memcpy (matrix, array, sizeof (float) * 16);
|
|
#else
|
|
_math_matrix_init_from_array (matrix, array);
|
|
#endif
|
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
|
}
|
|
|
|
gboolean
|
|
cogl_matrix_equal (gconstpointer v1, gconstpointer 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);
|
|
|
|
/* We want to avoid having a fuzzy _equal() function (e.g. that uses
|
|
* an arbitrary epsilon value) since this function noteably conforms
|
|
* to the prototype suitable for use with g_hash_table_new() and a
|
|
* fuzzy hash function isn't really appropriate for comparing hash
|
|
* table keys since it's possible that you could end up fetching
|
|
* different values if you end up with multiple similar keys in use
|
|
* at the same time. If you consider that fuzzyness allows cases
|
|
* such as A == B == C but A != C then you could also end up loosing
|
|
* values in a hash table.
|
|
*
|
|
* We do at least use the == operator to compare values though so
|
|
* that -0 is considered equal to 0.
|
|
*/
|
|
|
|
/* XXX: We don't compare the flags, inverse matrix or padding */
|
|
if (a->xx == b->xx &&
|
|
a->xy == b->xy &&
|
|
a->xz == b->xz &&
|
|
a->xw == b->xw &&
|
|
a->yx == b->yx &&
|
|
a->yy == b->yy &&
|
|
a->yz == b->yz &&
|
|
a->yw == b->yw &&
|
|
a->zx == b->zx &&
|
|
a->zy == b->zy &&
|
|
a->zz == b->zz &&
|
|
a->zw == b->zw &&
|
|
a->wx == b->wx &&
|
|
a->wy == b->wy &&
|
|
a->wz == b->wz &&
|
|
a->ww == b->ww)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
const float *
|
|
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,
|
|
float *y,
|
|
float *z,
|
|
float *w)
|
|
{
|
|
float _x = *x, _y = *y, _z = *z, _w = *w;
|
|
|
|
*x = matrix->xx * _x + matrix->xy * _y + matrix->xz * _z + matrix->xw * _w;
|
|
*y = matrix->yx * _x + matrix->yy * _y + matrix->yz * _z + matrix->yw * _w;
|
|
*z = matrix->zx * _x + matrix->zy * _y + matrix->zz * _z + matrix->zw * _w;
|
|
*w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w;
|
|
}
|
|
|
|
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
|
|
_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)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point2f p = *(Point2f *)((guint8 *)points_in + i * stride_in);
|
|
Point3f *o = (Point3f *)((guint8 *)points_out + i * stride_out);
|
|
|
|
o->x = matrix->xx * p.x + matrix->xy * p.y + matrix->xw;
|
|
o->y = matrix->yx * p.x + matrix->yy * p.y + matrix->yw;
|
|
o->z = matrix->zx * p.x + matrix->zy * p.y + matrix->zw;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point2f p = *(Point2f *)((guint8 *)points_in + i * stride_in);
|
|
Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
|
|
|
|
o->x = matrix->xx * p.x + matrix->xy * p.y + matrix->xw;
|
|
o->y = matrix->yx * p.x + matrix->yy * p.y + matrix->yw;
|
|
o->z = matrix->zx * p.x + matrix->zy * p.y + matrix->zw;
|
|
o->w = matrix->wx * p.x + matrix->wy * p.y + matrix->ww;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point3f p = *(Point3f *)((guint8 *)points_in + i * stride_in);
|
|
Point3f *o = (Point3f *)((guint8 *)points_out + i * stride_out);
|
|
|
|
o->x = matrix->xx * p.x + matrix->xy * p.y +
|
|
matrix->xz * p.z + matrix->xw;
|
|
o->y = matrix->yx * p.x + matrix->yy * p.y +
|
|
matrix->yz * p.z + matrix->yw;
|
|
o->z = matrix->zx * p.x + matrix->zy * p.y +
|
|
matrix->zz * p.z + matrix->zw;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point3f p = *(Point3f *)((guint8 *)points_in + i * stride_in);
|
|
Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
|
|
|
|
o->x = matrix->xx * p.x + matrix->xy * p.y +
|
|
matrix->xz * p.z + matrix->xw;
|
|
o->y = matrix->yx * p.x + matrix->yy * p.y +
|
|
matrix->yz * p.z + matrix->yw;
|
|
o->z = matrix->zx * p.x + matrix->zy * p.y +
|
|
matrix->zz * p.z + matrix->zw;
|
|
o->w = matrix->wx * p.x + matrix->wy * p.y +
|
|
matrix->wz * p.z + matrix->ww;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point4f p = *(Point4f *)((guint8 *)points_in + i * stride_in);
|
|
Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
|
|
|
|
o->x = matrix->xx * p.x + matrix->xy * p.y +
|
|
matrix->xz * p.z + matrix->xw * p.w;
|
|
o->y = matrix->yx * p.x + matrix->yy * p.y +
|
|
matrix->yz * p.z + matrix->yw * p.w;
|
|
o->z = matrix->zx * p.x + matrix->zy * p.y +
|
|
matrix->zz * p.z + matrix->zw * p.w;
|
|
o->w = matrix->wx * p.x + matrix->wy * p.y +
|
|
matrix->wz * p.z + matrix->ww * p.w;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|