3e42af2a00
Both cogl_matrix_transform_points and _project_points take points_in and points_out arguments and explicitly allow pointing to the same array (i.e. to transform in-place) The implementation of the various internal transform functions though were not handling this possability and so it was possible the reference partially transformed vertex values as if they were original input values leading to incorrect results. This patch ensures we take a temporary copy of the current input point when transforming.
763 lines
23 KiB
C
763 lines
23 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-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_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_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_packed (const CoglMatrix *matrix,
|
|
void *points_in,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
Point3f *o = points_out;
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point2f p = ((Point2f *)points_in)[i];
|
|
o[i].x = matrix->xx * p.x + matrix->xy * p.y +
|
|
matrix->xw;
|
|
o[i].y = matrix->yx * p.x + matrix->yy * p.y +
|
|
matrix->yw;
|
|
o[i].z = matrix->zx * p.x + matrix->zy * p.y +
|
|
matrix->zw;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_transform_points_f2_strided (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
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_packed (const CoglMatrix *matrix,
|
|
void *points_in,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
Point4f *o = points_out;
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point2f p = ((Point2f *)points_in)[i];
|
|
o[i].x = matrix->xx * p.x + matrix->xy * p.y +
|
|
matrix->xw;
|
|
o[i].y = matrix->yx * p.x + matrix->yy * p.y +
|
|
matrix->yw;
|
|
o[i].z = matrix->zx * p.x + matrix->zy * p.y +
|
|
matrix->zw;
|
|
o[i].w = matrix->wx * p.x + matrix->wy * p.y +
|
|
matrix->ww;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_project_points_f2_strided (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
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_packed (const CoglMatrix *matrix,
|
|
void *points_in,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
Point3f *o = points_out;
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point3f p = ((Point3f *)points_in)[i];
|
|
o[i].x = matrix->xx * p.x + matrix->xy * p.y +
|
|
matrix->xz * p.z + matrix->xw;
|
|
o[i].y = matrix->yx * p.x + matrix->yy * p.y +
|
|
matrix->yz * p.z + matrix->yw;
|
|
o[i].z = matrix->zx * p.x + matrix->zy * p.y +
|
|
matrix->zz * p.z + matrix->zw;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_transform_points_f3_strided (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
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_packed (const CoglMatrix *matrix,
|
|
void *points_in,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
Point4f *o = points_out;
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point3f p = ((Point3f *)points_in)[i];
|
|
o[i].x = matrix->xx * p.x + matrix->xy * p.y +
|
|
matrix->xz * p.z + matrix->xw;
|
|
o[i].y = matrix->yx * p.x + matrix->yy * p.y +
|
|
matrix->yz * p.z + matrix->yw;
|
|
o[i].z = matrix->zx * p.x + matrix->zy * p.y +
|
|
matrix->zz * p.z + matrix->zw;
|
|
o[i].w = matrix->wx * p.x + matrix->wy * p.y +
|
|
matrix->wz * p.z + matrix->ww;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_project_points_f3_strided (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
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_packed (const CoglMatrix *matrix,
|
|
void *points_in,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
Point4f *o = points_out;
|
|
int i;
|
|
|
|
for (i = 0; i < n_points; i++)
|
|
{
|
|
Point4f p = ((Point4f *)points_in)[i];
|
|
o[i].x = matrix->xx * p.x + matrix->xy * p.y +
|
|
matrix->xz * p.z + matrix->xw * p.w;
|
|
o[i].y = matrix->yx * p.x + matrix->yy * p.y +
|
|
matrix->yz * p.z + matrix->yw * p.w;
|
|
o[i].z = matrix->zx * p.x + matrix->zy * p.y +
|
|
matrix->zz * p.z + matrix->zw * p.w;
|
|
o[i].w = matrix->wx * p.x + matrix->wy * p.y +
|
|
matrix->wz * p.z + matrix->ww * p.w;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cogl_matrix_project_points_f4_strided (const CoglMatrix *matrix,
|
|
size_t stride_in,
|
|
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,
|
|
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)
|
|
{
|
|
if (stride_in == sizeof (Point2f) &&
|
|
stride_out == sizeof (Point3f))
|
|
_cogl_matrix_transform_points_f2_packed (matrix,
|
|
points_in, points_out,
|
|
n_points);
|
|
else
|
|
_cogl_matrix_transform_points_f2_strided (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
}
|
|
else
|
|
{
|
|
g_return_if_fail (n_components == 3);
|
|
|
|
if (stride_in == sizeof (Point3f) && stride_out == stride_in)
|
|
_cogl_matrix_transform_points_f3_packed (matrix,
|
|
points_in, points_out,
|
|
n_points);
|
|
else
|
|
_cogl_matrix_transform_points_f3_strided (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,
|
|
void *points_in,
|
|
size_t stride_out,
|
|
void *points_out,
|
|
int n_points)
|
|
{
|
|
if (n_components == 2)
|
|
{
|
|
if (stride_in == sizeof (Point2f) &&
|
|
stride_out == sizeof (Point4f))
|
|
_cogl_matrix_project_points_f2_packed (matrix,
|
|
points_in, points_out,
|
|
n_points);
|
|
else
|
|
_cogl_matrix_project_points_f2_strided (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
}
|
|
else if (n_components == 3)
|
|
{
|
|
if (stride_in == sizeof (Point3f) &&
|
|
stride_out == sizeof (Point4f))
|
|
_cogl_matrix_project_points_f3_packed (matrix,
|
|
points_in, points_out,
|
|
n_points);
|
|
else
|
|
_cogl_matrix_project_points_f3_strided (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
}
|
|
else
|
|
{
|
|
g_return_if_fail (n_components == 4);
|
|
|
|
if (stride_in == sizeof (Point4f) && stride_out == stride_in)
|
|
_cogl_matrix_project_points_f4_packed (matrix,
|
|
points_in, points_out,
|
|
n_points);
|
|
else
|
|
_cogl_matrix_project_points_f4_strided (matrix,
|
|
stride_in, points_in,
|
|
stride_out, points_out,
|
|
n_points);
|
|
}
|
|
}
|
|
|