566 lines
12 KiB
C
566 lines
12 KiB
C
/*
|
|
* Copyright (c), Recep Aslantas.
|
|
*
|
|
* MIT License (MIT), http://opensource.org/licenses/MIT
|
|
* Full license can be found in the LICENSE file
|
|
*/
|
|
|
|
/*
|
|
Macros:
|
|
GLMS_QUAT_IDENTITY_INIT
|
|
GLMS_QUAT_IDENTITY
|
|
|
|
Functions:
|
|
CGLM_INLINE versors glms_quat_identity(void)
|
|
CGLM_INLINE void glms_quat_identity_array(versor *q, size_t count)
|
|
CGLM_INLINE versors glms_quat_init(float x, float y, float z, float w)
|
|
CGLM_INLINE versors glms_quatv(float angle, vec3s axis)
|
|
CGLM_INLINE versors glms_quat(float angle, float x, float y, float z)
|
|
CGLM_INLINE versors glms_quat_from_vecs(vec3s a, vec3s b)
|
|
CGLM_INLINE float glms_quat_norm(versors q)
|
|
CGLM_INLINE versors glms_quat_normalize(versors q)
|
|
CGLM_INLINE float glms_quat_dot(versors p, versors q)
|
|
CGLM_INLINE versors glms_quat_conjugate(versors q)
|
|
CGLM_INLINE versors glms_quat_inv(versors q)
|
|
CGLM_INLINE versors glms_quat_add(versors p, versors q)
|
|
CGLM_INLINE versors glms_quat_sub(versors p, versors q)
|
|
CGLM_INLINE vec3s glms_quat_imagn(versors q)
|
|
CGLM_INLINE float glms_quat_imaglen(versors q)
|
|
CGLM_INLINE float glms_quat_angle(versors q)
|
|
CGLM_INLINE vec3s glms_quat_axis(versors q)
|
|
CGLM_INLINE versors glms_quat_mul(versors p, versors q)
|
|
CGLM_INLINE mat4s glms_quat_mat4(versors q)
|
|
CGLM_INLINE mat4s glms_quat_mat4t(versors q)
|
|
CGLM_INLINE mat3s glms_quat_mat3(versors q)
|
|
CGLM_INLINE mat3s glms_quat_mat3t(versors q)
|
|
CGLM_INLINE versors glms_quat_lerp(versors from, versors to, float t)
|
|
CGLM_INLINE versors glms_quat_lerpc(versors from, versors to, float t)
|
|
CGLM_INLINE versors glms_quat_nlerp(versors from, versors to, float t)
|
|
CGLM_INLINE versors glms_quat_slerp(versors from, versors to, float t)
|
|
CGLM_INLINE mat4s. glms_quat_look(vec3s eye, versors ori)
|
|
CGLM_INLINE versors glms_quat_for(vec3s dir, vec3s fwd, vec3s up)
|
|
CGLM_INLINE versors glms_quat_forp(vec3s from, vec3s to, vec3s fwd, vec3s up)
|
|
CGLM_INLINE vec3s glms_quat_rotatev(versors q, vec3s v)
|
|
CGLM_INLINE mat4s glms_quat_rotate(mat4s m, versors q)
|
|
CGLM_INLINE mat4s glms_quat_rotate_at(mat4s m, versors q, vec3s pivot)
|
|
CGLM_INLINE mat4s glms_quat_rotate_atm(versors q, vec3s pivot)
|
|
*/
|
|
|
|
#ifndef cglms_quat_h
|
|
#define cglms_quat_h
|
|
|
|
#include "../common.h"
|
|
#include "../types-struct.h"
|
|
#include "../plane.h"
|
|
#include "../quat.h"
|
|
|
|
/*
|
|
* IMPORTANT:
|
|
* ----------------------------------------------------------------------------
|
|
* cglm stores quat as [x, y, z, w] since v0.3.6
|
|
*
|
|
* it was [w, x, y, z] before v0.3.6 it has been changed to [x, y, z, w]
|
|
* with v0.3.6 version.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#define GLMS_QUAT_IDENTITY_INIT {GLM_QUAT_IDENTITY_INIT}
|
|
#define GLMS_QUAT_IDENTITY ((versors)GLMS_QUAT_IDENTITY_INIT)
|
|
|
|
/*!
|
|
* @brief makes given quat to identity
|
|
*
|
|
* @returns identity quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_identity(void) {
|
|
versors dest;
|
|
glm_quat_identity(dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief make given quaternion array's each element identity quaternion
|
|
*
|
|
* @param[in, out] q quat array (must be aligned (16)
|
|
* if alignment is not disabled)
|
|
*
|
|
* @param[in] count count of quaternions
|
|
*/
|
|
CGLM_INLINE
|
|
void
|
|
glms_quat_identity_array(versors * __restrict q, size_t count) {
|
|
CGLM_ALIGN(16) versor v = GLM_QUAT_IDENTITY_INIT;
|
|
size_t i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
glm_vec4_copy(v, q[i].raw);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @brief inits quaterion with raw values
|
|
*
|
|
* @param[in] x x
|
|
* @param[in] y y
|
|
* @param[in] z z
|
|
* @param[in] w w (real part)
|
|
* @returns quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_init(float x, float y, float z, float w) {
|
|
versors dest;
|
|
glm_quat_init(dest.raw, x, y, z, w);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief creates NEW quaternion with axis vector
|
|
*
|
|
* @param[in] angle angle (radians)
|
|
* @param[in] axis axis
|
|
* @returns quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quatv(float angle, vec3s axis) {
|
|
versors dest;
|
|
glm_quatv(dest.raw, angle, axis.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief creates NEW quaternion with individual axis components
|
|
*
|
|
* @param[in] angle angle (radians)
|
|
* @param[in] x axis.x
|
|
* @param[in] y axis.y
|
|
* @param[in] z axis.z
|
|
* @returns quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat(float angle, float x, float y, float z) {
|
|
versors dest;
|
|
glm_quat(dest.raw, angle, x, y, z);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief compute quaternion rotating vector A to vector B
|
|
*
|
|
* @param[in] a vec3 (must have unit length)
|
|
* @param[in] b vec3 (must have unit length)
|
|
* @returns quaternion (of unit length)
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_from_vecs(vec3s a, vec3s b) {
|
|
versors dest;
|
|
glm_quat_from_vecs(a.raw, b.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief returns norm (magnitude) of quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
float
|
|
glms_quat_norm(versors q) {
|
|
return glm_quat_norm(q.raw);
|
|
}
|
|
|
|
/*!
|
|
* @brief normalize quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_normalize(versors q) {
|
|
versors dest;
|
|
glm_quat_normalize_to(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief dot product of two quaternion
|
|
*
|
|
* @param[in] p quaternion 1
|
|
* @param[in] q quaternion 2
|
|
* @returns dot product
|
|
*/
|
|
CGLM_INLINE
|
|
float
|
|
glms_quat_dot(versors p, versors q) {
|
|
return glm_quat_dot(p.raw, q.raw);
|
|
}
|
|
|
|
/*!
|
|
* @brief conjugate of quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns conjugate
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_conjugate(versors q) {
|
|
versors dest;
|
|
glm_quat_conjugate(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief inverse of non-zero quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns inverse quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_inv(versors q) {
|
|
versors dest;
|
|
glm_quat_inv(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief add (componentwise) two quaternions and store result in dest
|
|
*
|
|
* @param[in] p quaternion 1
|
|
* @param[in] q quaternion 2
|
|
* @returns result quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_add(versors p, versors q) {
|
|
versors dest;
|
|
glm_quat_add(p.raw, q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief subtract (componentwise) two quaternions and store result in dest
|
|
*
|
|
* @param[in] p quaternion 1
|
|
* @param[in] q quaternion 2
|
|
* @returns result quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_sub(versors p, versors q) {
|
|
versors dest;
|
|
glm_quat_sub(p.raw, q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief returns normalized imaginary part of quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
vec3s
|
|
glms_quat_imagn(versors q) {
|
|
vec3s dest;
|
|
glm_normalize_to(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief returns length of imaginary part of quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
float
|
|
glms_quat_imaglen(versors q) {
|
|
return glm_quat_imaglen(q.raw);
|
|
}
|
|
|
|
/*!
|
|
* @brief returns angle of quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
float
|
|
glms_quat_angle(versors q) {
|
|
return glm_quat_angle(q.raw);
|
|
}
|
|
|
|
/*!
|
|
* @brief axis of quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns axis of quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
vec3s
|
|
glms_quat_axis(versors q) {
|
|
vec3s dest;
|
|
glm_quat_axis(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief multiplies two quaternion and stores result in dest
|
|
* this is also called Hamilton Product
|
|
*
|
|
* According to WikiPedia:
|
|
* The product of two rotation quaternions [clarification needed] will be
|
|
* equivalent to the rotation q followed by the rotation p
|
|
*
|
|
* @param[in] p quaternion 1
|
|
* @param[in] q quaternion 2
|
|
* @returns result quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_mul(versors p, versors q) {
|
|
versors dest;
|
|
glm_quat_mul(p.raw, q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief convert quaternion to mat4
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns result matrix
|
|
*/
|
|
CGLM_INLINE
|
|
mat4s
|
|
glms_quat_mat4(versors q) {
|
|
mat4s dest;
|
|
glm_quat_mat4(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief convert quaternion to mat4 (transposed)
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns result matrix as transposed
|
|
*/
|
|
CGLM_INLINE
|
|
mat4s
|
|
glms_quat_mat4t(versors q) {
|
|
mat4s dest;
|
|
glm_quat_mat4t(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief convert quaternion to mat3
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns result matrix
|
|
*/
|
|
CGLM_INLINE
|
|
mat3s
|
|
glms_quat_mat3(versors q) {
|
|
mat3s dest;
|
|
glm_quat_mat3(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief convert quaternion to mat3 (transposed)
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns result matrix
|
|
*/
|
|
CGLM_INLINE
|
|
mat3s
|
|
glms_quat_mat3t(versors q) {
|
|
mat3s dest;
|
|
glm_quat_mat3t(q.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief interpolates between two quaternions
|
|
* using linear interpolation (LERP)
|
|
*
|
|
* @param[in] from from
|
|
* @param[in] to to
|
|
* @param[in] t interpolant (amount)
|
|
* @returns result quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_lerp(versors from, versors to, float t) {
|
|
versors dest;
|
|
glm_quat_lerp(from.raw, to.raw, t, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief interpolates between two quaternions
|
|
* using linear interpolation (LERP)
|
|
*
|
|
* @param[in] from from
|
|
* @param[in] to to
|
|
* @param[in] t interpolant (amount) clamped between 0 and 1
|
|
* @returns result quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_lerpc(versors from, versors to, float t) {
|
|
versors dest;
|
|
glm_quat_lerpc(from.raw, to.raw, t, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief interpolates between two quaternions
|
|
* taking the shortest rotation path using
|
|
* normalized linear interpolation (NLERP)
|
|
*
|
|
* @param[in] from from
|
|
* @param[in] to to
|
|
* @param[in] t interpolant (amount)
|
|
* @returns result quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_nlerp(versors from, versors to, float t) {
|
|
versors dest;
|
|
glm_quat_nlerp(from.raw, to.raw, t, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief interpolates between two quaternions
|
|
* using spherical linear interpolation (SLERP)
|
|
*
|
|
* @param[in] from from
|
|
* @param[in] to to
|
|
* @param[in] t amout
|
|
* @returns result quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_slerp(versors from, versors to, float t) {
|
|
versors dest;
|
|
glm_quat_slerp(from.raw, to.raw, t, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief creates view matrix using quaternion as camera orientation
|
|
*
|
|
* @param[in] eye eye
|
|
* @param[in] ori orientation in world space as quaternion
|
|
* @returns view matrix
|
|
*/
|
|
CGLM_INLINE
|
|
mat4s
|
|
glms_quat_look(vec3s eye, versors ori) {
|
|
mat4s dest;
|
|
glm_quat_look(eye.raw, ori.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief creates look rotation quaternion
|
|
*
|
|
* @param[in] dir direction to look
|
|
* @param[in] up up vector
|
|
* @returns destination quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_for(vec3s dir, vec3s up) {
|
|
versors dest;
|
|
glm_quat_for(dir.raw, up.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief creates look rotation quaternion using source and
|
|
* destination positions p suffix stands for position
|
|
*
|
|
* @param[in] from source point
|
|
* @param[in] to destination point
|
|
* @param[in] up up vector
|
|
* @returns destination quaternion
|
|
*/
|
|
CGLM_INLINE
|
|
versors
|
|
glms_quat_forp(vec3s from, vec3s to, vec3s up) {
|
|
versors dest;
|
|
glm_quat_forp(from.raw, to.raw, up.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief rotate vector using using quaternion
|
|
*
|
|
* @param[in] q quaternion
|
|
* @param[in] v vector to rotate
|
|
* @returns rotated vector
|
|
*/
|
|
CGLM_INLINE
|
|
vec3s
|
|
glms_quat_rotatev(versors q, vec3s v) {
|
|
vec3s dest;
|
|
glm_quat_rotatev(q.raw, v.raw, dest.raw);
|
|
return dest;
|
|
}
|
|
|
|
/*!
|
|
* @brief rotate existing transform matrix using quaternion
|
|
*
|
|
* @param[in] m existing transform matrix
|
|
* @param[in] q quaternion
|
|
* @returns rotated matrix/transform
|
|
*/
|
|
CGLM_INLINE
|
|
mat4s
|
|
glms_quat_rotate(mat4s m, versors q) {
|
|
glm_quat_rotate(m.raw, q.raw, m.raw);
|
|
return m;
|
|
}
|
|
|
|
/*!
|
|
* @brief rotate existing transform matrix using quaternion at pivot point
|
|
*
|
|
* @param[in, out] m existing transform matrix
|
|
* @param[in] q quaternion
|
|
* @returns pivot
|
|
*/
|
|
CGLM_INLINE
|
|
mat4s
|
|
glms_quat_rotate_at(mat4s m, versors q, vec3s pivot) {
|
|
glm_quat_rotate_at(m.raw, q.raw, pivot.raw);
|
|
return m;
|
|
}
|
|
|
|
/*!
|
|
* @brief rotate NEW transform matrix using quaternion at pivot point
|
|
*
|
|
* this creates rotation matrix, it assumes you don't have a matrix
|
|
*
|
|
* this should work faster than glm_quat_rotate_at because it reduces
|
|
* one glm_translate.
|
|
*
|
|
* @param[in] q quaternion
|
|
* @returns pivot
|
|
*/
|
|
CGLM_INLINE
|
|
mat4s
|
|
glms_quat_rotate_atm(versors q, vec3s pivot) {
|
|
mat4s dest;
|
|
glm_quat_rotate_atm(dest.raw, q.raw, pivot.raw);
|
|
return dest;
|
|
}
|
|
|
|
#endif /* cglms_quat_h */
|