/* 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* x, const mat3* y, mat3* z) { z->row0 = x->row0 + y->row0; z->row1 = x->row1 + y->row1; z->row2 = x->row2 + y->row2; } inline void mat3_sub(const mat3* x, const mat3* y, mat3* z) { z->row0 = x->row0 - y->row0; z->row1 = x->row1 - y->row1; z->row2 = x->row2 - y->row2; } inline void mat3_mult(const mat3* x, const mat3* y, mat3* z) { __m128 t0; __m128 t1; __m128 t2; __m128 yt; __m128 zt; __m128 xt0; __m128 xt1; __m128 xt2; *(vec3*)&xt0 = x->row0; *(vec3*)&xt1 = x->row1; *(vec3*)&xt2 = x->row2; *(vec3*)&yt = y->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)); zt = _mm_add_ps(_mm_add_ps(t0, t1), t2); z->row0 = *(vec3*)&zt; *(vec3*)&yt = y->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)); zt = _mm_add_ps(_mm_add_ps(t0, t1), t2); z->row1 = *(vec3*)&zt; *(vec3*)&yt = y->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)); zt = _mm_add_ps(_mm_add_ps(t0, t1), t2); z->row2 = *(vec3*)&zt; } inline void mat3_mult_vec2(const mat3* x, const vec2* y, vec2* z) { __m128 xt; __m128 yt; __m128 zt; __m128 zt0; __m128 zt1; *(vec2*)&yt = *y; *(vec3*)&xt = x->row0; zt0 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x00)); *(vec3*)&xt = x->row1; zt1 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x55)); zt = _mm_add_ps(zt0, zt1); *z = *(vec2*)&zt; } inline void mat3_mult_vec(const mat3* x, const vec3* y, vec3* z) { __m128 xt; __m128 yt; __m128 zt; __m128 zt0; __m128 zt1; __m128 zt2; *(vec3*)&yt = *y; *(vec3*)&xt = x->row0; zt0 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x00)); *(vec3*)&xt = x->row1; zt1 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x55)); *(vec3*)&xt = x->row2; zt2 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0xAA)); zt = _mm_add_ps(_mm_add_ps(zt0, zt1), zt2); *z = *(vec3*)&zt; } inline void mat3_mult_scalar(const mat3* x, float_t y, mat3* z) { __m128 xt; __m128 yt; __m128 zt; yt = vec4::load_xmm(y); *(vec3*)&xt = x->row0; zt = _mm_mul_ps(xt, yt); z->row0 = *(vec3*)&zt; *(vec3*)&xt = x->row1; zt = _mm_mul_ps(xt, yt); z->row1 = *(vec3*)&zt; *(vec3*)&xt = x->row2; zt = _mm_mul_ps(xt, yt); z->row2 = *(vec3*)&zt; } inline void mat3_transpose(const mat3* x, mat3* z) { __m128 xt0; __m128 xt1; __m128 xt2; __m128 xt3; __m128 yt0; __m128 yt1; __m128 yt2; __m128 yt3; __m128 zt0; __m128 zt1; __m128 zt2; xt0 = vec3::load_xmm(x->row0); xt1 = vec3::load_xmm(x->row1); xt2 = vec3::load_xmm(x->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); zt0 = _mm_movelh_ps(yt0, yt2); zt1 = _mm_movehl_ps(yt2, yt0); zt2 = _mm_movelh_ps(yt1, yt3); z->row0 = *(vec3*)&zt0; z->row1 = *(vec3*)&zt1; z->row2 = *(vec3*)&zt2; } void mat3_inverse(const mat3* x, mat3* z) { vec3 xt0; vec3 xt1; vec3 xt2; __m128 yt; __m128 zt0; __m128 zt1; __m128 zt2; __m128 wt; xt0 = x->row0; xt1 = x->row1; xt2 = x->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); yt = vec3::load_xmm(xt0); wt = _mm_mul_ps(yt, 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); yt = _mm_mul_ps(zt0, wt); z->row0 = *(vec3*)&yt; yt = _mm_mul_ps(zt1, wt); z->row1 = *(vec3*)&yt; yt = _mm_mul_ps(zt2, wt); z->row2 = *(vec3*)&yt; } inline void mat3_invtrans(const mat3* x, mat3* z) { mat3 t = *x; mat3_inverse(&t, &t); mat3_transpose(&t, &t); *z = t; } inline void mat3_inverse_normalized(const mat3* x, mat3* z) { mat3_transpose(x, z); } inline void mat3_normalize(const mat3* x, mat3* z) { __m128 det; __m128 xt0; __m128 xt1; __m128 xt2; det = _mm_set_ss(mat3_determinant(x)); if (_mm_cvtss_f32(det) != 0.0f) det = _mm_div_ss(_mm_set_ss(1.0f), det); det = _mm_shuffle_ps(det, det, 0); *(vec3*)&xt0 = x->row0; *(vec3*)&xt1 = x->row1; *(vec3*)&xt2 = x->row2; xt0 = _mm_mul_ps(xt0, det); xt1 = _mm_mul_ps(xt1, det); xt2 = _mm_mul_ps(xt2, det); z->row0 = *(vec3*)&xt0; z->row1 = *(vec3*)&xt1; z->row2 = *(vec3*)&xt2; } inline void mat3_normalize_rotation(const mat3* x, mat3* z) { z->row0 = vec3::normalize(x->row0); z->row1 = vec3::normalize(x->row1); z->row2 = vec3::normalize(x->row2); } inline float_t mat3_determinant(const mat3* x) { vec3 xt0; vec3 xt1; vec3 xt2; xt0 = x->row0; xt1 = x->row1; xt2 = x->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_xyz(float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = mat3_identity; if (x != 0.0f) mat3_rotate_x(x, &dt); if (y != 0.0f) if (x != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); else mat3_rotate_y(y, &dt); if (z != 0.0f) if (y != 0.0f || x != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); else mat3_rotate_z(z, &dt); *d = dt; } inline void mat3_rotate_xzy(float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = mat3_identity; if (x != 0.0f) mat3_rotate_x(x, &dt); if (z != 0.0f) if (x != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); else mat3_rotate_z(z, &dt); if (y != 0.0f) if (z != 0.0f || x != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); else mat3_rotate_y(y, &dt); *d = dt; } inline void mat3_rotate_yxz(float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = mat3_identity; if (y != 0.0f) mat3_rotate_y(y, &dt); if (x != 0.0f) if (y != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); else mat3_rotate_x(x, &dt); if (z != 0.0f) if (x != 0.0f || y != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); else mat3_rotate_z(z, &dt); *d = dt; } inline void mat3_rotate_yzx(float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = mat3_identity; if (y != 0.0f) mat3_rotate_y(y, &dt); if (z != 0.0f) if (y != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); else mat3_rotate_z(z, &dt); if (x != 0.0f) if (z != 0.0f || y != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); else mat3_rotate_x(x, &dt); *d = dt; } inline void mat3_rotate_zxy(float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = mat3_identity; if (z != 0.0f) mat3_rotate_z(z, &dt); if (x != 0.0f) if (z != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); else mat3_rotate_x(x, &dt); if (y != 0.0f) if (x != 0.0f || z != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); else mat3_rotate_y(y, &dt); *d = dt; } inline void mat3_rotate_zyx(float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = mat3_identity; if (z != 0.0f) mat3_rotate_z(z, &dt); if (y != 0.0f) if (z != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); else mat3_rotate_y(y, &dt); if (x != 0.0f) if (y != 0.0f || z != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); else mat3_rotate_x(x, &dt); *d = dt; } inline void mat3_rotate_x_sin_cos(float_t sin_val, float_t cos_val, mat3* y) { mat3 yt; yt = mat3_identity; yt.row1.y = cos_val; yt.row1.z = sin_val; yt.row2.y = -sin_val; yt.row2.z = cos_val; *y = yt; } inline void mat3_rotate_y_sin_cos(float_t sin_val, float_t cos_val, mat3* y) { mat3 yt; yt = mat3_identity; yt.row0.x = cos_val; yt.row0.z = -sin_val; yt.row2.x = sin_val; yt.row2.z = cos_val; *y = yt; } inline void mat3_rotate_z_sin_cos(float_t sin_val, float_t cos_val, mat3* y) { mat3 yt; yt = mat3_identity; yt.row0.x = cos_val; yt.row0.y = sin_val; yt.row1.x = -sin_val; yt.row1.y = cos_val; *y = yt; } inline void mat3_rotate_x_mult_sin_cos(const mat3* x, float_t sin_val, float_t cos_val, mat3* z) { __m128 t1; __m128 t2; __m128 y0; __m128 y1; __m128 y2; __m128 zt; *(vec3*)&y0 = x->row0; *(vec3*)&y1 = x->row1; *(vec3*)&y2 = x->row2; z->row0 = *(vec3*)&y0; t1 = _mm_mul_ps(y1, vec4::load_xmm(cos_val)); t2 = _mm_mul_ps(y2, vec4::load_xmm(sin_val)); zt = _mm_add_ps(t1, t2); z->row1 = *(vec3*)&zt; t1 = _mm_mul_ps(y1, vec4::load_xmm(-sin_val)); t2 = _mm_mul_ps(y2, vec4::load_xmm(cos_val)); zt = _mm_add_ps(t1, t2); z->row2 = *(vec3*)&zt; } inline void mat3_rotate_y_mult_sin_cos(const mat3* x, float_t sin_val, float_t cos_val, mat3* z) { __m128 t0; __m128 t2; __m128 y0; __m128 y1; __m128 y2; __m128 zt; *(vec3*)&y0 = x->row0; *(vec3*)&y1 = x->row1; *(vec3*)&y2 = x->row2; t0 = _mm_mul_ps(y0, vec4::load_xmm(cos_val)); t2 = _mm_mul_ps(y2, vec4::load_xmm(-sin_val)); zt = _mm_add_ps(t0, t2); z->row0 = *(vec3*)&zt; z->row1 = *(vec3*)&y1; t0 = _mm_mul_ps(y0, vec4::load_xmm(sin_val)); t2 = _mm_mul_ps(y2, vec4::load_xmm(cos_val)); zt = _mm_add_ps(t0, t2); z->row2 = *(vec3*)&zt; } inline void mat3_rotate_z_mult_sin_cos(const mat3* x, float_t sin_val, float_t cos_val, mat3* z) { __m128 t0; __m128 t1; __m128 y0; __m128 y1; __m128 y2; __m128 zt; *(vec3*)&y0 = x->row0; *(vec3*)&y1 = x->row1; *(vec3*)&y2 = x->row2; t0 = _mm_mul_ps(y0, vec4::load_xmm(cos_val)); t1 = _mm_mul_ps(y1, vec4::load_xmm(sin_val)); zt = _mm_add_ps(t0, t1); z->row0 = *(vec3*)&zt; t0 = _mm_mul_ps(y0, vec4::load_xmm(-sin_val)); t1 = _mm_mul_ps(y1, vec4::load_xmm(cos_val)); zt = _mm_add_ps(t0, t1); z->row1 = *(vec3*)&zt; z->row2 = *(vec3*)&y2; } inline void mat3_rotate_x(float_t x, mat3* y) { mat3 yt; float_t x_sin = sinf(x); float_t x_cos = cosf(x); yt = mat3_identity; yt.row1.y = x_cos; yt.row1.z = x_sin; yt.row2.y = -x_sin; yt.row2.z = x_cos; *y = yt; } inline void mat3_rotate_y(float_t x, mat3* y) { mat3 yt; float_t x_sin = sinf(x); float_t x_cos = cosf(x); yt = mat3_identity; yt.row0.x = x_cos; yt.row0.z = -x_sin; yt.row2.x = x_sin; yt.row2.z = x_cos; *y = yt; } inline void mat3_rotate_z(float_t x, mat3* y) { mat3 yt; float_t x_sin = sinf(x); float_t x_cos = cosf(x); yt = mat3_identity; yt.row0.x = x_cos; yt.row0.y = x_sin; yt.row1.x = -x_sin; yt.row1.y = x_cos; *y = yt; } inline void mat3_rotate_xyz_mult(const mat3* s, float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = *s; if (x != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); if (y != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); if (z != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); *d = dt; } inline void mat3_rotate_xzy_mult(const mat3* s, float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = *s; if (x != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); if (z != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); if (y != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); *d = dt; } inline void mat3_rotate_yxz_mult(const mat3* s, float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = *s; if (y != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); if (x != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); if (z != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); *d = dt; } inline void mat3_rotate_yzx_mult(const mat3* s, float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = *s; if (y != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); if (z != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); if (x != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); *d = dt; } inline void mat3_rotate_zxy_mult(const mat3* s, float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = *s; if (z != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); if (x != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); if (y != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); *d = dt; } inline void mat3_rotate_zyx_mult(const mat3* s, float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = *s; if (z != 0.0f) mat3_rotate_z_mult(&dt, z, &dt); if (y != 0.0f) mat3_rotate_y_mult(&dt, y, &dt); if (x != 0.0f) mat3_rotate_x_mult(&dt, x, &dt); *d = dt; } inline void mat3_rotate_x_mult(const mat3* x, float_t y, mat3* z) { __m128 t1; __m128 t2; __m128 y0; __m128 y1; __m128 y2; __m128 zt; float_t y_sin = sinf(y); float_t y_cos = cosf(y); *(vec3*)&y0 = x->row0; *(vec3*)&y1 = x->row1; *(vec3*)&y2 = x->row2; z->row0 = *(vec3*)&y0; t1 = _mm_mul_ps(y1, vec4::load_xmm(y_cos)); t2 = _mm_mul_ps(y2, vec4::load_xmm(y_sin)); zt = _mm_add_ps(t1, t2); z->row1 = *(vec3*)&zt; t1 = _mm_mul_ps(y1, vec4::load_xmm(-y_sin)); t2 = _mm_mul_ps(y2, vec4::load_xmm(y_cos)); zt = _mm_add_ps(t1, t2); z->row2 = *(vec3*)&zt; } inline void mat3_rotate_y_mult(const mat3* x, float_t y, mat3* z) { __m128 t0; __m128 t2; __m128 y0; __m128 y1; __m128 y2; __m128 zt; float_t y_sin = sinf(y); float_t y_cos = cosf(y); *(vec3*)&y0 = x->row0; *(vec3*)&y1 = x->row1; *(vec3*)&y2 = x->row2; t0 = _mm_mul_ps(y0, vec4::load_xmm(y_cos)); t2 = _mm_mul_ps(y2, vec4::load_xmm(-y_sin)); zt = _mm_add_ps(t0, t2); z->row0 = *(vec3*)&zt; z->row1 = *(vec3*)&y1; t0 = _mm_mul_ps(y0, vec4::load_xmm(y_sin)); t2 = _mm_mul_ps(y2, vec4::load_xmm(y_cos)); zt = _mm_add_ps(t0, t2); z->row2 = *(vec3*)&zt; } inline void mat3_rotate_z_mult(const mat3* x, float_t y, mat3* z) { __m128 t0; __m128 t1; __m128 y0; __m128 y1; __m128 y2; __m128 zt; float_t y_sin = sinf(y); float_t y_cos = cosf(y); *(vec3*)&y0 = x->row0; *(vec3*)&y1 = x->row1; *(vec3*)&y2 = x->row2; t0 = _mm_mul_ps(y0, vec4::load_xmm(y_cos)); t1 = _mm_mul_ps(y1, vec4::load_xmm(y_sin)); zt = _mm_add_ps(t0, t1); z->row0 = *(vec3*)&zt; t0 = _mm_mul_ps(y0, vec4::load_xmm(-y_sin)); t1 = _mm_mul_ps(y1, vec4::load_xmm(y_cos)); zt = _mm_add_ps(t0, t1); z->row1 = *(vec3*)&zt; z->row2 = *(vec3*)&y2; } inline void mat3_scale(float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = mat3_identity; if (x != 1.0f) dt.row0.x = x; if (y != 1.0f) dt.row1.y = y; if (z != 1.0f) dt.row2.z = z; *d = dt; } inline void mat3_scale_x(float_t x, mat3* y) { mat3 yt; yt = mat3_identity; yt.row0.x = x; *y = yt; } inline void mat3_scale_y(float_t x, mat3* y) { mat3 yt; yt = mat3_identity; yt.row1.y = x; *y = yt; } inline void mat3_scale_z(float_t x, mat3* y) { mat3 yt; yt = mat3_identity; yt.row2.z = x; *y = yt; } inline void mat3_scale_mult(const mat3* s, float_t x, float_t y, float_t z, mat3* d) { mat3 st; mat3 dt; if (x != 1.0f || y != 1.0f || z != 1.0f) { st = *s; dt = mat3_identity; dt.row0.x = x; dt.row1.y = y; dt.row2.z = z; mat3_mult(&st, &dt, &dt); *d = dt; } else *d = *s; } inline void mat3_scale_x_mult(const mat3* x, float_t y, mat3* z) { mat3 yt; yt = mat3_identity; yt.row0.x = y; mat3_mult(x, &yt, z); } inline void mat3_scale_y_mult(const mat3* x, float_t y, mat3* z) { mat3 yt; yt = mat3_identity; yt.row1.y = y; mat3_mult(x, &yt, z); } inline void mat3_scale_z_mult(const mat3* x, float_t y, mat3* z) { mat3 yt; yt = mat3_identity; yt.row2.z = y; mat3_mult(x, &yt, z); } inline void mat3_from_quat(const quat* quat, mat3* mat) { float_t y; float_t x; float_t z; float_t w; float_t len; float_t xy; float_t yy; float_t xx; float_t wx; float_t wy; float_t zz; float_t xz; float_t wz; float_t yz; x = quat->x; y = quat->y; z = quat->z; w = quat->w; len = quat::length_squared(*quat); len = len > 0.0f ? 2.0f / len : 0.0f; xx = x * x * len; xy = x * y * len; xz = x * z * len; yy = y * y * len; zz = z * z * len; yz = y * z * len; wx = w * x * len; wy = w * y * len; wz = w * z * len; mat->row0.x = 1.0f - zz - yy; mat->row0.y = xy + wz; mat->row0.z = xz - wy; mat->row1.x = xy - wz; mat->row1.y = 1.0f - zz - xx; mat->row1.z = yz + wx; mat->row2.x = xz + wy; mat->row2.y = yz - wx; mat->row2.z = 1.0f - yy - xx; } inline void mat3_from_axis_angle(const vec3* axis, float_t angle, mat3* mat) { float_t angle_sin; float_t angle_cos; float_t angle_cos_1; vec3 _axis; vec3 _axis_sin; vec3 temp; angle_sin = sinf(angle); angle_cos = cosf(angle); angle_cos_1 = 1.0f - angle_cos; _axis = vec3::normalize(*axis); _axis_sin = _axis * angle_sin; temp = _axis * (_axis.x * angle_cos_1); mat->row0.x = temp.x + angle_cos; mat->row1.x = temp.y - _axis_sin.z; mat->row2.x = temp.z + _axis_sin.y; temp = _axis * (_axis.y * angle_cos_1); mat->row0.y = temp.x + _axis_sin.z; mat->row1.y = temp.y + angle_cos; mat->row2.y = temp.z - _axis_sin.x; temp = _axis * (_axis.z * angle_cos_1); mat->row0.z = temp.x - _axis_sin.y; mat->row1.z = temp.y + _axis_sin.x; mat->row2.z = temp.z + angle_cos; } inline void mat3_from_axis_angle_sin_cos(const vec3* axis, float_t sin_val, float_t cos_val, mat3* mat) { float_t cos_val_1; vec3 _axis; vec3 _axis_sin; vec3 temp; cos_val_1 = 1.0f - cos_val; _axis = vec3::normalize(*axis); _axis_sin = _axis * sin_val; temp = _axis * (_axis.x * cos_val_1); mat->row0.x = temp.x + cos_val; mat->row1.x = temp.y - _axis_sin.z; mat->row2.x = temp.z + _axis_sin.y; temp = _axis * (_axis.y * cos_val_1); mat->row0.y = temp.x + _axis_sin.z; mat->row1.y = temp.y + cos_val; mat->row2.y = temp.z - _axis_sin.x; temp = _axis * (_axis.z * cos_val_1); mat->row0.z = temp.x - _axis_sin.y; mat->row1.z = temp.y + _axis_sin.x; mat->row2.z = temp.z + cos_val; } inline void mat3_from_mat4(const mat4* x, mat3* z) { z->row0 = *(vec3*)&x->row0; z->row1 = *(vec3*)&x->row1; z->row2 = *(vec3*)&x->row2; } inline void mat3_from_mat4_inverse(const mat4* x, mat3* z) { mat4 yt; mat4_inverse(x, &yt); z->row0 = *(vec3*)&yt.row0; z->row1 = *(vec3*)&yt.row1; z->row2 = *(vec3*)&yt.row2; } inline void mat3_get_rotation(const mat3* x, vec3* z) { if (-x->row0.z >= 1.0f) z->y = (float_t)M_PI_2; else if (-x->row0.z <= -1.0f) z->y = (float_t)-M_PI_2; else z->y = asinf(-x->row0.z); if (fabs(x->row0.z) < 0.99999899f) { z->x = atan2f(x->row1.z, x->row2.z); z->z = atan2f(x->row0.y, x->row0.x); } else { z->x = 0.0f; z->z = atan2f(x->row2.y, x->row1.y); if (-x->row0.z < 0.0f) z->z = -z->z; } } inline void mat3_get_scale(const mat3* x, vec3* z) { z->x = vec3::length(x->row0); z->y = vec3::length(x->row1); z->z = vec3::length(x->row2); } inline float_t mat3_get_max_scale(const mat3* x) { mat3 mat; mat3_transpose(x, &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 mat3_mult_axis_angle(const mat3* x, const vec3* axis, const float_t angle, mat3* z) { quat q1; quat q2; quat q3; quat_from_mat3(x->row0.x, x->row1.x, x->row2.x, x->row0.y, x->row1.y, x->row2.y, x->row0.z, x->row1.z, x->row2.z, &q1); quat_from_axis_angle(axis, angle, &q2); quat_mult(&q2, &q1, &q3); mat3_from_quat(&q3, z); } inline void mat4_add(const mat4* x, const mat4* y, mat4* z) { z->row0 = x->row0 + y->row0; z->row1 = x->row1 + y->row1; z->row2 = x->row2 + y->row2; z->row3 = x->row3 + y->row3; } inline void mat4_sub(const mat4* x, const mat4* y, mat4* z) { z->row0 = x->row0 - y->row0; z->row1 = x->row1 - y->row1; z->row2 = x->row2 - y->row2; z->row3 = x->row3 - y->row3; } inline void mat4_mult(const mat4* x, const mat4* y, mat4* z) { __m128 t0; __m128 t1; __m128 t2; __m128 t3; __m128 xt; __m128 y0; __m128 y1; __m128 y2; __m128 y3; y0 = vec4::load_xmm(y->row0); y1 = vec4::load_xmm(y->row1); y2 = vec4::load_xmm(y->row2); y3 = vec4::load_xmm(y->row3); xt = vec4::load_xmm(x->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)); z->row0 = vec4::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), _mm_add_ps(t2, t3))); xt = vec4::load_xmm(x->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)); z->row1 = vec4::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), _mm_add_ps(t2, t3))); xt = vec4::load_xmm(x->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)); z->row2 = vec4::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), _mm_add_ps(t2, t3))); xt = vec4::load_xmm(x->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)); z->row3 = vec4::store_xmm(_mm_add_ps(_mm_add_ps(t0, t1), _mm_add_ps(t2, t3))); } inline void mat4_mult_vec2(const mat4* x, const vec2* y, vec2* z) { __m128 yt; __m128 zt; __m128 zt0; __m128 zt1; *(vec2*)&yt = *y; zt0 = _mm_mul_ps(vec4::load_xmm(x->row0), _mm_shuffle_ps(yt, yt, 0x00)); zt1 = _mm_mul_ps(vec4::load_xmm(x->row1), _mm_shuffle_ps(yt, yt, 0x55)); zt = _mm_add_ps(zt0, zt1); *z = *(vec2*)&zt; } inline void mat4_mult_vec2_trans(const mat4* x, const vec2* y, vec2* z) { __m128 yt; __m128 zt; __m128 zt0; __m128 zt1; __m128 zt2; *(vec2*)&yt = *y; zt0 = _mm_mul_ps(vec4::load_xmm(x->row0), _mm_shuffle_ps(yt, yt, 0x00)); zt1 = _mm_mul_ps(vec4::load_xmm(x->row1), _mm_shuffle_ps(yt, yt, 0x55)); zt2 = vec4::load_xmm(x->row3); zt = _mm_add_ps(_mm_add_ps(zt0, zt1), zt2); *z = *(vec2*)&zt; } inline void mat4_mult_vec3(const mat4* x, const vec3* y, vec3* z) { __m128 yt; __m128 zt; __m128 zt0; __m128 zt1; __m128 zt2; *(vec3*)&yt = *y; zt0 = _mm_mul_ps(vec4::load_xmm(x->row0), _mm_shuffle_ps(yt, yt, 0x00)); zt1 = _mm_mul_ps(vec4::load_xmm(x->row1), _mm_shuffle_ps(yt, yt, 0x55)); zt2 = _mm_mul_ps(vec4::load_xmm(x->row2), _mm_shuffle_ps(yt, yt, 0xAA)); zt = _mm_add_ps(_mm_add_ps(zt0, zt1), zt2); *z = *(vec3*)&zt; } inline void mat4_mult_vec3_inv(const mat4* x, const vec3* y, vec3* z) { __m128 yt; __m128 zt; yt = vec3::load_xmm(*y); zt = _mm_mul_ps(yt, vec4::load_xmm(x->row0)); zt = _mm_hadd_ps(zt, zt); z->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); zt = _mm_mul_ps(yt, vec4::load_xmm(x->row1)); zt = _mm_hadd_ps(zt, zt); z->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); zt = _mm_mul_ps(yt, vec4::load_xmm(x->row2)); zt = _mm_hadd_ps(zt, zt); z->z = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); } inline void mat4_mult_vec3_trans(const mat4* x, const vec3* y, vec3* z) { __m128 yt; __m128 zt; __m128 zt0; __m128 zt1; __m128 zt2; __m128 zt3; *(vec3*)&yt = *y; zt0 = _mm_mul_ps(vec4::load_xmm(x->row0), _mm_shuffle_ps(yt, yt, 0x00)); zt1 = _mm_mul_ps(vec4::load_xmm(x->row1), _mm_shuffle_ps(yt, yt, 0x55)); zt2 = _mm_mul_ps(vec4::load_xmm(x->row2), _mm_shuffle_ps(yt, yt, 0xAA)); zt3 = vec4::load_xmm(x->row3); zt = _mm_add_ps(_mm_add_ps(zt0, zt1), _mm_add_ps(zt2, zt3)); *z = *(vec3*)&zt; } inline void mat4_mult_vec3_inv_trans(const mat4* x, const vec3* y, vec3* z) { __m128 yt; __m128 zt; yt = vec3::load_xmm(*y); yt = _mm_sub_ps(yt, vec4::load_xmm(x->row3)); zt = _mm_mul_ps(yt, vec4::load_xmm(x->row0)); zt = _mm_hadd_ps(zt, zt); z->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); zt = _mm_mul_ps(yt, vec4::load_xmm(x->row1)); zt = _mm_hadd_ps(zt, zt); z->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); zt = _mm_mul_ps(yt, vec4::load_xmm(x->row2)); zt = _mm_hadd_ps(zt, zt); z->z = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); } inline void mat4_mult_vec(const mat4* x, vec4* y, vec4* z) { __m128 yt; __m128 zt0; __m128 zt1; __m128 zt2; __m128 zt3; yt = vec4::load_xmm(*y); zt0 = _mm_mul_ps(vec4::load_xmm(x->row0), _mm_shuffle_ps(yt, yt, 0x00)); zt1 = _mm_mul_ps(vec4::load_xmm(x->row1), _mm_shuffle_ps(yt, yt, 0x55)); zt2 = _mm_mul_ps(vec4::load_xmm(x->row2), _mm_shuffle_ps(yt, yt, 0xAA)); zt3 = _mm_mul_ps(vec4::load_xmm(x->row3), _mm_shuffle_ps(yt, yt, 0xFF)); *z = vec4::store_xmm(_mm_add_ps(_mm_add_ps(zt0, zt1), _mm_add_ps(zt2, zt3))); } inline void mat4_mult_scalar(const mat4* x, float_t y, mat4* z) { __m128 yt; yt = vec4::load_xmm(y); z->row0 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(x->row0), yt)); z->row1 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(x->row1), yt)); z->row2 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(x->row2), yt)); z->row3 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(x->row3), yt)); } inline void mat4_transpose(const mat4* x, mat4* z) { __m128 xt0; __m128 xt1; __m128 xt2; __m128 xt3; __m128 yt0; __m128 yt1; __m128 yt2; __m128 yt3; xt0 = vec4::load_xmm(x->row0); xt1 = vec4::load_xmm(x->row1); xt2 = vec4::load_xmm(x->row2); xt3 = vec4::load_xmm(x->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); z->row0 = vec4::store_xmm(_mm_movelh_ps(yt0, yt2)); z->row1 = vec4::store_xmm(_mm_movehl_ps(yt2, yt0)); z->row2 = vec4::store_xmm(_mm_movelh_ps(yt1, yt3)); z->row3 = vec4::store_xmm(_mm_movehl_ps(yt3, yt1)); } void mat4_inverse(const mat4* x, mat4* z) { 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(x->row0); xt1 = vec4::load_xmm(x->row1); xt2 = vec4::load_xmm(x->row2); xt3 = vec4::load_xmm(x->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); z->row0 = vec4::store_xmm(_mm_mul_ps(zt0, wt)); z->row1 = vec4::store_xmm(_mm_mul_ps(zt1, wt)); z->row2 = vec4::store_xmm(_mm_mul_ps(zt2, wt)); z->row3 = vec4::store_xmm(_mm_mul_ps(zt3, wt)); } inline void mat4_invtrans(const mat4* x, mat4* z) { mat4 t = *x; mat4_inverse(&t, &t); mat4_transpose(&t, &t); *z = t; } inline void mat4_invrot(const mat4* x, mat4* z) { mat3 yt; mat3_from_mat4(x, &yt); mat3_inverse(&yt, &yt); mat4_from_mat3(&yt, z); z->row0.w = x->row0.w; z->row1.w = x->row1.w; z->row2.w = x->row2.w; z->row3 = x->row3; } inline void mat4_inverse_normalized(const mat4* x, mat4* z) { mat3 yt; mat3_from_mat4(x, &yt); vec3 row3; row3.x = vec3::dot(*(vec3*)&x->row0, *(vec3*)&x->row3); row3.y = vec3::dot(*(vec3*)&x->row1, *(vec3*)&x->row3); row3.z = vec3::dot(*(vec3*)&x->row2, *(vec3*)&x->row3); mat3_transpose(&yt, &yt); mat4_from_mat3(&yt, z); *(vec3*)&z->row3 = -row3; z->row0.w = 0.0f; z->row1.w = 0.0f; z->row2.w = 0.0f; z->row3.w = 1.0f; } inline void mat4_invrot_normalized(const mat4* x, mat4* z) { mat3 yt; mat3_from_mat4(x, &yt); mat3_transpose(&yt, &yt); mat4_from_mat3(&yt, z); z->row0.w = x->row0.w; z->row1.w = x->row1.w; z->row2.w = x->row2.w; z->row3 = x->row3; } inline void mat4_normalize(const mat4* x, mat4* z) { __m128 det; det = _mm_set_ss(mat4_determinant(x)); if (_mm_cvtss_f32(det) != 0.0f) det = _mm_div_ss(_mm_set_ss(1.0f), det); det = _mm_shuffle_ps(det, det, 0); z->row0 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(x->row0), det)); z->row1 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(x->row1), det)); z->row2 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(x->row2), det)); z->row3 = vec4::store_xmm(_mm_mul_ps(vec4::load_xmm(x->row3), det)); } inline void mat4_normalize_rotation(const mat4* x, mat4* z) { *(vec3*)&z->row0 = vec3::normalize(*(vec3*)&x->row0); *(vec3*)&z->row1 = vec3::normalize(*(vec3*)&x->row1); *(vec3*)&z->row2 = vec3::normalize(*(vec3*)&x->row2); z->row0.w = x->row0.w; z->row1.w = x->row1.w; z->row2.w = x->row2.w; z->row3 = x->row3; } inline float_t mat4_determinant(const mat4* x) { vec4 xt0; vec4 xt1; vec4 xt2; vec4 xt3; xt0 = x->row0; xt1 = x->row1; xt2 = x->row2; xt3 = x->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_xyz(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; if (x != 0.0f) mat4_rotate_x(x, &dt); if (y != 0.0f) if (x != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); else mat4_rotate_y(y, &dt); if (z != 0.0f) if (y != 0.0f || x != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); else mat4_rotate_z(z, &dt); *d = dt; } inline void mat4_rotate_xzy(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; if (x != 0.0f) mat4_rotate_x(x, &dt); if (z != 0.0f) if (x != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); else mat4_rotate_z(z, &dt); if (y != 0.0f) if (z != 0.0f || x != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); else mat4_rotate_y(y, &dt); *d = dt; } inline void mat4_rotate_yxz(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; if (y != 0.0f) mat4_rotate_y(y, &dt); if (x != 0.0f) if (y != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); else mat4_rotate_x(x, &dt); if (z != 0.0f) if (x != 0.0f || y != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); else mat4_rotate_z(z, &dt); *d = dt; } inline void mat4_rotate_yzx(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; if (y != 0.0f) mat4_rotate_y(y, &dt); if (z != 0.0f) if (y != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); else mat4_rotate_z(z, &dt); if (x != 0.0f) if (z != 0.0f || y != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); else mat4_rotate_x(x, &dt); *d = dt; } inline void mat4_rotate_zxy(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; if (z != 0.0f) mat4_rotate_z(z, &dt); if (x != 0.0f) if (z != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); else mat4_rotate_x(x, &dt); if (y != 0.0f) if (x != 0.0f || z != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); else mat4_rotate_y(y, &dt); *d = dt; } inline void mat4_rotate_zyx(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; if (z != 0.0f) mat4_rotate_z(z, &dt); if (y != 0.0f) if (z != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); else mat4_rotate_y(y, &dt); if (x != 0.0f) if (y != 0.0f || z != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); else mat4_rotate_x(x, &dt); *d = dt; } inline void mat4_rotate_x(float_t x, mat4* y) { mat4 yt; float_t x_sin = sinf(x); float_t x_cos = cosf(x); yt = mat4_identity; yt.row1.y = x_cos; yt.row1.z = x_sin; yt.row2.y = -x_sin; yt.row2.z = x_cos; *y = yt; } inline void mat4_rotate_y(float_t x, mat4* y) { mat4 yt; float_t x_sin = sinf(x); float_t x_cos = cosf(x); yt = mat4_identity; yt.row0.x = x_cos; yt.row0.z = -x_sin; yt.row2.x = x_sin; yt.row2.z = x_cos; *y = yt; } inline void mat4_rotate_z(float_t x, mat4* y) { mat4 yt; float_t x_sin = sinf(x); float_t x_cos = cosf(x); yt = mat4_identity; yt.row0.x = x_cos; yt.row0.y = x_sin; yt.row1.x = -x_sin; yt.row1.y = x_cos; *y = yt; } inline void mat4_rotate_xyz_mult(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = *s; if (x != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); if (y != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); if (z != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); *d = dt; } inline void mat4_rotate_xzy_mult(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = *s; if (x != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); if (z != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); if (y != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); *d = dt; } inline void mat4_rotate_yxz_mult(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = *s; if (y != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); if (x != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); if (z != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); *d = dt; } inline void mat4_rotate_yzx_mult(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = *s; if (y != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); if (z != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); if (x != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); *d = dt; } inline void mat4_rotate_zxy_mult(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = *s; if (z != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); if (x != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); if (y != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); *d = dt; } inline void mat4_rotate_zyx_mult(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = *s; if (z != 0.0f) mat4_rotate_z_mult(&dt, z, &dt); if (y != 0.0f) mat4_rotate_y_mult(&dt, y, &dt); if (x != 0.0f) mat4_rotate_x_mult(&dt, x, &dt); *d = dt; } inline void mat4_rotate_x_mult(const mat4* x, float_t y, mat4* z) { __m128 t1; __m128 t2; __m128 y0; __m128 y1; __m128 y2; __m128 y3; float_t y_sin = sinf(y); float_t y_cos = cosf(y); y0 = vec4::load_xmm(x->row0); y1 = vec4::load_xmm(x->row1); y2 = vec4::load_xmm(x->row2); y3 = vec4::load_xmm(x->row3); z->row0 = vec4::store_xmm(y0); t1 = _mm_mul_ps(y1, vec4::load_xmm(y_cos)); t2 = _mm_mul_ps(y2, vec4::load_xmm(y_sin)); z->row1 = vec4::store_xmm(_mm_add_ps(t1, t2)); t1 = _mm_mul_ps(y1, vec4::load_xmm(-y_sin)); t2 = _mm_mul_ps(y2, vec4::load_xmm(y_cos)); z->row2 = vec4::store_xmm(_mm_add_ps(t1, t2)); z->row3 = vec4::store_xmm(y3); } inline void mat4_rotate_y_mult(const mat4* x, float_t y, mat4* z) { __m128 t0; __m128 t2; __m128 y0; __m128 y1; __m128 y2; __m128 y3; float_t y_sin = sinf(y); float_t y_cos = cosf(y); y0 = vec4::load_xmm(x->row0); y1 = vec4::load_xmm(x->row1); y2 = vec4::load_xmm(x->row2); y3 = vec4::load_xmm(x->row3); t0 = _mm_mul_ps(y0, vec4::load_xmm(y_cos)); t2 = _mm_mul_ps(y2, vec4::load_xmm(-y_sin)); z->row0 = vec4::store_xmm(_mm_add_ps(t0, t2)); z->row1 = vec4::store_xmm(y1); t0 = _mm_mul_ps(y0, vec4::load_xmm(y_sin)); t2 = _mm_mul_ps(y2, vec4::load_xmm(y_cos)); z->row2 = vec4::store_xmm(_mm_add_ps(t0, t2)); z->row3 = vec4::store_xmm(y3); } inline void mat4_rotate_z_mult(const mat4* x, float_t y, mat4* z) { __m128 t0; __m128 t1; __m128 y0; __m128 y1; __m128 y2; __m128 y3; float_t y_sin = sinf(y); float_t y_cos = cosf(y); y0 = vec4::load_xmm(x->row0); y1 = vec4::load_xmm(x->row1); y2 = vec4::load_xmm(x->row2); y3 = vec4::load_xmm(x->row3); t0 = _mm_mul_ps(y0, vec4::load_xmm(y_cos)); t1 = _mm_mul_ps(y1, vec4::load_xmm(y_sin)); z->row0 = vec4::store_xmm(_mm_add_ps(t0, t1)); t0 = _mm_mul_ps(y0, vec4::load_xmm(-y_sin)); t1 = _mm_mul_ps(y1, vec4::load_xmm(y_cos)); z->row1 = vec4::store_xmm(_mm_add_ps(t0, t1)); z->row2 = vec4::store_xmm(y2); z->row3 = vec4::store_xmm(y3); } inline void mat4_rotate_x_sin_cos(float_t sin_val, float_t cos_val, mat4* y) { mat4 yt; yt = mat4_identity; yt.row1.y = cos_val; yt.row1.z = sin_val; yt.row2.y = -sin_val; yt.row2.z = cos_val; *y = yt; } inline void mat4_rotate_y_sin_cos(float_t sin_val, float_t cos_val, mat4* y) { mat4 yt; yt = mat4_identity; yt.row0.x = cos_val; yt.row0.z = -sin_val; yt.row2.x = sin_val; yt.row2.z = cos_val; *y = yt; } inline void mat4_rotate_z_sin_cos(float_t sin_val, float_t cos_val, mat4* y) { mat4 yt; yt = mat4_identity; yt.row0.x = cos_val; yt.row0.y = sin_val; yt.row1.x = -sin_val; yt.row1.y = cos_val; *y = yt; } inline void mat4_rotate_x_mult_sin_cos(const mat4* x, float_t sin_val, float_t cos_val, mat4* z) { __m128 t1; __m128 t2; __m128 y0; __m128 y1; __m128 y2; __m128 y3; y0 = vec4::load_xmm(x->row0); y1 = vec4::load_xmm(x->row1); y2 = vec4::load_xmm(x->row2); y3 = vec4::load_xmm(x->row3); z->row0 = vec4::store_xmm(y0); t1 = _mm_mul_ps(y1, vec4::load_xmm(cos_val)); t2 = _mm_mul_ps(y2, vec4::load_xmm(sin_val)); z->row1 = vec4::store_xmm(_mm_add_ps(t1, t2)); t1 = _mm_mul_ps(y1, vec4::load_xmm(-sin_val)); t2 = _mm_mul_ps(y2, vec4::load_xmm(cos_val)); z->row2 = vec4::store_xmm(_mm_add_ps(t1, t2)); z->row3 = vec4::store_xmm(y3); } inline void mat4_rotate_y_mult_sin_cos(const mat4* x, float_t sin_val, float_t cos_val, mat4* z) { __m128 t0; __m128 t2; __m128 y0; __m128 y1; __m128 y2; __m128 y3; y0 = vec4::load_xmm(x->row0); y1 = vec4::load_xmm(x->row1); y2 = vec4::load_xmm(x->row2); y3 = vec4::load_xmm(x->row3); t0 = _mm_mul_ps(y0, vec4::load_xmm(cos_val)); t2 = _mm_mul_ps(y2, vec4::load_xmm(-sin_val)); z->row0 = vec4::store_xmm(_mm_add_ps(t0, t2)); z->row1 = vec4::store_xmm(y1); t0 = _mm_mul_ps(y0, vec4::load_xmm(sin_val)); t2 = _mm_mul_ps(y2, vec4::load_xmm(cos_val)); z->row2 = vec4::store_xmm(_mm_add_ps(t0, t2)); z->row3 = vec4::store_xmm(y3); } inline void mat4_rotate_z_mult_sin_cos(const mat4* x, float_t sin_val, float_t cos_val, mat4* z) { __m128 t0; __m128 t1; __m128 y0; __m128 y1; __m128 y2; __m128 y3; y0 = vec4::load_xmm(x->row0); y1 = vec4::load_xmm(x->row1); y2 = vec4::load_xmm(x->row2); y3 = vec4::load_xmm(x->row3); t0 = _mm_mul_ps(y0, vec4::load_xmm(cos_val)); t1 = _mm_mul_ps(y1, vec4::load_xmm(sin_val)); z->row0 = vec4::store_xmm(_mm_add_ps(t0, t1)); t0 = _mm_mul_ps(y0, vec4::load_xmm(-sin_val)); t1 = _mm_mul_ps(y1, vec4::load_xmm(cos_val)); z->row1 = vec4::store_xmm(_mm_add_ps(t0, t1)); z->row2 = vec4::store_xmm(y2); z->row3 = vec4::store_xmm(y3); } inline void mat4_scale(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; if (x != 1.0f) dt.row0.x = x; if (y != 1.0f) dt.row1.y = y; if (z != 1.0f) dt.row2.z = z; *d = dt; } inline void mat4_scale_x(float_t x, mat4* y) { mat4 yt; yt = mat4_identity; yt.row0.x = x; *y = yt; } inline void mat4_scale_y(float_t x, mat4* y) { mat4 yt; yt = mat4_identity; yt.row1.y = x; *y = yt; } inline void mat4_scale_z(float_t x, mat4* y) { mat4 yt; yt = mat4_identity; yt.row2.z = x; *y = yt; } inline void mat4_scale_mult(const mat4* s, float_t x, float_t y, float_t z, float_t w, mat4* d) { mat4 dt; if (x != 1.0f || y != 1.0f || z != 1.0f || w != 1.0f) { dt = mat4_identity; dt.row0.x = x; dt.row1.y = y; dt.row2.z = z; dt.row3.w = w; mat4_mult(s, &dt, d); } else if (s != d) *d = *s; } inline void mat4_scale_x_mult(const mat4* x, float_t y, mat4* z) { mat4 yt; yt = mat4_identity; yt.row0.x = y; mat4_mult(x, &yt, z); } inline void mat4_scale_y_mult(const mat4* x, float_t y, mat4* z) { mat4 yt; yt = mat4_identity; yt.row1.y = y; mat4_mult(x, &yt, z); } inline void mat4_scale_z_mult(const mat4* x, float_t y, mat4* z) { mat4 yt; yt = mat4_identity; yt.row2.z = y; mat4_mult(x, &yt, z); } inline void mat4_scale_w_mult(const mat4* x, float_t y, mat4* z) { mat4 yt; yt = mat4_identity; yt.row3.w = y; mat4_mult(x, &yt, z); } inline void mat4_scale_rot(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { mat3 st; mat3 dt; if (x != 1.0f || y != 1.0f || z != 1.0f) { st.row0 = *(vec3*)&s->row0; st.row1 = *(vec3*)&s->row1; st.row2 = *(vec3*)&s->row2; dt = mat3_identity; dt.row0.x = x; dt.row1.y = y; dt.row2.z = z; mat3_mult(&st, &dt, &dt); *(vec3*)&d->row0 = dt.row0; *(vec3*)&d->row1 = dt.row1; *(vec3*)&d->row2 = dt.row2; d->row0.w = s->row0.w; d->row1.w = s->row1.w; d->row2.w = s->row2.w; d->row3 = s->row3; } else *d = *s; } inline void mat4_scale_x_rot(const mat4* x, float_t y, mat4* z) { mat3 xt; mat3 yt; mat3 zt; xt.row0 = *(vec3*)&x->row0; xt.row1 = *(vec3*)&x->row1; xt.row2 = *(vec3*)&x->row2; yt = mat3_identity; yt.row0.x = y; mat3_mult(&xt, &yt, &zt); *(vec3*)&z->row0 = zt.row0; *(vec3*)&z->row1 = zt.row1; *(vec3*)&z->row2 = zt.row2; z->row0.w = x->row0.w; z->row1.w = x->row1.w; z->row2.w = x->row2.w; z->row3 = x->row3; } inline void mat4_scale_y_rot(const mat4* x, float_t y, mat4* z) { mat3 xt; mat3 yt; mat3 zt; xt.row0 = *(vec3*)&x->row0; xt.row1 = *(vec3*)&x->row1; xt.row2 = *(vec3*)&x->row2; yt = mat3_identity; yt.row1.y = y; mat3_mult(&xt, &yt, &zt); *(vec3*)&z->row0 = zt.row0; *(vec3*)&z->row1 = zt.row1; *(vec3*)&z->row2 = zt.row2; z->row0.w = x->row0.w; z->row1.w = x->row1.w; z->row2.w = x->row2.w; z->row3 = x->row3; } inline void mat4_scale_z_rot(const mat4* x, float_t y, mat4* z) { mat3 xt; mat3 yt; mat3 zt; xt.row0 = *(vec3*)&x->row0; xt.row1 = *(vec3*)&x->row1; xt.row2 = *(vec3*)&x->row2; yt = mat3_identity; yt.row2.z = y; mat3_mult(&xt, &yt, &zt); *(vec3*)&z->row0 = zt.row0; *(vec3*)&z->row1 = zt.row1; *(vec3*)&z->row2 = zt.row2; z->row0.w = x->row0.w; z->row1.w = x->row1.w; z->row2.w = x->row2.w; z->row3 = x->row3; } inline void mat4_translate(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; dt.row3.x = x; dt.row3.y = y; dt.row3.z = z; *d = dt; } inline void mat4_translate_x(float_t x, mat4* y) { mat4 yt; yt = mat4_identity; yt.row3.x = x; *y = yt; } inline void mat4_translate_y(float_t x, mat4* y) { mat4 yt; yt = mat4_identity; yt.row3.y = x; *y = yt; } inline void mat4_translate_z(float_t x, mat4* y) { mat4 yt; yt = mat4_identity; yt.row3.z = x; *y = yt; } inline void mat4_translate_mult(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { __m128 yt; __m128 yt0; __m128 yt1; __m128 yt2; __m128 yt3; if (s != d) *d = *s; if (x != 0.0f || y != 0.0f || z != 0.0f) { yt0 = _mm_mul_ps(vec4::load_xmm(s->row0), vec4::load_xmm(x)); yt1 = _mm_mul_ps(vec4::load_xmm(s->row1), vec4::load_xmm(y)); yt2 = _mm_mul_ps(vec4::load_xmm(s->row2), vec4::load_xmm(z)); yt3 = vec4::load_xmm(s->row3); yt = _mm_add_ps(_mm_add_ps(yt0, yt1), _mm_add_ps(yt2, yt3)); *(vec3*)&d->row3 = vec3::store_xmm(yt); } } inline void mat4_translate_x_mult(const mat4* x, float_t y, mat4* z) { __m128 yt0; __m128 yt1; if (x != z) *z = *x; if (y != 0.0f) { yt0 = vec4::load_xmm(x->row0); yt1 = vec4::load_xmm(x->row3); yt0 = _mm_add_ps(_mm_mul_ps(yt0, vec4::load_xmm(y)), yt1); *(vec3*)&z->row3 = vec3::store_xmm(yt0); } } inline void mat4_translate_y_mult(const mat4* x, float_t y, mat4* z) { __m128 yt0; __m128 yt1; if (x != z) *z = *x; if (y != 0.0f) { yt0 = vec4::load_xmm(x->row1); yt1 = vec4::load_xmm(x->row3); yt0 = _mm_add_ps(_mm_mul_ps(yt0, vec4::load_xmm(y)), yt1); *(vec3*)&z->row3 = vec3::store_xmm(yt0); } } inline void mat4_translate_z_mult(const mat4* x, float_t y, mat4* z) { __m128 yt0; __m128 yt1; if (x != z) *z = *x; if (y != 0.0f) { yt0 = vec4::load_xmm(x->row2); yt1 = vec4::load_xmm(x->row3); yt0 = _mm_add_ps(_mm_mul_ps(yt0, vec4::load_xmm(y)), yt1); *(vec3*)&z->row3 = vec3::store_xmm(yt0); } } inline void mat4_translate_add(const mat4* s, float_t x, float_t y, float_t z, mat4* d) { if (s != d) *d = *s; if (x != 0.0f || y != 0.0f || z != 0.0f) d->row3 = vec4::store_xmm(_mm_add_ps(vec4::load_xmm(s->row3), vec4::load_xmm(vec4(x, y, z, 0.0f)))); } inline void mat4_translate_x_add(const mat4* x, float_t y, mat4* z) { if (x != z) *z = *x; if (y != 0.0f) z->row3.x += y; } inline void mat4_translate_y_add(const mat4* x, float_t y, mat4* z) { if (x != z) *z = *x; if (y != 0.0f) z->row3.y += y; } inline void mat4_translate_z_add(const mat4* x, float_t y, mat4* z) { if (x != z) *z = *x; if (y != 0.0f) z->row3.z += y; } inline void mat4_from_quat(const quat* quat, mat4* mat) { float_t y; float_t x; float_t z; float_t w; float_t len; float_t xy; float_t yy; float_t xx; float_t wx; float_t wy; float_t zz; float_t xz; float_t wz; float_t yz; x = quat->x; y = quat->y; z = quat->z; w = quat->w; len = quat::length_squared(*quat); len = len > 0.0f ? 2.0f / len : 0.0f; xx = x * x * len; xy = x * y * len; xz = x * z * len; yy = y * y * len; zz = z * z * len; yz = y * z * len; wx = w * x * len; wy = w * y * len; wz = w * z * len; mat->row0.x = 1.0f - zz - yy; mat->row0.y = xy + wz; mat->row0.z = xz - wy; mat->row0.w = 0.0f; mat->row1.x = xy - wz; mat->row1.y = 1.0f - zz - xx; mat->row1.z = yz + wx; mat->row1.w = 0.0f; mat->row2.x = xz + wy; mat->row2.y = yz - wx; mat->row2.z = 1.0f - yy - xx; mat->row2.w = 0.0f; mat->row3 = { 0.0f, 0.0f, 0.0f, 1.0f }; } float_t vec3_angle_between_two_vectors(const vec3* x, const vec3* y) { vec3 z_t = vec3::cross(*x, *y); float_t v2 = vec3::length(z_t); float_t v3 = vec3::dot(*x, *y); return fabsf(atan2f(v2, v3)); } void mat4_from_two_vectors(const vec3* x, const vec3* y, mat4* mat) { *mat = mat4_identity; if (x->x == y->x && y->y == x->y && y->z == x->z) return; if (fabsf(1.0f - vec3::dot(*x, *y)) <= 0.000001f) return; vec3 axis = vec3::cross(*x, *y); float_t axis_length = vec3::length(axis); if (axis_length > 0.000001f) { float_t angle = vec3_angle_between_two_vectors(x, y); if (axis_length != 0.0) axis *= 1.0f / axis_length; mat4_from_axis_angle(&axis, angle, mat); } } inline void mat4_from_axis_angle(const vec3* axis, float_t angle, mat4* mat) { float_t angle_sin; float_t angle_cos; float_t angle_cos_1; vec3 _axis; vec3 _axis_sin; vec3 temp; angle_sin = sinf(angle); angle_cos = cosf(angle); angle_cos_1 = 1.0f - angle_cos; _axis = vec3::normalize(*axis); _axis_sin = _axis * angle_sin; temp = _axis * (_axis.x * angle_cos_1); mat->row0.x = temp.x + angle_cos; mat->row1.x = temp.y - _axis_sin.z; mat->row2.x = temp.z + _axis_sin.y; temp = _axis * (_axis.y * angle_cos_1); mat->row0.y = temp.x + _axis_sin.z; mat->row1.y = temp.y + angle_cos; mat->row2.y = temp.z - _axis_sin.x; temp = _axis * (_axis.z * angle_cos_1); mat->row0.z = temp.x - _axis_sin.y; mat->row1.z = temp.y + _axis_sin.x; mat->row2.z = temp.z + angle_cos; mat->row0.w = 0.0f; mat->row1.w = 0.0f; mat->row2.w = 0.0f; mat->row3 = { 0.0f, 0.0f, 0.0f, 1.0f }; } inline void mat4_from_axis_angle_sin_cos(const vec3* axis, float_t sin_val, float_t cos_val, mat4* mat) { float_t cos_val_1; vec3 _axis; vec3 _axis_sin; vec3 temp; cos_val_1 = 1.0f - cos_val; _axis = vec3::normalize(*axis); _axis_sin = _axis * sin_val; temp = _axis * (_axis.x * cos_val_1); mat->row0.x = temp.x + cos_val; mat->row1.x = temp.y - _axis_sin.z; mat->row2.x = temp.z + _axis_sin.y; temp = _axis * (_axis.y * cos_val_1); mat->row0.y = temp.x + _axis_sin.z; mat->row1.y = temp.y + cos_val; mat->row2.y = temp.z - _axis_sin.x; temp = _axis * (_axis.z * cos_val_1); mat->row0.z = temp.x - _axis_sin.y; mat->row1.z = temp.y + _axis_sin.x; mat->row2.z = temp.z + cos_val; mat->row0.w = 0.0f; mat->row1.w = 0.0f; mat->row2.w = 0.0f; mat->row3 = { 0.0f, 0.0f, 0.0f, 1.0f }; } inline void mat4_from_mat3(const mat3* x, mat4* z) { *(vec3*)&z->row0 = x->row0; z->row0.w = 0.0f; *(vec3*)&z->row1 = x->row1; z->row1.w = 0.0f; *(vec3*)&z->row2 = x->row2; z->row2.w = 0.0f; z->row3 = { 0.0f, 0.0f, 0.0f, 1.0f }; } inline void mat4_from_mat3_inverse(const mat3* x, mat4* z) { mat3 yt; mat3_inverse(x, &yt); *(vec3*)&z->row0 = yt.row0; z->row0.w = 0.0f; *(vec3*)&z->row1 = yt.row1; z->row1.w = 0.0f; *(vec3*)&z->row2 = yt.row2; z->row2.w = 0.0f; z->row3 = { 0.0f, 0.0f, 0.0f, 1.0f }; } inline void mat4_clear_rot(mat4* x, mat4* z) { z->row0 = mat4_identity.row0; z->row1 = mat4_identity.row1; z->row2 = mat4_identity.row2; z->row3 = x->row3; } inline void mat4_clear_trans(mat4* x, mat4* z) { if (x != z) { z->row0 = x->row0; z->row1 = x->row1; z->row2 = x->row2; } z->row3 = { 0.0f, 0.0f, 0.0f, 1.0f }; } inline void mat4_get_rotation(const mat4* x, vec3* z) { if (-x->row0.z >= 1.0f) z->y = (float_t)M_PI_2; else if (-x->row0.z <= -1.0f) z->y = (float_t)-M_PI_2; else z->y = asinf(-x->row0.z); if (fabs(x->row0.z) < 0.99999899f) { z->x = atan2f(x->row1.z, x->row2.z); z->z = atan2f(x->row0.y, x->row0.x); } else { z->x = 0.0f; z->z = atan2f(x->row2.y, x->row1.y); if (x->row0.z > 0.0f) z->z = -z->z; } } inline void mat4_get_scale(const mat4* x, vec3* z) { z->x = vec4::length(x->row0); z->y = vec4::length(x->row1); z->z = vec4::length(x->row2); } inline void mat4_get_translation(const mat4* x, vec3* z) { *z = *(vec3*)&x->row3; } inline void mat4_set_translation(mat4* x, vec3* z) { *(vec3*)&x->row3 = *z; } inline void mat4_blend(const mat4* x, const mat4* y, mat4* z, float_t blend) { quat q0; quat q1; quat q2; quat_from_mat3(x->row0.x, x->row1.x, x->row2.x, x->row0.y, x->row1.y, x->row2.y, x->row0.z, x->row1.z, x->row2.z, &q0); quat_from_mat3(y->row0.x, y->row1.x, y->row2.x, y->row0.y, y->row1.y, y->row2.y, y->row0.z, y->row1.z, y->row2.z, &q1); vec3 t1; vec3 t2; vec3 t3; mat4_get_translation(x, &t1); mat4_get_translation(y, &t2); q2 = quat::slerp(q0, q1, blend); t3 = vec3::lerp(t1, t2, blend); mat4_from_quat(&q2, z); mat4_set_translation(z, &t3); } inline void mat4_blend_rotation(const mat4* x, const mat4* y, mat4* z, float_t blend) { quat q0; quat q1; quat q2; quat_from_mat3(x->row0.x, x->row1.x, x->row2.x, x->row0.y, x->row1.y, x->row2.y, x->row0.z, x->row1.z, x->row2.z, &q1); quat_from_mat3(y->row0.x, y->row1.x, y->row2.x, y->row0.y, y->row1.y, y->row2.y, y->row0.z, y->row1.z, y->row2.z, &q1); q2 = quat::slerp(q0, q1, blend); mat4_from_quat(&q2, z); } void mat4_lerp_rotation(const mat4* x, const mat4* y, mat4* z, float_t blend) { vec3 m0; vec3 m1; m0 = vec3::lerp(*(vec3*)&x->row0, *(vec3*)&y->row0, blend); m1 = vec3::lerp(*(vec3*)&x->row1, *(vec3*)&y->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) { *z = *y; 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) { *z = *y; 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; *z = mat4_identity; *(vec3*)&z->row0 = m0; *(vec3*)&z->row1 = m1; *(vec3*)&z->row2 = m2; } inline float_t mat4_get_max_scale(const mat4* x) { mat4 mat; mat4_transpose(x, &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_mult_axis_angle(const mat4* x, const vec3* axis, const float_t angle, mat4* z) { quat q1; quat q2; quat q3; float_t t0; float_t t1; float_t t2; vec4 t3; t0 = x->row0.w; t1 = x->row1.w; t2 = x->row2.w; t3 = x->row3; quat_from_mat3(x->row0.x, x->row1.x, x->row2.x, x->row0.y, x->row1.y, x->row2.y, x->row0.z, x->row1.z, x->row2.z, &q1); quat_from_axis_angle(axis, angle, &q2); quat_mult(&q2, &q1, &q3); mat4_from_quat(&q3, z); z->row0.w = t0; z->row1.w = t1; z->row2.w = t2; z->row3 = t3; } 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* mat) { *mat = mat4_null; mat->row0.x = (float_t)((2.0 * z_near) / (right - left)); mat->row1.y = (float_t)((2.0 * z_near) / (top - bottom)); mat->row2.x = (float_t)((right + left) / (right - left)); mat->row2.y = (float_t)((top + bottom) / (top - bottom)); mat->row2.z = -(float_t)((z_far + z_near) / (z_far - z_near)); mat->row2.w = -1.0f; mat->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* mat) { *mat = mat4_identity; mat->row0.x = (float_t)(2.0 / (right - left)); mat->row1.y = (float_t)(2.0 / (top - bottom)); mat->row2.z = (float_t)(-2.0 / (z_far - z_near)); mat->row3.x = -(float_t)((right + left) / (right - left)); mat->row3.y = -(float_t)((top + bottom) / (top - bottom)); mat->row3.z = -(float_t)((z_far + z_near) / (z_far - z_near)); } inline void mat4_persp(double_t fov_y, double_t aspect, double_t z_near, double_t z_far, mat4* mat) { double_t tan_fov = tan(fov_y * 0.5); *mat = mat4_null; mat->row0.x = (float_t)(1.0 / (aspect * tan_fov)); mat->row1.y = (float_t)(1.0 / tan_fov); mat->row2.z = -(float_t)((z_far + z_near) / (z_far - z_near)); mat->row2.w = -1.0f; mat->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* mat) { 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); mat->row0 = { x_axis.x, y_axis.x, z_axis.x, 0.0f }; mat->row1 = { x_axis.y, y_axis.y, z_axis.y, 0.0f }; mat->row2 = { x_axis.z, y_axis.z, z_axis.z, 0.0f }; *(vec3*)&mat->row3 = -xyz; mat->row3.w = 1.0f; } inline void mat4_look_at(const vec3* eye, const vec3* target, mat4* mat) { 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, mat); }