Files
korenkonder_ReDIVA/src/KKdLib/mat.cpp
T

2009 lines
63 KiB
C++

/*
by korenkonder
GitHub/GitLab: korenkonder
Matrix Inverse algo: https://github.com/niswegmann/small-matrix-inverse
*/
#include "mat.hpp"
const mat3 mat3_identity = {
{ 1.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
};
const mat3 mat3_null = {
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
};
const mat4 mat4_identity = {
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f },
};
const mat4 mat4_null = {
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
};
inline void mat3_add(const mat3* in_m1, const float_t value, mat3* out_m) {
out_m->row0 = in_m1->row0 + value;
out_m->row1 = in_m1->row1 + value;
out_m->row2 = in_m1->row2 + value;
}
inline void mat3_add(const mat3* in_m1, const mat3* in_m2, mat3* out_m) {
out_m->row0 = in_m1->row0 + in_m2->row0;
out_m->row1 = in_m1->row1 + in_m2->row1;
out_m->row2 = in_m1->row2 + in_m2->row2;
}
inline void mat3_sub(const mat3* in_m1, const float_t value, mat3* out_m) {
out_m->row0 = in_m1->row0 - value;
out_m->row1 = in_m1->row1 - value;
out_m->row2 = in_m1->row2 - value;
}
inline void mat3_sub(const mat3* in_m1, const mat3* in_m2, mat3* out_m) {
out_m->row0 = in_m1->row0 - in_m2->row0;
out_m->row1 = in_m1->row1 - in_m2->row1;
out_m->row2 = in_m1->row2 - in_m2->row2;
}
inline void mat3_mul(const mat3* in_m1, const float_t value, mat3* out_m) {
out_m->row0 = in_m1->row0 * value;
out_m->row1 = in_m1->row1 * value;
out_m->row2 = in_m1->row2 * value;
}
inline void mat3_mul(const mat3* in_m1, const mat3* in_m2, mat3* out_m) {
__m128 t0;
__m128 t1;
__m128 t2;
__m128 yt;
__m128 xt0;
__m128 xt1;
__m128 xt2;
xt0 = vec3::load_xmm(in_m1->row0);
xt1 = vec3::load_xmm(in_m1->row1);
xt2 = vec3::load_xmm(in_m1->row2);
yt = vec3::load_xmm(in_m2->row0);
t0 = _mm_mul_ps(xt0, _mm_shuffle_ps(yt, yt, 0x00));
t1 = _mm_mul_ps(xt1, _mm_shuffle_ps(yt, yt, 0x55));
t2 = _mm_mul_ps(xt2, _mm_shuffle_ps(yt, yt, 0xAA));
out_m->row0 = vec3::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), t2));
yt = vec3::load_xmm(in_m2->row1);
t0 = _mm_mul_ps(xt0, _mm_shuffle_ps(yt, yt, 0x00));
t1 = _mm_mul_ps(xt1, _mm_shuffle_ps(yt, yt, 0x55));
t2 = _mm_mul_ps(xt2, _mm_shuffle_ps(yt, yt, 0xAA));
out_m->row1 = vec3::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), t2));
yt = vec3::load_xmm(in_m2->row2);
t0 = _mm_mul_ps(xt0, _mm_shuffle_ps(yt, yt, 0x00));
t1 = _mm_mul_ps(xt1, _mm_shuffle_ps(yt, yt, 0x55));
t2 = _mm_mul_ps(xt2, _mm_shuffle_ps(yt, yt, 0xAA));
out_m->row2 = vec3::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), t2));
}
inline void mat3_mul(const mat3* in_m1, const vec3* in_axis, const float_t in_angle, mat3* out_m) {
quat q1 = quat(in_m1->row0.x, in_m1->row1.x, in_m1->row2.x, in_m1->row0.y,
in_m1->row1.y, in_m1->row2.y, in_m1->row0.z, in_m1->row1.z, in_m1->row2.z);
quat q2 = quat(*in_axis, in_angle);
quat q3 = quat::mul(q2, q1);
mat3_set(&q3, out_m);
}
inline void mat3_transform_vector(const mat3* in_m1, const vec2* normal, vec2* normalOut) {
__m128 yt;
__m128 zt0;
__m128 zt1;
yt = vec2::load_xmm(*normal);
zt0 = _mm_mul_ps(vec3::load_xmm(in_m1->row0), _mm_shuffle_ps(yt, yt, 0x00));
zt1 = _mm_mul_ps(vec3::load_xmm(in_m1->row1), _mm_shuffle_ps(yt, yt, 0x55));
*normalOut = vec2::store_xmm(_mm_add_ps(zt0, zt1));
}
inline void mat3_transform_vector(const mat3* in_m1, const vec3* normal, vec3* normalOut) {
__m128 yt;
__m128 zt0;
__m128 zt1;
__m128 zt2;
yt = vec3::load_xmm(*normal);
zt0 = _mm_mul_ps(vec3::load_xmm(in_m1->row0), _mm_shuffle_ps(yt, yt, 0x00));
zt1 = _mm_mul_ps(vec3::load_xmm(in_m1->row1), _mm_shuffle_ps(yt, yt, 0x55));
zt2 = _mm_mul_ps(vec3::load_xmm(in_m1->row2), _mm_shuffle_ps(yt, yt, 0xAA));
*normalOut = vec3::store_xmm(_mm_add_ps(_mm_add_ps(zt0, zt1), zt2));
}
inline void mat3_inverse_transform_vector(const mat3* in_m1, const vec2* normal, vec2* normalOut) {
__m128 yt;
__m128 zt;
yt = vec2::load_xmm(*normal);
zt = _mm_mul_ps(yt, vec3::load_xmm(in_m1->row0));
normalOut->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec3::load_xmm(in_m1->row1));
normalOut->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
}
inline void mat3_inverse_transform_vector(const mat3* in_m1, const vec3* normal, vec3* normalOut) {
__m128 yt;
__m128 zt;
yt = vec3::load_xmm(*normal);
zt = _mm_mul_ps(yt, vec3::load_xmm(in_m1->row0));
zt = _mm_hadd_ps(zt, zt);
normalOut->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec3::load_xmm(in_m1->row1));
zt = _mm_hadd_ps(zt, zt);
normalOut->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec3::load_xmm(in_m1->row2));
zt = _mm_hadd_ps(zt, zt);
normalOut->z = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
}
inline void mat3_transpose(const mat3* in_m1, mat3* out_m) {
__m128 xt0;
__m128 xt1;
__m128 xt2;
__m128 xt3;
__m128 yt0;
__m128 yt1;
__m128 yt2;
__m128 yt3;
xt0 = vec3::load_xmm(in_m1->row0);
xt1 = vec3::load_xmm(in_m1->row1);
xt2 = vec3::load_xmm(in_m1->row2);
xt3 = vec4::load_xmm(0.0f);
yt0 = _mm_unpacklo_ps(xt0, xt1);
yt1 = _mm_unpackhi_ps(xt0, xt1);
yt2 = _mm_unpacklo_ps(xt2, xt3);
yt3 = _mm_unpackhi_ps(xt2, xt3);
out_m->row0 = vec3::store_xmm(_mm_movelh_ps(yt0, yt2));
out_m->row1 = vec3::store_xmm(_mm_movehl_ps(yt2, yt0));
out_m->row2 = vec3::store_xmm(_mm_movelh_ps(yt1, yt3));
}
void mat3_invert(const mat3* in_m1, mat3* out_m) {
vec3 xt0;
vec3 xt1;
vec3 xt2;
__m128 zt0;
__m128 zt1;
__m128 zt2;
__m128 wt;
xt0 = in_m1->row0;
xt1 = in_m1->row1;
xt2 = in_m1->row2;
zt0 = _mm_sub_ps(
_mm_mul_ps(
_mm_set_ps(0.0f, xt0.y, xt0.z, xt1.y),
_mm_set_ps(0.0f, xt1.z, xt2.y, xt2.z)
),
_mm_mul_ps(
_mm_set_ps(0.0f, xt0.z, xt0.y, xt1.z),
_mm_set_ps(0.0f, xt1.y, xt2.z, xt2.y)
)
);
zt1 = _mm_sub_ps(
_mm_mul_ps(
_mm_set_ps(0.0f, xt0.z, xt0.x, xt1.z),
_mm_set_ps(0.0f, xt1.x, xt2.z, xt2.x)
),
_mm_mul_ps(
_mm_set_ps(0.0f, xt0.x, xt0.z, xt1.x),
_mm_set_ps(0.0f, xt1.z, xt2.x, xt2.z)
)
);
zt2 = _mm_sub_ps(
_mm_mul_ps(
_mm_set_ps(0.0f, xt0.x, xt0.y, xt1.x),
_mm_set_ps(0.0f, xt1.y, xt2.x, xt2.y)
),
_mm_mul_ps(
_mm_set_ps(0.0f, xt0.y, xt0.x, xt1.y),
_mm_set_ps(0.0f, xt1.x, xt2.y, xt2.x)
)
);
wt = _mm_movelh_ps(_mm_unpacklo_ps(zt0, zt1), zt2);
wt = _mm_mul_ps(vec3::load_xmm(xt0), wt);
wt = _mm_hadd_ps(wt, wt);
wt = _mm_hadd_ps(wt, wt);
if (_mm_cvtss_f32(wt) != 0.0f)
wt = _mm_div_ss(_mm_set_ss(1.0f), wt);
wt = _mm_shuffle_ps(wt, wt, 0);
out_m->row0 = vec3::store_xmm(_mm_mul_ps(zt0, wt));
out_m->row1 = vec3::store_xmm(_mm_mul_ps(zt1, wt));
out_m->row2 = vec3::store_xmm(_mm_mul_ps(zt2, wt));
}
inline void mat3_invert_fast(const mat3* in_m1, mat3* out_m) {
mat3_transpose(in_m1, out_m);
}
inline void mat3_normalize(const mat3* in_m1, mat3* out_m) {
float_t det = mat3_determinant(in_m1);
if (det != 0.0f)
det = 1.0f / det;
out_m->row0 = in_m1->row0 * det;
out_m->row1 = in_m1->row1 * det;
out_m->row2 = in_m1->row2 * det;
}
inline void mat3_normalize_rotation(const mat3* in_m1, mat3* out_m) {
out_m->row0 = vec3::normalize(in_m1->row0);
out_m->row1 = vec3::normalize(in_m1->row1);
out_m->row2 = vec3::normalize(in_m1->row2);
}
inline float_t mat3_determinant(const mat3* in_m1) {
vec3 xt0;
vec3 xt1;
vec3 xt2;
xt0 = in_m1->row0;
xt1 = in_m1->row1;
xt2 = in_m1->row2;
float_t b00 = xt0.x * xt1.y * xt2.z;
float_t b01 = xt0.y * xt1.z * xt2.x;
float_t b02 = xt0.z * xt1.x * xt2.y;
float_t b03 = xt0.z * xt1.y * xt2.x;
float_t b04 = xt0.x * xt1.z * xt2.y;
float_t b05 = xt0.y * xt1.x * xt2.z;
return b00 + b01 + b02 - b03 - b04 - b05;
}
inline void mat3_rotate_x(float_t rad, mat3* out_m) {
float_t s = sinf(rad);
float_t c = cosf(rad);
*out_m = mat3_identity;
out_m->row1.y = c;
out_m->row1.z = s;
out_m->row2.y = -s;
out_m->row2.z = c;
}
inline void mat3_rotate_y(float_t rad, mat3* out_m) {
float_t s = sinf(rad);
float_t c = cosf(rad);
*out_m = mat3_identity;
out_m->row0.x = c;
out_m->row0.z = -s;
out_m->row2.x = s;
out_m->row2.z = c;
}
inline void mat3_rotate_z(float_t rad, mat3* out_m) {
float_t s = sinf(rad);
float_t c = cosf(rad);
*out_m = mat3_identity;
out_m->row0.x = c;
out_m->row0.y = s;
out_m->row1.x = -s;
out_m->row1.y = c;
}
inline void mat3_rotate_x(float_t s, float_t c, mat3* out_m) {
*out_m = mat3_identity;
out_m->row1.y = c;
out_m->row1.z = s;
out_m->row2.y = -s;
out_m->row2.z = c;
}
inline void mat3_rotate_y(float_t s, float_t c, mat3* out_m) {
*out_m = mat3_identity;
out_m->row0.x = c;
out_m->row0.z = -s;
out_m->row2.x = s;
out_m->row2.z = c;
}
inline void mat3_rotate_z(float_t s, float_t c, mat3* out_m) {
*out_m = mat3_identity;
out_m->row0.x = c;
out_m->row0.y = s;
out_m->row1.x = -s;
out_m->row1.y = c;
}
inline void mat3_rotate_xyz(float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = mat3_identity;
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
*out_m = dt;
}
inline void mat3_rotate_xzy(float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = mat3_identity;
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
*out_m = dt;
}
inline void mat3_rotate_yxz(float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = mat3_identity;
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
*out_m = dt;
}
inline void mat3_rotate_yzx(float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = mat3_identity;
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
*out_m = dt;
}
inline void mat3_rotate_zxy(float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = mat3_identity;
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
*out_m = dt;
}
inline void mat3_rotate_zyx(float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = mat3_identity;
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
*out_m = dt;
}
inline void mat3_mul_rotate_x(const mat3* in_m1, float_t rad, mat3* out_m) {
__m128 t1;
__m128 t2;
__m128 y0;
__m128 y1;
__m128 y2;
float_t s = sinf(rad);
float_t c = cosf(rad);
y0 = vec3::load_xmm(in_m1->row0);
y1 = vec3::load_xmm(in_m1->row1);
y2 = vec3::load_xmm(in_m1->row2);
out_m->row0 = vec3::store_xmm(y0);
t1 = _mm_mul_ps(y1, vec4::load_xmm(c));
t2 = _mm_mul_ps(y2, vec4::load_xmm(s));
out_m->row1 = vec3::store_xmm(_mm_add_ps(t1, t2));
t1 = _mm_mul_ps(y1, vec4::load_xmm(-s));
t2 = _mm_mul_ps(y2, vec4::load_xmm(c));
out_m->row2 = vec3::store_xmm(_mm_add_ps(t1, t2));
}
inline void mat3_mul_rotate_y(const mat3* in_m1, float_t rad, mat3* out_m) {
__m128 t0;
__m128 t2;
__m128 y0;
__m128 y1;
__m128 y2;
float_t s = sinf(rad);
float_t c = cosf(rad);
y0 = vec3::load_xmm(in_m1->row0);
y1 = vec3::load_xmm(in_m1->row1);
y2 = vec3::load_xmm(in_m1->row2);
t0 = _mm_mul_ps(y0, vec4::load_xmm(c));
t2 = _mm_mul_ps(y2, vec4::load_xmm(-s));
out_m->row0 = vec3::store_xmm(_mm_add_ps(t0, t2));
out_m->row1 = vec3::store_xmm(y1);
t0 = _mm_mul_ps(y0, vec4::load_xmm(s));
t2 = _mm_mul_ps(y2, vec4::load_xmm(c));
out_m->row2 = vec3::store_xmm(_mm_add_ps(t0, t2));
}
inline void mat3_mul_rotate_z(const mat3* in_m1, float_t rad, mat3* out_m) {
__m128 t0;
__m128 t1;
__m128 y0;
__m128 y1;
__m128 y2;
float_t s = sinf(rad);
float_t c = cosf(rad);
y0 = vec3::load_xmm(in_m1->row0);
y1 = vec3::load_xmm(in_m1->row1);
y2 = vec3::load_xmm(in_m1->row2);
t0 = _mm_mul_ps(y0, vec4::load_xmm(c));
t1 = _mm_mul_ps(y1, vec4::load_xmm(s));
out_m->row0 = vec3::store_xmm(_mm_add_ps(t0, t1));
t0 = _mm_mul_ps(y0, vec4::load_xmm(-s));
t1 = _mm_mul_ps(y1, vec4::load_xmm(c));
out_m->row1 = vec3::store_xmm(_mm_add_ps(t0, t1));
out_m->row2 = vec3::store_xmm(y2);
}
inline void mat3_mul_rotate_x(const mat3* in_m1, float_t s, float_t c, mat3* out_m) {
__m128 t1;
__m128 t2;
__m128 y0;
__m128 y1;
__m128 y2;
y0 = vec3::load_xmm(in_m1->row0);
y1 = vec3::load_xmm(in_m1->row1);
y2 = vec3::load_xmm(in_m1->row2);
out_m->row0 = vec3::store_xmm(y0);
t1 = _mm_mul_ps(y1, vec4::load_xmm(c));
t2 = _mm_mul_ps(y2, vec4::load_xmm(s));
out_m->row1 = vec3::store_xmm(_mm_add_ps(t1, t2));
t1 = _mm_mul_ps(y1, vec4::load_xmm(-s));
t2 = _mm_mul_ps(y2, vec4::load_xmm(c));
out_m->row2 = vec3::store_xmm(_mm_add_ps(t1, t2));
}
inline void mat3_mul_rotate_y(const mat3* in_m1, float_t s, float_t c, mat3* out_m) {
__m128 t0;
__m128 t2;
__m128 y0;
__m128 y1;
__m128 y2;
y0 = vec3::load_xmm(in_m1->row0);
y1 = vec3::load_xmm(in_m1->row1);
y2 = vec3::load_xmm(in_m1->row2);
t0 = _mm_mul_ps(y0, vec4::load_xmm(c));
t2 = _mm_mul_ps(y2, vec4::load_xmm(-s));
out_m->row0 = vec3::store_xmm(_mm_add_ps(t0, t2));
out_m->row1 = vec3::store_xmm(y1);
t0 = _mm_mul_ps(y0, vec4::load_xmm(s));
t2 = _mm_mul_ps(y2, vec4::load_xmm(c));
out_m->row2 = vec3::store_xmm(_mm_add_ps(t0, t2));
}
inline void mat3_mul_rotate_z(const mat3* in_m1, float_t s, float_t c, mat3* out_m) {
__m128 t0;
__m128 t1;
__m128 y0;
__m128 y1;
__m128 y2;
y0 = vec3::load_xmm(in_m1->row0);
y1 = vec3::load_xmm(in_m1->row1);
y2 = vec3::load_xmm(in_m1->row2);
t0 = _mm_mul_ps(y0, vec4::load_xmm(c));
t1 = _mm_mul_ps(y1, vec4::load_xmm(s));
out_m->row0 = vec3::store_xmm(_mm_add_ps(t0, t1));
t0 = _mm_mul_ps(y0, vec4::load_xmm(-s));
t1 = _mm_mul_ps(y1, vec4::load_xmm(c));
out_m->row1 = vec3::store_xmm(_mm_add_ps(t0, t1));
out_m->row2 = vec3::store_xmm(y2);
}
inline void mat3_mul_rotate_xyz(const mat3* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = *in_m1;
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
*out_m = dt;
}
inline void mat3_mul_rotate_xzy(const mat3* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = *in_m1;
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
*out_m = dt;
}
inline void mat3_mul_rotate_yxz(const mat3* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = *in_m1;
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
*out_m = dt;
}
inline void mat3_mul_rotate_yzx(const mat3* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = *in_m1;
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
*out_m = dt;
}
inline void mat3_mul_rotate_zxy(const mat3* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = *in_m1;
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
*out_m = dt;
}
inline void mat3_mul_rotate_zyx(const mat3* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat3* out_m) {
mat3 dt;
dt = *in_m1;
if (rad_z != 0.0f)
mat3_mul_rotate_z(&dt, rad_z, &dt);
if (rad_y != 0.0f)
mat3_mul_rotate_y(&dt, rad_y, &dt);
if (rad_x != 0.0f)
mat3_mul_rotate_x(&dt, rad_x, &dt);
*out_m = dt;
}
inline void mat3_scale(float_t sx, float_t sy, float_t sz, mat3* out_m) {
*out_m = mat3_identity;
out_m->row0.x = sx;
out_m->row1.y = sy;
out_m->row2.z = sz;
}
inline void mat3_scale_x(float_t s, mat3* out_m) {
*out_m = mat3_identity;
out_m->row0.x = s;
}
inline void mat3_scale_y(float_t s, mat3* out_m) {
*out_m = mat3_identity;
out_m->row1.y = s;
}
inline void mat3_scale_z(float_t s, mat3* out_m) {
*out_m = mat3_identity;
out_m->row2.z = s;
}
inline void mat3_mul_scale(const mat3* in_m1, float_t sx, float_t sy, float_t sz, mat3* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
if (sx != 1.0f || sy != 1.0f || sz != 1.0f) {
out_m->row0 *= sx;
out_m->row1 *= sy;
out_m->row2 *= sz;
}
}
inline void mat3_mul_scale_x(const mat3* in_m1, float_t s, mat3* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
out_m->row0 *= s;
}
inline void mat3_mul_scale_y(const mat3* in_m1, float_t s, mat3* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
out_m->row1 *= s;
}
inline void mat3_mul_scale_z(const mat3* in_m1, float_t s, mat3* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
out_m->row2 *= s;
}
inline void mat3_set(const quat* in_q1, mat3* out_m) {
float_t x = in_q1->x;
float_t y = in_q1->y;
float_t z = in_q1->z;
float_t w = in_q1->w;
float_t len = quat::length_squared(*in_q1);
len = len > 0.0f ? 2.0f / len : 0.0f;
float_t xx = x * x * len;
float_t xy = x * y * len;
float_t xz = x * z * len;
float_t yy = y * y * len;
float_t zz = z * z * len;
float_t yz = y * z * len;
float_t wx = w * x * len;
float_t wy = w * y * len;
float_t wz = w * z * len;
out_m->row0.x = 1.0f - zz - yy;
out_m->row0.y = xy + wz;
out_m->row0.z = xz - wy;
out_m->row1.x = xy - wz;
out_m->row1.y = 1.0f - zz - xx;
out_m->row1.z = yz + wx;
out_m->row2.x = xz + wy;
out_m->row2.y = yz - wx;
out_m->row2.z = 1.0f - yy - xx;
}
inline void mat3_set(const vec3* in_axis, float_t in_angle, mat3* out_m) {
mat3_set(in_axis, sinf(in_angle), cosf(in_angle), out_m);
}
inline void mat3_set(const vec3* in_axis, float_t s, float_t c, mat3* out_m) {
float_t c_1 = 1.0f - c;
vec3 axis = vec3::normalize(*in_axis);
vec3 axis_s = axis * s;
vec3 temp;
temp = axis * axis.x * c_1;
out_m->row0.x = temp.x + c;
out_m->row1.x = temp.y - axis_s.z;
out_m->row2.x = temp.z + axis_s.y;
temp = axis * axis.y * c_1;
out_m->row0.y = temp.x + axis_s.z;
out_m->row1.y = temp.y + c;
out_m->row2.y = temp.z - axis_s.x;
temp = axis * axis.z * c_1;
out_m->row0.z = temp.x - axis_s.y;
out_m->row1.z = temp.y + axis_s.x;
out_m->row2.z = temp.z + c;
}
inline void mat4_to_mat3(const mat4* in_m1, mat3* out_m) {
out_m->row0 = *(vec3*)&in_m1->row0;
out_m->row1 = *(vec3*)&in_m1->row1;
out_m->row2 = *(vec3*)&in_m1->row2;
}
inline void mat4_to_mat3_inverse(const mat4* in_m1, mat3* out_m) {
mat4 yt;
mat4_invert(in_m1, &yt);
out_m->row0 = *(vec3*)&yt.row0;
out_m->row1 = *(vec3*)&yt.row1;
out_m->row2 = *(vec3*)&yt.row2;
}
inline void mat3_get_rotation(const mat3* in_m1, vec3* out_rad) {
if (-in_m1->row0.z >= 1.0f)
out_rad->y = (float_t)M_PI_2;
else if (-in_m1->row0.z <= -1.0f)
out_rad->y = (float_t)-M_PI_2;
else
out_rad->y = asinf(-in_m1->row0.z);
if (fabsf(in_m1->row0.z) < 0.99999899f) {
out_rad->x = atan2f(in_m1->row1.z, in_m1->row2.z);
out_rad->z = atan2f(in_m1->row0.y, in_m1->row0.x);
}
else {
out_rad->x = 0.0f;
out_rad->z = atan2f(in_m1->row2.y, in_m1->row1.y);
if (in_m1->row0.z > 0.0f)
out_rad->z = -out_rad->z;
}
}
inline void mat3_get_scale(const mat3* in_m1, vec3* out_s) {
out_s->x = vec3::length(in_m1->row0);
out_s->y = vec3::length(in_m1->row1);
out_s->z = vec3::length(in_m1->row2);
}
inline float_t mat3_get_max_scale(const mat3* in_m1) {
mat3 mat;
mat3_transpose(in_m1, &mat);
float_t length;
float_t max = 0.0f;
length = vec3::length(mat.row0);
if (max < length)
max = length;
length = vec3::length(mat.row1);
if (max < length)
max = length;
length = vec3::length(mat.row2);
if (max < length)
max = length;
return max;
}
inline void mat4_set(const quat* in_q1, mat4* out_m) {
mat4_set_rotation(out_m, in_q1);
out_m->row0.w = 0.0f;
out_m->row1.w = 0.0f;
out_m->row2.w = 0.0f;
out_m->row3 = { 0.0f, 0.0f, 0.0f, 1.0f };
}
static float_t vec3_angle_between_two_vectors(const vec3& in_v1, const vec3& in_v2) {
vec3 z_t = vec3::cross(in_v1, in_v2);
float_t v2 = vec3::length(z_t);
float_t v3 = vec3::dot(in_v1, in_v2);
return fabsf(atan2f(v2, v3));
}
void mat4_set(const vec3* in_v1, const vec3* in_v2, mat4* out_m) {
*out_m = mat4_identity;
if (*in_v1 == *in_v2)
return;
if (fabsf(1.0f - vec3::dot(*in_v1, *in_v2)) <= 0.000001f)
return;
vec3 axis = vec3::cross(*in_v1, *in_v2);
float_t axis_length = vec3::length(axis);
if (axis_length > 0.000001f) {
float_t angle = vec3_angle_between_two_vectors(*in_v1, *in_v2);
if (axis_length != 0.0)
axis *= 1.0f / axis_length;
mat4_set(&axis, angle, out_m);
}
}
inline void mat4_set(const vec3* in_axis, float_t in_angle, mat4* out_m) {
mat4_set_rotation(out_m, in_axis, sinf(in_angle), cosf(in_angle));
out_m->row0.w = 0.0f;
out_m->row1.w = 0.0f;
out_m->row2.w = 0.0f;
out_m->row3 = { 0.0f, 0.0f, 0.0f, 1.0f };
}
inline void mat4_set(const vec3* in_axis, float_t s, float_t c, mat4* out_m) {
mat4_set_rotation(out_m, in_axis, s, c);
out_m->row0.w = 0.0f;
out_m->row1.w = 0.0f;
out_m->row2.w = 0.0f;
out_m->row3 = { 0.0f, 0.0f, 0.0f, 1.0f };
}
inline void mat4_set_rotation(mat4* in_m1, const quat* in_q1) {
float_t x = in_q1->x;
float_t y = in_q1->y;
float_t z = in_q1->z;
float_t w = in_q1->w;
float_t len = quat::length_squared(*in_q1);
len = len > 0.0f ? 2.0f / len : 0.0f;
float_t xx = x * x * len;
float_t xy = x * y * len;
float_t xz = x * z * len;
float_t yy = y * y * len;
float_t zz = z * z * len;
float_t yz = y * z * len;
float_t wx = w * x * len;
float_t wy = w * y * len;
float_t wz = w * z * len;
in_m1->row0.x = 1.0f - zz - yy;
in_m1->row0.y = xy + wz;
in_m1->row0.z = xz - wy;
in_m1->row1.x = xy - wz;
in_m1->row1.y = 1.0f - zz - xx;
in_m1->row1.z = yz + wx;
in_m1->row2.x = xz + wy;
in_m1->row2.y = yz - wx;
in_m1->row2.z = 1.0f - yy - xx;
}
inline void mat4_set_rotation(mat4* in_m1, const vec3* in_axis, const float_t in_angle) {
mat4_set_rotation(in_m1, in_axis, sinf(in_angle), cosf(in_angle));
}
inline void mat4_set_rotation(mat4* in_m1, const vec3* in_axis, const float_t s, const float_t c) {
float_t c_1 = 1.0f - c;
vec3 axis = vec3::normalize(*in_axis);
vec3 axis_s = axis * s;
vec3 temp;
temp = axis * axis.x * c_1;
in_m1->row0.x = temp.x + c;
in_m1->row1.x = temp.y - axis_s.z;
in_m1->row2.x = temp.z + axis_s.y;
temp = axis * axis.y * c_1;
in_m1->row0.y = temp.x + axis_s.z;
in_m1->row1.y = temp.y + c;
in_m1->row2.y = temp.z - axis_s.x;
temp = axis * axis.z * c_1;
in_m1->row0.z = temp.x - axis_s.y;
in_m1->row1.z = temp.y + axis_s.x;
in_m1->row2.z = temp.z + c;
}
inline void mat4_add(const mat4* in_m1, const float_t value, mat4* out_m) {
out_m->row0 = in_m1->row0 + value;
out_m->row1 = in_m1->row1 + value;
out_m->row2 = in_m1->row2 + value;
out_m->row3 = in_m1->row3 + value;
}
inline void mat4_add(const mat4* in_m1, const mat4* in_m2, mat4* out_m) {
out_m->row0 = in_m1->row0 + in_m2->row0;
out_m->row1 = in_m1->row1 + in_m2->row1;
out_m->row2 = in_m1->row2 + in_m2->row2;
out_m->row3 = in_m1->row3 + in_m2->row3;
}
inline void mat4_sub(const mat4* in_m1, const float_t value, mat4* out_m) {
out_m->row0 = in_m1->row0 - value;
out_m->row1 = in_m1->row1 - value;
out_m->row2 = in_m1->row2 - value;
out_m->row3 = in_m1->row3 - value;
}
inline void mat4_sub(const mat4* in_m1, const mat4* in_m2, mat4* out_m) {
out_m->row0 = in_m1->row0 - in_m2->row0;
out_m->row1 = in_m1->row1 - in_m2->row1;
out_m->row2 = in_m1->row2 - in_m2->row2;
out_m->row3 = in_m1->row3 - in_m2->row3;
}
inline void mat4_mul(const mat4* in_m1, const float_t value, mat4* out_m) {
out_m->row0 = in_m1->row0 * value;
out_m->row1 = in_m1->row1 * value;
out_m->row2 = in_m1->row2 * value;
out_m->row3 = in_m1->row3 * value;
}
inline void mat4_mul(const mat4* in_m1, const mat4* in_m2, mat4* out_m) {
__m128 t0;
__m128 t1;
__m128 t2;
__m128 t3;
__m128 xt;
__m128 y0;
__m128 y1;
__m128 y2;
__m128 y3;
y0 = vec4::load_xmm(in_m2->row0);
y1 = vec4::load_xmm(in_m2->row1);
y2 = vec4::load_xmm(in_m2->row2);
y3 = vec4::load_xmm(in_m2->row3);
xt = vec4::load_xmm(in_m1->row0);
t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00));
t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x55));
t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0xAA));
t3 = _mm_mul_ps(y3, _mm_shuffle_ps(xt, xt, 0xFF));
out_m->row0 = vec4::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), _mm_add_ps(t2, t3)));
xt = vec4::load_xmm(in_m1->row1);
t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00));
t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x55));
t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0xAA));
t3 = _mm_mul_ps(y3, _mm_shuffle_ps(xt, xt, 0xFF));
out_m->row1 = vec4::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), _mm_add_ps(t2, t3)));
xt = vec4::load_xmm(in_m1->row2);
t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00));
t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x55));
t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0xAA));
t3 = _mm_mul_ps(y3, _mm_shuffle_ps(xt, xt, 0xFF));
out_m->row2 = vec4::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), _mm_add_ps(t2, t3)));
xt = vec4::load_xmm(in_m1->row3);
t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00));
t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x55));
t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0xAA));
t3 = _mm_mul_ps(y3, _mm_shuffle_ps(xt, xt, 0xFF));
out_m->row3 = vec4::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), _mm_add_ps(t2, t3)));
}
inline void mat4_mul_rotation(const mat4* in_m1, const vec3* in_axis, const float_t in_angle, mat4* out_m) {
quat q1 = quat(in_m1->row0.x, in_m1->row1.x, in_m1->row2.x, in_m1->row0.y,
in_m1->row1.y, in_m1->row2.y, in_m1->row0.z, in_m1->row1.z, in_m1->row2.z);
quat q2 = quat(*in_axis, in_angle);
quat q3 = quat::mul(q2, q1);
mat4_set(&q3, out_m);
}
inline void mat4_transform_vector(const mat4* in_m1, const vec2* normal, vec2* normalOut) {
__m128 yt;
__m128 zt0;
__m128 zt1;
yt = vec2::load_xmm(*normal);
zt0 = _mm_mul_ps(vec4::load_xmm(in_m1->row0), _mm_shuffle_ps(yt, yt, 0x00));
zt1 = _mm_mul_ps(vec4::load_xmm(in_m1->row1), _mm_shuffle_ps(yt, yt, 0x55));
*normalOut = vec2::store_xmm(_mm_add_ps(zt0, zt1));
}
inline void mat4_transform_vector(const mat4* in_m1, const vec3* normal, vec3* normalOut) {
__m128 yt;
__m128 zt0;
__m128 zt1;
__m128 zt2;
yt = vec3::load_xmm(*normal);
zt0 = _mm_mul_ps(vec4::load_xmm(in_m1->row0), _mm_shuffle_ps(yt, yt, 0x00));
zt1 = _mm_mul_ps(vec4::load_xmm(in_m1->row1), _mm_shuffle_ps(yt, yt, 0x55));
zt2 = _mm_mul_ps(vec4::load_xmm(in_m1->row2), _mm_shuffle_ps(yt, yt, 0xAA));
*normalOut = vec3::store_xmm(_mm_add_ps(_mm_add_ps(zt0, zt1), zt2));
}
inline void mat4_transform_vector(const mat4* in_m1, const vec4* normal, vec4* normalOut) {
__m128 yt;
__m128 zt0;
__m128 zt1;
__m128 zt2;
__m128 zt3;
yt = vec4::load_xmm(*normal);
zt0 = _mm_mul_ps(vec4::load_xmm(in_m1->row0), _mm_shuffle_ps(yt, yt, 0x00));
zt1 = _mm_mul_ps(vec4::load_xmm(in_m1->row1), _mm_shuffle_ps(yt, yt, 0x55));
zt2 = _mm_mul_ps(vec4::load_xmm(in_m1->row2), _mm_shuffle_ps(yt, yt, 0xAA));
zt3 = _mm_mul_ps(vec4::load_xmm(in_m1->row3), _mm_shuffle_ps(yt, yt, 0xFF));
*normalOut = vec4::store_xmm(_mm_add_ps(_mm_add_ps(zt0, zt1), _mm_add_ps(zt2, zt3)));
}
inline void mat4_transform_point(const mat4* in_m1, const vec2* point, vec2* normalOut) {
__m128 yt;
__m128 zt0;
__m128 zt1;
__m128 zt2;
yt = vec2::load_xmm(*point);
zt0 = _mm_mul_ps(vec4::load_xmm(in_m1->row0), _mm_shuffle_ps(yt, yt, 0x00));
zt1 = _mm_mul_ps(vec4::load_xmm(in_m1->row1), _mm_shuffle_ps(yt, yt, 0x55));
zt2 = vec4::load_xmm(in_m1->row3);
*normalOut = vec2::store_xmm(_mm_add_ps(_mm_add_ps(zt0, zt1), zt2));
}
inline void mat4_transform_point(const mat4* in_m1, const vec3* point, vec3* normalOut) {
__m128 yt;
__m128 zt0;
__m128 zt1;
__m128 zt2;
__m128 zt3;
yt = vec3::load_xmm(*point);
zt0 = _mm_mul_ps(vec4::load_xmm(in_m1->row0), _mm_shuffle_ps(yt, yt, 0x00));
zt1 = _mm_mul_ps(vec4::load_xmm(in_m1->row1), _mm_shuffle_ps(yt, yt, 0x55));
zt2 = _mm_mul_ps(vec4::load_xmm(in_m1->row2), _mm_shuffle_ps(yt, yt, 0xAA));
zt3 = vec4::load_xmm(in_m1->row3);
*normalOut = vec3::store_xmm(_mm_add_ps(_mm_add_ps(zt0, zt1), _mm_add_ps(zt2, zt3)));
}
inline void mat4_inverse_transform_vector(const mat4* in_m1, const vec2* normal, vec2* normalOut) {
__m128 yt;
__m128 zt;
yt = vec2::load_xmm(*normal);
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row0));
normalOut->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row1));
normalOut->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
}
inline void mat4_inverse_transform_vector(const mat4* in_m1, const vec3* normal, vec3* normalOut) {
__m128 yt;
__m128 zt;
yt = vec3::load_xmm(*normal);
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row0));
zt = _mm_hadd_ps(zt, zt);
normalOut->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row1));
zt = _mm_hadd_ps(zt, zt);
normalOut->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row2));
zt = _mm_hadd_ps(zt, zt);
normalOut->z = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
}
inline void mat4_inverse_transform_vector(const mat4* in_m1, const vec4* normal, vec4* normalOut) {
__m128 yt;
__m128 zt;
yt = vec4::load_xmm(*normal);
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row0));
zt = _mm_hadd_ps(zt, zt);
normalOut->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row1));
zt = _mm_hadd_ps(zt, zt);
normalOut->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row2));
zt = _mm_hadd_ps(zt, zt);
normalOut->z = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row3));
zt = _mm_hadd_ps(zt, zt);
normalOut->w = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
}
inline void mat4_inverse_transform_point(const mat4* in_m1, const vec2* point, vec2* pointOut) {
__m128 yt;
__m128 zt;
yt = vec2::load_xmm(*point);
yt = _mm_sub_ps(yt, vec4::load_xmm(in_m1->row3));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row0));
pointOut->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row1));
pointOut->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
}
inline void mat4_inverse_transform_point(const mat4* in_m1, const vec3* point, vec3* pointOut) {
__m128 yt;
__m128 zt;
yt = vec3::load_xmm(*point);
yt = _mm_sub_ps(yt, vec4::load_xmm(in_m1->row3));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row0));
zt = _mm_hadd_ps(zt, zt);
pointOut->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row1));
zt = _mm_hadd_ps(zt, zt);
pointOut->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
zt = _mm_mul_ps(yt, vec4::load_xmm(in_m1->row2));
zt = _mm_hadd_ps(zt, zt);
pointOut->z = _mm_cvtss_f32(_mm_hadd_ps(zt, zt));
}
inline void mat4_transpose(const mat4* in_m1, mat4* out_m) {
__m128 xt0;
__m128 xt1;
__m128 xt2;
__m128 xt3;
__m128 yt0;
__m128 yt1;
__m128 yt2;
__m128 yt3;
xt0 = vec4::load_xmm(in_m1->row0);
xt1 = vec4::load_xmm(in_m1->row1);
xt2 = vec4::load_xmm(in_m1->row2);
xt3 = vec4::load_xmm(in_m1->row3);
yt0 = _mm_unpacklo_ps(xt0, xt1);
yt1 = _mm_unpackhi_ps(xt0, xt1);
yt2 = _mm_unpacklo_ps(xt2, xt3);
yt3 = _mm_unpackhi_ps(xt2, xt3);
out_m->row0 = vec4::store_xmm(_mm_movelh_ps(yt0, yt2));
out_m->row1 = vec4::store_xmm(_mm_movehl_ps(yt2, yt0));
out_m->row2 = vec4::store_xmm(_mm_movelh_ps(yt1, yt3));
out_m->row3 = vec4::store_xmm(_mm_movehl_ps(yt3, yt1));
}
void mat4_invert(const mat4* in_m1, mat4* out_m) {
static const __m128 xor0 = { -0.0f, 0.0f, -0.0f, 0.0f };
static const __m128 xor1 = { 0.0f, -0.0f, 0.0f, -0.0f };
__m128 xt0, xt1, xt2, xt3;
__m128 xt0x, xt1x, xt2x, xt3x;
__m128 xt0y, xt1y, xt2y, xt3y;
__m128 xt0z, xt1z, xt2z, xt3z;
__m128 xt0w, xt1w, xt2w, xt3w;
__m128 yt00, yt01, yt02, yt03, yt04, yt05, yt06, yt07, yt08, yt09, yt10, yt11;
__m128 zt0, zt1, zt2, zt3;
__m128 wt;
__m128 wt0, wt1, wt2;
__m128 t0, t1, t2, t3, t4, t5;
xt0 = vec4::load_xmm(in_m1->row0);
xt1 = vec4::load_xmm(in_m1->row1);
xt2 = vec4::load_xmm(in_m1->row2);
xt3 = vec4::load_xmm(in_m1->row3);
xt0x = _mm_shuffle_ps(xt0, xt0, 0x00);
xt0y = _mm_shuffle_ps(xt0, xt0, 0x55);
xt0z = _mm_shuffle_ps(xt0, xt0, 0xAA);
xt0w = _mm_shuffle_ps(xt0, xt0, 0xFF);
xt1x = _mm_shuffle_ps(xt1, xt1, 0x00);
xt1y = _mm_shuffle_ps(xt1, xt1, 0x55);
xt1z = _mm_shuffle_ps(xt1, xt1, 0xAA);
xt1w = _mm_shuffle_ps(xt1, xt1, 0xFF);
xt2x = _mm_shuffle_ps(xt2, xt2, 0x00);
xt2y = _mm_shuffle_ps(xt2, xt2, 0x55);
xt2z = _mm_shuffle_ps(xt2, xt2, 0xAA);
xt2w = _mm_shuffle_ps(xt2, xt2, 0xFF);
xt3x = _mm_shuffle_ps(xt3, xt3, 0x00);
xt3y = _mm_shuffle_ps(xt3, xt3, 0x55);
xt3z = _mm_shuffle_ps(xt3, xt3, 0xAA);
xt3w = _mm_shuffle_ps(xt3, xt3, 0xFF);
yt00 = _mm_movelh_ps(_mm_unpacklo_ps(xt1y, xt0y), xt0y);
yt01 = _mm_movelh_ps(xt2y, xt1y);
yt02 = _mm_movelh_ps(xt3y, _mm_unpacklo_ps(xt3y, xt2y));
yt03 = _mm_movelh_ps(xt2z, xt1z);
yt04 = _mm_movelh_ps(xt3w, _mm_unpacklo_ps(xt3w, xt2w));
yt05 = _mm_movelh_ps(xt2w, xt1w);
yt06 = _mm_movelh_ps(_mm_unpacklo_ps(xt3z, xt3z), _mm_unpacklo_ps(xt3z, xt2z));
yt07 = _mm_movelh_ps(_mm_unpacklo_ps(xt1z, xt0z), xt0z);
yt08 = _mm_movelh_ps(_mm_unpacklo_ps(xt1w, xt0w), xt0w);
yt09 = _mm_movelh_ps(_mm_unpacklo_ps(xt1x, xt0x), xt0x);
yt10 = _mm_movelh_ps(xt2x, xt1x);
yt11 = _mm_movelh_ps(xt3x, _mm_unpacklo_ps(xt3x, xt2x));
t0 = _mm_sub_ps(_mm_mul_ps(yt03, yt04), _mm_mul_ps(yt05, yt06));
t1 = _mm_sub_ps(_mm_mul_ps(yt07, yt04), _mm_mul_ps(yt08, yt06));
t2 = _mm_sub_ps(_mm_mul_ps(yt07, yt05), _mm_mul_ps(yt08, yt03));
t3 = _mm_xor_ps(yt09, xor0);
t4 = _mm_xor_ps(yt10, xor1);
t5 = _mm_xor_ps(yt11, xor0);
wt0 = _mm_mul_ps(_mm_xor_ps(yt00, xor1), t0);
wt1 = _mm_mul_ps(_mm_xor_ps(yt01, xor0), t1);
wt2 = _mm_mul_ps(_mm_xor_ps(yt02, xor1), t2);
zt0 = _mm_add_ps(_mm_add_ps(wt0, wt1), wt2);
wt0 = _mm_mul_ps(t3, t0);
wt1 = _mm_mul_ps(t4, t1);
wt2 = _mm_mul_ps(t5, t2);
zt1 = _mm_add_ps(_mm_add_ps(wt0, wt1), wt2);
wt0 = _mm_mul_ps(_mm_xor_ps(yt09, xor1), _mm_sub_ps(_mm_mul_ps(yt01, yt04), _mm_mul_ps(yt05, yt02)));
wt1 = _mm_mul_ps(_mm_xor_ps(yt10, xor0), _mm_sub_ps(_mm_mul_ps(yt00, yt04), _mm_mul_ps(yt08, yt02)));
wt2 = _mm_mul_ps(_mm_xor_ps(yt11, xor1), _mm_sub_ps(_mm_mul_ps(yt00, yt05), _mm_mul_ps(yt08, yt01)));
zt2 = _mm_add_ps(_mm_add_ps(wt0, wt1), wt2);
wt0 = _mm_mul_ps(t3, _mm_sub_ps(_mm_mul_ps(yt01, yt06), _mm_mul_ps(yt03, yt02)));
wt1 = _mm_mul_ps(t4, _mm_sub_ps(_mm_mul_ps(yt00, yt06), _mm_mul_ps(yt07, yt02)));
wt2 = _mm_mul_ps(t5, _mm_sub_ps(_mm_mul_ps(yt00, yt03), _mm_mul_ps(yt07, yt01)));
zt3 = _mm_add_ps(_mm_add_ps(wt0, wt1), wt2);
wt = _mm_movelh_ps(_mm_unpacklo_ps(zt0, zt1), _mm_unpacklo_ps(zt2, zt3));
wt = _mm_mul_ps(xt0, wt);
wt = _mm_hadd_ps(wt, wt);
wt = _mm_hadd_ps(wt, wt);
if (_mm_cvtss_f32(wt) != 0.0f)
wt = _mm_div_ss(_mm_set_ss(1.0f), wt);
wt = _mm_shuffle_ps(wt, wt, 0);
out_m->row0 = vec4::store_xmm(_mm_mul_ps(zt0, wt));
out_m->row1 = vec4::store_xmm(_mm_mul_ps(zt1, wt));
out_m->row2 = vec4::store_xmm(_mm_mul_ps(zt2, wt));
out_m->row3 = vec4::store_xmm(_mm_mul_ps(zt3, wt));
}
inline void mat4_invert_rotation(const mat4* in_m1, mat4* out_m) {
mat3 yt;
mat4_to_mat3(in_m1, &yt);
mat3_invert(&yt, &yt);
mat4_from_mat3(&yt, out_m);
out_m->row0.w = in_m1->row0.w;
out_m->row1.w = in_m1->row1.w;
out_m->row2.w = in_m1->row2.w;
out_m->row3 = in_m1->row3;
}
inline void mat4_invert_fast(const mat4* in_m1, mat4* out_m) {
mat3 yt;
mat4_to_mat3(in_m1, &yt);
vec3 row3;
row3.x = vec3::dot(*(vec3*)&in_m1->row0, *(vec3*)&in_m1->row3);
row3.y = vec3::dot(*(vec3*)&in_m1->row1, *(vec3*)&in_m1->row3);
row3.z = vec3::dot(*(vec3*)&in_m1->row2, *(vec3*)&in_m1->row3);
mat3_transpose(&yt, &yt);
mat4_from_mat3(&yt, out_m);
*(vec3*)&out_m->row3 = -row3;
out_m->row0.w = 0.0f;
out_m->row1.w = 0.0f;
out_m->row2.w = 0.0f;
out_m->row3.w = 1.0f;
}
inline void mat4_invert_rotation_fast(const mat4* in_m1, mat4* out_m) {
mat3 yt;
mat4_to_mat3(in_m1, &yt);
mat3_transpose(&yt, &yt);
mat4_from_mat3(&yt, out_m);
out_m->row0.w = in_m1->row0.w;
out_m->row1.w = in_m1->row1.w;
out_m->row2.w = in_m1->row2.w;
out_m->row3 = in_m1->row3;
}
inline void mat4_normalize(const mat4* in_m1, mat4* out_m) {
__m128 det;
det = _mm_set_ss(mat4_determinant(in_m1));
if (_mm_cvtss_f32(det) != 0.0f)
det = _mm_div_ss(_mm_set_ss(1.0f), det);
det = _mm_shuffle_ps(det, det, 0);
out_m->row0 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(in_m1->row0), det));
out_m->row1 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(in_m1->row1), det));
out_m->row2 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(in_m1->row2), det));
out_m->row3 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(in_m1->row3), det));
}
inline void mat4_normalize_rotation(const mat4* in_m1, mat4* out_m) {
*(vec3*)&out_m->row0 = vec3::normalize(*(vec3*)&in_m1->row0);
*(vec3*)&out_m->row1 = vec3::normalize(*(vec3*)&in_m1->row1);
*(vec3*)&out_m->row2 = vec3::normalize(*(vec3*)&in_m1->row2);
out_m->row0.w = in_m1->row0.w;
out_m->row1.w = in_m1->row1.w;
out_m->row2.w = in_m1->row2.w;
out_m->row3 = in_m1->row3;
}
inline float_t mat4_determinant(const mat4* in_m1) {
vec4 xt0;
vec4 xt1;
vec4 xt2;
vec4 xt3;
xt0 = in_m1->row0;
xt1 = in_m1->row1;
xt2 = in_m1->row2;
xt3 = in_m1->row3;
float_t b00 = xt0.x * xt1.y - xt0.y * xt1.x;
float_t b01 = xt0.x * xt1.z - xt0.z * xt1.x;
float_t b02 = xt0.x * xt1.w - xt0.w * xt1.x;
float_t b03 = xt0.y * xt1.z - xt0.z * xt1.y;
float_t b04 = xt0.y * xt1.w - xt0.w * xt1.y;
float_t b05 = xt0.z * xt1.w - xt0.w * xt1.z;
float_t b06 = xt2.x * xt3.y - xt2.y * xt3.x;
float_t b07 = xt2.x * xt3.z - xt2.z * xt3.x;
float_t b08 = xt2.x * xt3.w - xt2.w * xt3.x;
float_t b09 = xt2.y * xt3.z - xt2.z * xt3.y;
float_t b10 = xt2.y * xt3.w - xt2.w * xt3.y;
float_t b11 = xt2.z * xt3.w - xt2.w * xt3.z;
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
}
inline void mat4_rotate_x(float_t rad, mat4* out_m) {
float_t s = sinf(rad);
float_t c = cosf(rad);
*out_m = mat4_identity;
out_m->row1.y = c;
out_m->row1.z = s;
out_m->row2.y = -s;
out_m->row2.z = c;
}
inline void mat4_rotate_y(float_t rad, mat4* out_m) {
float_t s = sinf(rad);
float_t c = cosf(rad);
*out_m = mat4_identity;
out_m->row0.x = c;
out_m->row0.z = -s;
out_m->row2.x = s;
out_m->row2.z = c;
}
inline void mat4_rotate_z(float_t rad, mat4* out_m) {
float_t s = sinf(rad);
float_t c = cosf(rad);
*out_m = mat4_identity;
out_m->row0.x = c;
out_m->row0.y = s;
out_m->row1.x = -s;
out_m->row1.y = c;
}
inline void mat4_rotate_x(float_t s, float_t c, mat4* out_m) {
*out_m = mat4_identity;
out_m->row1.y = c;
out_m->row1.z = s;
out_m->row2.y = -s;
out_m->row2.z = c;
}
inline void mat4_rotate_y(float_t s, float_t c, mat4* out_m) {
*out_m = mat4_identity;
out_m->row0.x = c;
out_m->row0.z = -s;
out_m->row2.x = s;
out_m->row2.z = c;
}
inline void mat4_rotate_z(float_t s, float_t c, mat4* out_m) {
*out_m = mat4_identity;
out_m->row0.x = c;
out_m->row0.y = s;
out_m->row1.x = -s;
out_m->row1.y = c;
}
inline void mat4_rotate_xyz(float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = mat4_identity;
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
*out_m = dt;
}
inline void mat4_rotate_xzy(float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = mat4_identity;
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
*out_m = dt;
}
inline void mat4_rotate_yxz(float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = mat4_identity;
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
*out_m = dt;
}
inline void mat4_rotate_yzx(float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = mat4_identity;
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
*out_m = dt;
}
inline void mat4_rotate_zxy(float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = mat4_identity;
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
*out_m = dt;
}
inline void mat4_rotate_zyx(float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = mat4_identity;
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
*out_m = dt;
}
inline void mat4_mul_rotate_x(const mat4* in_m1, float_t rad, mat4* out_m) {
__m128 t1;
__m128 t2;
__m128 y0;
__m128 y1;
__m128 y2;
__m128 y3;
float_t s = sinf(rad);
float_t c = cosf(rad);
y0 = vec4::load_xmm(in_m1->row0);
y1 = vec4::load_xmm(in_m1->row1);
y2 = vec4::load_xmm(in_m1->row2);
y3 = vec4::load_xmm(in_m1->row3);
out_m->row0 = vec4::store_xmm(y0);
t1 = _mm_mul_ps(y1, vec4::load_xmm(c));
t2 = _mm_mul_ps(y2, vec4::load_xmm(s));
out_m->row1 = vec4::store_xmm(_mm_add_ps(t1, t2));
t1 = _mm_mul_ps(y1, vec4::load_xmm(-s));
t2 = _mm_mul_ps(y2, vec4::load_xmm(c));
out_m->row2 = vec4::store_xmm(_mm_add_ps(t1, t2));
out_m->row3 = vec4::store_xmm(y3);
}
inline void mat4_mul_rotate_y(const mat4* in_m1, float_t rad, mat4* out_m) {
__m128 t0;
__m128 t2;
__m128 y0;
__m128 y1;
__m128 y2;
__m128 y3;
float_t s = sinf(rad);
float_t c = cosf(rad);
y0 = vec4::load_xmm(in_m1->row0);
y1 = vec4::load_xmm(in_m1->row1);
y2 = vec4::load_xmm(in_m1->row2);
y3 = vec4::load_xmm(in_m1->row3);
t0 = _mm_mul_ps(y0, vec4::load_xmm(c));
t2 = _mm_mul_ps(y2, vec4::load_xmm(-s));
out_m->row0 = vec4::store_xmm(_mm_add_ps(t0, t2));
out_m->row1 = vec4::store_xmm(y1);
t0 = _mm_mul_ps(y0, vec4::load_xmm(s));
t2 = _mm_mul_ps(y2, vec4::load_xmm(c));
out_m->row2 = vec4::store_xmm(_mm_add_ps(t0, t2));
out_m->row3 = vec4::store_xmm(y3);
}
inline void mat4_mul_rotate_z(const mat4* in_m1, float_t rad, mat4* out_m) {
__m128 t0;
__m128 t1;
__m128 y0;
__m128 y1;
__m128 y2;
__m128 y3;
float_t s = sinf(rad);
float_t c = cosf(rad);
y0 = vec4::load_xmm(in_m1->row0);
y1 = vec4::load_xmm(in_m1->row1);
y2 = vec4::load_xmm(in_m1->row2);
y3 = vec4::load_xmm(in_m1->row3);
t0 = _mm_mul_ps(y0, vec4::load_xmm(c));
t1 = _mm_mul_ps(y1, vec4::load_xmm(s));
out_m->row0 = vec4::store_xmm(_mm_add_ps(t0, t1));
t0 = _mm_mul_ps(y0, vec4::load_xmm(-s));
t1 = _mm_mul_ps(y1, vec4::load_xmm(c));
out_m->row1 = vec4::store_xmm(_mm_add_ps(t0, t1));
out_m->row2 = vec4::store_xmm(y2);
out_m->row3 = vec4::store_xmm(y3);
}
inline void mat4_mul_rotate_x(const mat4* in_m1, float_t s, float_t c, mat4* out_m) {
__m128 t1;
__m128 t2;
__m128 y0;
__m128 y1;
__m128 y2;
__m128 y3;
y0 = vec4::load_xmm(in_m1->row0);
y1 = vec4::load_xmm(in_m1->row1);
y2 = vec4::load_xmm(in_m1->row2);
y3 = vec4::load_xmm(in_m1->row3);
out_m->row0 = vec4::store_xmm(y0);
t1 = _mm_mul_ps(y1, vec4::load_xmm(c));
t2 = _mm_mul_ps(y2, vec4::load_xmm(s));
out_m->row1 = vec4::store_xmm(_mm_add_ps(t1, t2));
t1 = _mm_mul_ps(y1, vec4::load_xmm(-s));
t2 = _mm_mul_ps(y2, vec4::load_xmm(c));
out_m->row2 = vec4::store_xmm(_mm_add_ps(t1, t2));
out_m->row3 = vec4::store_xmm(y3);
}
inline void mat4_mul_rotate_y(const mat4* in_m1, float_t s, float_t c, mat4* out_m) {
__m128 t0;
__m128 t2;
__m128 y0;
__m128 y1;
__m128 y2;
__m128 y3;
y0 = vec4::load_xmm(in_m1->row0);
y1 = vec4::load_xmm(in_m1->row1);
y2 = vec4::load_xmm(in_m1->row2);
y3 = vec4::load_xmm(in_m1->row3);
t0 = _mm_mul_ps(y0, vec4::load_xmm(c));
t2 = _mm_mul_ps(y2, vec4::load_xmm(-s));
out_m->row0 = vec4::store_xmm(_mm_add_ps(t0, t2));
out_m->row1 = vec4::store_xmm(y1);
t0 = _mm_mul_ps(y0, vec4::load_xmm(s));
t2 = _mm_mul_ps(y2, vec4::load_xmm(c));
out_m->row2 = vec4::store_xmm(_mm_add_ps(t0, t2));
out_m->row3 = vec4::store_xmm(y3);
}
inline void mat4_mul_rotate_z(const mat4* in_m1, float_t s, float_t c, mat4* out_m) {
__m128 t0;
__m128 t1;
__m128 y0;
__m128 y1;
__m128 y2;
__m128 y3;
y0 = vec4::load_xmm(in_m1->row0);
y1 = vec4::load_xmm(in_m1->row1);
y2 = vec4::load_xmm(in_m1->row2);
y3 = vec4::load_xmm(in_m1->row3);
t0 = _mm_mul_ps(y0, vec4::load_xmm(c));
t1 = _mm_mul_ps(y1, vec4::load_xmm(s));
out_m->row0 = vec4::store_xmm(_mm_add_ps(t0, t1));
t0 = _mm_mul_ps(y0, vec4::load_xmm(-s));
t1 = _mm_mul_ps(y1, vec4::load_xmm(c));
out_m->row1 = vec4::store_xmm(_mm_add_ps(t0, t1));
out_m->row2 = vec4::store_xmm(y2);
out_m->row3 = vec4::store_xmm(y3);
}
inline void mat4_mul_rotate_xyz(const mat4* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = *in_m1;
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
*out_m = dt;
}
inline void mat4_mul_rotate_xzy(const mat4* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = *in_m1;
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
*out_m = dt;
}
inline void mat4_mul_rotate_yxz(const mat4* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = *in_m1;
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
*out_m = dt;
}
inline void mat4_mul_rotate_yzx(const mat4* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = *in_m1;
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
*out_m = dt;
}
inline void mat4_mul_rotate_zxy(const mat4* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = *in_m1;
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
*out_m = dt;
}
inline void mat4_mul_rotate_zyx(const mat4* in_m1, float_t rad_x, float_t rad_y, float_t rad_z, mat4* out_m) {
mat4 dt;
dt = *in_m1;
if (rad_z != 0.0f)
mat4_mul_rotate_z(&dt, rad_z, &dt);
if (rad_y != 0.0f)
mat4_mul_rotate_y(&dt, rad_y, &dt);
if (rad_x != 0.0f)
mat4_mul_rotate_x(&dt, rad_x, &dt);
*out_m = dt;
}
inline void mat4_scale(float_t sx, float_t sy, float_t sz, mat4* out_m) {
*out_m = mat4_identity;
out_m->row0.x = sx;
out_m->row1.y = sy;
out_m->row2.z = sz;
}
inline void mat4_scale_x(float_t s, mat4* out_m) {
*out_m = mat4_identity;
out_m->row0.x = s;
}
inline void mat4_scale_y(float_t s, mat4* out_m) {
*out_m = mat4_identity;
out_m->row1.y = s;
}
inline void mat4_scale_z(float_t s, mat4* out_m) {
*out_m = mat4_identity;
out_m->row2.z = s;
}
inline void mat4_mul_scale(const mat4* in_m1, float_t sx, float_t sy, float_t sz, float_t sw, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
if (sx != 1.0f || sy != 1.0f || sz != 1.0f || sw != 1.0f) {
out_m->row0 *= sx;
out_m->row1 *= sy;
out_m->row2 *= sz;
out_m->row3 *= sw;
}
}
inline void mat4_mul_scale_x(const mat4* in_m1, float_t s, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
out_m->row0 *= s;
}
inline void mat4_mul_scale_y(const mat4* in_m1, float_t s, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
out_m->row1 *= s;
}
inline void mat4_mul_scale_z(const mat4* in_m1, float_t s, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
out_m->row2 *= s;
}
inline void mat4_scale_w_mult(const mat4* in_m1, float_t s, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
out_m->row3 *= s;
}
inline void mat4_scale_rot(const mat4* in_m1, float_t sx, float_t sy, float_t sz, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
if (sx != 1.0f || sy != 1.0f || sz != 1.0f) {
*(vec3*)&out_m->row0 *= sx;
*(vec3*)&out_m->row1 *= sy;
*(vec3*)&out_m->row2 *= sz;
}
else
*out_m = *in_m1;
}
inline void mat4_scale_x_rot(const mat4* in_m1, float_t s, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
*(vec3*)&out_m->row0 *= s;
}
inline void mat4_scale_y_rot(const mat4* in_m1, float_t s, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
*(vec3*)&out_m->row1 *= s;
}
inline void mat4_scale_z_rot(const mat4* in_m1, float_t s, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
*(vec3*)&out_m->row2 *= s;
}
inline void mat4_translate(float_t tx, float_t ty, float_t tz, mat4* out_m) {
*out_m = mat4_identity;
out_m->row3.x = tx;
out_m->row3.y = ty;
out_m->row3.z = tz;
}
inline void mat4_translate_x(float_t t, mat4* out_m) {
*out_m = mat4_identity;
out_m->row3.x = t;
}
inline void mat4_translate_y(float_t t, mat4* out_m) {
*out_m = mat4_identity;
out_m->row3.y = t;
}
inline void mat4_translate_z(float_t t, mat4* out_m) {
*out_m = mat4_identity;
out_m->row3.z = t;
}
inline void mat4_mul_translate(const mat4* in_m1, float_t tx, float_t ty, float_t tz, mat4* out_m) {
__m128 yt;
__m128 yt0;
__m128 yt1;
__m128 yt2;
__m128 yt3;
if (in_m1 != out_m)
*out_m = *in_m1;
if (tx != 0.0f || ty != 0.0f || tz != 0.0f) {
yt0 = _mm_mul_ps(vec4::load_xmm(in_m1->row0), vec4::load_xmm(tx));
yt1 = _mm_mul_ps(vec4::load_xmm(in_m1->row1), vec4::load_xmm(ty));
yt2 = _mm_mul_ps(vec4::load_xmm(in_m1->row2), vec4::load_xmm(tz));
yt3 = vec4::load_xmm(in_m1->row3);
yt = _mm_add_ps(_mm_add_ps(yt0, yt1), _mm_add_ps(yt2, yt3));
*(vec3*)&out_m->row3 = vec3::store_xmm(yt);
}
}
inline void mat4_mul_translate_x(const mat4* in_m1, float_t t, mat4* out_m) {
__m128 yt0;
__m128 yt1;
if (in_m1 != out_m)
*out_m = *in_m1;
if (t != 0.0f) {
yt0 = vec4::load_xmm(in_m1->row0);
yt1 = vec4::load_xmm(in_m1->row3);
yt0 = _mm_add_ps(_mm_mul_ps(yt0, vec4::load_xmm(t)), yt1);
*(vec3*)&out_m->row3 = vec3::store_xmm(yt0);
}
}
inline void mat4_mul_translate_y(const mat4* in_m1, float_t t, mat4* out_m) {
__m128 yt0;
__m128 yt1;
if (in_m1 != out_m)
*out_m = *in_m1;
if (t != 0.0f) {
yt0 = vec4::load_xmm(in_m1->row1);
yt1 = vec4::load_xmm(in_m1->row3);
yt0 = _mm_add_ps(_mm_mul_ps(yt0, vec4::load_xmm(t)), yt1);
*(vec3*)&out_m->row3 = vec3::store_xmm(yt0);
}
}
inline void mat4_mul_translate_z(const mat4* in_m1, float_t t, mat4* out_m) {
__m128 yt0;
__m128 yt1;
if (in_m1 != out_m)
*out_m = *in_m1;
if (t != 0.0f) {
yt0 = vec4::load_xmm(in_m1->row2);
yt1 = vec4::load_xmm(in_m1->row3);
yt0 = _mm_add_ps(_mm_mul_ps(yt0, vec4::load_xmm(t)), yt1);
*(vec3*)&out_m->row3 = vec3::store_xmm(yt0);
}
}
inline void mat4_add_translate(const mat4* in_m1, float_t tx, float_t ty, float_t tz, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
if (tx != 0.0f || ty != 0.0f || tz != 0.0f)
out_m->row3 = vec4::store_xmm(_mm_add_ps(vec4::load_xmm(in_m1->row3), vec4::load_xmm(vec4(tx, ty, tz, 0.0f))));
}
inline void mat4_add_translate_x(const mat4* in_m1, float_t t, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
if (t != 0.0f)
out_m->row3.x += t;
}
inline void mat4_add_translate_y(const mat4* in_m1, float_t t, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
if (t != 0.0f)
out_m->row3.y += t;
}
inline void mat4_add_translate_z(const mat4* in_m1, float_t t, mat4* out_m) {
if (in_m1 != out_m)
*out_m = *in_m1;
if (t != 0.0f)
out_m->row3.z += t;
}
inline void mat4_from_mat3(const mat3* in_m1, mat4* out_m) {
*(vec3*)&out_m->row0 = in_m1->row0;
out_m->row0.w = 0.0f;
*(vec3*)&out_m->row1 = in_m1->row1;
out_m->row1.w = 0.0f;
*(vec3*)&out_m->row2 = in_m1->row2;
out_m->row2.w = 0.0f;
out_m->row3 = { 0.0f, 0.0f, 0.0f, 1.0f };
}
inline void mat4_from_mat3_inverse(const mat3* in_m1, mat4* out_m) {
mat3 yt;
mat3_invert(in_m1, &yt);
*(vec3*)&out_m->row0 = yt.row0;
out_m->row0.w = 0.0f;
*(vec3*)&out_m->row1 = yt.row1;
out_m->row1.w = 0.0f;
*(vec3*)&out_m->row2 = yt.row2;
out_m->row2.w = 0.0f;
out_m->row3 = { 0.0f, 0.0f, 0.0f, 1.0f };
}
inline void mat4_clear_rot(const mat4* in_m1, mat4* out_m) {
out_m->row0 = mat4_identity.row0;
out_m->row1 = mat4_identity.row1;
out_m->row2 = mat4_identity.row2;
out_m->row3 = in_m1->row3;
}
inline void mat4_clear_trans(const mat4* in_m1, mat4* out_m) {
if (in_m1 != out_m) {
out_m->row0 = in_m1->row0;
out_m->row1 = in_m1->row1;
out_m->row2 = in_m1->row2;
}
out_m->row3 = { 0.0f, 0.0f, 0.0f, 1.0f };
}
inline void mat4_get_rotation(const mat4* in_m1, vec3* out_rad) {
if (-in_m1->row0.z >= 1.0f)
out_rad->y = (float_t)M_PI_2;
else if (-in_m1->row0.z <= -1.0f)
out_rad->y = (float_t)-M_PI_2;
else
out_rad->y = asinf(-in_m1->row0.z);
if (fabsf(in_m1->row0.z) < 0.99999899f) {
out_rad->x = atan2f(in_m1->row1.z, in_m1->row2.z);
out_rad->z = atan2f(in_m1->row0.y, in_m1->row0.x);
}
else {
out_rad->x = 0.0f;
out_rad->z = atan2f(in_m1->row2.y, in_m1->row1.y);
if (in_m1->row0.z > 0.0f)
out_rad->z = -out_rad->z;
}
}
inline void mat4_get_scale(const mat4* in_m1, vec3* out_s) {
out_s->x = vec4::length(in_m1->row0);
out_s->y = vec4::length(in_m1->row1);
out_s->z = vec4::length(in_m1->row2);
}
inline void mat4_get_translation(const mat4* in_m1, vec3* out_t) {
*out_t = *(vec3*)&in_m1->row3;
}
inline void mat4_set_translation(mat4* in_m1, const vec3* in_t) {
*(vec3*)&in_m1->row3 = *in_t;
}
inline float_t mat4_get_max_scale(const mat4* in_m1) {
mat4 mat;
mat4_transpose(in_m1, &mat);
float_t length;
float_t max = 0.0f;
length = vec3::length(*(vec3*)&mat.row0);
if (max < length)
max = length;
length = vec3::length(*(vec3*)&mat.row1);
if (max < length)
max = length;
length = vec3::length(*(vec3*)&mat.row2);
if (max < length)
max = length;
return max;
}
inline void mat4_blend(const mat4* in_m1, const mat4* in_m2, mat4* out_m, float_t blend) {
quat q0;
quat q1;
quat q2;
q0 = quat(in_m1->row0.x, in_m1->row1.x, in_m1->row2.x, in_m1->row0.y,
in_m1->row1.y, in_m1->row2.y, in_m1->row0.z, in_m1->row1.z, in_m1->row2.z);
q0 = quat::normalize(q0);
q1 = quat(in_m2->row0.x, in_m2->row1.x, in_m2->row2.x, in_m2->row0.y,
in_m2->row1.y, in_m2->row2.y, in_m2->row0.z, in_m2->row1.z, in_m2->row2.z);
q1 = quat::normalize(q1);
vec3 t0;
vec3 t1;
vec3 t2;
mat4_get_translation(in_m1, &t0);
mat4_get_translation(in_m2, &t1);
q2 = quat::lerp(q0, q1, blend);
t2 = vec3::lerp(t0, t1, blend);
mat4_set(&q2, out_m);
mat4_set_translation(out_m, &t2);
}
inline void mat4_blend_rotation(const mat4* in_m1, const mat4* in_m2, mat4* out_m, float_t blend) {
quat q1 = quat(in_m1->row0.x, in_m1->row1.x, in_m1->row2.x, in_m1->row0.y,
in_m1->row1.y, in_m1->row2.y, in_m1->row0.z, in_m1->row1.z, in_m1->row2.z);
quat q2 = quat(in_m2->row0.x, in_m2->row1.x, in_m2->row2.x, in_m2->row0.y,
in_m2->row1.y, in_m2->row2.y, in_m2->row0.z, in_m2->row1.z, in_m2->row2.z);
quat q3 = quat::slerp(q1, q2, blend);
mat4_set(&q3, out_m);
}
void mat4_lerp_rotation(const mat4* in_m1, const mat4* in_m2, mat4* out_m, float_t blend) {
vec3 m0;
vec3 m1;
m0 = vec3::lerp(*(vec3*)&in_m1->row0, *(vec3*)&in_m2->row0, blend);
m1 = vec3::lerp(*(vec3*)&in_m1->row1, *(vec3*)&in_m2->row1, blend);
float_t m0_len_sq = vec3::length_squared(m0);
float_t m1_len_sq = vec3::length_squared(m1);
if (m0_len_sq <= 0.000001f || m1_len_sq <= 0.000001f) {
*out_m = *in_m2;
return;
}
vec3 m2;
m2 = vec3::cross(m0, m1);
m1 = vec3::cross(m2, m0);
float_t m2_len_sq;
m1_len_sq = vec3::length_squared(m1);
m2_len_sq = vec3::length_squared(m2);
if (m2_len_sq <= 0.000001f || m1_len_sq <= 0.000001) {
*out_m = *in_m2;
return;
}
float_t m0_len = sqrtf(m0_len_sq);
if (m0_len != 0.0f)
m0 *= 1.0f / m0_len;
float_t m1_len = sqrtf(m1_len_sq);
if (m1_len != 0.0f)
m1 *= 1.0f / m1_len;
float_t m2_len = sqrtf(m2_len_sq);
if (m2_len != 0.0f)
m2 *= 1.0f / m2_len;
*out_m = mat4_identity;
*(vec3*)&out_m->row0 = m0;
*(vec3*)&out_m->row1 = m1;
*(vec3*)&out_m->row2 = m2;
}
inline void mat4_frustrum(double_t left, double_t right,
double_t bottom, double_t top, double_t z_near, double_t z_far, mat4* out_m) {
*out_m = mat4_null;
out_m->row0.x = (float_t)((2.0 * z_near) / (right - left));
out_m->row1.y = (float_t)((2.0 * z_near) / (top - bottom));
out_m->row2.x = (float_t)((right + left) / (right - left));
out_m->row2.y = (float_t)((top + bottom) / (top - bottom));
out_m->row2.z = -(float_t)((z_far + z_near) / (z_far - z_near));
out_m->row2.w = -1.0f;
out_m->row3.z = -(float_t)((2.0 * z_far * z_near) / (z_far - z_near));
}
inline void mat4_ortho(double_t left, double_t right,
double_t bottom, double_t top, double_t z_near, double_t z_far, mat4* out_m) {
*out_m = mat4_null;
out_m->row0.x = (float_t)(2.0 / (right - left));
out_m->row1.y = (float_t)(2.0 / (top - bottom));
out_m->row2.z = (float_t)(-2.0 / (z_far - z_near));
out_m->row3.x = -(float_t)((right + left) / (right - left));
out_m->row3.y = -(float_t)((top + bottom) / (top - bottom));
out_m->row3.z = -(float_t)((z_far + z_near) / (z_far - z_near));
out_m->row3.w = 1.0f;
}
inline void mat4_persp(double_t fov_y, double_t aspect, double_t z_near, double_t z_far, mat4* out_m) {
double_t tan_fov = tan(fov_y * 0.5);
*out_m = mat4_null;
out_m->row0.x = (float_t)(1.0 / (aspect * tan_fov));
out_m->row1.y = (float_t)(1.0 / tan_fov);
out_m->row2.z = -(float_t)((z_far + z_near) / (z_far - z_near));
out_m->row2.w = -1.0f;
out_m->row3.z = -(float_t)((2.0 * z_far * z_near) / (z_far - z_near));
}
inline void mat4_look_at(const vec3* eye, const vec3* target, const vec3* up, mat4* out_m) {
vec3 x_axis, y_axis, z_axis;
vec3 xyz;
z_axis = vec3::normalize(*eye - *target);
x_axis = vec3::normalize(vec3::cross(*up, z_axis));
if (vec3::length(x_axis) == 0.0f)
x_axis = { 1.0f, 0.0f, 0.0f };
y_axis = vec3::normalize(vec3::cross(z_axis, x_axis));
xyz.x = vec3::dot(x_axis, *eye);
xyz.y = vec3::dot(y_axis, *eye);
xyz.z = vec3::dot(z_axis, *eye);
out_m->row0 = { x_axis.x, y_axis.x, z_axis.x, 0.0f };
out_m->row1 = { x_axis.y, y_axis.y, z_axis.y, 0.0f };
out_m->row2 = { x_axis.z, y_axis.z, z_axis.z, 0.0f };
*(vec3*)&out_m->row3 = -xyz;
out_m->row3.w = 1.0f;
}
inline void mat4_look_at(const vec3* eye, const vec3* target, mat4* out_m) {
vec3 up = { 0.0f, 1.0f, 0.0f };
vec3 dir;
dir = *target - *eye;
if (vec3::length_squared(dir) <= 0.000001f) {
up.x = 0.0f;
up.y = 0.0f;
if (dir.z < 0.0f)
up.z = 1.0f;
else
up.z = -1.0f;
}
mat4_look_at(eye, target, &up, out_m);
}