diff options
author | talha <talha@talhaamir.xyz> | 2023-08-30 11:04:00 +0500 |
---|---|---|
committer | talha <talha@talhaamir.xyz> | 2023-08-30 11:04:00 +0500 |
commit | d980dcd2b66e4879989ce18291d044d5a4ffc902 (patch) | |
tree | 4f5fbd30d5152ffd21783eb02976bbaed6e0dd21 /code/math.h |
setting up font-rendering repo
Diffstat (limited to 'code/math.h')
-rw-r--r-- | code/math.h | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/code/math.h b/code/math.h new file mode 100644 index 0000000..7a64285 --- /dev/null +++ b/code/math.h @@ -0,0 +1,465 @@ +#ifndef MATH_H +#define MATH_H + +#define Sq(x) ((x)*(x)) +#define Sqrt(x) sqrt((x)) +#define PI 3.14159265358f +#define DegToRad(x) ((x)*(PI/180.0f)) +#define RadToDeg(x) ((x)*(180.0f/PI)) + +#define PIVOT_X 0 +#define PIVOT_Y 1 +#define PIVOT_Z 2 + +typedef struct Vec2 { + r32 x; + r32 y; + + Vec2 operator-(Vec2 S) + { + Vec2 R = {0}; + R.x = x - S.x; + R.y = y - S.y; + return R; + } + + Vec2 operator+(Vec2 S) + { + Vec2 R = {0}; + R.x = x + S.x; + R.y = y + S.y; + return R; + } + + Vec2 operator*(Vec2 S) + { + Vec2 R = {0}; + R.x = x * S.x; + R.y = y * S.y; + return R; + } + + Vec2 operator/(r32 s) + { + Vec2 R = {0}; + R.x = x/2; + R.y = y/2; + return R; + } + + Vec2 operator/(Vec2 S) + { + Vec2 R = {0}; + R.x = x / S.x; + R.y = y / S.y; + return R; + } +} Vec2; + +typedef struct Vec3 { + r32 x; + r32 y; + r32 z; + + Vec3 operator+(Vec3 S) + { + Vec3 R = {0}; + R.x = x + S.x; + R.y = y + S.y; + R.z = z + S.z; + return R; + } + + Vec3 operator+(r32 S) + { + Vec3 R = {0}; + R.x = x + S; + R.y = y + S; + R.z = z + S; + return R; + } + + Vec3 operator*(r32 S) + { + Vec3 R; + R.x = x * S; + R.y = y * S; + R.z = z * S; + + return R; + } + + Vec3 operator/(r32 S) + { + Vec3 R; + R.x = x / S; + R.y = y / S; + R.z = z / S; + + return R; + } +} Vec3; + +typedef struct Vec4 { + r32 x; + r32 y; + r32 z; + r32 w; +} Vec4; + +typedef struct Mat4 { + r32 x0, x1, x2, x3; + r32 y0, y1, y2, y3; + r32 z0, z1, z2, z3; + r32 w0, w1, w2, w3; +} Mat4; + +Vec3 InitVec3(r32 Val); +Vec3 InitVec3(r32 x, r32 y, r32 z); +r32 LenVec3(Vec3 V); +Vec3 UnitVec3(Vec3 V); +r32 DotProductVec3(Vec3 S, Vec3 K); +Vec3 CrossProductVec3(Vec3 S, Vec3 K); + +Vec4 InitVec4(r32 x, r32 y, r32 z, r32 w); +Vec4 ScalerAdd4(Vec4 Vec, r32 Scaler); +Vec4 ScalerMul4(Vec4 Vec, r32 Scaler); +Vec4 ScalerDiv4(Vec4 Vec, r32 Scaler); +Vec4 AddVec4(Vec4 V, Vec4 K); +r32 LenVec4(Vec4 V); +Vec4 UnitVec4(Vec4 V); +r32 DotProductVec4(Vec4 S, Vec4 K); +Vec4 Mul_Mat4Vec4(Mat4 Matrix, Vec4 S); +Mat4 IdentityMat(); +Mat4 Mul_Mat4Mat4(Mat4 M1, Mat4 M2); +Mat4 CreateTranslationMat(Vec4 S); +Mat4 CreateScaleMat(Vec4 S); +Mat4 CreateRotationMat(r32 Theta, u8 Pivot); +Mat4 CreateFrustum(r32 left, r32 right, r32 bot, r32 top, r32 nearCam, r32 farCam); +Mat4 CreatePerspectiveUsingFrustum(r32 fov, r32 aspect, r32 nearCam, r32 farCam); +Mat4 CreateOrthographic(r32 left, r32 right, r32 bot, r32 top, r32 nearCam, r32 farCam); +Mat4 CreateOrthographicWithRatio(r32 scrWidth, r32 scrHeight, r32 nearCam, r32 farCam); +Mat4 CreateLookAtMat4(Vec3 CameraPos, Vec3 CameraTarget, Vec3 Up); + +Vec3 InitVec3(r32 val) +{ + Vec3 R = Vec3{val,val,val}; + return R; +} + +Vec3 InitVec3(r32 x, r32 y, r32 z) +{ + Vec3 R = Vec3{x,y,z}; + return R; +} + +r32 LenVec3(Vec3 V) +{ + r32 L = Sqrt(Sq(V.x) + Sq(V.y) + Sq(V.z)); + return L; +} + +Vec3 UnitVec3(Vec3 V) +{ + Vec3 R; + r32 L = LenVec3(V); + R.x = V.x/L; + R.y = V.y/L; + R.z = V.z/L; + + return R; +} + +r32 DotProductVec3(Vec3 S, Vec3 K) +{ + Vec3 R; + R.x = S.x*K.x; + R.y = S.y*K.y; + R.z = S.z*K.z; + + r32 DotProd = R.x + R.y + R.z; + return DotProd; +} + +Vec3 CrossProductVec3(Vec3 S, Vec3 K) +{ + Vec3 R; + R.x = (S.y*K.z) - (S.z*K.y); + R.y = (S.z*K.x) - (S.x*K.z); + R.z = (S.x*K.y) - (S.y*K.x); + + return R; +} + + + +// @note: I am creating vectors in many places so created a function to make initialising abit easier +Vec4 InitVec4(r32 x, r32 y, r32 z, r32 w) +{ + Vec4 V = {0}; + V.x = x; + V.y = y; + V.z = z; + V.w = w; + + return V; +} + + +Vec4 ScalerAdd4(Vec4 Vec, r32 Scaler) +{ + Vec.x += Scaler; + Vec.y += Scaler; + Vec.z += Scaler; + Vec.w += Scaler; + + return Vec; +} + +Vec4 ScalerMul4(Vec4 Vec, r32 Scaler) +{ + Vec.x *= Scaler; + Vec.y *= Scaler; + Vec.z *= Scaler; + Vec.w *= Scaler; + + return Vec; +} + +Vec4 ScalerDiv4(Vec4 Vec, r32 Scaler) +{ + Vec.x = Vec.x/Scaler; + Vec.y = Vec.y/Scaler; + Vec.z = Vec.z/Scaler; + Vec.w = Vec.w/Scaler; + + return Vec; +} + +Vec4 AddVec4(Vec4 V, Vec4 K) +{ + Vec4 Res = {0}; + Res.x = V.x + K.x; + Res.y = V.y + K.y; + Res.z = V.z + K.z; + Res.w = V.w + K.w; + + return Res; +} + +r32 LenVec4(Vec4 V) +{ + r32 L = Sqrt(Sq(V.x) + Sq(V.y) + Sq(V.z) +Sq(V.w)); + return L; +} + +Vec4 UnitVec4(Vec4 V) +{ + Vec4 R = {0}; + r32 L = LenVec4(V); + R.x = V.x/L; + R.y = V.y/L; + R.z = V.z/L; + R.w = V.w/L; + + return R; +} + +r32 DotProductVec4(Vec4 S, Vec4 K) +{ + Vec4 R = {0}; + R.x = S.x*K.x; + R.y = S.y*K.y; + R.z = S.z*K.z; + R.w = S.w*K.w; + + r32 DotProd = R.x + R.y + R.z + R.w; + return DotProd; +} + +// TODO: multiplication operations can be SIMD'd +Vec4 Mul_Mat4Vec4(Mat4 Matrix, Vec4 S) +{ + Vec4 Res = {0}; + Res.x = (Matrix.x0*S.x) + (Matrix.x1*S.y) + (Matrix.x2*S.z) + (Matrix.x3*S.w); + Res.y = (Matrix.y0*S.y) + (Matrix.y1*S.y) + (Matrix.y2*S.z) + (Matrix.y3*S.w); + Res.z = (Matrix.z0*S.z) + (Matrix.z1*S.y) + (Matrix.z2*S.z) + (Matrix.z3*S.w); + Res.w = (Matrix.w0*S.w) + (Matrix.w1*S.y) + (Matrix.w2*S.z) + (Matrix.w3*S.w); + + return Res; +} + +Mat4 IdentityMat() +{ + Mat4 M = {0}; + M.x0 = 1.0f; + M.y1 = 1.0f; + M.z2 = 1.0f; + M.w3 = 1.0f; + + return M; +} + +Mat4 Mul_Mat4Mat4(Mat4 M1, Mat4 M2) +{ + Mat4 Res = {0}; + // Row 0 + Res.x0 = (M1.x0*M2.x0) + (M1.x1*M2.y0) + (M1.x2*M2.z0) + (M1.x3*M2.w0); + Res.x1 = (M1.x0*M2.x1) + (M1.x1*M2.y1) + (M1.x2*M2.z1) + (M1.x3*M2.w1); + Res.x2 = (M1.x0*M2.x2) + (M1.x1*M2.y2) + (M1.x2*M2.z2) + (M1.x3*M2.w2); + Res.x3 = (M1.x0*M2.x3) + (M1.x1*M2.y3) + (M1.x2*M2.z3) + (M1.x3*M2.w3); + + Res.y0 = (M1.y0*M2.x0) + (M1.y1*M2.y0) + (M1.y2*M2.z0) + (M1.y3*M2.w0); + Res.y1 = (M1.y0*M2.x1) + (M1.y1*M2.y1) + (M1.y2*M2.z1) + (M1.y3*M2.w1); + Res.y2 = (M1.y0*M2.x2) + (M1.y1*M2.y2) + (M1.y2*M2.z2) + (M1.y3*M2.w2); + Res.y3 = (M1.y0*M2.x3) + (M1.y1*M2.y3) + (M1.y2*M2.z3) + (M1.y3*M2.w3); + + Res.z0 = (M1.z0*M2.x0) + (M1.z1*M2.y0) + (M1.z2*M2.z0) + (M1.z3*M2.w0); + Res.z1 = (M1.z0*M2.x1) + (M1.z1*M2.y1) + (M1.z2*M2.z1) + (M1.z3*M2.w1); + Res.z2 = (M1.z0*M2.x2) + (M1.z1*M2.y2) + (M1.z2*M2.z2) + (M1.z3*M2.w2); + Res.z3 = (M1.z0*M2.x3) + (M1.z1*M2.y3) + (M1.z2*M2.z3) + (M1.z3*M2.w3); + + Res.w0 = (M1.w0*M2.x0) + (M1.w1*M2.y0) + (M1.w2*M2.z0) + (M1.w3*M2.w0); + Res.w1 = (M1.w0*M2.x1) + (M1.w1*M2.y1) + (M1.w2*M2.z1) + (M1.w3*M2.w1); + Res.w2 = (M1.w0*M2.x2) + (M1.w1*M2.y2) + (M1.w2*M2.z2) + (M1.w3*M2.w2); + Res.w3 = (M1.w0*M2.x3) + (M1.w1*M2.y3) + (M1.w2*M2.z3) + (M1.w3*M2.w3); + + return Res; +} + +/* + * Matrix multiplication orders + * Scale -> Rotate -> Translate + */ +Mat4 CreateTranslationMat(Vec4 S) +{ + Mat4 TM = {0}; + TM.x0=1.0f; TM.x3=S.x, + TM.y1=1.0f; TM.y3=S.y, + TM.z2=1.0f; TM.z3=S.z, + TM.w3=1.0f; + + return TM; +} + +Mat4 CreateScaleMat(Vec4 S) +{ + Mat4 SM = {0}; + SM.x0=S.x; + SM.y1=S.y; + SM.z2=S.z; + SM.w3=1.0f; + return SM; +} + +Mat4 CreateRotationMat(r32 Theta, u8 Pivot) +{ + r32 CosTheta = cos(Theta); + r32 SinTheta = sin(Theta); + + Mat4 RotMat = {0}; + if (Pivot == PIVOT_X) + { + RotMat.x0 = 1.0f; + RotMat.y1 = CosTheta; RotMat.y2 = -SinTheta; + RotMat.z1 = SinTheta; RotMat.z2 = CosTheta; + RotMat.w3 = 1.0f; + } + else if (Pivot == PIVOT_Y) + { + RotMat.x0 = CosTheta; RotMat.x2 = SinTheta; + RotMat.y1 = 1.0f; + RotMat.z0 = -SinTheta; RotMat.z2 = CosTheta; + RotMat.w3 = 1.0f; + } + else if (Pivot == PIVOT_Z) + { + RotMat.x0 = CosTheta; RotMat.x1 = -SinTheta; + RotMat.y0 = SinTheta; RotMat.y1 = CosTheta; + RotMat.z3 = 1.0f; + RotMat.w3 = 1.0f; + } + + return RotMat; +} + +Mat4 CreateFrustum(r32 left, r32 right, r32 bot, r32 top, r32 nearCam, r32 farCam) +{ + Mat4 F = {0}; + F.x0 = 2.0f*nearCam/(right - left); + F.x3 = -nearCam*(right + left)/(right - left); + F.y1 = 2.0f*nearCam/(top-bot); + F.y3 = -nearCam*(top + bot)/(top - bot); + F.z2 = -(farCam+nearCam)/(farCam-nearCam); + F.z3 = 2.0f*farCam*nearCam/(nearCam - farCam); + F.w2 = -1.0f; + F.w3 = 0.0f; + + return F; +} + +Mat4 CreatePerspectiveUsingFrustum(r32 fov, r32 aspect, r32 nearCam, r32 farCam) +{ + r32 top = nearCam*tan(fov)/2; + r32 bot = -top; + r32 right = top*aspect; + r32 left = -right; + + return CreateFrustum(left, right, bot, top, nearCam, farCam); +} + +Mat4 CreateOrthographic(r32 left, r32 right, r32 bot, r32 top, r32 nearCam, r32 farCam) +{ + Mat4 F = {0}; + F.x0 = 2.0f/(right - left); + F.w0 = -(right + left)/(right - left); + + F.y1 = 2.0f/(top - bot); + F.w1 = -(top + bot)/(top - bot); + + F.z2 = -2.0f/(farCam - nearCam); + F.w2 = -(farCam + nearCam)/(farCam - nearCam); + + F.w3 = 1.0f; + + return F; +} + +Mat4 CreateOrthographicWithRatio(r32 scrWidth, r32 scrHeight, r32 nearCam, r32 farCam) +{ + r32 ratio_h = scrWidth/scrHeight; + r32 left = -ratio_h; + r32 right = ratio_h; + + r32 ratio_v = scrHeight/scrWidth; + r32 top = ratio_v; + r32 bot = -ratio_v; + + return CreateOrthographic(left, right, bot, top, nearCam, farCam); +} + +// @research: the gram-schmidt process: +// https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process +Mat4 CreateLookAtMat4(Vec3 CameraPos, Vec3 CameraTarget, Vec3 Up) +{ + // deriving the respective camera vectors + Vec3 CameraDir = UnitVec3((CameraPos + (CameraTarget * -1.0f))); + Vec3 CameraRight = UnitVec3(CrossProductVec3(Up, CameraDir)); + Vec3 CameraUp = CrossProductVec3(CameraRight, CameraDir); + + Mat4 DirMat = IdentityMat(); + DirMat.x0 = CameraRight.x; DirMat.x1 = CameraRight.y; DirMat.x2 = CameraRight.z; + DirMat.y0 = CameraUp.x; DirMat.y1 = CameraUp.y; DirMat.y2 = CameraUp.z; + DirMat.z0 = CameraDir.x; DirMat.z1 = CameraDir.y; DirMat.z2 = CameraDir.z; + + // make camera position -ve + Mat4 TranslationMat = IdentityMat(); + TranslationMat.x3 = -CameraPos.x; + TranslationMat.y3 = -CameraPos.y; + TranslationMat.z3 = -CameraPos.z; + + Mat4 LookAt = Mul_Mat4Mat4(DirMat, TranslationMat); + return LookAt; +} + +#endif |