frillrun/include/cglm/struct/quat.h
2024-08-24 00:47:58 -04:00

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 */