matrix functions

most matrix functions are converted over, no benefit to converting over the project/ortho because they would be scalar anyway but may need to move them regardless.
This commit is contained in:
marauder2k7 2026-03-03 19:09:00 +00:00
parent 67f12311d4
commit bc3145bc55
21 changed files with 1881 additions and 136 deletions

View file

@ -99,7 +99,7 @@ namespace math_backend::float3
f32x4 invLen = v_mul(v_set1(r), v_rsqrt_nr(v_dot3(va, va)));
f32x4 vnorm = v_mul(va, invLen);
v_store(a, vnorm);
v_store3(a, vnorm);
}
// Linear interpolation: r = from + (to - from) * f

View file

@ -0,0 +1,312 @@
#pragma once
#include <cmath> // for sqrtf, etc.
#include "../mConstants.h"
namespace math_backend::mat44
{
//------------------------------------------------------------------
// Matrix Transpose
inline void mat44_transpose_impl(float* m)
{
f32x4x4 ma = m_load(m);
f32x4x4 mr = m_transpose(ma);
m_store(m, mr);
}
inline float mat44_get_determinant(const float* m)
{
f32x4x4 ma = m_load(m);
return v_extract0(m_determinant_affine(ma));
}
// Matrix Scale: Float3 (assume w = 1.0f)
inline void mat44_scale_impl(float* m, const float* s)
{
f32x4x4 ma = m_load(m);
f32x4 va = v_load3_pos(s);
ma.r0 = v_mul(ma.r0, va);
ma.r1 = v_mul(ma.r1, va);
ma.r2 = v_mul(ma.r2, va);
ma.r3 = v_mul(ma.r3, va);
m_store(m, ma);
}
inline void mat44_get_scale_impl(const float* m, float* s)
{
f32x4x4 ma = m_load(m);
// squared lengths
f32x4 len2_x = v_dot3(ma.r0, ma.r0);
f32x4 len2_y = v_dot3(ma.r1, ma.r1);
f32x4 len2_z = v_dot3(ma.r2, ma.r2);
// extract and sqrt
s[0] = 1.0f / v_extract0(v_rsqrt_nr(len2_x));
s[1] = 1.0f / v_extract0(v_rsqrt_nr(len2_y));
s[2] = 1.0f / v_extract0(v_rsqrt_nr(len2_z));
}
// Matrix Scale Uniform: Float value (assume w = 1.0f)
inline void mat44_scale_uniform(float* m, float s)
{
f32x4x4 ma = m_load(m);
// (s, s, s, 1)
f32x4 scale = v_set(s, s, s, 1.0f);
// Scale only rotation rows (xyz part)
ma.r0 = v_mul(ma.r0, scale);
ma.r1 = v_mul(ma.r1, scale);
ma.r2 = v_mul(ma.r2, scale);
m_store(m, ma);
}
// Matrix Inverse
inline void mat44_inverse_impl(float* m)
{
f32x4x4 ma = m_load(m);
// Compute cofactors using cross products
f32x4x4 mTemp;
mTemp.r0 = v_cross(ma.r1, ma.r2);
mTemp.r1 = v_cross(ma.r2, ma.r0);
mTemp.r2 = v_cross(ma.r0, ma.r1);
// Determinant = dot(ma.r0, c0)
f32x4 det = v_dot3(ma.r0, mTemp.r0);
f32x4 invDet = v_rcp_nr(det);
// Scale cofactors
mTemp.r0 = v_mul(mTemp.r0, invDet);
mTemp.r1 = v_mul(mTemp.r1, invDet);
mTemp.r2 = v_mul(mTemp.r2, invDet);
// Store inverse 3x3 (transpose of cofactor matrix)
mTemp = m_transpose(mTemp);
mTemp.r3 = v_set(0, 0, 0, 1.0f);
// ---- Translation ----
// Load original translation
f32x4 T = v_set(m[3], m[7], m[11], 0.0f);
// Compute -(Tx*ma.r0 + Ty*ma.r1 + Tz*ma.r2)
f32x4 result = v_mul(ma.r0, v_swizzle_singular_mask(T, 0));
result = v_add(result, v_mul(ma.r1, v_swizzle_singular_mask(T, 1)));
result = v_add(result, v_mul(ma.r2, v_swizzle_singular_mask(T, 2)));
result = v_mul(result, v_set1(-1.0f));
m_store(m, mTemp);
// Store translation
m[3] = v_extract0(result);
m[7] = v_extract0(v_swizzle_singular_mask(result, 1));
m[11] = v_extract0(v_swizzle_singular_mask(result, 2));
}
// Matrix Affine Inverse
inline void mat44_affine_inverse_impl(float* m)
{
f32x4x4 ma = m_load(m);
f32x4x4 mTemp = m_transpose(ma);
mTemp.r3 = v_set(0, 0, 0, 1);
// ---- Translation ----
// Load original translation
f32x4 T = v_set(m[3], m[7], m[11], 0.0f);
// Compute -(Tx*ma.r0 + Ty*ma.r1 + Tz*ma.r2)
f32x4 result = v_mul(ma.r0, v_swizzle_singular_mask(T, 0));
result = v_add(result, v_mul(ma.r1, v_swizzle_singular_mask(T, 1)));
result = v_add(result, v_mul(ma.r2, v_swizzle_singular_mask(T, 2)));
result = v_mul(result, v_set1(-1.0f));
m_store(m, mTemp);
// Store translation
m[3] = v_extract0(result);
m[7] = v_extract0(v_swizzle_singular_mask(result, 1));
m[11] = v_extract0(v_swizzle_singular_mask(result, 2));
}
inline void mat44_normalize_impl(float* a)
{
// Load the matrix
f32x4x4 m = m_load(a);
// Extract axes (rows 0-2), zero out w using v_mask_xyz
f32x4 xaxis = v_mul(m.r0, v_mask_xyz());
f32x4 yaxis = v_mul(m.r1, v_mask_xyz());
f32x4 zaxis = v_mul(m.r2, v_mask_xyz());
xaxis = v_normalize3(xaxis);
float dotXY = v_extract0(v_hadd4(v_mul(xaxis, yaxis)));
f32x4 projYonX = v_mul(v_set1(dotXY), xaxis);
yaxis = v_normalize3(v_sub(yaxis, projYonX));
zaxis = v_cross(xaxis, yaxis);
// Store normalized axes back (preserve translation w)
m.r0 = v_preserve_w(xaxis, m.r0);
m.r1 = v_preserve_w(yaxis, m.r1);
m.r2 = v_preserve_w(zaxis, m.r2);
// Store back to memory
m_store(a, m);
}
// Matrix Multiply: a * b
inline void mat44_mul_mat44_impl(const float* a, const float* b, float* r)
{
f32x4x4 ma = m_load(a);
f32x4x4 mb = m_load(b);
f32x4x4 mr = m_mul(ma, mb);
m_store(r, mr);
}
// Vector Multiply: m * p (assume w = 1.0f)
inline void mat44_mul_pos3_impl(const float *m, const float *p, float* r)
{
f32x4x4 ma = m_load(m);
f32x4 va = v_load3_pos(p);
f32x4 vr = m_mul_vec4(ma, va);
v_store3(r, vr);
}
// Vector Multiply: m * v (assume w = 0.0f)
inline void mat44_mul_vec3_impl(const float* m, const float* v, float* r)
{
f32x4x4 ma = m_load(m);
f32x4 va = v_load3_vec(v);
f32x4 vr = m_mul_vec4(ma, va);
v_store3(r, vr);
}
// Vector Multiply: m * p (full [4x4] * [1x4])
inline void mat44_mul_float4_impl(const float* m, const float* p, float* r)
{
f32x4x4 ma = m_load(m);
f32x4 va = v_load(p);
f32x4 vr = m_mul_vec4(ma, va);
v_store(r, vr);
}
//--------------------------------------------------
// MATRIX ROTATION FUNCTIONS
//--------------------------------------------------
inline void mat44_rotation_x_impl(float* m, float angle)
{
float c = cosf(angle), s = sinf(angle);
f32x4x4 mr = m_identity();
mr.r1 = v_set(0, c, s, 0);
mr.r2 = v_set(0, -s, c, 0);
m_store(m, mr);
}
inline void mat44_rotation_y_impl(float* m, float angle)
{
float c = cosf(angle), s = sinf(angle);
f32x4x4 mr = m_identity();
mr.r0 = v_set(c, 0, -s, 0);
mr.r2 = v_set(s, 0, c, 0);
m_store(m, mr);
}
inline void mat44_rotation_z_impl(float* m, float angle)
{
float c = cosf(angle), s = sinf(angle);
f32x4x4 mr = m_identity();
mr.r0 = v_set(c, s, 0, 0);
mr.r1 = v_set(-s, c, 0, 0);
m_store(m, mr);
}
// Compose rotation from Euler angles (pitch=X, yaw=Y, roll=Z)
inline void mat44_rotation_euler_impl(float* m, float pitch, float yaw, float roll)
{
f32x4x4 rx, ry, rz;
mat44_rotation_x_impl((float*)&rx, pitch);
mat44_rotation_y_impl((float*)&ry, yaw);
mat44_rotation_z_impl((float*)&rz, roll);
f32x4x4 r = m_mul(rz, m_mul(ry, rx));
m_store(m, r);
}
inline void mat44_trs_impl(float* m, const float* t, const float* r_euler, const float* s)
{
f32x4x4 mr;
mat44_rotation_euler_impl((float*)&mr, r_euler[0], r_euler[1], r_euler[2]);
f32x4 vs = v_load3_vec(s); // scale xyz
mr.r0 = v_mul(mr.r0, vs);
mr.r1 = v_mul(mr.r1, vs);
mr.r2 = v_mul(mr.r2, vs);
mr.r0 = v_insert_w(mr.r0, _mm_set_ss(t[0]));
mr.r1 = v_insert_w(mr.r1, _mm_set_ss(t[1]));
mr.r2 = v_insert_w(mr.r2, _mm_set_ss(t[2]));
mr.r3 = v_set(0, 0, 0, 1.0f);
m_store(m, mr);
}
inline void mat44_lookat_impl(float* m, const float* eye, const float* target, const float* up)
{
f32x4 vEye = v_load3_pos(eye);
f32x4 vTarget = v_load3_pos(target);
f32x4 vUp = v_load3_vec(up);
// Forward (z+)
f32x4 zaxis = v_normalize3(v_sub(vTarget, vEye));
// Right (x+)
f32x4 xaxis = v_normalize3(v_cross(vUp, zaxis));
// Up (y+)
f32x4 yaxis = v_cross(zaxis, xaxis);
// Compute translation components: -dot(axis, eye)
f32x4 t_x = v_mul(v_dot3(xaxis, vEye), v_set1(-1.0f));
f32x4 t_y = v_mul(v_dot3(yaxis, vEye), v_set1(-1.0f));
f32x4 t_z = v_mul(v_dot3(zaxis, vEye), v_set1(-1.0f));
f32x4x4 view;
view.r0 = v_insert_w(xaxis, t_x);
view.r1 = v_insert_w(yaxis, t_y);
view.r2 = v_insert_w(zaxis, t_z);
view.r3 = v_set(0, 0, 0, 1.0f);
m_store(m, view);
}
inline void mat44_perspective_impl(float* m, float fovY, float aspect, float znear, float zfar)
{
float f = 1.0f / tanf(fovY * 0.5f);
float nf = 1.0f / (znear - zfar);
f32x4x4 mp = m_zero();
mp.r0 = v_set(f / aspect, 0, 0, 0);
mp.r1 = v_set(0, f, 0, 0);
mp.r2 = v_set(0, 0, (zfar + znear) * nf, 2 * zfar * znear * nf);
mp.r3 = v_set(0, 0, -1, 0); // row-major projection
m_store(m, mp);
}
inline void mat44_orthographic_impl(float* m, float left, float right, float bottom, float top, float znear, float zfar)
{
f32x4x4 mo = m_zero();
mo.r0 = v_set(2.0f / (right - left), 0, 0, -(right + left) / (right - left));
mo.r1 = v_set(0, 2.0f / (top - bottom), 0, -(top + bottom) / (top - bottom));
mo.r2 = v_set(0, 0, -2.0f / (zfar - znear), -(zfar + znear) / (zfar - znear));
mo.r3 = v_set(0, 0, 0, 1.0f);
m_store(m, mo);
}
} // namespace math_backend::mat44

View file

@ -1,3 +1,4 @@
#include "platform/platform.h"
#include "math/public/float4_dispatch.h"
#include "math/public/float3_dispatch.h"
#include "math/public/mat44_dispatch.h"
@ -196,6 +197,89 @@ namespace math_backend::mat44::dispatch
swap(a[11], a[14]);
};
gMat44.determinant = [](const float* m) {
return m[0] * (m[5] * m[10] - m[6] * m[9]) +
m[4] * (m[2] * m[9] - m[1] * m[10]) +
m[8] * (m[1] * m[6] - m[2] * m[5]);
};
gMat44.mul_vec3 = [](const float* a, const float* b, float* r) {
#ifdef TORQUE_COMPILER_GCC
const F32 v0 = b[0], v1 = b[1], v2 = b[2];
const F32 m0 = a[0], m1 = a[1], m2 = a[2];
const F32 m4 = a[4], m5 = a[5], m6 = a[6];
const F32 m8 = a[8], m9 = a[9], m10 = a[10];
r[0] = m0 * v0 + m1 * v1 + m2 * v2;
r[1] = m4 * v0 + m5 * v1 + m6 * v2;
r[2] = m8 * v0 + m9 * v1 + m10 * v2;
#else
r[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
r[1] = a[4] * b[0] + a[5] * b[1] + a[6] * b[2];
r[2] = a[8] * b[0] + a[9] * b[1] + a[10] * b[2];
#endif
};
gMat44.inverse = [](float* m) {
// using Cramers Rule find the Inverse
// Minv = (1/det(M)) * adjoint(M)
float det = gMat44.determinant(m);
AssertFatal(det != 0.0f, "MatrixF::inverse: non-singular matrix, no inverse.");
float invDet = 1.0f / det;
float temp[16];
temp[0] = (m[5] * m[10] - m[6] * m[9]) * invDet;
temp[1] = (m[9] * m[2] - m[10] * m[1]) * invDet;
temp[2] = (m[1] * m[6] - m[2] * m[5]) * invDet;
temp[4] = (m[6] * m[8] - m[4] * m[10]) * invDet;
temp[5] = (m[10] * m[0] - m[8] * m[2]) * invDet;
temp[6] = (m[2] * m[4] - m[0] * m[6]) * invDet;
temp[8] = (m[4] * m[9] - m[5] * m[8]) * invDet;
temp[9] = (m[8] * m[1] - m[9] * m[0]) * invDet;
temp[10] = (m[0] * m[5] - m[1] * m[4]) * invDet;
m[0] = temp[0];
m[1] = temp[1];
m[2] = temp[2];
m[4] = temp[4];
m[5] = temp[5];
m[6] = temp[6];
m[8] = temp[8];
m[9] = temp[9];
m[10] = temp[10];
// invert the translation
temp[0] = -m[3];
temp[1] = -m[7];
temp[2] = -m[11];
gMat44.mul_vec3(m, temp, &temp[4]);
m[3] = temp[4];
m[7] = temp[5];
m[11] = temp[6];
};
gMat44.affine_inverse = [](float* a) {
F32 temp[16];
dMemcpy(temp, a, 16 * sizeof(F32));
// Transpose rotation
a[1] = temp[4];
a[4] = temp[1];
a[2] = temp[8];
a[8] = temp[2];
a[6] = temp[9];
a[9] = temp[6];
a[3] = -(temp[0] * temp[3] + temp[4] * temp[7] + temp[8] * temp[11]);
a[7] = -(temp[1] * temp[3] + temp[5] * temp[7] + temp[9] * temp[11]);
a[11] = -(temp[2] * temp[3] + temp[6] * temp[7] + temp[10] * temp[11]);
};
gMat44.scale = [](float* a, const float* s) {
// Note, doesn't allow scaling w...
@ -204,5 +288,86 @@ namespace math_backend::mat44::dispatch
a[8] *= s[0]; a[9] *= s[1]; a[10] *= s[2];
a[12] *= s[0]; a[13] *= s[1]; a[14] *= s[2];
};
gMat44.get_scale = [](const float* a, float* s) {
// Note, doesn't allow scaling w...
s[0] = sqrt(a[0] * a[0] + a[4] * a[4] + a[8] * a[8]);
s[1] = sqrt(a[1] * a[1] + a[5] * a[5] + a[9] * a[9]);
s[2] = sqrt(a[2] * a[2] + a[6] * a[6] + a[10] * a[10]);
};
gMat44.mul_float4 = [](const float* a, const float* b, float* r) {
AssertFatal(b != r, "Error, aliasing matrix mul pointers not allowed here!");
r[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
r[1] = a[4] * b[0] + a[5] * b[1] + a[6] * b[2] + a[7] * b[3];
r[2] = a[8] * b[0] + a[9] * b[1] + a[10] * b[2] + a[11] * b[3];
r[2] = a[12] * b[0] + a[13] * b[1] + a[14] * b[2] + a[15] * b[3];
};
gMat44.mul_pos3 = [](const float* a, const float* b, float* r) {
AssertFatal(b != r, "Error, aliasing matrix mul pointers not allowed here!");
r[0] = a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3];
r[1] = a[4]*b[0] + a[5]*b[1] + a[6]*b[2] + a[7];
r[2] = a[8]*b[0] + a[9]*b[1] + a[10]*b[2] + a[11];
};
gMat44.mul_vec3 = [](const float* a, const float* b, float* r) {
AssertFatal(b != r, "Error, aliasing matrix mul pointers not allowed here!");
r[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
r[1] = a[4] * b[0] + a[5] * b[1] + a[6] * b[2];
r[2] = a[8] * b[0] + a[9] * b[1] + a[10] * b[2];
};
gMat44.mul_mat44 = [](const float* a, const float* b, float* r) {
r[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12];
r[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13];
r[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14];
r[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15];
r[4] = a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12];
r[5] = a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13];
r[6] = a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14];
r[7] = a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15];
r[8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12];
r[9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13];
r[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14];
r[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15];
r[12] = a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12];
r[13] = a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13];
r[14] = a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14];
r[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15];
};
gMat44.normalize = [](float* a) {
F32 col0[3], col1[3], col2[3];
// extract columns 0 and 1
col0[0] = a[0];
col0[1] = a[4];
col0[2] = a[8];
col1[0] = a[1];
col1[1] = a[5];
col1[2] = a[9];
math_backend::float3::dispatch::gFloat3.normalize(col0);
math_backend::float3::dispatch::gFloat3.normalize(col1);
math_backend::float3::dispatch::gFloat3.normalize(col2);
// store the normalized columns
a[0] = col0[0];
a[4] = col0[1];
a[8] = col0[2];
a[1] = col1[0];
a[5] = col1[1];
a[9] = col1[2];
a[2] = col2[0];
a[6] = col2[1];
a[10] = col2[2];
};
}
}