/* File: cwasm_matrices.c Author: Taylor Robbins Date: 09\01\2025 Description: ** Holds matrix structs (mat2, mat3, and mat4) which hold NxN r32 components */ //NOTE: These structures are in row-major order in memory because that's the order WebGL expects them in when we call something like gl.uniformMatrix4fv typedef union Matrix2x2 Matrix2x2; union Matrix2x2 { r32 Values[4]; struct { v2 Row[2]; }; struct { r32 r0c0, r0c1; r32 r1c0, r1c1; }; }; typedef union Matrix3x3 Matrix3x3; union Matrix3x3 { r32 Values[9]; struct { v3 Row[3]; }; struct { r32 r0c0, r0c1, r0c2; r32 r1c0, r1c1, r1c2; r32 r2c0, r2c1, r2c2; }; }; typedef union Matrix4x4 Matrix4x4; union Matrix4x4 { r32 Values[16]; struct { v4 Row[4]; }; struct { r32 r0c0, r0c1, r0c2, r0c3; r32 r1c0, r1c1, r1c2, r1c3; r32 r2c0, r2c1, r2c2, r2c3; r32 r3c0, r3c1, r3c2, r3c3; }; }; typedef Matrix2x2 mat2; typedef Matrix3x3 mat3; typedef Matrix4x4 mat4; static inline mat2 NewMat2(r32 r0c0, r32 r0c1, r32 r1c0, r32 r1c1) { mat2 result; result.r0c0 = r0c0; result.r0c1 = r0c1; result.r1c0 = r1c0; result.r1c1 = r1c1; return result; } static inline mat3 NewMat3(r32 r0c0, r32 r0c1, r32 r0c2, r32 r1c0, r32 r1c1, r32 r1c2, r32 r2c0, r32 r2c1, r32 r2c2) { mat3 result; result.r0c0 = r0c0; result.r0c1 = r0c1; result.r0c2 = r0c2; result.r1c0 = r1c0; result.r1c1 = r1c1; result.r1c2 = r1c2; result.r2c0 = r2c0; result.r2c1 = r2c1; result.r2c2 = r2c2; return result; } static inline mat4 NewMat4(r32 r0c0, r32 r0c1, r32 r0c2, r32 r0c3, r32 r1c0, r32 r1c1, r32 r1c2, r32 r1c3, r32 r2c0, r32 r2c1, r32 r2c2, r32 r2c3, r32 r3c0, r32 r3c1, r32 r3c2, r32 r3c3) { mat4 result; result.r0c0 = r0c0; result.r0c1 = r0c1; result.r0c2 = r0c2; result.r0c3 = r0c3; result.r1c0 = r1c0; result.r1c1 = r1c1; result.r1c2 = r1c2; result.r1c3 = r1c3; result.r2c0 = r2c0; result.r2c1 = r2c1; result.r2c2 = r2c2; result.r2c3 = r2c3; result.r3c0 = r3c0; result.r3c1 = r3c1; result.r3c2 = r3c2; result.r3c3 = r3c3; return result; } #define NewMat2_Const(R0C0, R0C1, R1C0, R1C1) { .r0c0=(R0C0), .r0c1=(R0C1), .r1c0=(R1C0), .r1c1=(R1C1) } #define NewMat3_Const(R0C0, R0C1, R0C2, R1C0, R1C1, R1C2, R2C0, R2C1, R2C2) { .r0c0=(R0C0), .r0c1=(R0C1), .r0c2=(R0C2), .r1c0=(R1C0), .r1c1=(R1C1), .r1c2=(R1C2), .r2c0=(R2C0), .r2c1=(R2C1), .r2c2=(R2C2) } #define NewMat4_Const(R0C0, R0C1, R0C2, R0C3, R1C0, R1C1, R1C2, R1C3, R2C0, R2C1, R2C2, R2C3, R3C0, R3C1, R3C2, R3C3) { .r0c0=(R0C0), .r0c1=(R0C1), .r0c2=(R0C2), .r0c3=(R0C3), .r1c0=(R1C0), .r1c1=(R1C1), .r1c2=(R1C2), .r1c3=(R1C3), .r2c0=(R2C0), .r2c1=(R2C1), .r2c2=(R2C2), .r2c3=(R2C3), .r3c0=(R3C0), .r3c1=(R3C1), .r3c2=(R3C2), .r3c3=(R3C3) } #define Mat2_Zero NewMat2(0,0, 0,0) #define Mat2_Zero_Const NewMat2_Const(0,0, 0,0) #define Mat2_Identity NewMat2(1,0, 0,1) #define Mat2_Identity_Const NewMat2_Const(1,0, 0,1) #define Mat3_Zero NewMat3(0,0,0, 0,0,0, 0,0,0) #define Mat3_Zero_Const NewMat3_Const(0,0,0, 0,0,0, 0,0,0) #define Mat3_Identity NewMat3(1,0,0, 0,1,0, 0,0,1) #define Mat3_Identity_Const NewMat3_Const(1,0,0, 0,1,0, 0,0,1) #define Mat4_Zero NewMat4(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) #define Mat4_Zero_Const NewMat4_Const(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) #define Mat4_Identity NewMat4(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1) #define Mat4_Identity_Const NewMat4_Const(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1) static inline bool AreEqualMat2(mat2 left, mat2 right) { return (left.r0c0==right.r0c0 && left.r0c1==right.r0c1 && left.r1c0==right.r1c0 && left.r1c1==right.r1c1); } static inline bool AreEqualMat3(mat3 left, mat3 right) { return (left.r0c0==right.r0c0 && left.r0c1==right.r0c1 && left.r0c2==right.r0c2 && left.r1c0==right.r1c0 && left.r1c1==right.r1c1 && left.r1c2==right.r1c2 && left.r2c0==right.r2c0 && left.r2c1==right.r2c1 && left.r2c2==right.r2c2); } static inline bool AreEqualMat4(mat4 left, mat4 right) { return (left.r0c0==right.r0c0 && left.r0c1==right.r0c1 && left.r0c2==right.r0c2 && left.r0c3==right.r0c3 && left.r1c0==right.r1c0 && left.r1c1==right.r1c1 && left.r1c2==right.r1c2 && left.r1c3==right.r1c3 && left.r2c0==right.r2c0 && left.r2c1==right.r2c1 && left.r2c2==right.r2c2 && left.r2c3==right.r2c3 && left.r3c0==right.r3c0 && left.r3c1==right.r3c1 && left.r3c2==right.r3c2 && left.r3c3==right.r3c3); } //TODO: AddMatX //TODO: SubMatX //TODO: MulMat2 and MulMat3 static inline mat4 MulMat4(mat4 left, mat4 right) { mat4 result = NewMat4_Const( left.r0c0*right.r0c0 + left.r0c1*right.r1c0 + left.r0c2*right.r2c0 + left.r0c3*right.r3c0, //r0c0 left.r0c0*right.r0c1 + left.r0c1*right.r1c1 + left.r0c2*right.r2c1 + left.r0c3*right.r3c1, //r0c1 left.r0c0*right.r0c2 + left.r0c1*right.r1c2 + left.r0c2*right.r2c2 + left.r0c3*right.r3c2, //r0c2 left.r0c0*right.r0c3 + left.r0c1*right.r1c3 + left.r0c2*right.r2c3 + left.r0c3*right.r3c3, //r0c3 left.r1c0*right.r0c0 + left.r1c1*right.r1c0 + left.r1c2*right.r2c0 + left.r1c3*right.r3c0, //r1c0 left.r1c0*right.r0c1 + left.r1c1*right.r1c1 + left.r1c2*right.r2c1 + left.r1c3*right.r3c1, //r1c1 left.r1c0*right.r0c2 + left.r1c1*right.r1c2 + left.r1c2*right.r2c2 + left.r1c3*right.r3c2, //r1c2 left.r1c0*right.r0c3 + left.r1c1*right.r1c3 + left.r1c2*right.r2c3 + left.r1c3*right.r3c3, //r1c3 left.r2c0*right.r0c0 + left.r2c1*right.r1c0 + left.r2c2*right.r2c0 + left.r2c3*right.r3c0, //r2c0 left.r2c0*right.r0c1 + left.r2c1*right.r1c1 + left.r2c2*right.r2c1 + left.r2c3*right.r3c1, //r2c1 left.r2c0*right.r0c2 + left.r2c1*right.r1c2 + left.r2c2*right.r2c2 + left.r2c3*right.r3c2, //r2c2 left.r2c0*right.r0c3 + left.r2c1*right.r1c3 + left.r2c2*right.r2c3 + left.r2c3*right.r3c3, //r2c3 left.r3c0*right.r0c0 + left.r3c1*right.r1c0 + left.r3c2*right.r2c0 + left.r3c3*right.r3c0, //r3c0 left.r3c0*right.r0c1 + left.r3c1*right.r1c1 + left.r3c2*right.r2c1 + left.r3c3*right.r3c1, //r3c1 left.r3c0*right.r0c2 + left.r3c1*right.r1c2 + left.r3c2*right.r2c2 + left.r3c3*right.r3c2, //r3c2 left.r3c0*right.r0c3 + left.r3c1*right.r1c3 + left.r3c2*right.r2c3 + left.r3c3*right.r3c3 //r3c3 ); return result; } //TODO: DivMatX //TODO: MulMatXAndVX //TODO: TransformMatX //TODO: TransposeMatX //TODO: DeterminantMatX //TODO: CofactorMatX? //TODO: AdjointMatX? //TODO: InverseMatX? //TODO: LinearCombineVXMatX? static inline mat2 MakeScaleMat2(r32 scaleX, r32 scaleY) { mat2 result = NewMat2_Const( scaleX, 0.0f, 0.0f, scaleY ); return result; } static inline mat3 MakeScaleMat3(r32 scaleX, r32 scaleY, r32 scaleZ) { mat3 result = NewMat3_Const( scaleX, 0.0f, 0.0f, 0.0f, scaleY, 0.0f, 0.0f, 0.0f, scaleZ ); return result; } static inline mat4 MakeScaleMat4(r32 scaleX, r32 scaleY, r32 scaleZ) { mat4 result = NewMat4_Const( scaleX, 0.0f, 0.0f, 0.0f, 0.0f, scaleY, 0.0f, 0.0f, 0.0f, 0.0f, scaleZ, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); return result; } static inline mat2 MakeScaleMat2V(v2 scale) { return MakeScaleMat2(scale.X, scale.Y); } static inline mat3 MakeScaleMat3V(v3 scale) { return MakeScaleMat3(scale.X, scale.Y, scale.Z); } static inline mat4 MakeScaleMat4V(v3 scale) { return MakeScaleMat4(scale.X, scale.Y, scale.Z); } static inline mat3 MakeTranslateMat3(r32 translateX, r32 translateY) { mat3 result = NewMat3_Const( 1.0f, 0.0f, translateX, 0.0f, 1.0f, translateY, 0.0f, 0.0f, 1.0f ); return result; } static inline mat3 MakeTranslateMat3V(v2 translate) { return MakeTranslateMat3(translate.X, translate.Y); } static inline mat3 MakeTranslateXMat3(r32 translateX) { return MakeTranslateMat3(translateX, 0.0f); } static inline mat3 MakeTranslateYMat3(r32 translateY) { return MakeTranslateMat3(0.0f, translateY); } static inline mat4 MakeTranslateMat4(r32 translateX, r32 translateY, r32 translateZ) { mat4 result = NewMat4_Const( 1.0f, 0.0f, 0.0f, translateX, 0.0f, 1.0f, 0.0f, translateY, 0.0f, 0.0f, 1.0f, translateZ, 0.0f, 0.0f, 0.0f, 1.0f ); return result; } static inline mat4 MakeTranslateMat4V(v3 translate) { return MakeTranslateMat4(translate.X, translate.Y, translate.Z); } static inline mat4 MakeTranslateXMat4(r32 translateX) { return MakeTranslateMat4(translateX, 0.0f, 0.0f); } static inline mat4 MakeTranslateYMat4(r32 translateY) { return MakeTranslateMat4(0.0f, translateY, 0.0f); } static inline mat4 MakeTranslateZMat4(r32 translateZ) { return MakeTranslateMat4(0.0f, 0.0f, translateZ); } //TODO: MakeRotateMat2 //TODO: MakeRotateXMat3, MakeRotateYMat3 and MakeRotateZMat3 static inline mat4 MakeRotateXMat4(r32 angleX) { r32 s = sinf(angleX); r32 c = cosf(angleX); mat4 result = NewMat4_Const( 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, c, -s, 0.0f, 0.0f, s, c, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); return result; } static inline mat4 MakeRotateYMat4(r32 angleY) { r32 s = sinf(angleY); r32 c = cosf(angleY); mat4 result = NewMat4_Const( c, 0.0f, -s, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, s, 0.0f, c, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); return result; } static inline mat4 MakeRotateZMat4(r32 angleZ) { r32 s = sinf(angleZ); r32 c = cosf(angleZ); mat4 result = NewMat4_Const( c, -s, 0.0f, 0.0f, s, c, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); return result; } //TODO: MakeOrthographicMatX? //TODO: MakePerspectiveMatX? //TODO: MakeLookAtMatX? // static inline mat4 Make2DTransformMat4(v2 position, v2 scale, v2 origin, r32 rotation) // { // }