Files
cglm/include/cglm-affine.h
Recep Aslantas 4462a84f4a rename _dup (duplicate) to _copy
I think _copy is better and COMMON  name for duplicating/copying
vector, matrices
2017-02-23 09:57:28 +03:00

367 lines
8.0 KiB
C

/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_affine_h
#define cglm_affine_h
#include "cglm-common.h"
#include "cglm-vec.h"
#include "cglm-affine-mat.h"
#include "cglm-util.h"
CGLM_INLINE
void
glm_translate_to(mat4 m, vec3 v, mat4 dest) {
mat4 t = GLM_MAT4_IDENTITY_INIT;
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(dest[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_load_ps(t[0]),
_mm_set1_ps(v[0])),
_mm_mul_ps(_mm_load_ps(t[1]),
_mm_set1_ps(v[1]))),
_mm_add_ps(_mm_mul_ps(_mm_load_ps(t[2]),
_mm_set1_ps(v[2])),
_mm_load_ps(t[3]))))
;
_mm_store_ps(dest[0], _mm_load_ps(m[0]));
_mm_store_ps(dest[1], _mm_load_ps(m[1]));
_mm_store_ps(dest[2], _mm_load_ps(m[2]));
#else
vec4 v1, v2, v3;
glm_vec4_scale(t[0], v[0], v1);
glm_vec4_scale(t[1], v[1], v2);
glm_vec4_scale(t[2], v[2], v3);
glm_vec4_add(v1, t[3], t[3]);
glm_vec4_add(v2, t[3], t[3]);
glm_vec4_add(v3, t[3], t[3]);
glm__memcpy(float, dest, t, sizeof(mat4));
#endif
}
CGLM_INLINE
void
glm_translate(mat4 m, vec3 v) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3],
_mm_add_ps(_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]),
_mm_set1_ps(v[0])),
_mm_mul_ps(_mm_load_ps(m[1]),
_mm_set1_ps(v[1]))),
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]),
_mm_set1_ps(v[2])),
_mm_load_ps(m[3]))))
;
#else
vec4 v1, v2, v3;
glm_vec4_scale(m[0], v[0], v1);
glm_vec4_scale(m[1], v[1], v2);
glm_vec4_scale(m[2], v[2], v3);
glm_vec4_add(v1, m[3], m[3]);
glm_vec4_add(v2, m[3], m[3]);
glm_vec4_add(v3, m[3], m[3]);
#endif
}
CGLM_INLINE
void
glm_translate_x(mat4 m, float to) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[0]),
_mm_set1_ps(to)),
_mm_load_ps(m[3])))
;
#else
vec4 v1;
glm_vec4_scale(m[0], to, v1);
glm_vec4_add(v1, m[3], m[3]);
#endif
}
CGLM_INLINE
void
glm_translate_y(mat4 m, float to) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[1]),
_mm_set1_ps(to)),
_mm_load_ps(m[3])))
;
#else
vec4 v1;
glm_vec4_scale(m[1], to, v1);
glm_vec4_add(v1, m[3], m[3]);
#endif
}
CGLM_INLINE
void
glm_translate_z(mat4 m, float to) {
#if defined( __SSE__ ) || defined( __SSE2__ )
_mm_store_ps(m[3],
_mm_add_ps(_mm_mul_ps(_mm_load_ps(m[2]),
_mm_set1_ps(to)),
_mm_load_ps(m[3])))
;
#else
vec4 v1;
glm_vec4_scale(m[2], to, v1);
glm_vec4_add(v1, m[3], m[3]);
#endif
}
/* scale */
CGLM_INLINE
void
glm_scale_to(mat4 m, vec3 v, mat4 dest) {
glm_vec4_scale(m[0], v[0], dest[0]);
glm_vec4_scale(m[1], v[1], dest[1]);
glm_vec4_scale(m[2], v[2], dest[2]);
glm_vec4_copy(m[3], dest[3]);
}
CGLM_INLINE
void
glm_scale(mat4 m, vec3 v) {
glm_scale_to(m, v, m);
}
CGLM_INLINE
void
glm_scale1(mat4 m, float s) {
vec3 v = { s, s, s };
glm_scale_to(m, v, m);
}
CGLM_INLINE
void
glm_rotate_x(mat4 m, float rad, mat4 dest) {
float cosVal;
float sinVal;
mat4 t = GLM_MAT4_IDENTITY_INIT;
cosVal = cosf(rad);
sinVal = sinf(rad);
t[1][1] = cosVal;
t[1][2] = sinVal;
t[2][1] = -sinVal;
t[2][2] = cosVal;
glm_mat4_mul(m, t, dest);
}
CGLM_INLINE
void
glm_rotate_y(mat4 m, float rad, mat4 dest) {
float cosVal;
float sinVal;
mat4 t = GLM_MAT4_IDENTITY_INIT;
cosVal = cosf(rad);
sinVal = sinf(rad);
t[0][0] = cosVal;
t[0][2] = -sinVal;
t[2][0] = sinVal;
t[2][2] = cosVal;
glm_mat4_mul(m, t, dest);
}
CGLM_INLINE
void
glm_rotate_z(mat4 m, float rad, mat4 dest) {
float cosVal;
float sinVal;
mat4 t = GLM_MAT4_IDENTITY_INIT;
cosVal = cosf(rad);
sinVal = sinf(rad);
t[0][0] = cosVal;
t[0][1] = sinVal;
t[1][0] = -sinVal;
t[1][1] = cosVal;
glm_mat4_mul(m, t, dest);
}
CGLM_INLINE
void
glm_rotate_ndc_make(mat4 m, float angle, vec3 axis_ndc) {
/* https://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml */
vec3 v, vs;
float c;
c = cosf(angle);
glm_vec_scale(axis_ndc, 1.0f - c, v);
glm_vec_scale(axis_ndc, sinf(angle), vs);
glm_vec_scale(axis_ndc, v[0], m[0]);
glm_vec_scale(axis_ndc, v[1], m[1]);
glm_vec_scale(axis_ndc, v[2], m[2]);
m[0][0] += c;
m[0][1] += vs[2];
m[0][2] -= vs[1];
m[1][0] -= vs[2];
m[1][1] += c;
m[1][2] += vs[0];
m[2][0] += vs[1];
m[2][1] -= vs[0];
m[2][2] += c;
m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0f;
m[3][3] = 1.0f;
}
CGLM_INLINE
void
glm_rotate_make(mat4 m, float angle, vec3 axis) {
vec3 axis_ndc;
glm_vec_normalize_to(axis, axis_ndc);
glm_rotate_ndc_make(m, angle, axis_ndc);
}
CGLM_INLINE
void
glm_rotate_ndc(mat4 m, float angle, vec3 axis_ndc) {
mat4 rot, tmp;
glm_rotate_ndc_make(rot, angle, axis_ndc);
glm_vec4_scale(m[0], rot[0][0], tmp[1]);
glm_vec4_scale(m[1], rot[0][1], tmp[0]);
glm_vec4_add(tmp[1], tmp[0], tmp[1]);
glm_vec4_scale(m[2], rot[0][2], tmp[0]);
glm_vec4_add(tmp[1], tmp[0], tmp[1]);
glm_vec4_scale(m[0], rot[1][0], tmp[2]);
glm_vec4_scale(m[1], rot[1][1], tmp[0]);
glm_vec4_add(tmp[2], tmp[0], tmp[2]);
glm_vec4_scale(m[2], rot[1][2], tmp[0]);
glm_vec4_add(tmp[2], tmp[0], tmp[2]);
glm_vec4_scale(m[0], rot[2][0], tmp[3]);
glm_vec4_scale(m[1], rot[2][1], tmp[0]);
glm_vec4_add(tmp[3], tmp[0], tmp[3]);
glm_vec4_scale(m[2], rot[2][2], tmp[0]);
glm_vec4_add(tmp[3], tmp[0], tmp[3]);
glm_vec4_copy(tmp[1], m[0]);
glm_vec4_copy(tmp[2], m[1]);
glm_vec4_copy(tmp[3], m[2]);
}
CGLM_INLINE
void
glm_rotate(mat4 m, float angle, vec3 axis) {
vec3 axis_ndc;
glm_vec_normalize_to(axis, axis_ndc);
glm_rotate_ndc(m, angle, axis_ndc);
}
/*!
* @brief decompose scale vector
*
* @param[in] m affine transform
* @param[out] s scale vector (Sx, Sy, Sz)
*/
CGLM_INLINE
void
glm_decompose_scalev(mat4 m, vec3 s) {
s[0] = glm_vec_norm(m[0]);
s[1] = glm_vec_norm(m[1]);
s[2] = glm_vec_norm(m[2]);
}
/*!
* @brief returns true if matrix is uniform scaled. This is helpful for
* creating normal matrix.
*
* @param m[in] m
*
* @return boolean
*/
CGLM_INLINE
bool
glm_uniscaled(mat4 m) {
vec3 s;
glm_decompose_scalev(m, s);
return glm_vec_eq_all(s);
}
/*!
* @brief decompose rotation matrix (mat4) and scale vector [Sx, Sy, Sz]
*
* @param[in] m affine transform
* @param[out] r rotation matrix
* @param[out] r scale matrix
*/
CGLM_INLINE
void
glm_decompose_rs(mat4 m, mat4 r, vec3 s) {
vec4 t = {0.0f, 0.0f, 0.0f, 1.0f};
vec3 v;
glm_vec4_copy(m[0], r[0]);
glm_vec4_copy(m[1], r[1]);
glm_vec4_copy(m[2], r[2]);
glm_vec4_copy(t, r[3]);
s[0] = glm_vec_norm(m[0]);
s[1] = glm_vec_norm(m[1]);
s[2] = glm_vec_norm(m[2]);
glm_vec4_scale(r[0], 1.0f/s[0], r[0]);
glm_vec4_scale(r[1], 1.0f/s[1], r[1]);
glm_vec4_scale(r[2], 1.0f/s[2], r[2]);
glm_vec_cross(m[0], m[1], v);
if (glm_vec_dot(v, m[2]) < 0.0f) {
glm_vec4_scale(r[0], -1.0f, r[0]);
glm_vec4_scale(r[1], -1.0f, r[1]);
glm_vec4_scale(r[2], -1.0f, r[2]);
glm_vec_scale(s, -1.0f, s);
}
}
/*!
* @brief decompose affine transform
*
* @param[in] m affine transfrom
* @param[out] t translation vector
* @param[out] r rotation matrix (mat4)
* @param[out] s scaling vector [X, Y, Z]
*/
CGLM_INLINE
void
glm_decompose(mat4 m, vec4 t, mat4 r, vec3 s) {
glm_vec4_copy(m[3], t);
glm_decompose_rs(m, r, s);
}
#endif /* cglm_affine_h */