// Math functions are default 32 bit (f32, i32, etc) unless specified #define Pi ((f32)3.14159265358979323846) #define Tau ((f32)6.28318530717958647693) #define GoldenRatio ((f32)1.61803398874989484820) //////////////////////////////////////////////////////////// //~ Axis types Enum(Axis) { Axis_X = 0, Axis_Y = 1, Axis_Z = 2, Axis_COUNTXY = 2, Axis_COUNTXYZ = 3 }; //////////////////////////////////////////////////////////// //~ Vector types //- Vec2 Union(Vec2) { struct { f32 x, y; }; f32 v[2]; }; Union(Vec2F64) { struct { f64 x, y; }; f64 v[2]; }; Union(Vec2I32) { struct { i32 x, y; }; i32 v[2]; }; Union(Vec2I64) { struct { i64 x, y; }; i64 v[2]; }; Union(Vec2U32) { struct { u32 x, y; }; u32 v[2]; }; Union(Vec2U64) { struct { u64 x, y; }; u64 v[2]; }; Struct(Vec2Array) { Vec2 *points; u64 count; }; #define VEC2(x, y) (Vec2) { (x), (y) } #define VEC2F64(x, y) (Vec2F64) { (x), (y) } #define VEC2I32(x, y) (Vec2I32) { (x), (y) } #define VEC2I64(x, y) (Vec2I64) { (x), (y) } #define VEC2U32(x, y) (Vec2U32) { (x), (y) } #define VEC2U64(x, y) (Vec2U64) { (x), (y) } #define Vec2FromVec(v) VEC2((v).x, (v).y) #define Vec2F64FromVec(v) VEC2F64((v).x, (v).y) #define Vec2I32FromVec(v) VEC2I32((v).x, (v).y) #define Vec2I64FromVec(v) VEC2I64((v).x, (v).y) #define Vec2U32FromVec(v) VEC2U32((v).x, (v).y) #define Vec2U64FromVec(v) VEC2U64((v).x, (v).y) //- Vec3 Union(Vec3) { struct { f32 x, y, z; }; f32 v[3]; }; Union(Vec3F64) { struct { f64 x, y, z; }; f64 v[3]; }; Union(Vec3I32) { struct { i32 x, y, z; }; i32 v[3]; }; Union(Vec3I64) { struct { i64 x, y, z; }; i64 v[3]; }; Union(Vec3U32) { struct { u32 x, y, z; }; u32 v[3]; }; Union(Vec3U64) { struct { u64 x, y, z; }; u64 v[3]; }; Struct(Vec3Array) { Vec3 *points; u64 count; }; #define VEC3(x, y, z) (Vec3) { (x), (y), (z) } #define VEC3F64(x, y, z) (Vec3F64) { (x), (y), (z) } #define VEC3I32(x, y, z) (Vec3I32) { (x), (y), (z) } #define VEC3I64(x, y, z) (Vec3I64) { (x), (y), (z) } #define VEC3U32(x, y, z) (Vec3U32) { (x), (y), (z) } #define VEC3U64(x, y, z) (Vec3U64) { (x), (y), (z) } #define Vec3FromVec(v) VEC3((v).x, (v).y, (v).z) #define Vec3F64FromVec(v) VEC3F64((v).x, (v).y, (v).z) #define Vec3I32FromVec(v) VEC3I32((v).x, (v).y, (v).z) #define Vec3I64FromVec(v) VEC3I64((v).x, (v).y, (v).z) #define Vec3U32FromVec(v) VEC3U32((v).x, (v).y, (v).z) #define Vec3U64FromVec(v) VEC3U64((v).x, (v).y, (v).z) //- Vec4 Union(Vec4) { struct { f32 x, y, z, w; }; f32 v[4]; }; Union(Vec4F64) { struct { f64 x, y, z, w; }; f64 v[4]; }; Union(Vec4I32) { struct { i32 x, y, z, w; }; i32 v[4]; }; Union(Vec4I64) { struct { i64 x, y, z, w; }; i64 v[4]; }; Union(Vec4U32) { struct { u32 x, y, z, w; }; u32 v[4]; }; Union(Vec4U64) { struct { u64 x, y, z, w; }; u64 v[4]; }; Struct(Vec4Array) { Vec4 *points; u64 count; }; #define VEC4(x, y, z, w) (Vec4) { (x), (y), (z), (w) } #define VEC4F64(x, y, z, w) (Vec4F64) { (x), (y), (z), (w) } #define VEC4I32(x, y, z, w) (Vec4I32) { (x), (y), (z), (w) } #define VEC4I64(x, y, z, w) (Vec4I64) { (x), (y), (z), (w) } #define VEC4U32(x, y, z, w) (Vec4U32) { (x), (y), (z), (w) } #define VEC4U64(x, y, z, w) (Vec4U64) { (x), (y), (z), (w) } #define Vec4FromVec(v) VEC4((v).x, (v).y, (v).z, (v).w) #define Vec4F64FromVec(v) VEC4F64((v).x, (v).y, (v).z, (v).w) #define Vec4I32FromVec(v) VEC4I32((v).x, (v).y, (v).z, (v).w) #define Vec4I64FromVec(v) VEC4I64((v).x, (v).y, (v).z, (v).w) #define Vec4U32FromVec(v) VEC4U32((v).x, (v).y, (v).z, (v).w) #define Vec4U64FromVec(v) VEC4U64((v).x, (v).y, (v).z, (v).w) //////////////////////////////////////////////////////////// //~ Range types //- Rng1 Struct(Rng) { f32 min, max; }; Struct(RngF64) { f64 min, max; }; Struct(RngI32) { i32 min, max; }; Struct(RngI64) { i64 min, max; }; Struct(RngU32) { u32 min, max; }; Struct(RngU64) { u64 min, max; }; #define RNG(min, max) (Rng) { (min), (max) } #define RNGF64(min, max) (RngF46) { (min), (max) } #define RNGI32(min, max) (RngI32) { (min), (max) } #define RNGI64(min, max) (RngI64) { (min), (max) } #define RNGU32(min, max) (RngU32) { (min), (max) } #define RNGU64(min, max) (RngU64) { (min), (max) } //- Rng2 Struct(Rng2) { Vec2 p0, p1; }; Struct(Rng2F64) { Vec2F64 p0, p1; }; Struct(Rng2I32) { Vec2I32 p0, p1; }; Struct(Rng2I64) { Vec2I64 p0, p1; }; Struct(Rng2U32) { Vec2U32 p0, p1; }; Struct(Rng2U64) { Vec2U64 p0, p1; }; #define RNG2(p0, p1) (Rng2) { (p0), (p1) } #define RNG2F64(p0, p1) (Rng2F46) { (p0), (p1) } #define RNG2I32(p0, p1) (Rng2I32) { (p0), (p1) } #define RNG2I64(p0, p1) (Rng2I64) { (p0), (p1) } #define RNG2U32(p0, p1) (Rng2U32) { (p0), (p1) } #define RNG2U64(p0, p1) (Rng2U64) { (p0), (p1) } //- Rng3 Struct(Rng3) { Vec3 p0, p1; }; Struct(Rng3F64) { Vec3F64 p0, p1; }; Struct(Rng3I32) { Vec3I32 p0, p1; }; Struct(Rng3I64) { Vec3I64 p0, p1; }; Struct(Rng3U32) { Vec3U32 p0, p1; }; Struct(Rng3U64) { Vec3U64 p0, p1; }; #define RNG3(p0, p1) (Rng3) { (p0), (p1) } #define RNG3F64(p0, p1) (Rng3F46) { (p0), (p1) } #define RNG3I32(p0, p1) (Rng3I32) { (p0), (p1) } #define RNG3I64(p0, p1) (Rng3I64) { (p0), (p1) } #define RNG3U32(p0, p1) (Rng3U32) { (p0), (p1) } #define RNG3U64(p0, p1) (Rng3U64) { (p0), (p1) } //////////////////////////////////////////////////////////// //~ Xform types Struct(Xform) { Vec2 bx; // X basis vector (x axis) Vec2 by; // Y basis vector (y axis) Vec2 og; // Translation vector (origin) }; // (T)ranslation, (R)otation, (S)cale Struct(Trs) { Vec2 t; Vec2 s; f32 r; }; //////////////////////////////////////////////////////////// //~ Spring types Struct(SoftSpring) { f32 bias_rate; f32 mass_scale; f32 impulse_scale; }; //////////////////////////////////////////////////////////// //~ Mat4x4 types Struct(Mat4x4) { union { struct { Vec4 bx, by, bz, bw; }; f32 e[4][4]; }; }; //////////////////////////////////////////////////////////// //~ Min / max //- Min u8 MinU8(u8 a, u8 b); i8 MinI8(i8 a, i8 b); u32 MinU32(u32 a, u32 b); i32 MinI32(i32 a, i32 b); f32 MinF32(f32 a, f32 b); u64 MinU64(u64 a, u64 b); i64 MinI64(i64 a, i64 b); f64 MinF64(f64 a, f64 b); //- Max u8 MaxU8(u8 a, u8 b); i8 MaxI8(i8 a, i8 b); u32 MaxU32(u32 a, u32 b); i32 MaxI32(i32 a, i32 b); f32 MaxF32(f32 a, f32 b); u64 MaxU64(u64 a, u64 b); i64 MaxI64(i64 a, i64 b); f64 MaxF64(f64 a, f64 b); //- Clamp u32 ClampU32(u32 v, u32 min, u32 max); i32 ClampI32(i32 v, i32 min, i32 max); f32 ClampF32(f32 v, f32 min, f32 max); u64 ClampU64(u64 v, u64 min, u64 max); i64 ClampI64(i64 v, i64 min, i64 max); f64 ClampF64(f64 v, f64 min, f64 max); //- Saturate u32 SaturateU32(u32 v); i32 SaturateI32(i32 v); f32 SaturateF32(f32 v); u64 SaturateU64(u64 v); i64 SaturateI64(i64 v); f64 SaturateF64(f64 v); //////////////////////////////////////////////////////////// //~ Float ops //- Round #define RoundF32(v) roundf(v) #define RoundF64(v) round(v) //- Floor #define FloorF32(v) floorf(v) #define FloorF64(v) floor(v) //- Ceil #define CeilF32(v) ceilf(v) #define CeilF64(v) ceil(v) //- Trunc #define TruncF32(v) truncf(v) #define TruncF64(v) trunc(v) //- Mod #define ModF32(v, m) fmodf((v), (m)) #define ModF64(v, m) fmod((v), (m)) //- Abs #define AbsF32(v) fabsf(v) #define AbsF64(v) fabs(v) //- Sign i32 SignF32(f32 v); i32 SignF64(f64 v); //////////////////////////////////////////////////////////// //~ Exponential ops u64 PowU64(u64 v, u8 exp); #define PowF32(v, exp) powf((v), (exp)) #define PowF64(v, exp) pow((v), (exp)) #define SqrtF32(v) sqrtf(v) #define SqrtF64(v) sqrt(v) #define LnF32(v) log(v) #define Log2F32(v) log2f(v) #define Log10F32(v) log10f(v) //////////////////////////////////////////////////////////// //~ Align u64 AlignU64(u64 x, u64 align); u64 NextPow2U64(u64 x); //////////////////////////////////////////////////////////// //~ Trig #define SinF32(v) sinf(v) #define CosF32(v) cosf(v) #define TanF32(x) tanf(x) #define ArcTanF32(x) atanf(x) #define ArcTan2F32(y, x) atan2f((y), (x)) //////////////////////////////////////////////////////////// //~ Angle unwind // Returns angle in range [-Pi, Pi] f32 UnwindAngleF32(f32 a); //////////////////////////////////////////////////////////// //~ Float lerp f32 LerpF32(f32 val0, f32 val1, f32 t); f64 LerpF64(f64 val0, f64 val1, f64 t); f32 LerpAngleF32(f32 a, f32 b, f32 t); //////////////////////////////////////////////////////////// //~ Int lerp i32 LerpI32(i32 val0, i32 val1, f32 t); i64 LerpI64(i64 val0, i64 val1, f64 t); i32 LerpU32(u32 val0, u32 val1, f32 t); i64 LerpU64(u64 val0, u64 val1, f64 t); //////////////////////////////////////////////////////////// //~ Smoothstep f32 SmoothstepF32(f32 a, f32 b, f32 t); f64 SmoothstepF64(f64 a, f64 b, f64 t); //////////////////////////////////////////////////////////// //~ Color u8 MulNormalizedU8(u8 a, u8 b); f32 SrgbFromLinearF32(f32 lin); f32 LinearFromSrgbF32(f32 srgb); Vec4 LinearFromSrgb(Vec4 srgb); Vec4 SrgbFromLinear(Vec4 lin); Vec4 PremulFromLinear(Vec4 lin); Vec4 PremulFromSrgb(Vec4 srgb); Vec4 LerpSrgb(Vec4 v0, Vec4 v1, f32 t); //////////////////////////////////////////////////////////// //~ Vec2 b32 IsVec2Zero(Vec2 a); b32 MatchVec2(Vec2 a, Vec2 b); //- Mul Vec2 MulVec2(Vec2 a, f32 s); Vec2 MulVec2Vec2(Vec2 a, Vec2 b); Vec2 NegVec2(Vec2 a); //- Div Vec2 DivVec2(Vec2 a, f32 s); Vec2 DivVec2Vec2(Vec2 a, Vec2 b); //- Add Vec2 AddVec2(Vec2 a, Vec2 b); Vec2 SubVec2(Vec2 a, Vec2 b); //- Len f32 Vec2Len(Vec2 a); f32 Vec2LenSq(Vec2 a); Vec2 Vec2WithLen(Vec2 a, f32 len); f32 Vec2Distance(Vec2 a, Vec2 b); Vec2 NormVec2(Vec2 a); Vec2 ClampVec2Len(Vec2 a, f32 max); //- Clamp Vec2 ClampVec2(Vec2 v, Rng2 r); Vec2 SaturateVec2(Vec2 v); //- Dot f32 DotVec2(Vec2 a, Vec2 b); f32 WedgeVec2(Vec2 a, Vec2 b); Vec2 PerpVec2(Vec2 a); Vec2 MulPerpVec2(Vec2 a, f32 s); Vec2 PerpVec2TowardsDir(Vec2 v, Vec2 dir); //- Round / floor / ceil Vec2 RoundVec2(Vec2 a); Vec2 FloorVec2(Vec2 a); Vec2 CeilVec2(Vec2 a); //- Angle i32 WindingFromVec2(Vec2 a, Vec2 b); Vec2 RotateVec2(Vec2 v, f32 a); Vec2 Vec2FromAngle(f32 a); f32 AngleFromVec2(Vec2 v); f32 AngleFromVec2Dirs(Vec2 dir1, Vec2 dir2); f32 AngleFromVec2Points(Vec2 pt1, Vec2 pt2); //- Closest point Vec2 ClosestPointFromRay(Vec2 ray_pos, Vec2 ray_dir_norm, Vec2 p); //- Lerp Vec2 LerpVec2(Vec2 v0, Vec2 v1, f32 t); Vec2 LerpVec2Vec2(Vec2 v0, Vec2 v1, Vec2 t); Vec2 SlerpVec2(Vec2 v0, Vec2 v1, f32 t); //////////////////////////////////////////////////////////// //~ Vec2I32 b32 MatchVec2I32(Vec2I32 a, Vec2I32 b); Vec2I32 NegVec2I32(Vec2I32 a); Vec2I32 AddVec2I32(Vec2I32 a, Vec2I32 b); Vec2I32 SubVec2I32(Vec2I32 a, Vec2I32 b); //////////////////////////////////////////////////////////// //~ Vec4 //- Mul Vec4 MulVec4(Vec4 v, f32 s); Vec4 MulVec4Vec4(Vec4 a, Vec4 b); //- Lerp Vec4 LerpVec4(Vec4 v0, Vec4 v1, f32 t); //- Conversion Vec4 Vec4FromU32(u32 v); u32 U32FromVec4(Vec4 v); //////////////////////////////////////////////////////////// //~ Range //- Rng1 f32 NormRng(Rng r, f32 v); #define Norm(min, max, v) NormRng(RNG((min), (max)), (v)) //- Rng2 Vec2 DimsFromRng2(Rng2 r); Vec2 CenterFromRng2(Rng2 r); Vec2 NormRng2(Rng2 r, Vec2 v); Rng2 UnionRng2(Rng2 a, Rng2 b); Rng2 AddRng2Vec2(Rng2 r, Vec2 v); Rng2 MulRng2Vec2(Rng2 a, Vec2 v); Rng2 DivRng2Vec2(Rng2 a, Vec2 v); //- Rng2I32 Vec2I32 DimsFromRng2I32(Rng2I32 r); Vec2I32 CenterFromRng2I32(Rng2I32 r); Rng2I32 UnionRng2I32(Rng2I32 a, Rng2I32 b); Rng2I32 AddRng2I32Vec2I32(Rng2I32 r, Vec2I32 v); Rng2I32 MulRng2I32Vec2I32(Rng2I32 a, Vec2I32 v); Rng2I32 DivRng2I32Vec2I32(Rng2I32 a, Vec2I32 v); //////////////////////////////////////////////////////////// //~ Xform b32 MatchXform(Xform xf1, Xform xf2); //- Initialization #define XformIdentity (Xform) { .bx = { .x = 1 }, .by = { .y = 1 } } #define CompXformIdentity { .bx = { .x = 1 }, .by = { .y = 1 } } Xform XformFromPos(Vec2 v); Xform XformFromRot(f32 r); Xform XformFromScale(Vec2 scale); Xform XformFromTrs(Trs trs); //- Translation Xform TranslateXform(Xform xf, Vec2 v); Xform WorldTranslateXform(Xform xf, Vec2 v); //- Rotation Xform RotateXform(Xform xf, f32 r); Xform WorldRotateXform(Xform xf, f32 r); Xform WorldRotateXformBasis(Xform xf, f32 r); Xform XformWithWorldRotation(Xform xf, f32 r); //- Scale Xform ScaleXform(Xform xf, Vec2 scale); Xform WorldScaleXform(Xform xf, Vec2 scale); //- Lerp Xform LerpXform(Xform a, Xform b, f32 t); //- Invert Xform InvertXform(Xform xf); //- Mul Vec2 MulXformV2(Xform xf, Vec2 v); Xform MulXform(Xform a, Xform b); Vec2 MulXformBasisV2(Xform xf, Vec2 v); Vec2 InvertXformMulV2(Xform xf, Vec2 v); Vec2 InvertXformBasisMulV2(Xform xf, Vec2 v); //- Helpers Xform BasisFromXform(Xform xf); f32 DeterminantFromXform(Xform xf); Vec2 RightFromXform(Xform xf); Vec2 LeftFromXform(Xform xf); Vec2 UpFromXform(Xform xf); Vec2 DownFromXform(Xform xf); f32 RotationFromXform(Xform xf); Vec2 ScaleFromXform(Xform xf); //- Trs #define TRS(...) ((Trs) { .t = VEC2(0,0), .s = VEC2(1, 1), .r = 0, __VA_ARGS__ }) //////////////////////////////////////////////////////////// //~ Spring SoftSpring MakeSpring(f32 hertz, f32 damping_ratio, f32 dt); //////////////////////////////////////////////////////////// //~ Mat4x4 Mat4x4 Mat4x4FromXform(Xform xf); Mat4x4 Mat4x4FromOrtho(f32 left, f32 right, f32 bottom, f32 top, f32 near_z, f32 far_z); Mat4x4 MulMat4x4(Mat4x4 m1, Mat4x4 m2); Mat4x4 ProjectMat4x4View(Xform view, f32 viewport_width, f32 viewport_height);