/* lerps */ UN_INLINE float un_m_lerpf(float a, float b, float t) { return (1.0 - t) * a + b * t; } UN_INLINE double un_m_lerpd(double a, double b, double t) { return (1.0 - t) * a + b * t; } /* easing */ UN_INLINE float un_m_ease_isinef(float t) { return 1.0 - cosf((t * PI) / 2.0); } UN_INLINE float un_m_ease_iosinef(float t) { return sinf((t * PI) / 2.0f); } UN_INLINE float un_m_ease_osinef(float t) { return -(cosf(t * PI) - 1.0) / 2.0; } UN_INLINE float un_m_ease_iquadf(float t) { return t * t; } UN_INLINE float un_m_ease_ioquadf(float t) { return 1.0 - (1.0 - t) * (1.0 - t); } UN_INLINE float un_m_ease_oquadf(float t) { return t < 0.5 ? 2.0 * t * t : 1.0 - ((-2.0 * t + 2.0) * (-2.0 * t + 2.0)) / 2.0; } UN_INLINE double un_m_ease_isined(double t) { return 1.0 - cos((t * PI) / 2.0); } UN_INLINE double un_m_ease_iosined(double t) { return sin((t * PI) / 2.0f); } UN_INLINE double un_m_ease_osined(double t) { return -(cos(t * PI) - 1.0) / 2.0; } UN_INLINE double un_m_ease_iquadd(double t) { return t * t; } UN_INLINE double un_m_ease_ioquadd(double t) { return 1.0 - (1.0 - t) * (1.0 - t); } UN_INLINE double un_m_ease_oquadd(double t) { return t < 0.5 ? 2.0 * t * t : 1.0 - ((-2.0 * t + 2.0) * (-2.0 * t + 2.0)) / 2.0; } /* complex */ UN_INLINE float2 un_m_complex_divf(float2 a, float2 b) { float f; float2 result; // un_m_complex_mulf(v, a, conjugated_b) result.x = a.x * b.x - a.y * -b.y; result.y = a.x * -b.y + a.y * b.x; f = b.x * b.x + b.y * b.y; result.x /= f; result.y /= f; return result; } UN_INLINE float2 un_m_complex_mulf(float2 a, float2 b) { float2 result; result.x = a.x * b.x - a.y * b.y; result.y = a.x * b.y + a.y * b.x; return result; } UN_INLINE double2 un_m_complex_divd(double2 a, double2 b) { double f; double2 result; // un_m_complex_mulf(v, a, conjugated_b) result.x = a.x * b.x - a.y * -b.y; result.y = a.x * -b.y + a.y * b.x; f = b.x * b.x + b.y * b.y; result.x /= f; result.y /= f; return result; } UN_INLINE double2 un_m_complex_muld(double2 a, double2 b) { double2 result; result.x = a.x * b.x - a.y * b.y; result.y = a.x * b.y + a.y * b.x; return result; } /* splines */ UN_INLINE float un_m_bezierf(float a, float q0, float q1, float b, float t) { float i0, i1, i2, p0, p1, ti; ti = 1.0 - t; i0 = ti * a + q0 * t; i1 = ti * q0 + q1 * t; i2 = ti * q1 + b * t; p0 = ti * i0 + i1 * t; p1 = ti * i1 + i2 * t; return ti * p0 + p1 * t; } UN_INLINE float2 un_m_bezier2f(float2 a, float2 q0, float2 q1, float2 b, float t) { float2 result; result.x = un_m_bezierf(a.x, q0.x, q1.x, b.x, t); result.y = un_m_bezierf(a.y, q0.y, q1.y, b.y, t); return result; } float3 un_m_bezier3f(float3 a, float3 q0, float3 q1, float3 b, float t) { float3 result; result.x = un_m_bezierf(a.x, q0.x, q1.x, b.x, t); result.y = un_m_bezierf(a.y, q0.y, q1.y, b.y, t); result.z = un_m_bezierf(a.z, q0.z, q1.z, b.z, t); return result; } UN_INLINE float4 un_m_bezier4f(float4 a, float4 q0, float4 q1, float4 b, float t) { float4 result; result.x = un_m_bezierf(a.x, q0.x, q1.x, b.x, t); result.y = un_m_bezierf(a.y, q0.y, q1.y, b.y, t); result.z = un_m_bezierf(a.z, q0.z, q1.z, b.z, t); result.w = un_m_bezierf(a.w, q0.w, q1.w, b.w, t); return result; } UN_INLINE double un_m_bezierd(double a, double q0, double q1, double b, double t) { double i0, i1, i2, p0, p1, ti; ti = 1.0 - t; i0 = ti * a + q0 * t; i1 = ti * q0 + q1 * t; i2 = ti * q1 + b * t; p0 = ti * i0 + i1 * t; p1 = ti * i1 + i2 * t; return ti * p0 + p1 * t; } UN_INLINE double2 un_m_bezier2d(double2 a, double2 q0, double2 q1, double2 b, double t) { double2 result; result.x = un_m_bezierd(a.x, q0.x, q1.x, b.x, t); result.y = un_m_bezierd(a.y, q0.y, q1.y, b.y, t); return result; } UN_INLINE double3 un_m_bezier3d(double3 a, double3 q0, double3 q1, double3 b, double t) { double3 result; result.x = un_m_bezierd(a.x, q0.x, q1.x, b.x, t); result.y = un_m_bezierd(a.y, q0.y, q1.y, b.y, t); result.z = un_m_bezierd(a.z, q0.z, q1.z, b.z, t); return result; } UN_INLINE double4 un_m_bezier4d(double4 a, double4 q0, double4 q1, double4 b, double t) { double4 result; result.x = un_m_bezierd(a.x, q0.x, q1.x, b.x, t); result.y = un_m_bezierd(a.y, q0.y, q1.y, b.y, t); result.z = un_m_bezierd(a.z, q0.z, q1.z, b.z, t); result.w = un_m_bezierd(a.w, q0.w, q1.w, b.w, t); return result; } /* matrix and quaternions */ /* convention of matrix is: Column-major * * stored in memory as x0 y0 z0 w0 x1 y1 z1 w1 ... * * transform * inverse transform * multiply * reverse * rotate * quaternion -> matrix * matrix -> quaternion * matrix to components: un_mat_disassemble(float *pos3, float *scale3, float *quat4) * un_mat_assemble(float *v, float *pos3, float *scale3, float *quat4) * assembe_inverse * * */ UN_INLINE void un_m_mat_identityf(float *v) { memset((void*)v, 0, sizeof(*v) * UN_MATRIX_SIZE); v[0 + 0 * UN_MATRIX_STRIPE] = 1.0f; v[1 + 1 * UN_MATRIX_STRIPE] = 1.0f; v[2 + 2 * UN_MATRIX_STRIPE] = 1.0f; v[3 + 3 * UN_MATRIX_STRIPE] = 1.0f; } UN_INLINE void un_m_mat_mulf(float *v, float *left, float *right) { u64 row, col, i; memset((void*)v, 0, sizeof(*v) * UN_MATRIX_SIZE); for (col = 0; col < 4; col++) { for (row = 0; row < 4; row++) { for (i = 0; i < 4; i++) { v[row + col * UN_MATRIX_STRIPE] += left[row + i * UN_MATRIX_STRIPE] * right[i + col * UN_MATRIX_STRIPE]; } } } } UN_INLINE void un_mat_xformf(float *v, float *xform) { un_m_mat_identityf(v); v[3 + 0 * UN_MATRIX_STRIPE] += xform[0]; v[3 + 1 * UN_MATRIX_STRIPE] += xform[1]; v[3 + 2 * UN_MATRIX_STRIPE] += xform[2]; } UN_INLINE void un_mat_scalef(float *v, float *scale) { un_m_mat_identityf(v); v[0 + 0 * UN_MATRIX_STRIPE] = scale[0]; v[1 + 1 * UN_MATRIX_STRIPE] = scale[1]; v[2 + 2 * UN_MATRIX_STRIPE] = scale[2]; }