mirror of
https://github.com/brl/mutter.git
synced 2024-11-28 11:00:54 -05:00
Replace CoglQuaternion by graphene_quaternion_t
Same story, but smaller damage area. CoglQuaternion was used in fewer places than CoglEuler, resulting in a smaller patch. https://gitlab.gnome.org/GNOME/mutter/merge_requests/458
This commit is contained in:
parent
4a4a423182
commit
41a03f0589
@ -1603,7 +1603,7 @@ cogl_framebuffer_rotate (CoglFramebuffer *framebuffer,
|
||||
|
||||
void
|
||||
cogl_framebuffer_rotate_quaternion (CoglFramebuffer *framebuffer,
|
||||
const CoglQuaternion *quaternion)
|
||||
const graphene_quaternion_t *quaternion)
|
||||
{
|
||||
CoglMatrixStack *modelview_stack =
|
||||
_cogl_framebuffer_get_modelview_stack (framebuffer);
|
||||
|
@ -51,7 +51,6 @@ typedef struct _CoglFramebuffer CoglFramebuffer;
|
||||
#include <cogl/cogl-pipeline.h>
|
||||
#include <cogl/cogl-indices.h>
|
||||
#include <cogl/cogl-bitmap.h>
|
||||
#include <cogl/cogl-quaternion.h>
|
||||
#include <cogl/cogl-texture.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
@ -365,7 +364,7 @@ cogl_framebuffer_rotate (CoglFramebuffer *framebuffer,
|
||||
/**
|
||||
* cogl_framebuffer_rotate_quaternion:
|
||||
* @framebuffer: A #CoglFramebuffer pointer
|
||||
* @quaternion: A #CoglQuaternion
|
||||
* @quaternion: A #graphene_quaternion_t
|
||||
*
|
||||
* Multiplies the current model-view matrix by one that rotates
|
||||
* according to the rotation described by @quaternion.
|
||||
@ -375,7 +374,7 @@ cogl_framebuffer_rotate (CoglFramebuffer *framebuffer,
|
||||
*/
|
||||
void
|
||||
cogl_framebuffer_rotate_quaternion (CoglFramebuffer *framebuffer,
|
||||
const CoglQuaternion *quaternion);
|
||||
const graphene_quaternion_t *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_framebuffer_rotate_euler:
|
||||
|
@ -97,9 +97,7 @@ typedef struct _CoglMatrixEntryRotateQuaternion
|
||||
{
|
||||
CoglMatrixEntry _parent_data;
|
||||
|
||||
/* This doesn't store an actual CoglQuaternion in order to avoid the
|
||||
* padding */
|
||||
float values[4];
|
||||
graphene_quaternion_t quaternion;
|
||||
} CoglMatrixEntryRotateQuaternion;
|
||||
|
||||
typedef struct _CoglMatrixEntryScale
|
||||
|
@ -182,17 +182,13 @@ cogl_matrix_stack_rotate (CoglMatrixStack *stack,
|
||||
|
||||
void
|
||||
cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack,
|
||||
const CoglQuaternion *quaternion)
|
||||
const graphene_quaternion_t *quaternion)
|
||||
{
|
||||
CoglMatrixEntryRotateQuaternion *entry;
|
||||
|
||||
entry = _cogl_matrix_stack_push_operation (stack,
|
||||
COGL_MATRIX_OP_ROTATE_QUATERNION);
|
||||
|
||||
entry->values[0] = quaternion->w;
|
||||
entry->values[1] = quaternion->x;
|
||||
entry->values[2] = quaternion->y;
|
||||
entry->values[3] = quaternion->z;
|
||||
graphene_quaternion_init_from_quaternion (&entry->quaternion, quaternion);
|
||||
}
|
||||
|
||||
void
|
||||
@ -585,9 +581,7 @@ initialized:
|
||||
{
|
||||
CoglMatrixEntryRotateQuaternion *rotate =
|
||||
(CoglMatrixEntryRotateQuaternion *)children[i];
|
||||
CoglQuaternion quaternion;
|
||||
cogl_quaternion_init_from_array (&quaternion, rotate->values);
|
||||
cogl_matrix_rotate_quaternion (matrix, &quaternion);
|
||||
cogl_matrix_rotate_quaternion (matrix, &rotate->quaternion);
|
||||
continue;
|
||||
}
|
||||
case COGL_MATRIX_OP_SCALE:
|
||||
@ -987,9 +981,8 @@ cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
|
||||
(CoglMatrixEntryRotateQuaternion *)entry0;
|
||||
CoglMatrixEntryRotateQuaternion *rotate1 =
|
||||
(CoglMatrixEntryRotateQuaternion *)entry1;
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (rotate0->values[i] != rotate1->values[i])
|
||||
if (!graphene_quaternion_equal (&rotate0->quaternion,
|
||||
&rotate1->quaternion))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
@ -1096,11 +1089,13 @@ cogl_debug_matrix_entry_print (CoglMatrixEntry *entry)
|
||||
{
|
||||
CoglMatrixEntryRotateQuaternion *rotate =
|
||||
(CoglMatrixEntryRotateQuaternion *)entry;
|
||||
graphene_vec4_t v;
|
||||
graphene_quaternion_to_vec4 (&rotate->quaternion, &v);
|
||||
g_print (" ROTATE QUATERNION w=%f x=%f y=%f z=%f\n",
|
||||
rotate->values[0],
|
||||
rotate->values[1],
|
||||
rotate->values[2],
|
||||
rotate->values[3]);
|
||||
graphene_vec4_get_w (&v),
|
||||
graphene_vec4_get_x (&v),
|
||||
graphene_vec4_get_y (&v),
|
||||
graphene_vec4_get_z (&v));
|
||||
continue;
|
||||
}
|
||||
case COGL_MATRIX_OP_ROTATE_EULER:
|
||||
|
@ -310,14 +310,14 @@ cogl_matrix_stack_rotate (CoglMatrixStack *stack,
|
||||
/**
|
||||
* cogl_matrix_stack_rotate_quaternion:
|
||||
* @stack: A #CoglMatrixStack
|
||||
* @quaternion: A #CoglQuaternion
|
||||
* @quaternion: A #graphene_quaternion_t
|
||||
*
|
||||
* Multiplies the current matrix by one that rotates according to the
|
||||
* rotation described by @quaternion.
|
||||
*/
|
||||
void
|
||||
cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack,
|
||||
const CoglQuaternion *quaternion);
|
||||
const graphene_quaternion_t *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_matrix_stack_rotate_euler:
|
||||
|
@ -73,11 +73,9 @@
|
||||
|
||||
#include <cogl-util.h>
|
||||
#include <cogl-debug.h>
|
||||
#include <cogl-quaternion.h>
|
||||
#include <cogl-quaternion-private.h>
|
||||
#include <cogl-matrix.h>
|
||||
#include <cogl-matrix-private.h>
|
||||
#include <cogl-quaternion-private.h>
|
||||
#include <cogl-vector.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <math.h>
|
||||
@ -1360,7 +1358,7 @@ cogl_matrix_rotate (CoglMatrix *matrix,
|
||||
|
||||
void
|
||||
cogl_matrix_rotate_quaternion (CoglMatrix *matrix,
|
||||
const CoglQuaternion *quaternion)
|
||||
const graphene_quaternion_t *quaternion)
|
||||
{
|
||||
CoglMatrix rotation_transform;
|
||||
|
||||
@ -1737,22 +1735,25 @@ _cogl_matrix_init_from_matrix_without_inverse (CoglMatrix *matrix,
|
||||
|
||||
static void
|
||||
_cogl_matrix_init_from_quaternion (CoglMatrix *matrix,
|
||||
const CoglQuaternion *quaternion)
|
||||
const graphene_quaternion_t *quaternion)
|
||||
{
|
||||
float qnorm = _COGL_QUATERNION_NORM (quaternion);
|
||||
graphene_vec4_t quaternion_v;
|
||||
graphene_quaternion_to_vec4 (quaternion, &quaternion_v);
|
||||
|
||||
float qnorm = graphene_quaternion_dot (quaternion, quaternion);
|
||||
float s = (qnorm > 0.0f) ? (2.0f / qnorm) : 0.0f;
|
||||
float xs = quaternion->x * s;
|
||||
float ys = quaternion->y * s;
|
||||
float zs = quaternion->z * s;
|
||||
float wx = quaternion->w * xs;
|
||||
float wy = quaternion->w * ys;
|
||||
float wz = quaternion->w * zs;
|
||||
float xx = quaternion->x * xs;
|
||||
float xy = quaternion->x * ys;
|
||||
float xz = quaternion->x * zs;
|
||||
float yy = quaternion->y * ys;
|
||||
float yz = quaternion->y * zs;
|
||||
float zz = quaternion->z * zs;
|
||||
float xs = graphene_vec4_get_x (&quaternion_v) * s;
|
||||
float ys = graphene_vec4_get_y (&quaternion_v) * s;
|
||||
float zs = graphene_vec4_get_z (&quaternion_v) * s;
|
||||
float wx = graphene_vec4_get_w (&quaternion_v) * xs;
|
||||
float wy = graphene_vec4_get_w (&quaternion_v) * ys;
|
||||
float wz = graphene_vec4_get_w (&quaternion_v) * zs;
|
||||
float xx = graphene_vec4_get_x (&quaternion_v) * xs;
|
||||
float xy = graphene_vec4_get_x (&quaternion_v) * ys;
|
||||
float xz = graphene_vec4_get_x (&quaternion_v) * zs;
|
||||
float yy = graphene_vec4_get_y (&quaternion_v) * ys;
|
||||
float yz = graphene_vec4_get_y (&quaternion_v) * zs;
|
||||
float zz = graphene_vec4_get_z (&quaternion_v) * zs;
|
||||
|
||||
matrix->xx = 1.0f - (yy + zz);
|
||||
matrix->yx = xy + wz;
|
||||
@ -1772,7 +1773,7 @@ _cogl_matrix_init_from_quaternion (CoglMatrix *matrix,
|
||||
|
||||
void
|
||||
cogl_matrix_init_from_quaternion (CoglMatrix *matrix,
|
||||
const CoglQuaternion *quaternion)
|
||||
const graphene_quaternion_t *quaternion)
|
||||
{
|
||||
_cogl_matrix_init_from_quaternion (matrix, quaternion);
|
||||
}
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include <cogl/cogl-types.h>
|
||||
#include <cogl/cogl-macros.h>
|
||||
|
||||
#include <cogl/cogl-quaternion.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <graphene.h>
|
||||
@ -204,13 +203,13 @@ cogl_matrix_rotate (CoglMatrix *matrix,
|
||||
* @quaternion: A quaternion describing a rotation
|
||||
*
|
||||
* Multiplies @matrix with a rotation transformation described by the
|
||||
* given #CoglQuaternion.
|
||||
* given #graphene_quaternion_t.
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_matrix_rotate_quaternion (CoglMatrix *matrix,
|
||||
const CoglQuaternion *quaternion);
|
||||
const graphene_quaternion_t *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_matrix_rotate_euler:
|
||||
@ -520,13 +519,13 @@ cogl_matrix_get_array (const CoglMatrix *matrix);
|
||||
/**
|
||||
* cogl_matrix_init_from_quaternion:
|
||||
* @matrix: A 4x4 transformation matrix
|
||||
* @quaternion: A #CoglQuaternion
|
||||
* @quaternion: A #graphene_quaternion_t
|
||||
*
|
||||
* Initializes @matrix from a #CoglQuaternion rotation.
|
||||
* Initializes @matrix from a #graphene_quaternion_t rotation.
|
||||
*/
|
||||
void
|
||||
cogl_matrix_init_from_quaternion (CoglMatrix *matrix,
|
||||
const CoglQuaternion *quaternion);
|
||||
const graphene_quaternion_t *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_matrix_init_from_euler:
|
||||
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* A Low Level GPU Graphics and Utilities API
|
||||
*
|
||||
* Copyright (C) 2008,2009 Intel Corporation.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef __COGL_QUATERNION_PRIVATE_H__
|
||||
#define __COGL_QUATERNION_PRIVATE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* squared length */
|
||||
#define _COGL_QUATERNION_NORM(Q) \
|
||||
((Q)->x*(Q)->x + (Q)->y*(Q)->y + (Q)->z*(Q)->z + (Q)->w*(Q)->w)
|
||||
|
||||
#define _COGL_QUATERNION_DEGREES_TO_RADIANS (G_PI / 180.0f)
|
||||
#define _COGL_QUATERNION_RADIANS_TO_DEGREES (180.0f / G_PI)
|
||||
|
||||
#endif /* __COGL_QUATERNION_PRIVATE_H__ */
|
@ -1,670 +0,0 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* A Low Level GPU Graphics and Utilities API
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
* Various references relating to quaternions:
|
||||
*
|
||||
* http://www.cs.caltech.edu/courses/cs171/quatut.pdf
|
||||
* http://mathworld.wolfram.com/Quaternion.html
|
||||
* http://www.gamedev.net/reference/articles/article1095.asp
|
||||
* http://www.cprogramming.com/tutorial/3d/quaternions.html
|
||||
* http://www.isner.com/tutorials/quatSpells/quaternion_spells_12.htm
|
||||
* http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
|
||||
* 3D Maths Primer for Graphics and Game Development ISBN-10: 1556229119
|
||||
*/
|
||||
|
||||
#include "cogl-config.h"
|
||||
|
||||
#include <cogl-util.h>
|
||||
#include <cogl-quaternion.h>
|
||||
#include <cogl-quaternion-private.h>
|
||||
#include <cogl-matrix.h>
|
||||
#include <cogl-vector.h>
|
||||
#include "cogl-gtype-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define FLOAT_EPSILON 1e-03
|
||||
|
||||
COGL_GTYPE_DEFINE_BOXED (Quaternion, quaternion,
|
||||
cogl_quaternion_copy,
|
||||
cogl_quaternion_free);
|
||||
|
||||
static CoglQuaternion zero_quaternion =
|
||||
{
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
};
|
||||
|
||||
static CoglQuaternion identity_quaternion =
|
||||
{
|
||||
1.0, 0.0, 0.0, 0.0,
|
||||
};
|
||||
|
||||
/* This function is just here to be called from GDB so we don't really
|
||||
want to put a declaration in a header and we just add it here to
|
||||
avoid a warning */
|
||||
void
|
||||
_cogl_quaternion_print (CoglQuaternion *quarternion);
|
||||
|
||||
void
|
||||
_cogl_quaternion_print (CoglQuaternion *quaternion)
|
||||
{
|
||||
g_print ("[ %6.4f (%6.4f, %6.4f, %6.4f)]\n",
|
||||
quaternion->w,
|
||||
quaternion->x,
|
||||
quaternion->y,
|
||||
quaternion->z);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init (CoglQuaternion *quaternion,
|
||||
float angle,
|
||||
float x,
|
||||
float y,
|
||||
float z)
|
||||
{
|
||||
float axis[3] = { x, y, z};
|
||||
cogl_quaternion_init_from_angle_vector (quaternion, angle, axis);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init_from_angle_vector (CoglQuaternion *quaternion,
|
||||
float angle,
|
||||
const float *axis3f_in)
|
||||
{
|
||||
/* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair
|
||||
* in this form:
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
*/
|
||||
float axis[3];
|
||||
float half_angle;
|
||||
float sin_half_angle;
|
||||
|
||||
/* XXX: Should we make cogl_vector3_normalize have separate in and
|
||||
* out args? */
|
||||
axis[0] = axis3f_in[0];
|
||||
axis[1] = axis3f_in[1];
|
||||
axis[2] = axis3f_in[2];
|
||||
cogl_vector3_normalize (axis);
|
||||
|
||||
half_angle = angle * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f;
|
||||
sin_half_angle = sinf (half_angle);
|
||||
|
||||
quaternion->w = cosf (half_angle);
|
||||
|
||||
quaternion->x = axis[0] * sin_half_angle;
|
||||
quaternion->y = axis[1] * sin_half_angle;
|
||||
quaternion->z = axis[2] * sin_half_angle;
|
||||
|
||||
cogl_quaternion_normalize (quaternion);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init_identity (CoglQuaternion *quaternion)
|
||||
{
|
||||
quaternion->w = 1.0;
|
||||
|
||||
quaternion->x = 0.0;
|
||||
quaternion->y = 0.0;
|
||||
quaternion->z = 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init_from_array (CoglQuaternion *quaternion,
|
||||
const float *array)
|
||||
{
|
||||
quaternion->w = array[0];
|
||||
quaternion->x = array[1];
|
||||
quaternion->y = array[2];
|
||||
quaternion->z = array[3];
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init_from_x_rotation (CoglQuaternion *quaternion,
|
||||
float angle)
|
||||
{
|
||||
/* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair
|
||||
* in this form:
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
*/
|
||||
float half_angle = angle * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f;
|
||||
|
||||
quaternion->w = cosf (half_angle);
|
||||
|
||||
quaternion->x = sinf (half_angle);
|
||||
quaternion->y = 0.0f;
|
||||
quaternion->z = 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init_from_y_rotation (CoglQuaternion *quaternion,
|
||||
float angle)
|
||||
{
|
||||
/* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair
|
||||
* in this form:
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
*/
|
||||
float half_angle = angle * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f;
|
||||
|
||||
quaternion->w = cosf (half_angle);
|
||||
|
||||
quaternion->x = 0.0f;
|
||||
quaternion->y = sinf (half_angle);
|
||||
quaternion->z = 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init_from_z_rotation (CoglQuaternion *quaternion,
|
||||
float angle)
|
||||
{
|
||||
/* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair
|
||||
* in this form:
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
*/
|
||||
float half_angle = angle * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f;
|
||||
|
||||
quaternion->w = cosf (half_angle);
|
||||
|
||||
quaternion->x = 0.0f;
|
||||
quaternion->y = 0.0f;
|
||||
quaternion->z = sinf (half_angle);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init_from_euler (CoglQuaternion *quaternion,
|
||||
const graphene_euler_t *euler)
|
||||
{
|
||||
/* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair
|
||||
* in this form:
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
*/
|
||||
float sin_heading =
|
||||
sinf (graphene_euler_get_y (euler) * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f);
|
||||
float sin_pitch =
|
||||
sinf (graphene_euler_get_x (euler) * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f);
|
||||
float sin_roll =
|
||||
sinf (graphene_euler_get_z (euler) * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f);
|
||||
float cos_heading =
|
||||
cosf (graphene_euler_get_y (euler) * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f);
|
||||
float cos_pitch =
|
||||
cosf (graphene_euler_get_x (euler) * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f);
|
||||
float cos_roll =
|
||||
cosf (graphene_euler_get_z (euler) * _COGL_QUATERNION_DEGREES_TO_RADIANS * 0.5f);
|
||||
|
||||
quaternion->w =
|
||||
cos_heading * cos_pitch * cos_roll +
|
||||
sin_heading * sin_pitch * sin_roll;
|
||||
|
||||
quaternion->x =
|
||||
cos_heading * sin_pitch * cos_roll +
|
||||
sin_heading * cos_pitch * sin_roll;
|
||||
quaternion->y =
|
||||
sin_heading * cos_pitch * cos_roll -
|
||||
cos_heading * sin_pitch * sin_roll;
|
||||
quaternion->z =
|
||||
cos_heading * cos_pitch * sin_roll -
|
||||
sin_heading * sin_pitch * cos_roll;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_init_from_quaternion (CoglQuaternion *quaternion,
|
||||
CoglQuaternion *src)
|
||||
{
|
||||
memcpy (quaternion, src, sizeof (float) * 4);
|
||||
}
|
||||
|
||||
/* XXX: it could be nice to make something like this public... */
|
||||
/*
|
||||
* COGL_MATRIX_READ:
|
||||
* @MATRIX: A 4x4 transformation matrix
|
||||
* @ROW: The row of the value you want to read
|
||||
* @COLUMN: The column of the value you want to read
|
||||
*
|
||||
* Reads a value from the given matrix using integers to index
|
||||
* into the matrix.
|
||||
*/
|
||||
#define COGL_MATRIX_READ(MATRIX, ROW, COLUMN) \
|
||||
(((const float *)matrix)[COLUMN * 4 + ROW])
|
||||
|
||||
void
|
||||
cogl_quaternion_init_from_matrix (CoglQuaternion *quaternion,
|
||||
const CoglMatrix *matrix)
|
||||
{
|
||||
/* Algorithm devised by Ken Shoemake, Ref:
|
||||
* http://campar.in.tum.de/twiki/pub/Chair/DwarfTutorial/quatut.pdf
|
||||
*/
|
||||
|
||||
/* 3D maths literature refers to the diagonal of a matrix as the
|
||||
* "trace" of a matrix... */
|
||||
float trace = matrix->xx + matrix->yy + matrix->zz;
|
||||
float root;
|
||||
|
||||
if (trace > 0.0f)
|
||||
{
|
||||
root = sqrtf (trace + 1);
|
||||
quaternion->w = root * 0.5f;
|
||||
root = 0.5f / root;
|
||||
quaternion->x = (matrix->zy - matrix->yz) * root;
|
||||
quaternion->y = (matrix->xz - matrix->zx) * root;
|
||||
quaternion->z = (matrix->yx - matrix->xy) * root;
|
||||
}
|
||||
else
|
||||
{
|
||||
#define X 0
|
||||
#define Y 1
|
||||
#define Z 2
|
||||
#define W 3
|
||||
int h = X;
|
||||
if (matrix->yy > matrix->xx)
|
||||
h = Y;
|
||||
if (matrix->zz > COGL_MATRIX_READ (matrix, h, h))
|
||||
h = Z;
|
||||
switch (h)
|
||||
{
|
||||
#define CASE_MACRO(i, j, k, I, J, K) \
|
||||
case I: \
|
||||
root = sqrtf ((COGL_MATRIX_READ (matrix, I, I) - \
|
||||
(COGL_MATRIX_READ (matrix, J, J) + \
|
||||
COGL_MATRIX_READ (matrix, K, K))) + \
|
||||
COGL_MATRIX_READ (matrix, W, W)); \
|
||||
quaternion->i = root * 0.5f;\
|
||||
root = 0.5f / root;\
|
||||
quaternion->j = (COGL_MATRIX_READ (matrix, I, J) + \
|
||||
COGL_MATRIX_READ (matrix, J, I)) * root; \
|
||||
quaternion->k = (COGL_MATRIX_READ (matrix, K, I) + \
|
||||
COGL_MATRIX_READ (matrix, I, K)) * root; \
|
||||
quaternion->w = (COGL_MATRIX_READ (matrix, K, J) - \
|
||||
COGL_MATRIX_READ (matrix, J, K)) * root;\
|
||||
break
|
||||
CASE_MACRO (x, y, z, X, Y, Z);
|
||||
CASE_MACRO (y, z, x, Y, Z, X);
|
||||
CASE_MACRO (z, x, y, Z, X, Y);
|
||||
#undef CASE_MACRO
|
||||
#undef X
|
||||
#undef Y
|
||||
#undef Z
|
||||
}
|
||||
}
|
||||
|
||||
if (matrix->ww != 1.0f)
|
||||
{
|
||||
float s = 1.0 / sqrtf (matrix->ww);
|
||||
quaternion->w *= s;
|
||||
quaternion->x *= s;
|
||||
quaternion->y *= s;
|
||||
quaternion->z *= s;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_quaternion_equal (const void *v1, const void *v2)
|
||||
{
|
||||
const CoglQuaternion *a = v1;
|
||||
const CoglQuaternion *b = v2;
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (v1 != NULL, FALSE);
|
||||
_COGL_RETURN_VAL_IF_FAIL (v2 != NULL, FALSE);
|
||||
|
||||
if (v1 == v2)
|
||||
return TRUE;
|
||||
|
||||
return (a->w == b->w &&
|
||||
a->x == b->x &&
|
||||
a->y == b->y &&
|
||||
a->z == b->z);
|
||||
}
|
||||
|
||||
CoglQuaternion *
|
||||
cogl_quaternion_copy (const CoglQuaternion *src)
|
||||
{
|
||||
if (G_LIKELY (src))
|
||||
{
|
||||
CoglQuaternion *new = g_slice_new (CoglQuaternion);
|
||||
memcpy (new, src, sizeof (float) * 4);
|
||||
return new;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_free (CoglQuaternion *quaternion)
|
||||
{
|
||||
g_slice_free (CoglQuaternion, quaternion);
|
||||
}
|
||||
|
||||
float
|
||||
cogl_quaternion_get_rotation_angle (const CoglQuaternion *quaternion)
|
||||
{
|
||||
/* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair
|
||||
* in this form:
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
*/
|
||||
|
||||
/* FIXME: clamp [-1, 1] */
|
||||
return 2.0f * acosf (quaternion->w) * _COGL_QUATERNION_RADIANS_TO_DEGREES;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_get_rotation_axis (const CoglQuaternion *quaternion,
|
||||
float *vector3)
|
||||
{
|
||||
float sin_half_angle_sqr;
|
||||
float one_over_sin_angle_over_2;
|
||||
|
||||
/* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair
|
||||
* in this form:
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
*/
|
||||
|
||||
/* NB: sin²(𝜃) + cos²(𝜃) = 1 */
|
||||
|
||||
sin_half_angle_sqr = 1.0f - quaternion->w * quaternion->w;
|
||||
|
||||
if (sin_half_angle_sqr <= 0.0f)
|
||||
{
|
||||
/* Either an identity quaternion or numerical imprecision.
|
||||
* Either way we return an arbitrary vector. */
|
||||
vector3[0] = 1;
|
||||
vector3[1] = 0;
|
||||
vector3[2] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate 1 / sin(𝜃/2) */
|
||||
one_over_sin_angle_over_2 = 1.0f / sqrtf (sin_half_angle_sqr);
|
||||
|
||||
vector3[0] = quaternion->x * one_over_sin_angle_over_2;
|
||||
vector3[1] = quaternion->y * one_over_sin_angle_over_2;
|
||||
vector3[2] = quaternion->z * one_over_sin_angle_over_2;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_normalize (CoglQuaternion *quaternion)
|
||||
{
|
||||
float slen = _COGL_QUATERNION_NORM (quaternion);
|
||||
float factor = 1.0f / sqrtf (slen);
|
||||
|
||||
quaternion->x *= factor;
|
||||
quaternion->y *= factor;
|
||||
quaternion->z *= factor;
|
||||
|
||||
quaternion->w *= factor;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
float
|
||||
cogl_quaternion_dot_product (const CoglQuaternion *a,
|
||||
const CoglQuaternion *b)
|
||||
{
|
||||
return a->w * b->w + a->x * b->x + a->y * b->y + a->z * b->z;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_invert (CoglQuaternion *quaternion)
|
||||
{
|
||||
quaternion->x = -quaternion->x;
|
||||
quaternion->y = -quaternion->y;
|
||||
quaternion->z = -quaternion->z;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_multiply (CoglQuaternion *result,
|
||||
const CoglQuaternion *a,
|
||||
const CoglQuaternion *b)
|
||||
{
|
||||
float w = a->w;
|
||||
float x = a->x;
|
||||
float y = a->y;
|
||||
float z = a->z;
|
||||
|
||||
_COGL_RETURN_IF_FAIL (b != result);
|
||||
|
||||
result->w = w * b->w - x * b->x - y * b->y - z * b->z;
|
||||
|
||||
result->x = w * b->x + x * b->w + y * b->z - z * b->y;
|
||||
result->y = w * b->y + y * b->w + z * b->x - x * b->z;
|
||||
result->z = w * b->z + z * b->w + x * b->y - y * b->x;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_pow (CoglQuaternion *quaternion, float exponent)
|
||||
{
|
||||
float half_angle;
|
||||
float new_half_angle;
|
||||
float factor;
|
||||
|
||||
/* Try and identify and nop identity quaternions to avoid
|
||||
* dividing by zero */
|
||||
if (fabs (quaternion->w) > 0.9999f)
|
||||
return;
|
||||
|
||||
/* NB: We are using quaternions to represent an axis (a), angle (𝜃) pair
|
||||
* in this form:
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
*/
|
||||
|
||||
/* FIXME: clamp [-1, 1] */
|
||||
/* Extract 𝜃/2 from w */
|
||||
half_angle = acosf (quaternion->w);
|
||||
|
||||
/* Compute the new 𝜃/2 */
|
||||
new_half_angle = half_angle * exponent;
|
||||
|
||||
/* Compute the new w value */
|
||||
quaternion->w = cosf (new_half_angle);
|
||||
|
||||
/* And new xyz values */
|
||||
factor = sinf (new_half_angle) / sinf (half_angle);
|
||||
quaternion->x *= factor;
|
||||
quaternion->y *= factor;
|
||||
quaternion->z *= factor;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_slerp (CoglQuaternion *result,
|
||||
const CoglQuaternion *a,
|
||||
const CoglQuaternion *b,
|
||||
float t)
|
||||
{
|
||||
float cos_difference;
|
||||
float qb_w;
|
||||
float qb_x;
|
||||
float qb_y;
|
||||
float qb_z;
|
||||
float fa;
|
||||
float fb;
|
||||
|
||||
_COGL_RETURN_IF_FAIL (t >=0 && t <= 1.0f);
|
||||
|
||||
if (t == 0)
|
||||
{
|
||||
*result = *a;
|
||||
return;
|
||||
}
|
||||
else if (t == 1)
|
||||
{
|
||||
*result = *b;
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute the cosine of the angle between the two given quaternions */
|
||||
cos_difference = cogl_quaternion_dot_product (a, b);
|
||||
|
||||
/* If negative, use -b. Two quaternions q and -q represent the same angle but
|
||||
* may produce a different slerp. We choose b or -b to rotate using the acute
|
||||
* angle.
|
||||
*/
|
||||
if (cos_difference < 0.0f)
|
||||
{
|
||||
qb_w = -b->w;
|
||||
qb_x = -b->x;
|
||||
qb_y = -b->y;
|
||||
qb_z = -b->z;
|
||||
cos_difference = -cos_difference;
|
||||
}
|
||||
else
|
||||
{
|
||||
qb_w = b->w;
|
||||
qb_x = b->x;
|
||||
qb_y = b->y;
|
||||
qb_z = b->z;
|
||||
}
|
||||
|
||||
/* If we have two unit quaternions the dot should be <= 1.0 */
|
||||
g_assert (cos_difference < 1.1f);
|
||||
|
||||
|
||||
/* Determine the interpolation factors for each quaternion, simply using
|
||||
* linear interpolation for quaternions that are nearly exactly the same.
|
||||
* (this will avoid divisions by zero)
|
||||
*/
|
||||
|
||||
if (cos_difference > 0.9999f)
|
||||
{
|
||||
fa = 1.0f - t;
|
||||
fb = t;
|
||||
|
||||
/* XXX: should we also normalize() at the end in this case? */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate the sin of the angle between the two quaternions using the
|
||||
* trig identity: sin²(𝜃) + cos²(𝜃) = 1
|
||||
*/
|
||||
float sin_difference = sqrtf (1.0f - cos_difference * cos_difference);
|
||||
|
||||
float difference = atan2f (sin_difference, cos_difference);
|
||||
float one_over_sin_difference = 1.0f / sin_difference;
|
||||
fa = sinf ((1.0f - t) * difference) * one_over_sin_difference;
|
||||
fb = sinf (t * difference) * one_over_sin_difference;
|
||||
}
|
||||
|
||||
/* Finally interpolate the two quaternions */
|
||||
|
||||
result->x = fa * a->x + fb * qb_x;
|
||||
result->y = fa * a->y + fb * qb_y;
|
||||
result->z = fa * a->z + fb * qb_z;
|
||||
result->w = fa * a->w + fb * qb_w;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_nlerp (CoglQuaternion *result,
|
||||
const CoglQuaternion *a,
|
||||
const CoglQuaternion *b,
|
||||
float t)
|
||||
{
|
||||
float cos_difference;
|
||||
float qb_w;
|
||||
float qb_x;
|
||||
float qb_y;
|
||||
float qb_z;
|
||||
float fa;
|
||||
float fb;
|
||||
|
||||
_COGL_RETURN_IF_FAIL (t >=0 && t <= 1.0f);
|
||||
|
||||
if (t == 0)
|
||||
{
|
||||
*result = *a;
|
||||
return;
|
||||
}
|
||||
else if (t == 1)
|
||||
{
|
||||
*result = *b;
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute the cosine of the angle between the two given quaternions */
|
||||
cos_difference = cogl_quaternion_dot_product (a, b);
|
||||
|
||||
/* If negative, use -b. Two quaternions q and -q represent the same angle but
|
||||
* may produce a different slerp. We choose b or -b to rotate using the acute
|
||||
* angle.
|
||||
*/
|
||||
if (cos_difference < 0.0f)
|
||||
{
|
||||
qb_w = -b->w;
|
||||
qb_x = -b->x;
|
||||
qb_y = -b->y;
|
||||
qb_z = -b->z;
|
||||
cos_difference = -cos_difference;
|
||||
}
|
||||
else
|
||||
{
|
||||
qb_w = b->w;
|
||||
qb_x = b->x;
|
||||
qb_y = b->y;
|
||||
qb_z = b->z;
|
||||
}
|
||||
|
||||
/* If we have two unit quaternions the dot should be <= 1.0 */
|
||||
g_assert (cos_difference < 1.1f);
|
||||
|
||||
fa = 1.0f - t;
|
||||
fb = t;
|
||||
|
||||
result->x = fa * a->x + fb * qb_x;
|
||||
result->y = fa * a->y + fb * qb_y;
|
||||
result->z = fa * a->z + fb * qb_z;
|
||||
result->w = fa * a->w + fb * qb_w;
|
||||
|
||||
cogl_quaternion_normalize (result);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_quaternion_squad (CoglQuaternion *result,
|
||||
const CoglQuaternion *prev,
|
||||
const CoglQuaternion *a,
|
||||
const CoglQuaternion *b,
|
||||
const CoglQuaternion *next,
|
||||
float t)
|
||||
{
|
||||
CoglQuaternion slerp0;
|
||||
CoglQuaternion slerp1;
|
||||
|
||||
cogl_quaternion_slerp (&slerp0, a, b, t);
|
||||
cogl_quaternion_slerp (&slerp1, prev, next, t);
|
||||
cogl_quaternion_slerp (result, &slerp0, &slerp1, 2.0f * t * (1.0f - t));
|
||||
}
|
||||
|
||||
const CoglQuaternion *
|
||||
cogl_get_static_identity_quaternion (void)
|
||||
{
|
||||
return &identity_quaternion;
|
||||
}
|
||||
|
||||
const CoglQuaternion *
|
||||
cogl_get_static_zero_quaternion (void)
|
||||
{
|
||||
return &zero_quaternion;
|
||||
}
|
||||
|
@ -1,561 +0,0 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* A Low Level GPU Graphics and Utilities API
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION)
|
||||
#error "Only <cogl/cogl.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __COGL_QUATERNION_H__
|
||||
#define __COGL_QUATERNION_H__
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
#include <cogl/cogl-types.h>
|
||||
#include <cogl/cogl-vector.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:cogl-quaternion
|
||||
* @short_description: Functions for initializing and manipulating
|
||||
* quaternions.
|
||||
*
|
||||
* Quaternions have become a standard form for representing 3D
|
||||
* rotations and have some nice properties when compared with other
|
||||
* representation such as (roll,pitch,yaw) Euler angles. They can be
|
||||
* used to interpolate between different rotations and they don't
|
||||
* suffer from a problem called
|
||||
* <ulink url="http://en.wikipedia.org/wiki/Gimbal_lock">"Gimbal lock"</ulink>
|
||||
* where two of the axis of rotation may become aligned and you loose a
|
||||
* degree of freedom.
|
||||
* .
|
||||
*/
|
||||
#include <cogl/cogl-vector.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
/**
|
||||
* CoglQuaternion:
|
||||
* @w: based on the angle of rotation it is cos(𝜃/2)
|
||||
* @x: based on the angle of rotation and x component of the axis of
|
||||
* rotation it is sin(𝜃/2)*axis.x
|
||||
* @y: based on the angle of rotation and y component of the axis of
|
||||
* rotation it is sin(𝜃/2)*axis.y
|
||||
* @z: based on the angle of rotation and z component of the axis of
|
||||
* rotation it is sin(𝜃/2)*axis.z
|
||||
*
|
||||
* A quaternion is comprised of a scalar component and a 3D vector
|
||||
* component. The scalar component is normally referred to as w and the
|
||||
* vector might either be referred to as v or a (for axis) or expanded
|
||||
* with the individual components: (x, y, z) A full quaternion would
|
||||
* then be written as <literal>[w (x, y, z)]</literal>.
|
||||
*
|
||||
* Quaternions can be considered to represent an axis and angle
|
||||
* pair although sadly these numbers are buried somewhat under some
|
||||
* maths...
|
||||
*
|
||||
* For the curious you can see here that a given axis (a) and angle (𝜃)
|
||||
* pair are represented in a quaternion as follows:
|
||||
* |[
|
||||
* [w=cos(𝜃/2) ( x=sin(𝜃/2)*a.x, y=sin(𝜃/2)*a.y, z=sin(𝜃/2)*a.x )]
|
||||
* ]|
|
||||
*
|
||||
* Unit Quaternions:
|
||||
* When using Quaternions to represent spatial orientations for 3D
|
||||
* graphics it's always assumed you have a unit quaternion. The
|
||||
* magnitude of a quaternion is defined as:
|
||||
* |[
|
||||
* sqrt (w² + x² + y² + z²)
|
||||
* ]|
|
||||
* and a unit quaternion satisfies this equation:
|
||||
* |[
|
||||
* w² + x² + y² + z² = 1
|
||||
* ]|
|
||||
*
|
||||
* Thankfully most of the time we don't actually have to worry about
|
||||
* the maths that goes on behind the scenes but if you are curious to
|
||||
* learn more here are some external references:
|
||||
*
|
||||
* <itemizedlist>
|
||||
* <listitem>
|
||||
* <ulink url="http://mathworld.wolfram.com/Quaternion.html"/>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* <ulink url="http://www.gamedev.net/reference/articles/article1095.asp"/>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* <ulink url="http://www.cprogramming.com/tutorial/3d/quaternions.html"/>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* <ulink url="http://www.isner.com/tutorials/quatSpells/quaternion_spells_12.htm"/>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* 3D Maths Primer for Graphics and Game Development ISBN-10: 1556229119
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* <ulink url="http://www.cs.caltech.edu/courses/cs171/quatut.pdf"/>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* <ulink url="http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56"/>
|
||||
* </listitem>
|
||||
* </itemizedlist>
|
||||
*
|
||||
*/
|
||||
struct _CoglQuaternion
|
||||
{
|
||||
/*< public >*/
|
||||
float w;
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
/*< private >*/
|
||||
float padding0;
|
||||
float padding1;
|
||||
float padding2;
|
||||
float padding3;
|
||||
};
|
||||
COGL_STRUCT_SIZE_ASSERT (CoglQuaternion, 32);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_get_gtype:
|
||||
*
|
||||
* Returns: a #GType that can be used with the GLib type system.
|
||||
*/
|
||||
GType cogl_quaternion_get_gtype (void);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init:
|
||||
* @quaternion: An uninitialized #CoglQuaternion
|
||||
* @angle: The angle you want to rotate around the given axis
|
||||
* @x: The x component of your axis vector about which you want to
|
||||
* rotate.
|
||||
* @y: The y component of your axis vector about which you want to
|
||||
* rotate.
|
||||
* @z: The z component of your axis vector about which you want to
|
||||
* rotate.
|
||||
*
|
||||
* Initializes a quaternion that rotates @angle degrees around the
|
||||
* axis vector (@x, @y, @z). The axis vector does not need to be
|
||||
* normalized.
|
||||
*
|
||||
* Returns: A normalized, unit quaternion representing an orientation
|
||||
* rotated @angle degrees around the axis vector (@x, @y, @z)
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init (CoglQuaternion *quaternion,
|
||||
float angle,
|
||||
float x,
|
||||
float y,
|
||||
float z);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_from_angle_vector:
|
||||
* @quaternion: An uninitialized #CoglQuaternion
|
||||
* @angle: The angle to rotate around @axis3f
|
||||
* @axis3f: your 3 component axis vector about which you want to rotate.
|
||||
*
|
||||
* Initializes a quaternion that rotates @angle degrees around the
|
||||
* given @axis vector. The axis vector does not need to be
|
||||
* normalized.
|
||||
*
|
||||
* Returns: A normalized, unit quaternion representing an orientation
|
||||
* rotated @angle degrees around the given @axis vector.
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_from_angle_vector (CoglQuaternion *quaternion,
|
||||
float angle,
|
||||
const float *axis3f);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_identity:
|
||||
* @quaternion: An uninitialized #CoglQuaternion
|
||||
*
|
||||
* Initializes the quaternion with the canonical quaternion identity
|
||||
* [1 (0, 0, 0)] which represents no rotation. Multiplying a
|
||||
* quaternion with this identity leaves the quaternion unchanged.
|
||||
*
|
||||
* You might also want to consider using
|
||||
* cogl_get_static_identity_quaternion().
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_identity (CoglQuaternion *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_from_array:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
* @array: An array of 4 floats w,(x,y,z)
|
||||
*
|
||||
* Initializes a [w (x, y,z)] quaternion directly from an array of 4
|
||||
* floats: [w,x,y,z].
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_from_array (CoglQuaternion *quaternion,
|
||||
const float *array);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_from_x_rotation:
|
||||
* @quaternion: An uninitialized #CoglQuaternion
|
||||
* @angle: The angle to rotate around the x axis
|
||||
*
|
||||
* XXX: check which direction this rotates
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_from_x_rotation (CoglQuaternion *quaternion,
|
||||
float angle);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_from_y_rotation:
|
||||
* @quaternion: An uninitialized #CoglQuaternion
|
||||
* @angle: The angle to rotate around the y axis
|
||||
*
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_from_y_rotation (CoglQuaternion *quaternion,
|
||||
float angle);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_from_z_rotation:
|
||||
* @quaternion: An uninitialized #CoglQuaternion
|
||||
* @angle: The angle to rotate around the z axis
|
||||
*
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_from_z_rotation (CoglQuaternion *quaternion,
|
||||
float angle);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_from_euler:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
* @euler: A #graphene_euler_t with which to initialize the quaternion
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_from_euler (CoglQuaternion *quaternion,
|
||||
const graphene_euler_t *euler);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_from_quaternion:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
* @src: A #CoglQuaternion with which to initialize @quaternion
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_from_quaternion (CoglQuaternion *quaternion,
|
||||
CoglQuaternion *src);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_init_from_matrix:
|
||||
* @quaternion: A Cogl Quaternion
|
||||
* @matrix: A rotation matrix with which to initialize the quaternion
|
||||
*
|
||||
* Initializes a quaternion from a rotation matrix.
|
||||
*
|
||||
* Since: 1.10
|
||||
* Stability: unstable
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_init_from_matrix (CoglQuaternion *quaternion,
|
||||
const CoglMatrix *matrix);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_equal:
|
||||
* @v1: A #CoglQuaternion
|
||||
* @v2: A #CoglQuaternion
|
||||
*
|
||||
* Compares that all the components of quaternions @a and @b are
|
||||
* equal.
|
||||
*
|
||||
* An epsilon value is not used to compare the float components, but
|
||||
* the == operator is at least used so that 0 and -0 are considered
|
||||
* equal.
|
||||
*
|
||||
* Returns: %TRUE if the quaternions are equal else %FALSE.
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
gboolean
|
||||
cogl_quaternion_equal (const void *v1, const void *v2);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_copy:
|
||||
* @src: A #CoglQuaternion
|
||||
*
|
||||
* Allocates a new #CoglQuaternion on the stack and initializes it with
|
||||
* the same values as @src.
|
||||
*
|
||||
* Returns: A newly allocated #CoglQuaternion which should be freed
|
||||
* using cogl_quaternion_free()
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
CoglQuaternion *
|
||||
cogl_quaternion_copy (const CoglQuaternion *src);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_free:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
*
|
||||
* Frees a #CoglQuaternion that was previously allocated via
|
||||
* cogl_quaternion_copy().
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_free (CoglQuaternion *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_get_rotation_angle:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
*
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
float
|
||||
cogl_quaternion_get_rotation_angle (const CoglQuaternion *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_get_rotation_axis:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
* @vector3: (out): an allocated 3-float array
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_get_rotation_axis (const CoglQuaternion *quaternion,
|
||||
float *vector3);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_normalize:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
*
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_normalize (CoglQuaternion *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_dot_product:
|
||||
* @a: A #CoglQuaternion
|
||||
* @b: A #CoglQuaternion
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
float
|
||||
cogl_quaternion_dot_product (const CoglQuaternion *a,
|
||||
const CoglQuaternion *b);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_invert:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
*
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_invert (CoglQuaternion *quaternion);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_multiply:
|
||||
* @result: The destination #CoglQuaternion
|
||||
* @left: The second #CoglQuaternion rotation to apply
|
||||
* @right: The first #CoglQuaternion rotation to apply
|
||||
*
|
||||
* This combines the rotations of two quaternions into @result. The
|
||||
* operation is not commutative so the order is important because AxB
|
||||
* != BxA. Cogl follows the standard convention for quaternions here
|
||||
* so the rotations are applied @right to @left. This is similar to the
|
||||
* combining of matrices.
|
||||
*
|
||||
* <note>It is possible to multiply the @a quaternion in-place, so
|
||||
* @result can be equal to @a but can't be equal to @b.</note>
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_multiply (CoglQuaternion *result,
|
||||
const CoglQuaternion *left,
|
||||
const CoglQuaternion *right);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_pow:
|
||||
* @quaternion: A #CoglQuaternion
|
||||
* @exponent: the exponent
|
||||
*
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_pow (CoglQuaternion *quaternion, float exponent);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_slerp:
|
||||
* @result: The destination #CoglQuaternion
|
||||
* @a: The first #CoglQuaternion
|
||||
* @b: The second #CoglQuaternion
|
||||
* @t: The factor in the range [0,1] used to interpolate between
|
||||
* quaternion @a and @b.
|
||||
*
|
||||
* Performs a spherical linear interpolation between two quaternions.
|
||||
*
|
||||
* Noteable properties:
|
||||
* <itemizedlist>
|
||||
* <listitem>
|
||||
* commutative: No
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* constant velocity: Yes
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* torque minimal (travels along the surface of the 4-sphere): Yes
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* more expensive than cogl_quaternion_nlerp()
|
||||
* </listitem>
|
||||
* </itemizedlist>
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_slerp (CoglQuaternion *result,
|
||||
const CoglQuaternion *a,
|
||||
const CoglQuaternion *b,
|
||||
float t);
|
||||
|
||||
/**
|
||||
* cogl_quaternion_nlerp:
|
||||
* @result: The destination #CoglQuaternion
|
||||
* @a: The first #CoglQuaternion
|
||||
* @b: The second #CoglQuaternion
|
||||
* @t: The factor in the range [0,1] used to interpolate between
|
||||
* quaterion @a and @b.
|
||||
*
|
||||
* Performs a normalized linear interpolation between two quaternions.
|
||||
* That is it does a linear interpolation of the quaternion components
|
||||
* and then normalizes the result. This will follow the shortest arc
|
||||
* between the two orientations (just like the slerp() function) but
|
||||
* will not progress at a constant speed. Unlike slerp() nlerp is
|
||||
* commutative which is useful if you are blending animations
|
||||
* together. (I.e. nlerp (tmp, a, b) followed by nlerp (result, tmp,
|
||||
* d) is the same as nlerp (tmp, a, d) followed by nlerp (result, tmp,
|
||||
* b)). Finally nlerp is cheaper than slerp so it can be a good choice
|
||||
* if you don't need the constant speed property of the slerp() function.
|
||||
*
|
||||
* Notable properties:
|
||||
* <itemizedlist>
|
||||
* <listitem>
|
||||
* commutative: Yes
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* constant velocity: No
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* torque minimal (travels along the surface of the 4-sphere): Yes
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* faster than cogl_quaternion_slerp()
|
||||
* </listitem>
|
||||
* </itemizedlist>
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_nlerp (CoglQuaternion *result,
|
||||
const CoglQuaternion *a,
|
||||
const CoglQuaternion *b,
|
||||
float t);
|
||||
/**
|
||||
* cogl_quaternion_squad:
|
||||
* @result: The destination #CoglQuaternion
|
||||
* @prev: A #CoglQuaternion used before @a
|
||||
* @a: The first #CoglQuaternion
|
||||
* @b: The second #CoglQuaternion
|
||||
* @next: A #CoglQuaternion that will be used after @b
|
||||
* @t: The factor in the range [0,1] used to interpolate between
|
||||
* quaternion @a and @b.
|
||||
*
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
void
|
||||
cogl_quaternion_squad (CoglQuaternion *result,
|
||||
const CoglQuaternion *prev,
|
||||
const CoglQuaternion *a,
|
||||
const CoglQuaternion *b,
|
||||
const CoglQuaternion *next,
|
||||
float t);
|
||||
|
||||
/**
|
||||
* cogl_get_static_identity_quaternion:
|
||||
*
|
||||
* Returns a pointer to a singleton quaternion constant describing the
|
||||
* canonical identity [1 (0, 0, 0)] which represents no rotation.
|
||||
*
|
||||
* If you multiply a quaternion with the identity quaternion you will
|
||||
* get back the same value as the original quaternion.
|
||||
*
|
||||
* Returns: A pointer to an identity quaternion
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
const CoglQuaternion *
|
||||
cogl_get_static_identity_quaternion (void);
|
||||
|
||||
/**
|
||||
* cogl_get_static_zero_quaternion:
|
||||
*
|
||||
* Returns: a pointer to a singleton quaternion constant describing a
|
||||
* rotation of 180 degrees around a degenerate axis:
|
||||
* [0 (0, 0, 0)]
|
||||
*
|
||||
* Since: 2.0
|
||||
*/
|
||||
const CoglQuaternion *
|
||||
cogl_get_static_zero_quaternion (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_QUATERNION_H__ */
|
||||
|
@ -117,10 +117,6 @@ cogl_handle_unref (CoglHandle handle);
|
||||
* between cogl-matrix.h and cogl-quaterion.h */
|
||||
typedef struct _CoglMatrix CoglMatrix;
|
||||
|
||||
/* Same as above we forward declared CoglQuaternion to avoid
|
||||
* circular dependencies. */
|
||||
typedef struct _CoglQuaternion CoglQuaternion;
|
||||
|
||||
/**
|
||||
* CoglAngle:
|
||||
*
|
||||
|
@ -103,7 +103,6 @@
|
||||
#include <cogl/cogl-buffer.h>
|
||||
#include <cogl/cogl-pixel-buffer.h>
|
||||
#include <cogl/cogl-vector.h>
|
||||
#include <cogl/cogl-quaternion.h>
|
||||
#include <cogl/cogl-texture-2d.h>
|
||||
#include <cogl/cogl-texture-2d-gl.h>
|
||||
#include <cogl/cogl-texture-rectangle.h>
|
||||
|
@ -749,31 +749,6 @@ cogl_push_gles2_context
|
||||
cogl_push_matrix
|
||||
cogl_push_source
|
||||
|
||||
cogl_quaternion_copy
|
||||
cogl_quaternion_dot_product
|
||||
cogl_quaternion_equal
|
||||
cogl_quaternion_free
|
||||
#ifdef COGL_HAS_GTYPE_SUPPORT
|
||||
cogl_quaternion_get_gtype
|
||||
#endif
|
||||
cogl_quaternion_get_rotation_angle
|
||||
cogl_quaternion_get_rotation_axis
|
||||
cogl_quaternion_init
|
||||
cogl_quaternion_init_from_angle_vector
|
||||
cogl_quaternion_init_from_array
|
||||
cogl_quaternion_init_from_euler
|
||||
cogl_quaternion_init_from_x_rotation
|
||||
cogl_quaternion_init_from_y_rotation
|
||||
cogl_quaternion_init_from_z_rotation
|
||||
cogl_quaternion_init_identity
|
||||
cogl_quaternion_invert
|
||||
cogl_quaternion_multiply
|
||||
cogl_quaternion_nlerp
|
||||
cogl_quaternion_normalize
|
||||
cogl_quaternion_pow
|
||||
cogl_quaternion_slerp
|
||||
cogl_quaternion_squad
|
||||
|
||||
cogl_read_pixels
|
||||
cogl_read_pixels_flags_get_type
|
||||
|
||||
|
@ -115,7 +115,6 @@ cogl_nonintrospected_headers = [
|
||||
'cogl-frame-info.h',
|
||||
'cogl-vector.h',
|
||||
'cogl-output.h',
|
||||
'cogl-quaternion.h',
|
||||
'cogl-matrix-stack.h',
|
||||
'cogl-poll.h',
|
||||
'cogl-texture-3d.h',
|
||||
@ -269,8 +268,6 @@ cogl_sources = [
|
||||
'cogl-primitive.c',
|
||||
'cogl-matrix.c',
|
||||
'cogl-vector.c',
|
||||
'cogl-quaternion-private.h',
|
||||
'cogl-quaternion.c',
|
||||
'cogl-matrix-private.h',
|
||||
'cogl-matrix-stack.c',
|
||||
'cogl-matrix-stack-private.h',
|
||||
|
@ -39,7 +39,7 @@ void
|
||||
test_euler_quaternion (void)
|
||||
{
|
||||
graphene_euler_t euler;
|
||||
CoglQuaternion quaternion;
|
||||
graphene_quaternion_t quaternion;
|
||||
CoglMatrix matrix_a, matrix_b;
|
||||
|
||||
/* Try doing the rotation with three separate rotations */
|
||||
@ -56,7 +56,7 @@ test_euler_quaternion (void)
|
||||
COMPARE_MATRICES (&matrix_a, &matrix_b);
|
||||
|
||||
/* Try converting the euler to a matrix via a quaternion */
|
||||
cogl_quaternion_init_from_euler (&quaternion, &euler);
|
||||
graphene_quaternion_init_from_euler (&quaternion, &euler);
|
||||
memset (&matrix_b, 0, sizeof (matrix_b));
|
||||
cogl_matrix_init_from_quaternion (&matrix_b, &quaternion);
|
||||
COMPARE_MATRICES (&matrix_a, &matrix_b);
|
||||
|
Loading…
Reference in New Issue
Block a user