From a844aaa225b50dbc321afb9a4fffa559f28f5dac Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 30 Jul 2025 12:58:22 -0500 Subject: [PATCH] base_math refactor progress --- build.c | 1 + src/base/base.c | 1 + src/base/base_incbin.c | 2 +- src/base/base_intrinsics.h | 62 +- src/base/base_math.c | 1444 +++++++++++++++++++++++++++++++ src/base/base_math.h | 1515 +++++++-------------------------- src/collider/collider_core.c | 2 +- src/config.h | 2 +- src/draw/draw_core.c | 10 +- src/draw/draw_core.h | 4 +- src/editor_include.h | 2 +- src/font/font_core.c | 2 +- src/gp/gp_core.h | 12 +- src/gp/gp_core_dx12.c | 26 +- src/kernel/kernel_core.h | 4 +- src/kernel/kernel_shade.knl | 2 +- src/platform/platform_snc.c | 4 +- src/platform/platform_win32.c | 4 +- src/sim/sim_core.c | 24 +- src/sim/sim_core.h | 12 +- src/sim/sim_ent.c | 10 +- src/sim/sim_ent.h | 10 +- src/sim/sim_space.c | 30 +- src/sim/sim_space.h | 10 +- src/sim/sim_step.c | 60 +- src/sprite/sprite_core.c | 12 +- src/user/user_core.c | 54 +- 27 files changed, 1919 insertions(+), 1402 deletions(-) create mode 100644 src/base/base_math.c diff --git a/build.c b/build.c index b3a0f8a9..0118c3cc 100644 --- a/build.c +++ b/build.c @@ -1049,6 +1049,7 @@ void OnBuild(StringList cli_args) String line = StringF(&perm, Lit("#include \"%F\""), FmtStr(include_path)); StringListAppend(&perm, &file_contents, line); } + StringListAppend(&perm, &file_contents, Lit("")); String file_contents_str = StringFromStringList(&perm, Lit("\n"), file_contents); D_ClearWrite(editor_include_file, file_contents_str); } diff --git a/src/base/base.c b/src/base/base.c index 3967a72f..140bd0eb 100644 --- a/src/base/base.c +++ b/src/base/base.c @@ -5,6 +5,7 @@ #include "base_gstat.c" #include "base_memory.c" #include "base_buddy.c" +#include "base_math.c" #include "base_rand.c" #include "base_string.c" #include "base_uid.c" diff --git a/src/base/base_incbin.c b/src/base/base_incbin.c index 1f4916b6..00341525 100644 --- a/src/base/base_incbin.c +++ b/src/base/base_incbin.c @@ -67,7 +67,7 @@ String StringFromIncbinRcResource(IncbinRcResource *inc) /* Spin while another thread searches */ while (state != IncbinStatus_Searched) { - ix_pause(); + IxPause(); state = Atomic32Fetch(&inc->state); } diff --git a/src/base/base_intrinsics.h b/src/base/base_intrinsics.h index f5618be2..5819f2ac 100644 --- a/src/base/base_intrinsics.h +++ b/src/base/base_intrinsics.h @@ -1,118 +1,118 @@ -/* ========================== * - * Math - * ========================== */ +//////////////////////////////// +//~ Sqrt intrinsics -/* Sqrt */ - -Inline f32 ix_sqrt_f32(f32 f) +Inline f32 IxSqrtF32(f32 f) { __m128 n = _mm_set_ss(f); n = _mm_sqrt_ss(n); return _mm_cvtss_f32(n); } -Inline f64 ix_sqrt_f64(f64 f) +Inline f64 IxSqrtF64(f64 f) { __m128d n = _mm_set_sd(f); n = _mm_sqrt_sd(_mm_setzero_pd(), n); return _mm_cvtsd_f64(n); } -Inline f32 ix_rsqrt_f32(f32 f) +Inline f32 IxRsqrtF32(f32 f) { __m128 n = _mm_set_ss(f); n = _mm_rsqrt_ss(n); return _mm_cvtss_f32(n); } -/* Round */ +//////////////////////////////// +//~ Round intrinsics -Inline i32 ix_round_f32_to_i32(f32 f) +Inline i32 IxRoundF32ToI32(f32 f) { return _mm_cvtss_si32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); } -Inline f32 ix_round_f32_to_f32(f32 f) +Inline f32 IxRoundF32ToF32(f32 f) { return _mm_cvtss_f32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); } -Inline i64 ix_round_f64_to_i64(f64 f) +Inline i64 IxRoundF64ToI64(f64 f) { return _mm_cvtsd_si64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); } -Inline f64 ix_round_f64_to_f64(f64 f) +Inline f64 IxRoundF64ToF64(f64 f) { return _mm_cvtsd_f64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); } -/* Floor */ +//////////////////////////////// +//~ Floor intrinsics -Inline i32 ix_floor_f32_to_i32(f32 f) +Inline i32 IxFloorF32ToI32(f32 f) { return _mm_cvtss_si32(_mm_floor_ss(_mm_setzero_ps(), _mm_set_ss(f))); } -Inline f32 ix_floor_f32_to_f32(f32 f) +Inline f32 IxFloorF32ToF32(f32 f) { return _mm_cvtss_f32(_mm_floor_ss(_mm_setzero_ps(), _mm_set_ss(f))); } -Inline i64 ix_floor_f64_to_i64(f64 f) +Inline i64 IxFloorF64ToI64(f64 f) { return _mm_cvtsd_si64(_mm_floor_sd(_mm_setzero_pd(), _mm_set_sd(f))); } -Inline f64 ix_floor_f64_to_f64(f64 f) +Inline f64 IxFloorF64ToF64(f64 f) { return _mm_cvtsd_f64(_mm_floor_sd(_mm_setzero_pd(), _mm_set_sd(f))); } -/* Ceil */ +//////////////////////////////// +//~ Ceil intrinsics -Inline i32 ix_ceil_f32_to_i32(f32 f) +Inline i32 IxCeilF32ToI32(f32 f) { return _mm_cvtss_si32(_mm_ceil_ss(_mm_setzero_ps(), _mm_set_ss(f))); } -Inline f32 ix_ceil_f32_to_f32(f32 f) +Inline f32 IxCeilF32ToF32(f32 f) { return _mm_cvtss_f32(_mm_ceil_ss(_mm_setzero_ps(), _mm_set_ss(f))); } -Inline i64 ix_ceil_f64_to_i64(f64 f) +Inline i64 IxCeilF64ToI64(f64 f) { return _mm_cvtsd_si64(_mm_ceil_sd(_mm_setzero_pd(), _mm_set_sd(f))); } -Inline f64 ix_ceil_f64_to_f64(f64 f) +Inline f64 IxCeilF64ToF64(f64 f) { return _mm_cvtsd_f64(_mm_ceil_sd(_mm_setzero_pd(), _mm_set_sd(f))); } -/* Truncate */ +//////////////////////////////// +//~ Truncate intrinsics -Inline f32 ix_trunc_f32_to_f32(f32 f) +Inline f32 IxTruncF32ToF32(f32 f) { return _mm_cvtss_f32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)); } -Inline f64 ix_trunc_f64_to_f64(f64 f) +Inline f64 IxTruncF64ToF64(f64 f) { return _mm_cvtsd_f64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)); } -/* ========================== * - * Util - * ========================== */ +//////////////////////////////// +//~ Utility intrinsics -Inline void ix_pause(void) +Inline void IxPause(void) { _mm_pause(); } -Inline u64 ix_clock(void) +Inline u64 IxClock(void) { return __rdtsc(); } diff --git a/src/base/base_math.c b/src/base/base_math.c new file mode 100644 index 00000000..aec52454 --- /dev/null +++ b/src/base/base_math.c @@ -0,0 +1,1444 @@ +/* Math functions are default 32 bit (f32, i32, etc) unless specified */ + +//////////////////////////////// +//~ Clamping + +u8 min_u8(u8 a, u8 b) { return a <= b ? a : b; } +u8 max_u8(u8 a, u8 b) { return a >= b ? a : b; } +u32 min_u32(u32 a, u32 b) { return a <= b ? a : b; } +u32 max_u32(u32 a, u32 b) { return a >= b ? a : b; } +u64 min_u64(u64 a, u64 b) { return a <= b ? a : b; } +u64 max_u64(u64 a, u64 b) { return a >= b ? a : b; } +i32 min_i32(i32 a, i32 b) { return a <= b ? a : b; } +i32 max_i32(i32 a, i32 b) { return a >= b ? a : b; } +i64 min_i64(i64 a, i64 b) { return a <= b ? a : b; } +i64 max_i64(i64 a, i64 b) { return a >= b ? a : b; } +f32 min_f32(f32 a, f32 b) { return a <= b ? a : b; } +f32 max_f32(f32 a, f32 b) { return a >= b ? a : b; } +f64 min_f64(f64 a, f64 b) { return a <= b ? a : b; } +f64 max_f64(f64 a, f64 b) { return a >= b ? a : b; } + +u32 clamp_u32(u32 v, u32 min, u32 max) { return v < min ? min : v > max ? max : v; } +u64 clamp_u64(u64 v, u64 min, u64 max) { return v < min ? min : v > max ? max : v; } +i32 clamp_i32(i32 v, i32 min, i32 max) { return v < min ? min : v > max ? max : v; } +i64 clamp_i64(i64 v, i64 min, i64 max) { return v < min ? min : v > max ? max : v; } +f32 clamp_f32(f32 v, f32 min, f32 max) { return v < min ? min : v > max ? max : v; } +f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; } + +//////////////////////////////// +//~ Rounding + +f32 math_round(f32 f) +{ + return IxRoundF32ToF32(f); +} + +f64 math_round64(f64 f) +{ + return IxRoundF64ToF64(f); +} + +i32 math_round_to_int(f32 f) +{ + return IxRoundF32ToI32(f); +} + +i64 math_round_to_int64(f64 f) +{ + return IxRoundF64ToI64(f); +} + +//////////////////////////////// +//~ Flooring + +f32 math_floor(f32 f) +{ + return IxFloorF32ToF32(f); +} + +f64 math_floor64(f64 f) +{ + return IxFloorF64ToF64(f); +} + +i32 math_floor_to_int(f32 f) +{ + return IxFloorF32ToI32(f); +} + +i64 math_floor_to_int64(f64 f) +{ + return IxFloorF64ToI64(f); +} + +//////////////////////////////// +//~ Ceiling + +f32 math_ceil(f32 f) +{ + return IxCeilF32ToF32(f); +} + +f64 math_ceil64(f64 f) +{ + return IxCeilF64ToF64(f); +} + +i32 math_ceil_to_int(f32 f) +{ + return IxCeilF32ToI32(f); +} + +i64 math_ceil_to_int64(f64 f) +{ + return IxCeilF64ToI64(f); +} + +//////////////////////////////// +//~ Truncing + +f32 math_trunc(f32 f) +{ + return IxTruncF32ToF32(f); +} + +f64 math_trunc64(f64 f) +{ + return IxTruncF64ToF64(f); +} + +//////////////////////////////// +//~ Fmod + +f32 math_fmod(f32 x, f32 m) +{ + return x - m * math_trunc(x / m); +} + +f64 math_fmod64(f64 x, f64 m) +{ + return x - m * math_trunc64(x / m); +} + +//////////////////////////////// +//~ Floating point sign + +f32 math_fabs(f32 f) +{ + u32 truncated = *(u32 *)&f & 0x7FFFFFFF; + return *(f32 *)&truncated; +} + +f64 math_fabs64(f64 f) +{ + u64 truncated = *(u64 *)&f & 0x7FFFFFFFFFFFFFFFULL; + return *(f64 *)&truncated; +} + +i32 math_fsign(f32 f) +{ + u32 sign_bit = (*(u32 *)&f >> 31) & 1; + return 1 + -((i32)(sign_bit << 1)); +} + +i64 math_fsign64(f64 f) +{ + u64 sign_bit = (*(u64 *)&f >> 63) & 1; + return 1 + -((i64)(sign_bit << 1)); +} + +//////////////////////////////// +//~ Integer bs + +u32 math_abs_i32(i32 v) +{ + return (u32)(v * ((v >= 0) - (v < 0))); +} + +u64 math_abs_i64(i64 v) +{ + return (u64)(v * ((v >= 0) - (v < 0))); +} + +//////////////////////////////// +//~ U64 pow + +/* Taken from https://gist.github.com/orlp/3551590 */ +u64 math_pow_u64(u64 base, u8 exp) +{ + LocalPersist const u8 highest_bit_set[] = { + 0, 1, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 255, /* Anything past 63 is a guaranteed overflow with base > 1 */ + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + }; + + u64 result = 1; + + switch (highest_bit_set[exp]) + { + case 255: + { + /* 255 = overflow, return 0 */ + if (base == 1) + { + return 1; + } + // if (base == -1) { + // return 1 - 2 * (exp & 1); + // } + return 0; + } break; + case 6: + { + if (exp & 1) result *= base; + exp >>= 1; + base *= base; + } FALLTHROUGH; + case 5: + { + if (exp & 1) result *= base; + exp >>= 1; + base *= base; + } FALLTHROUGH; + case 4: + { + if (exp & 1) result *= base; + exp >>= 1; + base *= base; + } FALLTHROUGH; + case 3: + { + if (exp & 1) result *= base; + exp >>= 1; + base *= base; + } FALLTHROUGH; + case 2: + { + if (exp & 1) result *= base; + exp >>= 1; + base *= base; + } FALLTHROUGH; + case 1: + { + if (exp & 1) result *= base; + } FALLTHROUGH; + default: return result; + } +} + +//////////////////////////////// +//~ Logn + +/* Based on FreeBSD's implementation + * https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_logf.c */ +f32 math_ln(f32 x) +{ + LocalPersist const f32 ln2_hi = 6.9313812256e-01f; + LocalPersist const f32 ln2_lo = 9.0580006145e-06f; + + i32 x_int = *(i32 *)&x; + + i32 k = 0; + if (x_int < 0x00800000) + { + f32 two_p25 = 3.3554432000e+07; + if ((x_int & 0x7fffffff) == 0) + { + /* Return -inf if x is 0 */ + return -two_p25 / 0; + } + else if (x_int < 0) + { + /* Return NaN if x is negative */ + return (x - x) / 0; + } + k -= 25; + x *= two_p25; + x_int = *(i32 *)&x; + } + else if (x_int >= 0x7f800000) + { + return x + x; + } + + k += (x_int >> 23) - 127; + x_int &= 0x007fffff; + i32 i = (x_int + (0x95f64 << 3)) & 0x800000; + i32 x_int_normalized = x_int | (i ^ 0x3f800000); + x = *(f32 *)&x_int_normalized - 1.0f; + k += (i >> 23); + + if ((0x007fffff & (0x8000 + x_int)) < 0xc000) + { + if (x == 0) + { + if (k == 0) + { + return 0; + } + else + { + return (f32)k * ln2_hi + (f32)k * ln2_lo; + } + } + f32 r = x * x * (0.5f - 0.33333333333333333f * x); + if (k == 0) + { + return x - r; + } + else + { + return (f32)k * ln2_hi - ((r - (f32)k * ln2_lo) - x); + } + } + + f32 s = x / (2.0f + x); + f32 z = s * s; + f32 w = z * z; + f32 r = (z * (0.66666662693f + w * 0.28498786688f)) + (w * (0.40000972152f + w * 0.24279078841f)); + if (((x_int - (0x6147a << 3)) | ((0x6b851 << 3) - x_int)) > 0) + { + f32 hfsq = 0.5f * x * x; + if (k == 0) + { + return x - (hfsq - s * (hfsq + r)); + } + else + { + return (f32)k * ln2_hi - ((hfsq - (s * (hfsq + r) + (f32)k * ln2_lo)) - x); + } + } + else + { + if (k == 0) + { + return x - s * (x - r); + } + else + { + return (f32)k * ln2_hi - ((s * (x - r) - (f32)k * ln2_lo) - x); + } + } +} + +//////////////////////////////// +//~ Exp + +/* Based on FreeBSD's implementation + * https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_expf.c */ +f32 math_exp(f32 x) +{ + LocalPersist const f32 half[2] = { 0.5, -0.5 }; + LocalPersist const f32 o_threshold = 8.8721679688e+01f; + LocalPersist const f32 u_threshold = -1.0397208405e+02f; + LocalPersist const f32 ln2_hi[2] = { 6.9314575195e-01f, -6.9314575195e-01f }; + LocalPersist const f32 ln2_lo[2] = { 1.4286067653e-06f, -1.4286067653e-06f }; + LocalPersist const f32 inv_ln2 = 1.4426950216e+00f; + LocalPersist const f32 huge = 1.0e+30f; + LocalPersist const f32 two_m100 = 7.8886090522e-31f; + + u32 x_uint = *(u32 *)&x; + i32 x_sign_bit = (i32)((x_uint >> 31) & 1); + x_uint &= 0x7fffffff; + + /* Filter out non-finite argument */ + if (x_uint >= 0x42b17218) + { /* if |x|>=88.721... */ + if (x_uint > 0x7f800000) + { + return x + x; /* NaN */ + } + else if (x_uint == 0x7f800000) + { + return (x_sign_bit == 0) ? x : 0; + } + if (x > o_threshold) + { + /* Overflow */ + return F32_INFINITY; + } + else if (x < u_threshold) + { + /* Underflow */ + return two_m100 * two_m100; + } + } + + /* Argument reduction */ + i32 k = 0; + f32 hi = 0; + f32 lo = 0; + if (x_uint > 0x3eb17218) + { + if (x_uint < 0x3F851592) + { + hi = x - ln2_hi[x_sign_bit]; + lo = ln2_lo[x_sign_bit]; + k = 1 - x_sign_bit - x_sign_bit; + } + else + { + k = (i32)(inv_ln2 * x + half[x_sign_bit]); + hi = x - (f32)k * ln2_hi[0]; + lo = (f32)k * ln2_lo[0]; + } + x = hi - lo; + } + else if (x_uint < 0x39000000) + { + if (huge + x > 1.0f) + { + return 1.0f + x; + } + } + else + { + k = 0; + } + + f32 two_pk; + if (k >= -125) + { + u32 temp = ((u32)(0x7f + k)) << 23; + two_pk = *(f32 *)&temp; + } + else + { + u32 temp = ((u32)(0x7f + (k + 100))) << 23; + two_pk = *(f32 *)&temp; + } + + f32 t = x * x; + f32 c = x - t * (1.6666625440e-1f + t * -2.7667332906e-3f); + if (k == 0) + { + return 1.0f - ((x * c) / (c - 2.0f) - x); + } + else + { + f32 y = 1.0f - ((lo - (x * c) / (2.0f - c)) - hi); + if (k >= -125) + { + if (k == 128) + { + u32 temp = 0x7f800000; + return y * 2.0f * (*(f32 *)&temp); + } + return y * two_pk; + } + else + { + return y * two_pk * two_m100; + } + } +} + +//////////////////////////////// +//~ Pow + +f32 math_pow(f32 a, f32 b) +{ + if (a >= 0) + { + /* a is positive */ + return math_exp(math_ln(a) * b); + } + else + { + /* a is negative */ + f32 res_sign = math_round_to_int(b) % 2 == 0 ? 1 : -1; + return math_exp(math_ln(-a) * b) * res_sign; + } +} + +//////////////////////////////// +//~ Sqrt + +f32 math_sqrt(f32 x) +{ + return IxSqrtF32(x); +} + +f64 math_sqrt64(f64 x) +{ + return IxSqrtF64(x); +} + +f32 math_rsqrt(f32 x) +{ + return IxRsqrtF32(x); +} + +//////////////////////////////// +//~ Trig + +/* Functions based on Cephes implementation (https://www.netlib.org/cephes/): + * - math_sin_approx + * - math_cos_approx + * - math_reduce_positive_to_pio4 + * - math_atan + */ + +//- Reduce +/* Reduce postive x to range [0, Pi/4] (Cody-Waite argument reduction). + * Returns 0 if x > (2^24 - 1); + * Sets octant_out=-1 on error. */ +f32 math_reduce_positive_to_pio4(f32 x, i32 *octant_out) +{ + i32 octant = -1; + + if (x <= ((1 << 24) - 1)) + { + octant = x * (4 / Pi); /* Integer part of x/(Pi/4) */ + f32 y = octant; + if (octant & 1) + { + octant += 1; + y += 1.0; + } + + /* Modulo 360 degrees */ + octant &= 7; + + if (x > 8192) + { + x = x - y * (Pi / 4); + } + else + { + /* Extended precision modular arithmetic */ + x = ((x - y * 0.78515625) - y * 2.4187564849853515625e-4) - y * 3.77489497744594108e-8; + } + } + + *octant_out = octant; + return x; +} + +//- Sin approximation +/* Approximate sin in range [0, Pi/4] */ +f32 math_sin_approx(f32 x) +{ + f32 x_sq = x * x; + return (((-1.9515295891E-4 * x_sq + 8.3321608736E-3) * x_sq - 1.6666654611E-1) * x_sq * x) + x; +} + +//- Cos approximation +f32 math_cos_approx(f32 x) +{ + f32 x_sq = x * x; + return (((2.443315711809948E-005 * x_sq - 1.388731625493765E-003) * x_sq + 4.166664568298827E-002) * x_sq * x_sq) - (x_sq * 0.5) + 1; +} + +//- Sin +f32 math_sin(f32 x) +{ + f32 sign = 1; + + if (IsF32Nan(x)) + { + return 0; + } + else if (x < 0) + { + sign = -1; + x = -x; + } + + i32 octant; + x = math_reduce_positive_to_pio4(x, &octant); + + /* Reflect in x axis */ + if (octant > 3) + { + sign = -sign; + octant -= 4; + } + + switch (octant) + { + case -1: return 0; + case 1: case 2: return math_cos_approx(x) * sign; + default: return math_sin_approx(x) * sign; + } +} + +//- Cos +f32 math_cos(f32 x) +{ + f32 sign = 1; + + if (IsF32Nan(x)) + { + return 0; + } + else if (x < 0) + { + x = -x; + } + + i32 octant; + x = math_reduce_positive_to_pio4(x, &octant); + + /* Reflect in x axis */ + if (octant > 3) + { + sign = -sign; + octant -= 4; + } + + if (octant > 1) + { + sign = -sign; + } + + switch (octant) + { + case -1: return 0; + case 1: case 2: return math_sin_approx(x) * sign; + default: return math_cos_approx(x) * sign; + } +} + +//- ArcTan +f32 math_atan(f32 x) +{ + f32 sign = 1; + if (x < 0) + { + sign = -1; + x = -x; + } + + /* Reduce range */ + f32 y; + if (x > 2.414213562373095) + { /* tan((Pi / 8) * 3) */ + y = Pi / 2; + x = -(1.f / x); + } + else if (x > 0.4142135623730950) + { /* tan(Pi / 8) */ + y = Pi / 4; + x = (x - 1.f) / (x + 1.f); + } + else + { + y = 0; + } + + f32 x_sq = x * x; + y += ((((8.05374449538e-2 * x_sq - 1.38776856032E-1) * x_sq + 1.99777106478E-1) * x_sq - 3.33329491539E-1) * x_sq * x + x); + + return y * sign; +} + +//- ArcTan2 +f32 math_atan2(f32 y, f32 x) +{ + f32 res; + if (x == 0) + { + if (y < 0) + { + res = 3 * Pi / 2; + } + else if (y == 0) + { + res = 0; + } + else + { + res = Pi / 2; + } + } + else if (y == 0) + { + if (x < 0) + { + res = Pi; + } + else + { + res = 0; + } + } + else + { + f32 offset; + if (x < 0) + { + offset = Pi; + } + else if (y < 0) + { + offset = Pi * 2; + } + else + { + offset = 0; + } + res = math_atan(y / x) + offset; + } + return res; +} + +//- ArcSin +f32 math_asin(f32 x) +{ + /* TODO: Dedicated arcsin approximation */ + return math_atan2(x, math_sqrt(1.0f - (x * x))); +} + +//- ArcCos +f32 math_acos(f32 x) +{ + /* TODO: Dedicated arccos approximation */ + return (Pi / 2.0f) - math_atan2(x, math_sqrt(1.0f - (x * x))); +} + +//////////////////////////////// +//~ Angle unwind + +/* Returns angle in range [-Pi, Pi] */ +f32 math_unwind_angle(f32 a) +{ + f32 d = math_fmod(a, Tau); + return math_fmod(2.0f * d, Tau) - d; +} + +//////////////////////////////// +//~ Float lerp + +f32 math_lerp_f32(f32 val0, f32 val1, f32 t) +{ + return val0 + ((val1 - val0) * t); +} + +f64 math_lerp_f64(f64 val0, f64 val1, f64 t) +{ + return val0 + ((val1 - val0) * t); +} + +f32 math_lerp_angle(f32 a, f32 b, f32 t) +{ + f32 diff = math_unwind_angle(b - a); + return a + diff * t; +} + +//////////////////////////////// +//~ Int lerp + +i32 math_lerp_i32(i32 val0, i32 val1, f32 t) +{ + return val0 + math_round_to_int(((f32)(val1 - val0) * t)); +} + + +//- Lerp i64 +i64 math_lerp_i64(i64 val0, i64 val1, f64 t) +{ + return val0 + math_round_to_int64(((f64)(val1 - val0) * t)); +} + +//////////////////////////////// +//~ V2 operations + +b32 v2_is_zero(V2 a) +{ + return a.x == 0 && a.y == 0; +} + +b32 v2_eq(V2 a, V2 b) +{ + return a.x == b.x && a.y == b.y; +} + +//- Mul + +V2 v2_mul(V2 a, f32 s) +{ + return V2FromXY(a.x * s, a.y * s); +} + +V2 v2_mul_v2(V2 a, V2 b) +{ + return V2FromXY(a.x * b.x, a.y * b.y); +} + +V2 v2_neg(V2 a) +{ + return V2FromXY(-a.x, -a.y); +} + +//- Div + +V2 v2_div(V2 a, f32 s) +{ + f32 d = 1 / s; + return V2FromXY(a.x * d, a.y * d); +} + +V2 v2_div_v2(V2 a, V2 b) +{ + return V2FromXY(a.x * (1 / b.x), a.y * (1 / b.y)); +} + +//- Add + +V2 v2_add(V2 a, V2 b) +{ + return V2FromXY(a.x + b.x, a.y + b.y); +} + +V2 v2_sub(V2 a, V2 b) +{ + return V2FromXY(a.x - b.x, a.y - b.y); +} + +//- Len + +f32 v2_len(V2 a) +{ + return math_sqrt(a.x * a.x + a.y * a.y); +} + +f32 v2_len_sq(V2 a) +{ + return a.x * a.x + a.y * a.y; +} + +V2 v2_with_len(V2 a, f32 len) +{ + f32 l_sq = a.x * a.x + a.y * a.y; + if (l_sq != 0) + { + f32 denom = len / math_sqrt(l_sq); + a.x *= denom; + a.y *= denom; + } + return a; +} + +V2 v2_clamp_len(V2 a, f32 max) +{ + f32 l_sq = a.x * a.x + a.y * a.y; + if (l_sq > max * max) + { + f32 denom = max / math_sqrt(l_sq); + a.x *= denom; + a.y *= denom; + } + return a; +} + +f32 v2_distance(V2 a, V2 b) +{ + f32 dx = b.x - a.x; + f32 dy = b.y - a.y; + return math_sqrt(dx * dx + dy * dy); +} + +V2 v2_norm(V2 a) +{ + return v2_with_len(a, 1.f); +} + + +//- Dot + +f32 v2_dot(V2 a, V2 b) +{ + return a.x * b.x + a.y * b.y; +} + +/* Returns signed area between vectors (positive in clockwise direction) + * AKA perpendicular dot product + * AKA 2d cross-product */ +f32 v2_wedge(V2 a, V2 b) +{ + return a.x * b.y - a.y * b.x; +} + +/* Clockwise (right) perpendicular vector */ +V2 v2_perp(V2 a) +{ + return V2FromXY(-a.y, a.x); +} + +/* Clockwise (right) perpendicular vector scaled by s */ +V2 v2_perp_mul(V2 a, f32 s) +{ + return V2FromXY(s * -a.y, s * a.x); +} + +V2 v2_perp_towards_dir(V2 v, V2 dir) +{ + f32 wedge = v2_wedge(v, dir); + return v2_perp_mul(v, (wedge >= 0) - (wedge < 0)); +} + +//- Round / floor / ceil + +V2 v2_round(V2 a) +{ + return V2FromXY(math_round(a.x), math_round(a.y)); +} + +V2I32 v2_round_to_int(V2 a) +{ + return V2I32FromXY(math_round_to_int(a.x), math_round_to_int(a.y)); +} + +V2 v2_floor(V2 a) +{ + return V2FromXY(math_floor(a.x), math_floor(a.y)); +} + +V2 v2_ceil(V2 a) +{ + return V2FromXY(math_ceil(a.x), math_ceil(a.y)); +} + +//- Angle + +/* Returns 1 if winding between vectors a & b is clockwise or straight, -1 if counter-clockwise */ +i32 v2_winding(V2 a, V2 b) +{ + f32 w = v2_wedge(a, b); + return (w >= 0) - (w < 0); +} + +V2 v2_rotated(V2 v, f32 a) +{ + f32 c = math_cos(a); + f32 s = math_sin(a); + return V2FromXY(v.x * c - v.y * s, v.x * s + v.y * c); +} + +V2 v2_from_angle(f32 a) +{ + return V2FromXY(math_cos(a), math_sin(a)); +} + +f32 v2_angle(V2 v) +{ + return math_atan2(v.y, v.x); +} + +f32 v2_angle_from_dirs(V2 dir1, V2 dir2) +{ + return math_atan2(v2_wedge(dir1, dir2), v2_dot(dir1, dir2)); +} + +f32 v2_angle_from_points(V2 pt1, V2 pt2) +{ + return v2_angle(v2_sub(pt2, pt1)); +} + +//- Closest point + +V2 v2_closest_point_ray(V2 ray_pos, V2 ray_dir_norm, V2 p) +{ + V2 ray_p_dir = v2_sub(p, ray_pos); + f32 dot = v2_dot(ray_dir_norm, ray_p_dir); + V2 ray_dir_closest = v2_mul(ray_dir_norm, dot); + return v2_add(ray_pos, ray_dir_closest); +} + +//- Lerp + +/* Interpolate position vectors */ +V2 v2_lerp(V2 val0, V2 val1, f32 t) +{ + return V2FromXY(math_lerp_f32(val0.x, val1.x, t), math_lerp_f32(val0.y, val1.y, t)); +} + +/* Interpolate direction vectors (spherical lerp) */ +V2 v2_slerp(V2 val0, V2 val1, f32 t) +{ + f32 rot = math_lerp_angle(v2_angle(val0), v2_angle(val1), t); + f32 len = math_lerp_f32(v2_len(val0), v2_len(val1), t); + return v2_mul(v2_from_angle(rot), len); +} + +//////////////////////////////// +//~ V2I32 Operations + +b32 v2i32_eq(V2I32 a, V2I32 b) +{ + return a.x == b.x && a.y == b.y; +} + +V2I32 v2i32_neg(V2I32 a) +{ + return V2I32FromXY(-a.x, -a.y); +} + +V2I32 v2i32_add(V2I32 a, V2I32 b) +{ + return V2I32FromXY(a.x + b.x, a.y + b.y); +} + +V2I32 v2i32_sub(V2I32 a, V2I32 b) +{ + return V2I32FromXY(a.x - b.x, a.y - b.y); +} + +//////////////////////////////// +//~ Mat4x4 operations + +Mat4x4 mat4x4_from_xform(Xform xf) +{ + return CppCompatInitListType(Mat4x4) + { + .e = { + {xf.bx.x, xf.bx.y, 0, 0}, + {xf.by.x, xf.by.y, 0, 0}, + {0, 0, 1, 0}, + {xf.og.x, xf.og.y, 0, 1}, + } + }; +} + +Mat4x4 mat4x4_from_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near_z, f32 far_z) +{ + Mat4x4 m = ZI; + + f32 rl = 1.0f / (right - left); + f32 tb = 1.0f / (top - bottom); + f32 fn = -1.0f / (far_z - near_z); + + m.e[0][0] = 2.0f * rl; + m.e[1][1] = 2.0f * tb; + m.e[2][2] = 2.0f * fn; + m.e[3][0] = -(right + left) * rl; + m.e[3][1] = -(top + bottom) * tb; + m.e[3][2] = (far_z + near_z) * fn; + m.e[3][3] = 1.0f; + + return m; +} + +Mat4x4 mat4x4_mul(Mat4x4 m1, Mat4x4 m2) +{ + f32 a00 = m1.e[0][0], a01 = m1.e[0][1], a02 = m1.e[0][2], a03 = m1.e[0][3], + a10 = m1.e[1][0], a11 = m1.e[1][1], a12 = m1.e[1][2], a13 = m1.e[1][3], + a20 = m1.e[2][0], a21 = m1.e[2][1], a22 = m1.e[2][2], a23 = m1.e[2][3], + a30 = m1.e[3][0], a31 = m1.e[3][1], a32 = m1.e[3][2], a33 = m1.e[3][3], + + b00 = m2.e[0][0], b01 = m2.e[0][1], b02 = m2.e[0][2], b03 = m2.e[0][3], + b10 = m2.e[1][0], b11 = m2.e[1][1], b12 = m2.e[1][2], b13 = m2.e[1][3], + b20 = m2.e[2][0], b21 = m2.e[2][1], b22 = m2.e[2][2], b23 = m2.e[2][3], + b30 = m2.e[3][0], b31 = m2.e[3][1], b32 = m2.e[3][2], b33 = m2.e[3][3]; + + Mat4x4 res; + res.e[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; + res.e[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; + res.e[0][2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03; + res.e[0][3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03; + res.e[1][0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; + res.e[1][1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; + res.e[1][2] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13; + res.e[1][3] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13; + res.e[2][0] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23; + res.e[2][1] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23; + res.e[2][2] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23; + res.e[2][3] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23; + res.e[3][0] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33; + res.e[3][1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33; + res.e[3][2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33; + res.e[3][3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33; + + return res; +} + +//////////////////////////////// +//~ Xform operations + +/* Construct identity xform */ +#define XFORM_IDENT CppCompatInitListType(Xform) { .bx = V2FromXY(1, 0), .by = V2FromXY(0, 1) } +#define XFORM_IDENT_NOCAST { .bx = V2FromXY(1, 0), .by = V2FromXY(0, 1) } + +#define XFORM_POS(p) CppCompatInitListType(Xform) { .bx = V2FromXY(1, 0), .by = V2FromXY(0, 1), .og = (p) } + +/* Takes a translation, rotation, and scale as optional parameters for constructing an xform */ +#define XFORM_TRS(...) xform_from_trs((Trs) { .t = V2FromXY(0,0), .s = V2FromXY(1, 1), .r = 0, __VA_ARGS__ }) + +Xform xform_mul(Xform a, Xform b); +Xform xform_rotated(Xform xf, f32 angle); +Xform xform_scaled(Xform xf, V2 v); +V2 xform_basis_mul_v2(Xform xf, V2 v); +V2 xform_mul_v2(Xform xf, V2 v); +f32 xform_get_determinant(Xform xf); +V2 xform_get_scale(Xform xf); +f32 xform_get_rotation(Xform xf); + +b32 xform_eq(Xform xf1, Xform xf2) +{ + return v2_eq(xf1.og, xf2.og) && v2_eq(xf1.bx, xf2.bx) && v2_eq(xf1.by, xf2.by); +} + +Xform xform_from_pos(V2 v) +{ + Xform xf; + xf.bx = V2FromXY(1, 0); + xf.by = V2FromXY(0, 1); + xf.og = v; + return xf; +} + +Xform xform_from_rotation(f32 r) +{ + Xform res; + f32 c = math_cos(r); + f32 s = math_sin(r); + res.bx = V2FromXY(c, s); + res.by = V2FromXY(-s, c); + res.og = V2FromXY(0, 0); + return res; +} + +Xform xform_from_scale(V2 scale) +{ + Xform res; + res.bx = V2FromXY(scale.x, 0); + res.by = V2FromXY(0, scale.y); + res.og = V2FromXY(0, 0); + return res; +} + +Xform xform_from_trs(Trs trs) +{ + Xform xf = XFORM_POS(trs.t); + xf = xform_rotated(xf, trs.r); + xf = xform_scaled(xf, trs.s); + return xf; +} + +Xform xform_from_rect(Rect rect) +{ + V2 half_size = v2_mul(rect.size, 0.5); + Xform xf = ZI; + xf.bx = V2FromXY(rect.size.x, 0); + xf.by = V2FromXY(0, rect.size.y); + xf.og = v2_add(rect.pos, half_size); + return xf; +} + +Xform xform_translated(Xform xf, V2 v) +{ + xf.og = V2FromXY(xf.bx.x * v.x + xf.by.x * v.y + xf.og.x, xf.bx.y * v.x + xf.by.y * v.y + xf.og.y); + return xf; +} + +Xform xform_translated_world(Xform xf, V2 v) +{ + xf.og = v2_add(xf.og, v); + return xf; +} + +Xform xform_rotated(Xform xf, f32 r) +{ + return xform_mul(xf, xform_from_rotation(r)); +} + +Xform xform_rotated_world(Xform xf, f32 r) +{ + return xform_mul(xform_from_rotation(r), xf); +} + +Xform xform_basis_rotated_world(Xform xf, f32 r) +{ + f32 diff = r; + f32 c = math_cos(diff); + f32 s = math_sin(diff); + xf.bx = V2FromXY(xf.bx.x * c - xf.bx.y * s, xf.bx.x * s + xf.bx.y * c); + xf.by = V2FromXY(xf.by.x * c - xf.by.y * s, xf.by.x * s + xf.by.y * c); + return xf; +} + +Xform xform_basis_with_rotation_world(Xform xf, f32 r) +{ + return xform_basis_rotated_world(xf, r - xform_get_rotation(xf)); +} + +Xform xform_scaled(Xform xf, V2 scale) +{ + xf.bx = v2_mul(xf.bx, scale.x); + xf.by = v2_mul(xf.by, scale.y); + return xf; +} + +Xform xform_scaled_world(Xform xf, V2 scale) +{ + Xform res; + res.bx = v2_mul_v2(xf.bx, scale); + res.by = v2_mul_v2(xf.by, scale); + res.og = v2_mul_v2(xf.og, scale); + return res; +} + +Xform xform_lerp(Xform a, Xform b, f32 t) +{ + Xform res; + res.bx = v2_slerp(a.bx, b.bx, t); + res.by = v2_slerp(a.by, b.by, t); + res.og = v2_lerp(a.og, b.og, t); + return res; +} + +Xform xform_invert(Xform xf) +{ + f32 det = xform_get_determinant(xf); + f32 inv_det = 1.0f / det; + + f32 old_bx_x = xf.bx.x; + xf.bx.x = xf.by.y; + xf.by.y = old_bx_x; + + xf.bx = v2_mul_v2(xf.bx, V2FromXY(inv_det, -inv_det)); + xf.by = v2_mul_v2(xf.by, V2FromXY(-inv_det, inv_det)); + + xf.og = xform_basis_mul_v2(xf, v2_neg(xf.og)); + + return xf; +} + +Xform xform_mul(Xform a, Xform b) +{ + Xform res; + res.bx.x = a.bx.x * b.bx.x + a.by.x * b.bx.y; + res.bx.y = a.bx.y * b.bx.x + a.by.y * b.bx.y; + res.by.x = a.bx.x * b.by.x + a.by.x * b.by.y; + res.by.y = a.bx.y * b.by.x + a.by.y * b.by.y; + res.og = xform_mul_v2(a, b.og); + return res; +} + +V2 xform_basis_mul_v2(Xform xf, V2 v) +{ + return V2FromXY( + xf.bx.x * v.x + xf.by.x * v.y, + xf.bx.y * v.x + xf.by.y * v.y + ); +} + +V2 xform_mul_v2(Xform xf, V2 v) +{ + V2 res = xform_basis_mul_v2(xf, v); + res = v2_add(res, xf.og); + return res; +} + +Xform xform_basis(Xform xf) +{ + Xform res = ZI; + res.bx = xf.bx; + res.by = xf.by; + return res; +} + +V2 xform_basis_invert_mul_v2(Xform xf, V2 v) +{ + Xform inv = xform_invert(xf); + V2 res = xform_basis_mul_v2(inv, v); + return res; +} + +/* TODO: Get rid of this? Just force caller to use invert manually since it's expensive. */ +V2 xform_invert_mul_v2(Xform xf, V2 v) +{ + Xform inv = xform_invert(xf); + return xform_mul_v2(inv, v); +} + +Quad xform_mul_quad(Xform xf, Quad quad) +{ + Quad res; + res.p0 = xform_mul_v2(xf, quad.p0); + res.p1 = xform_mul_v2(xf, quad.p1); + res.p2 = xform_mul_v2(xf, quad.p2); + res.p3 = xform_mul_v2(xf, quad.p3); + return res; +} + +f32 xform_get_determinant(Xform xf) +{ + return v2_wedge(xf.bx, xf.by); +} + +V2 xform_get_right(Xform xf) +{ + return xf.bx; +} + +V2 xform_get_left(Xform xf) +{ + return v2_neg(xf.bx); +} + +V2 xform_get_up(Xform xf) +{ + return v2_neg(xf.by); +} + +V2 xform_get_down(Xform xf) +{ + return xf.by; +} + +f32 xform_get_rotation(Xform xf) +{ + return v2_angle(xf.bx); +} + +V2 xform_get_scale(Xform xf) +{ + f32 det_sign = math_fsign(xform_get_determinant(xf)); + return V2FromXY(v2_len(xf.bx), det_sign * v2_len(xf.by)); +} + +//////////////////////////////// +//~ Quad operations + +Quad quad_from_rect(Rect rect) +{ + Quad res; + res.p0 = V2FromXY(rect.x, rect.y); /* Top left */ + res.p1 = V2FromXY(rect.x + rect.width, rect.y); /* Top right */ + res.p2 = V2FromXY(rect.x + rect.width, rect.y + rect.height); /* Bottom right */ + res.p3 = V2FromXY(rect.x, rect.y + rect.height); /* Bottom left */ + return res; +} + +Quad quad_from_aabb(Aabb aabb) +{ + Quad res; + res.p0 = V2FromXY(aabb.p0.x, aabb.p0.y); /* Top left */ + res.p1 = V2FromXY(aabb.p1.x, aabb.p0.y); /* Top right */ + res.p2 = V2FromXY(aabb.p1.x, aabb.p1.y); /* Bottom right */ + res.p3 = V2FromXY(aabb.p0.x, aabb.p1.y); /* Bottom left */ + return res; +} + +Quad quad_from_line(V2 start, V2 end, f32 thickness) +{ + f32 width = thickness / 2.f; + + V2 dir = v2_norm(v2_sub(end, start)); + V2 dir_perp = v2_perp(dir); + + V2 left = v2_mul(dir_perp, -width); + V2 right = v2_mul(dir_perp, width); + + Quad res; + res.p0 = v2_add(start, left); + res.p1 = v2_add(start, right); + res.p2 = v2_add(end, right); + res.p3 = v2_add(end, left); + return res; +} + +Quad quad_from_ray(V2 pos, V2 rel, f32 thickness) +{ + V2 end = v2_add(pos, rel); + return quad_from_line(pos, end, thickness); +} + +Quad quad_scale(Quad q, f32 s) +{ + q.p0 = v2_mul(q.p0, s); + q.p1 = v2_mul(q.p1, s); + q.p2 = v2_mul(q.p2, s); + q.p3 = v2_mul(q.p3, s); + return q; +} + +Quad quad_round(Quad quad) +{ + Quad res; + res.p0 = v2_round(quad.p0); + res.p1 = v2_round(quad.p1); + res.p2 = v2_round(quad.p2); + res.p3 = v2_round(quad.p3); + return res; +} + +Quad quad_floor(Quad quad) +{ + Quad res; + res.p0 = v2_floor(quad.p0); + res.p1 = v2_floor(quad.p1); + res.p2 = v2_floor(quad.p2); + res.p3 = v2_floor(quad.p3); + return res; +} + +//////////////////////////////// +//~ Polygon operations + +V2 math_poly_center(V2Array a) +{ + V2 sum = V2FromXY(0, 0); + for (u64 i = 0; i < a.count; ++i) + { + sum = v2_add(sum, a.points[i]); + } + return v2_div(sum, a.count); +} + +//////////////////////////////// +//~ Spring operations + +/* https://box2d.org/files/ErinCatto_SoftConstraints_GDC2011.pdf */ +SoftSpring math_spring_init(f32 hertz, f32 damping_ratio, f32 dt) +{ + SoftSpring res; + if (hertz == 0.0f) + { + res.bias_rate = 0; + res.mass_scale = 1; + res.impulse_scale = 0; + } + else + { + f32 angular_frequency = Tau * hertz; + f32 a = 2 * damping_ratio + angular_frequency * dt; + f32 b = angular_frequency * a * dt; + f32 c = 1 / (b + 1); + res.bias_rate = angular_frequency / a; + res.mass_scale = b * c; + res.impulse_scale = c; + } + return res; +} diff --git a/src/base/base_math.h b/src/base/base_math.h index c5d8af9c..536f44f3 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -1,14 +1,13 @@ /* Math functions are default 32 bit (f32, i32, etc) unless specified */ -#define PI ((f32)3.14159265358979323846) -#define TAU ((f32)6.28318530717958647693) +#define Pi ((f32)3.14159265358979323846) +#define Tau ((f32)6.28318530717958647693) -/* ========================== * - * Math types - * ========================== */ +//////////////////////////////// +//~ Floating point vector2 types #define V2FromXY(x, y) CppCompatInitListType(V2) { (x), (y) } -#define V2FromV2i32(v) V2FromXY((v).x, (v).y) +#define V2FromV2I32(v) V2FromXY((v).x, (v).y) Struct(V2) { f32 x, y; }; @@ -18,6 +17,9 @@ Struct(V2Array) { u64 count; }; +//////////////////////////////// +//~ Floating point vector3 types + #define V3FromXYZ(x, y, z) ((V3) { (x), (y), (z) }) Struct(V3) { f32 x, y, z; @@ -28,6 +30,9 @@ Struct(V3Array) { u64 count; }; +//////////////////////////////// +//~ Floating point vector4 types + #define V4FromXYZW(x, y, z, w) ((V4) { (x), (y), (z), (w) }) Struct(V4) { f32 x, y, z, w; @@ -38,31 +43,57 @@ Struct(V4Array) { u64 count; }; -#define V2i32FromXY(x, y) CppCompatInitListType(V2i32) { (x), (y) } -Struct(V2i32) { +//////////////////////////////// +//~ Integer vector2 types + +#define V2I32FromXY(x, y) CppCompatInitListType(V2I32) { (x), (y) } +Struct(V2I32) { i32 x, y; }; -#define V3i32FromXYZ(x, y, z) CppCompatInitListType(V3i32) { (x), (y), (z) } -Struct(V3i32) { +//////////////////////////////// +//~ Integer vector3 types + +#define V3I32FromXYZ(x, y, z) CppCompatInitListType(V3I32) { (x), (y), (z) } +Struct(V3I32) { i32 x, y, z; }; +//////////////////////////////// +//~ Mat4x4 types + +Struct(Mat4x4) +{ + union + { + struct { V4 bx, by, bz, bw; }; + f32 e[4][4]; + }; +}; + +//////////////////////////////// +//~ Xform types + Struct(Xform) { V2 bx; /* X basis vector (x axis) */ V2 by; /* Y basis vector (y axis)*/ V2 og; /* Translation vector (origin) */ }; -Struct(Mat4x4) { - union { - struct { V4 bx, by, bz, bw; }; - f32 e[4][4]; - }; +/* (T)ranslation, (R)otation, (S)cale */ +#define MakeTrs(...) ((Trs) { .t = V2FromXY(0,0), .s = V2FromXY(1, 1), .r = 0, __VA_ARGS__ }) +Struct(Trs) +{ + V2 t; + V2 s; + f32 r; }; -#define RECT(_x, _y, _width, _height) (Rect) { .x = (_x), .y = (_y), .width = (_width), .height = (_height) } -#define RECT_FROM_V2(_pos, _size) (Rect) { .pos = (_pos), .size = (_size) } +//////////////////////////////// +//~ Rect types + +#define RectFromScalar(_x, _y, _width, _height) (Rect) { .x = (_x), .y = (_y), .width = (_width), .height = (_height) } +#define RectFromV2(_pos, _size) (Rect) { .pos = (_pos), .size = (_size) } Struct(Rect) { union { struct { f32 x, y, width, height; }; @@ -70,20 +101,25 @@ Struct(Rect) { }; }; -Inline b32 rect_eq(Rect r1, Rect r2) { return r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height == r2.height; } +/* Values expected to be normalized 0.0 -> 1.0 */ +#define ClipAll ((ClipRect) { { 0.0f, 0.0f }, { 1.0f, 1.0f } }) +Struct(ClipRect) +{ + V2 p0, p1; +}; + +//////////////////////////////// +//~ Axis aligned bounding box types Struct(Aabb) { V2 p0, p1; }; -/* Values expected to be normalized 0.0 -> 1.0 */ -#define CLIP_ALL ((ClipRect) { { 0.0f, 0.0f }, { 1.0f, 1.0f } }) -Struct(ClipRect) { - V2 p0, p1; -}; +//////////////////////////////// +//~ Quad types -#define QUAD_UNIT_SQUARE (Quad) { .p0 = V2FromXY(0, 0), .p1 = V2FromXY(0, 1), .p2 = V2FromXY(1, 1), .p3 = V2FromXY(1, 0) } -#define QUAD_UNIT_SQUARE_CENTERED (Quad) { .p0 = V2FromXY(-0.5f, -0.5f), .p1 = V2FromXY(0.5f, -0.5f), .p2 = V2FromXY(0.5f, 0.5f), .p3 = V2FromXY(-0.5f, 0.5f) } +#define QuadUnitSquare (Quad) { .p0 = V2FromXY(0, 0), .p1 = V2FromXY(0, 1), .p2 = V2FromXY(1, 1), .p3 = V2FromXY(1, 0) } +#define QuadUnitSquareCentered (Quad) { .p0 = V2FromXY(-0.5f, -0.5f), .p1 = V2FromXY(0.5f, -0.5f), .p2 = V2FromXY(0.5f, 0.5f), .p3 = V2FromXY(-0.5f, 0.5f) } Struct(Quad) { union { struct { V2 p0, p1, p2, p3; }; @@ -91,446 +127,125 @@ Struct(Quad) { }; }; -/* (T)ranslation, (R)otation, (S)cale */ -#define MakeTrs(...) ((Trs) { .t = V2FromXY(0,0), .s = V2FromXY(1, 1), .r = 0, __VA_ARGS__ }) -Struct(Trs) { - V2 t; - V2 s; - f32 r; +//////////////////////////////// +//~ Spring types + +Struct(SoftSpring) +{ + f32 bias_rate; + f32 mass_scale; + f32 impulse_scale; }; -/* ========================== * - * Clamping - * ========================== */ +//////////////////////////////// +//~ Clamping -Inline u8 min_u8(u8 a, u8 b) { return a <= b ? a : b; } -Inline u8 max_u8(u8 a, u8 b) { return a >= b ? a : b; } -Inline u32 min_u32(u32 a, u32 b) { return a <= b ? a : b; } -Inline u32 max_u32(u32 a, u32 b) { return a >= b ? a : b; } -Inline u64 min_u64(u64 a, u64 b) { return a <= b ? a : b; } -Inline u64 max_u64(u64 a, u64 b) { return a >= b ? a : b; } -Inline i32 min_i32(i32 a, i32 b) { return a <= b ? a : b; } -Inline i32 max_i32(i32 a, i32 b) { return a >= b ? a : b; } -Inline i64 min_i64(i64 a, i64 b) { return a <= b ? a : b; } -Inline i64 max_i64(i64 a, i64 b) { return a >= b ? a : b; } -Inline f32 min_f32(f32 a, f32 b) { return a <= b ? a : b; } -Inline f32 max_f32(f32 a, f32 b) { return a >= b ? a : b; } -Inline f64 min_f64(f64 a, f64 b) { return a <= b ? a : b; } -Inline f64 max_f64(f64 a, f64 b) { return a >= b ? a : b; } +u8 min_u8(u8 a, u8 b); +u8 max_u8(u8 a, u8 b); +u32 min_u32(u32 a, u32 b); +u32 max_u32(u32 a, u32 b); +u64 min_u64(u64 a, u64 b); +u64 max_u64(u64 a, u64 b); +i32 min_i32(i32 a, i32 b); +i32 max_i32(i32 a, i32 b); +i64 min_i64(i64 a, i64 b); +i64 max_i64(i64 a, i64 b); +f32 min_f32(f32 a, f32 b); +f32 max_f32(f32 a, f32 b); +f64 min_f64(f64 a, f64 b); +f64 max_f64(f64 a, f64 b); -Inline u32 clamp_u32(u32 v, u32 min, u32 max) { return v < min ? min : v > max ? max : v; } -Inline u64 clamp_u64(u64 v, u64 min, u64 max) { return v < min ? min : v > max ? max : v; } -Inline i32 clamp_i32(i32 v, i32 min, i32 max) { return v < min ? min : v > max ? max : v; } -Inline i64 clamp_i64(i64 v, i64 min, i64 max) { return v < min ? min : v > max ? max : v; } -Inline f32 clamp_f32(f32 v, f32 min, f32 max) { return v < min ? min : v > max ? max : v; } -Inline f64 clamp_f64(f64 v, f64 min, f64 max) { return v < min ? min : v > max ? max : v; } +u32 clamp_u32(u32 v, u32 min, u32 max); +u64 clamp_u64(u64 v, u64 min, u64 max); +i32 clamp_i32(i32 v, i32 min, i32 max); +i64 clamp_i64(i64 v, i64 min, i64 max); +f32 clamp_f32(f32 v, f32 min, f32 max); +f64 clamp_f64(f64 v, f64 min, f64 max); -/* ========================== * - * Float rounding - * ========================== */ +//////////////////////////////// +//~ Rounding -/* TODO: Don't use intrinsics for these. */ +f32 math_round(f32 f); +f64 math_round64(f64 f); +i32 math_round_to_int(f32 f); +i64 math_round_to_int64(f64 f); -/* Round */ +//////////////////////////////// +//~ Flooring -Inline f32 math_round(f32 f) -{ - return ix_round_f32_to_f32(f); -} +f32 math_floor(f32 f); +f64 math_floor64(f64 f); +i32 math_floor_to_int(f32 f); +i64 math_floor_to_int64(f64 f); -Inline f64 math_round64(f64 f) -{ - return ix_round_f64_to_f64(f); -} +//////////////////////////////// +//~ Ceiling -Inline i32 math_round_to_int(f32 f) -{ - return ix_round_f32_to_i32(f); -} +f32 math_ceil(f32 f); +f64 math_ceil64(f64 f); +i32 math_ceil_to_int(f32 f); +i64 math_ceil_to_int64(f64 f); -Inline i64 math_round_to_int64(f64 f) -{ - return ix_round_f64_to_i64(f); -} +//////////////////////////////// +//~ Truncing -/* Floor */ +f32 math_trunc(f32 f); +f64 math_trunc64(f64 f); -Inline f32 math_floor(f32 f) -{ - return ix_floor_f32_to_f32(f); -} +//////////////////////////////// +//~ Fmod -Inline f64 math_floor64(f64 f) -{ - return ix_floor_f64_to_f64(f); -} +f32 math_fmod(f32 x, f32 m); +f64 math_fmod64(f64 x, f64 m); -Inline i32 math_floor_to_int(f32 f) -{ - return ix_floor_f32_to_i32(f); -} +//////////////////////////////// +//~ Floating point sign +f32 math_fabs(f32 f); +f64 math_fabs64(f64 f); +i32 math_fsign(f32 f); +i64 math_fsign64(f64 f); -Inline i64 math_floor_to_int64(f64 f) -{ - return ix_floor_f64_to_i64(f); -} +//////////////////////////////// +//~ Integer bs -/* Ceil */ +u32 math_abs_i32(i32 v); +u64 math_abs_i64(i64 v); -Inline f32 math_ceil(f32 f) -{ - return ix_ceil_f32_to_f32(f); -} - -Inline f64 math_ceil64(f64 f) -{ - return ix_ceil_f64_to_f64(f); -} - -Inline i32 math_ceil_to_int(f32 f) -{ - return ix_ceil_f32_to_i32(f); -} - -Inline i64 math_ceil_to_int64(f64 f) -{ - return ix_ceil_f64_to_i64(f); -} - -/* Truncate */ - -Inline f32 math_trunc(f32 f) -{ - return ix_trunc_f32_to_f32(f); -} - -Inline f64 math_trunc64(f64 f) -{ - return ix_trunc_f64_to_f64(f); -} - -/* ========================== * - * Float properties - * ========================== */ - -Inline f32 math_fmod(f32 x, f32 m) -{ - return x - m * math_trunc(x / m); -} - -Inline f64 math_fmod64(f64 x, f64 m) -{ - return x - m * math_trunc64(x / m); -} - -Inline f32 math_fabs(f32 f) -{ - u32 truncated = *(u32 *)&f & 0x7FFFFFFF; - return *(f32 *)&truncated; -} - -Inline f64 math_fabs64(f64 f) -{ - u64 truncated = *(u64 *)&f & 0x7FFFFFFFFFFFFFFFULL; - return *(f64 *)&truncated; -} - -Inline i32 math_fsign(f32 f) -{ - u32 sign_bit = (*(u32 *)&f >> 31) & 1; - return 1 + -((i32)(sign_bit << 1)); -} - -Inline i64 math_fsign64(f64 f) -{ - u64 sign_bit = (*(u64 *)&f >> 63) & 1; - return 1 + -((i64)(sign_bit << 1)); -} - -/* ========================== * - * Integer abs - * ========================== */ - -Inline u32 math_abs_i32(i32 v) -{ - return (u32)(v * ((v >= 0) - (v < 0))); -} - -Inline u64 math_abs_i64(i64 v) -{ - return (u64)(v * ((v >= 0) - (v < 0))); -} - -/* ========================== * - * Exponential - * ========================== */ +//////////////////////////////// +//~ U64 pow /* Taken from https://gist.github.com/orlp/3551590 */ -Inline u64 math_pow_u64(u64 base, u8 exp) -{ - LocalPersist const u8 highest_bit_set[] = { - 0, 1, 2, 2, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 255, /* Anything past 63 is a guaranteed overflow with base > 1 */ - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, - }; +u64 math_pow_u64(u64 base, u8 exp); - u64 result = 1; - - switch (highest_bit_set[exp]) { - case 255: { - /* 255 = overflow, return 0 */ - if (base == 1) { - return 1; - } - // if (base == -1) { - // return 1 - 2 * (exp & 1); - // } - return 0; - } break; - case 6: { - if (exp & 1) result *= base; - exp >>= 1; - base *= base; - } FALLTHROUGH; - case 5: { - if (exp & 1) result *= base; - exp >>= 1; - base *= base; - } FALLTHROUGH; - case 4: { - if (exp & 1) result *= base; - exp >>= 1; - base *= base; - } FALLTHROUGH; - case 3: { - if (exp & 1) result *= base; - exp >>= 1; - base *= base; - } FALLTHROUGH; - case 2: { - if (exp & 1) result *= base; - exp >>= 1; - base *= base; - } FALLTHROUGH; - case 1: { - if (exp & 1) result *= base; - } FALLTHROUGH; - default: return result; - } -} +//////////////////////////////// +//~ Logn /* Based on FreeBSD's implementation * https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_logf.c */ -Inline f32 math_ln(f32 x) -{ - LocalPersist const f32 ln2_hi = 6.9313812256e-01f; - LocalPersist const f32 ln2_lo = 9.0580006145e-06f; +f32 math_ln(f32 x); - i32 x_int = *(i32 *)&x; - - i32 k = 0; - if (x_int < 0x00800000) { - f32 two_p25 = 3.3554432000e+07; - if ((x_int & 0x7fffffff) == 0) { - /* Return -inf if x is 0 */ - return -two_p25 / 0; - } else if (x_int < 0) { - /* Return NaN if x is negative */ - return (x - x) / 0; - } - k -= 25; - x *= two_p25; - x_int = *(i32 *)&x; - } else if (x_int >= 0x7f800000) { - return x + x; - } - - k += (x_int >> 23) - 127; - x_int &= 0x007fffff; - i32 i = (x_int + (0x95f64 << 3)) & 0x800000; - i32 x_int_normalized = x_int | (i ^ 0x3f800000); - x = *(f32 *)&x_int_normalized - 1.0f; - k += (i >> 23); - - if ((0x007fffff & (0x8000 + x_int)) < 0xc000) { - if (x == 0) { - if (k == 0) { - return 0; - } else { - return (f32)k * ln2_hi + (f32)k * ln2_lo; - } - } - f32 r = x * x * (0.5f - 0.33333333333333333f * x); - if (k == 0) { - return x - r; - } else { - return (f32)k * ln2_hi - ((r - (f32)k * ln2_lo) - x); - } - } - - f32 s = x / (2.0f + x); - f32 z = s * s; - f32 w = z * z; - f32 r = (z * (0.66666662693f + w * 0.28498786688f)) + (w * (0.40000972152f + w * 0.24279078841f)); - if (((x_int - (0x6147a << 3)) | ((0x6b851 << 3) - x_int)) > 0) { - f32 hfsq = 0.5f * x * x; - if (k == 0) { - return x - (hfsq - s * (hfsq + r)); - } else { - return (f32)k * ln2_hi - ((hfsq - (s * (hfsq + r) + (f32)k * ln2_lo)) - x); - } - } else { - if (k == 0) { - return x - s * (x - r); - } else { - return (f32)k * ln2_hi - ((s * (x - r) - (f32)k * ln2_lo) - x); - } - } -} +//////////////////////////////// +//~ Exp /* Based on FreeBSD's implementation * https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_expf.c */ -Inline f32 math_exp(f32 x) -{ - LocalPersist const f32 half[2] = { 0.5, -0.5 }; - LocalPersist const f32 o_threshold = 8.8721679688e+01f; - LocalPersist const f32 u_threshold = -1.0397208405e+02f; - LocalPersist const f32 ln2_hi[2] = { 6.9314575195e-01f, -6.9314575195e-01f }; - LocalPersist const f32 ln2_lo[2] = { 1.4286067653e-06f, -1.4286067653e-06f }; - LocalPersist const f32 inv_ln2 = 1.4426950216e+00f; - LocalPersist const f32 huge = 1.0e+30f; - LocalPersist const f32 two_m100 = 7.8886090522e-31f; +f32 math_exp(f32 x); - u32 x_uint = *(u32 *)&x; - i32 x_sign_bit = (i32)((x_uint >> 31) & 1); - x_uint &= 0x7fffffff; +//////////////////////////////// +//~ Pow - /* Filter out non-finite argument */ - if (x_uint >= 0x42b17218) { /* if |x|>=88.721... */ - if (x_uint > 0x7f800000) { - return x + x; /* NaN */ - } else if (x_uint == 0x7f800000) { - return (x_sign_bit == 0) ? x : 0; - } - if (x > o_threshold) { - /* Overflow */ - return F32_INFINITY; - } else if (x < u_threshold) { - /* Underflow */ - return two_m100 * two_m100; - } - } +f32 math_pow(f32 a, f32 b); - /* Argument reduction */ - i32 k = 0; - f32 hi = 0; - f32 lo = 0; - if (x_uint > 0x3eb17218) { - if (x_uint < 0x3F851592) { - hi = x - ln2_hi[x_sign_bit]; - lo = ln2_lo[x_sign_bit]; - k = 1 - x_sign_bit - x_sign_bit; - } else { - k = (i32)(inv_ln2 * x + half[x_sign_bit]); - hi = x - (f32)k * ln2_hi[0]; - lo = (f32)k * ln2_lo[0]; - } - x = hi - lo; - } else if (x_uint < 0x39000000) { - if (huge + x > 1.0f) { - return 1.0f + x; - } - } else { - k = 0; - } +//////////////////////////////// +//~ Sqrt - f32 two_pk; - if (k >= -125) { - u32 temp = ((u32)(0x7f + k)) << 23; - two_pk = *(f32 *)&temp; - } else { - u32 temp = ((u32)(0x7f + (k + 100))) << 23; - two_pk = *(f32 *)&temp; - } +f32 math_sqrt(f32 x); +f64 math_sqrt64(f64 x); +f32 math_rsqrt(f32 x); - f32 t = x * x; - f32 c = x - t * (1.6666625440e-1f + t * -2.7667332906e-3f); - if (k == 0) { - return 1.0f - ((x * c) / (c - 2.0f) - x); - } else { - f32 y = 1.0f - ((lo - (x * c)/(2.0f - c))-hi); - if (k >= -125) { - if (k==128) { - u32 temp = 0x7f800000; - return y * 2.0f * (*(f32 *)&temp); - } - return y * two_pk; - } else { - return y * two_pk * two_m100; - } - } -} - -Inline f32 math_pow(f32 a, f32 b) -{ - if (a >= 0) { - /* a is positive */ - return math_exp(math_ln(a) * b); - } else { - /* a is negative */ - f32 res_sign = math_round_to_int(b) % 2 == 0 ? 1 : -1; - return math_exp(math_ln(-a) * b) * res_sign; - } -} - -Inline f32 math_sqrt(f32 x) -{ - return ix_sqrt_f32(x); -} - -Inline f64 math_sqrt64(f64 x) -{ - return ix_sqrt_f64(x); -} - -Inline f32 math_rsqrt(f32 x) -{ - return ix_rsqrt_f32(x); -} - -/* ========================== * - * Trig - * ========================== */ +//////////////////////////////// +//~ Trig /* Functions based on Cephes implementation (https://www.netlib.org/cephes/): * - math_sin_approx @@ -541,508 +256,153 @@ Inline f32 math_rsqrt(f32 x) /* TODO: Vectorize */ -/* Approximate sin in range [0, PI/4] */ -Inline f32 math_sin_approx(f32 x) -{ - f32 x_sq = x * x; - return (((-1.9515295891E-4 * x_sq + 8.3321608736E-3) * x_sq - 1.6666654611E-1) * x_sq * x) + x; -} - -/* Approximate cos in range [0, PI/4] */ -Inline f32 math_cos_approx(f32 x) -{ - f32 x_sq = x * x; - return (((2.443315711809948E-005 * x_sq - 1.388731625493765E-003) * x_sq + 4.166664568298827E-002) * x_sq * x_sq) - (x_sq * 0.5) + 1; -} - -/* Reduce postive x to range [0, PI/4] (Cody-Waite argument reduction). +//- Reduce +/* Reduce postive x to range [0, Pi/4] (Cody-Waite argument reduction). * Returns 0 if x > (2^24 - 1); * Sets octant_out=-1 on error. */ -Inline f32 math_reduce_positive_to_pio4(f32 x, i32 *octant_out) -{ - i32 octant = -1; +f32 math_reduce_positive_to_pio4(f32 x, i32 *octant_out); - if (x <= ((1 << 24) - 1)) { - octant = x * (4 / PI); /* Integer part of x/(PI/4) */ - f32 y = octant; - if (octant & 1) { - octant += 1; - y += 1.0; - } +//- Sin approximation +/* Approximate sin in range [0, Pi/4] */ +f32 math_sin_approx(f32 x); - /* Modulo 360 degrees */ - octant &= 7; +//- Cos approximation +f32 math_cos_approx(f32 x); - if (x > 8192) { - x = x - y * (PI / 4); - } else { - /* Extended precision modular arithmetic */ - x = ((x - y * 0.78515625) - y * 2.4187564849853515625e-4) - y * 3.77489497744594108e-8; - } - } +//- Sin +f32 math_sin(f32 x); - *octant_out = octant; - return x; -} +//- Cos +f32 math_cos(f32 x); -Inline f32 math_sin(f32 x) -{ - f32 sign = 1; +//- ArcTan +f32 math_atan(f32 x); - if (IsF32Nan(x)) { - return 0; - } else if (x < 0) { - sign = -1; - x = -x; - } +//- ArcTan2 +f32 math_atan2(f32 y, f32 x); - i32 octant; - x = math_reduce_positive_to_pio4(x, &octant); +//- ArcSin +f32 math_asin(f32 x); - /* Reflect in x axis */ - if (octant > 3) { - sign = -sign; - octant -= 4; - } +//- ArcCos +f32 math_acos(f32 x); - switch (octant) { - case -1: return 0; - case 1: case 2: return math_cos_approx(x) * sign; - default: return math_sin_approx(x) * sign; - } -} +//////////////////////////////// +//~ Angle unwind -Inline f32 math_cos(f32 x) -{ - f32 sign = 1; +/* Returns angle in range [-Pi, Pi] */ +f32 math_unwind_angle(f32 a); - if (IsF32Nan(x)) { - return 0; - } else if (x < 0) { - x = -x; - } +//////////////////////////////// +//~ Float lerp - i32 octant; - x = math_reduce_positive_to_pio4(x, &octant); +f32 math_lerp_f32(f32 val0, f32 val1, f32 t); +f64 math_lerp_f64(f64 val0, f64 val1, f64 t); +f32 math_lerp_angle(f32 a, f32 b, f32 t); - /* Reflect in x axis */ - if (octant > 3) { - sign = -sign; - octant -= 4; - } +//////////////////////////////// +//~ Int lerp - if (octant > 1) { - sign = -sign; - } +i32 math_lerp_i32(i32 val0, i32 val1, f32 t); - switch (octant) { - case -1: return 0; - case 1: case 2: return math_sin_approx(x) * sign; - default: return math_cos_approx(x) * sign; - } -} +//- Lerp i64 +i64 math_lerp_i64(i64 val0, i64 val1, f64 t); -Inline f32 math_atan(f32 x) -{ - f32 sign = 1; - if (x < 0) { - sign = -1; - x = -x; - } +//////////////////////////////// +//~ V2 operations - /* Reduce range */ - f32 y; - if (x > 2.414213562373095) { /* tan((PI / 8) * 3) */ - y = PI / 2; - x = -(1.f / x); - } else if (x > 0.4142135623730950) { /* tan(PI / 8) */ - y = PI / 4; - x = (x - 1.f) / (x + 1.f); - } else { - y = 0; - } +b32 v2_is_zero(V2 a); +b32 v2_eq(V2 a, V2 b); - f32 x_sq = x * x; - y += ((((8.05374449538e-2 * x_sq - 1.38776856032E-1) * x_sq + 1.99777106478E-1) * x_sq - 3.33329491539E-1) * x_sq * x + x); +//- Mul - return y * sign; -} +V2 v2_mul(V2 a, f32 s); +V2 v2_mul_v2(V2 a, V2 b); +V2 v2_neg(V2 a); -Inline f32 math_atan2(f32 y, f32 x) -{ - f32 res; - if (x == 0) { - if (y < 0) { - res = 3 * PI / 2; - } else if (y == 0) { - res = 0; - } else { - res = PI / 2; - } - } else if (y == 0) { - if (x < 0) { - res = PI; - } else { - res = 0; - } - } else { - f32 offset; - if (x < 0) { - offset = PI; - } else if (y < 0) { - offset = PI * 2; - } else { - offset = 0; - } - res = math_atan(y / x) + offset; - } - return res; -} +//- Div -Inline f32 math_asin(f32 x) -{ - /* TODO: Dedicated arcsin approximation */ - return math_atan2(x, math_sqrt(1.0f - (x * x))); -} +V2 v2_div(V2 a, f32 s); +V2 v2_div_v2(V2 a, V2 b); -Inline f32 math_acos(f32 x) -{ - /* TODO: Dedicated arccos approximation */ - return (PI / 2.0f) - math_atan2(x, math_sqrt(1.0f - (x * x))); -} +//- Add -/* Returns angle in range [-PI, PI] */ -Inline f32 math_unwind_angle(f32 a) -{ - f32 d = math_fmod(a, TAU); - return math_fmod(2.0f * d, TAU) - d; -} +V2 v2_add(V2 a, V2 b); +V2 v2_sub(V2 a, V2 b); -/* ========================== * - * Lerp - * ========================== */ +//- Len -Inline f32 math_lerp_f32(f32 val0, f32 val1, f32 t) -{ - return val0 + ((val1 - val0) * t); -} +f32 v2_len(V2 a); +f32 v2_len_sq(V2 a); +V2 v2_with_len(V2 a, f32 len); +V2 v2_clamp_len(V2 a, f32 max); +f32 v2_distance(V2 a, V2 b); +V2 v2_norm(V2 a); -Inline f64 math_lerp_f64(f64 val0, f64 val1, f64 t) -{ - return val0 + ((val1 - val0) * t); -} -Inline i32 math_lerp_i32(i32 val0, i32 val1, f32 t) -{ - return val0 + math_round_to_int(((f32)(val1 - val0) * t)); -} +//- Dot -Inline i64 math_lerp_i64(i64 val0, i64 val1, f64 t) -{ - return val0 + math_round_to_int64(((f64)(val1 - val0) * t)); -} - -Inline f32 math_lerp_angle(f32 a, f32 b, f32 t) { - f32 diff = math_unwind_angle(b - a); - return a + diff * t; -} - -/* ========================== * - * V2 - * ========================== */ - -Inline V2 v2_mul(V2 a, f32 s) -{ - return V2FromXY(a.x * s, a.y * s); -} - -Inline V2 v2_mul_v2(V2 a, V2 b) -{ - return V2FromXY(a.x * b.x, a.y * b.y); -} - -Inline V2 v2_div(V2 a, f32 s) -{ - f32 d = 1 / s; - return V2FromXY(a.x * d, a.y * d); -} - -Inline V2 v2_div_v2(V2 a, V2 b) -{ - return V2FromXY(a.x * (1 / b.x), a.y * (1 / b.y)); -} - -Inline V2 v2_neg(V2 a) -{ - return V2FromXY(-a.x, -a.y); -} - -Inline V2 v2_add(V2 a, V2 b) -{ - return V2FromXY(a.x + b.x, a.y + b.y); -} - -Inline V2 v2_sub(V2 a, V2 b) -{ - return V2FromXY(a.x - b.x, a.y - b.y); -} - -Inline f32 v2_len(V2 a) -{ - return math_sqrt(a.x * a.x + a.y * a.y); -} - -Inline f32 v2_len_sq(V2 a) -{ - return a.x * a.x + a.y * a.y; -} - -Inline f32 v2_dot(V2 a, V2 b) -{ - return a.x * b.x + a.y * b.y; -} +f32 v2_dot(V2 a, V2 b); /* Returns signed area between vectors (positive in clockwise direction) * AKA perpendicular dot product * AKA 2d cross-product */ -Inline f32 v2_wedge(V2 a, V2 b) -{ - return a.x * b.y - a.y * b.x; -} +f32 v2_wedge(V2 a, V2 b); /* Clockwise (right) perpendicular vector */ -Inline V2 v2_perp(V2 a) -{ - return V2FromXY(-a.y, a.x); -} +V2 v2_perp(V2 a); /* Clockwise (right) perpendicular vector scaled by s */ -Inline V2 v2_perp_mul(V2 a, f32 s) -{ - return V2FromXY(s * -a.y, s * a.x); -} +V2 v2_perp_mul(V2 a, f32 s); -Inline V2 v2_perp_towards_dir(V2 v, V2 dir) -{ - f32 wedge = v2_wedge(v, dir); - return v2_perp_mul(v, (wedge >= 0) - (wedge < 0)); -} +V2 v2_perp_towards_dir(V2 v, V2 dir); + +//- Round / floor / ceil + +V2 v2_round(V2 a); +V2I32 v2_round_to_int(V2 a); +V2 v2_floor(V2 a); +V2 v2_ceil(V2 a); + +//- Angle /* Returns 1 if winding between vectors a & b is clockwise or straight, -1 if counter-clockwise */ -Inline i32 v2_winding(V2 a, V2 b) -{ - f32 w = v2_wedge(a, b); - return (w >= 0) - (w < 0); -} +i32 v2_winding(V2 a, V2 b); +V2 v2_rotated(V2 v, f32 a); +V2 v2_from_angle(f32 a); +f32 v2_angle(V2 v); +f32 v2_angle_from_dirs(V2 dir1, V2 dir2); +f32 v2_angle_from_points(V2 pt1, V2 pt2); -Inline V2 v2_with_len(V2 a, f32 len) -{ - f32 l_sq = a.x * a.x + a.y * a.y; - if (l_sq != 0) { - f32 denom = len / math_sqrt(l_sq); - a.x *= denom; - a.y *= denom; - } - return a; -} +//- Closest point -Inline V2 v2_clamp_len(V2 a, f32 max) -{ - f32 l_sq = a.x * a.x + a.y * a.y; - if (l_sq > max * max) { - f32 denom = max / math_sqrt(l_sq); - a.x *= denom; - a.y *= denom; - } - return a; -} +V2 v2_closest_point_ray(V2 ray_pos, V2 ray_dir_norm, V2 p); -Inline V2 v2_norm(V2 a) -{ - return v2_with_len(a, 1.f); -} - -Inline V2 v2_round(V2 a) -{ - return V2FromXY(math_round(a.x), math_round(a.y)); -} - -Inline V2i32 v2_round_to_int(V2 a) -{ - return V2i32FromXY(math_round_to_int(a.x), math_round_to_int(a.y)); -} - -Inline V2 v2_floor(V2 a) -{ - return V2FromXY(math_floor(a.x), math_floor(a.y)); -} - -Inline V2 v2_ceil(V2 a) -{ - return V2FromXY(math_ceil(a.x), math_ceil(a.y)); -} - -Inline f32 v2_distance(V2 a, V2 b) -{ - f32 dx = b.x - a.x; - f32 dy = b.y - a.y; - return math_sqrt(dx * dx + dy * dy); -} - -Inline b32 v2_eq(V2 a, V2 b) -{ - return a.x == b.x && a.y == b.y; -} - -Inline b32 v2_is_zero(V2 a) -{ - return a.x == 0 && a.y == 0; -} - -Inline V2 v2_rotated(V2 v, f32 a) -{ - f32 c = math_cos(a); - f32 s = math_sin(a); - return V2FromXY(v.x * c - v.y * s, v.x * s + v.y * c); -} - -Inline V2 v2_from_angle(f32 a) -{ - return V2FromXY(math_cos(a), math_sin(a)); -} - -Inline f32 v2_angle(V2 v) -{ - return math_atan2(v.y, v.x); -} - -Inline f32 v2_angle_from_dirs(V2 dir1, V2 dir2) -{ - return math_atan2(v2_wedge(dir1, dir2), v2_dot(dir1, dir2)); -} - -Inline f32 v2_angle_from_points(V2 pt1, V2 pt2) -{ - return v2_angle(v2_sub(pt2, pt1)); -} - -Inline V2 v2_closest_point_ray(V2 ray_pos, V2 ray_dir_norm, V2 p) -{ - V2 ray_p_dir = v2_sub(p, ray_pos); - f32 dot = v2_dot(ray_dir_norm, ray_p_dir); - V2 ray_dir_closest = v2_mul(ray_dir_norm, dot); - return v2_add(ray_pos, ray_dir_closest); -} +//- Lerp /* Interpolate position vectors */ -Inline V2 v2_lerp(V2 val0, V2 val1, f32 t) -{ - return V2FromXY(math_lerp_f32(val0.x, val1.x, t), math_lerp_f32(val0.y, val1.y, t)); -} +V2 v2_lerp(V2 val0, V2 val1, f32 t); /* Interpolate direction vectors (spherical lerp) */ -Inline V2 v2_slerp(V2 val0, V2 val1, f32 t) -{ - f32 rot = math_lerp_angle(v2_angle(val0), v2_angle(val1), t); - f32 len = math_lerp_f32(v2_len(val0), v2_len(val1), t); - return v2_mul(v2_from_angle(rot), len); -} +V2 v2_slerp(V2 val0, V2 val1, f32 t); -/* ========================== * - * V2i32 - * ========================== */ +//////////////////////////////// +//~ V2I32 Operations -Inline b32 v2i32_eq(V2i32 a, V2i32 b) -{ - return a.x == b.x && a.y == b.y; -} +b32 v2i32_eq(V2I32 a, V2I32 b); +V2I32 v2i32_neg(V2I32 a); +V2I32 v2i32_add(V2I32 a, V2I32 b); +V2I32 v2i32_sub(V2I32 a, V2I32 b); -Inline V2i32 v2i32_neg(V2i32 a) -{ - return V2i32FromXY(-a.x, -a.y); -} +//////////////////////////////// +//~ Mat4x4 operations -Inline V2i32 v2i32_add(V2i32 a, V2i32 b) -{ - return V2i32FromXY(a.x + b.x, a.y + b.y); -} +Mat4x4 mat4x4_from_xform(Xform xf); +Mat4x4 mat4x4_from_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near_z, f32 far_z); +Mat4x4 mat4x4_mul(Mat4x4 m1, Mat4x4 m2); -Inline V2i32 v2i32_sub(V2i32 a, V2i32 b) -{ - return V2i32FromXY(a.x - b.x, a.y - b.y); -} - -/* ========================== * - * Mat4x4 - * ========================== */ - -Inline Mat4x4 mat4x4_from_xform(Xform xf) -{ - return CppCompatInitListType(Mat4x4) { - .e = { - {xf.bx.x, xf.bx.y, 0, 0}, - {xf.by.x, xf.by.y, 0, 0}, - {0, 0, 1, 0}, - {xf.og.x, xf.og.y, 0, 1}, - } - }; -} - -Inline Mat4x4 mat4x4_from_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near_z, f32 far_z) -{ - Mat4x4 m = ZI; - - f32 rl = 1.0f / (right - left); - f32 tb = 1.0f / (top - bottom); - f32 fn = -1.0f / (far_z - near_z); - - m.e[0][0] = 2.0f * rl; - m.e[1][1] = 2.0f * tb; - m.e[2][2] = 2.0f * fn; - m.e[3][0] = -(right + left) * rl; - m.e[3][1] = -(top + bottom) * tb; - m.e[3][2] = (far_z + near_z) * fn; - m.e[3][3] = 1.0f; - - return m; -} - -Inline Mat4x4 mat4x4_mul(Mat4x4 m1, Mat4x4 m2) -{ - f32 a00 = m1.e[0][0], a01 = m1.e[0][1], a02 = m1.e[0][2], a03 = m1.e[0][3], - a10 = m1.e[1][0], a11 = m1.e[1][1], a12 = m1.e[1][2], a13 = m1.e[1][3], - a20 = m1.e[2][0], a21 = m1.e[2][1], a22 = m1.e[2][2], a23 = m1.e[2][3], - a30 = m1.e[3][0], a31 = m1.e[3][1], a32 = m1.e[3][2], a33 = m1.e[3][3], - - b00 = m2.e[0][0], b01 = m2.e[0][1], b02 = m2.e[0][2], b03 = m2.e[0][3], - b10 = m2.e[1][0], b11 = m2.e[1][1], b12 = m2.e[1][2], b13 = m2.e[1][3], - b20 = m2.e[2][0], b21 = m2.e[2][1], b22 = m2.e[2][2], b23 = m2.e[2][3], - b30 = m2.e[3][0], b31 = m2.e[3][1], b32 = m2.e[3][2], b33 = m2.e[3][3]; - - Mat4x4 res; - res.e[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03; - res.e[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03; - res.e[0][2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03; - res.e[0][3] = a03 * b00 + a13 * b01 + a23 * b02 + a33 * b03; - res.e[1][0] = a00 * b10 + a10 * b11 + a20 * b12 + a30 * b13; - res.e[1][1] = a01 * b10 + a11 * b11 + a21 * b12 + a31 * b13; - res.e[1][2] = a02 * b10 + a12 * b11 + a22 * b12 + a32 * b13; - res.e[1][3] = a03 * b10 + a13 * b11 + a23 * b12 + a33 * b13; - res.e[2][0] = a00 * b20 + a10 * b21 + a20 * b22 + a30 * b23; - res.e[2][1] = a01 * b20 + a11 * b21 + a21 * b22 + a31 * b23; - res.e[2][2] = a02 * b20 + a12 * b21 + a22 * b22 + a32 * b23; - res.e[2][3] = a03 * b20 + a13 * b21 + a23 * b22 + a33 * b23; - res.e[3][0] = a00 * b30 + a10 * b31 + a20 * b32 + a30 * b33; - res.e[3][1] = a01 * b30 + a11 * b31 + a21 * b32 + a31 * b33; - res.e[3][2] = a02 * b30 + a12 * b31 + a22 * b32 + a32 * b33; - res.e[3][3] = a03 * b30 + a13 * b31 + a23 * b32 + a33 * b33; - - return res; -} - -/* ========================== * - * Xform - * ========================== */ +//////////////////////////////// +//~ Xform operations /* Construct identity xform */ #define XFORM_IDENT CppCompatInitListType(Xform) { .bx = V2FromXY(1, 0), .by = V2FromXY(0, 1) } @@ -1053,356 +413,67 @@ Inline Mat4x4 mat4x4_mul(Mat4x4 m1, Mat4x4 m2) /* Takes a translation, rotation, and scale as optional parameters for constructing an xform */ #define XFORM_TRS(...) xform_from_trs((Trs) { .t = V2FromXY(0,0), .s = V2FromXY(1, 1), .r = 0, __VA_ARGS__ }) -Inline Xform xform_mul(Xform a, Xform b); -Inline Xform xform_rotated(Xform xf, f32 angle); -Inline Xform xform_scaled(Xform xf, V2 v); -Inline V2 xform_basis_mul_v2(Xform xf, V2 v); -Inline V2 xform_mul_v2(Xform xf, V2 v); -Inline f32 xform_get_determinant(Xform xf); -Inline V2 xform_get_scale(Xform xf); -Inline f32 xform_get_rotation(Xform xf); +Xform xform_mul(Xform a, Xform b);; +Xform xform_rotated(Xform xf, f32 angle);; +Xform xform_scaled(Xform xf, V2 v);; +V2 xform_basis_mul_v2(Xform xf, V2 v);; +V2 xform_mul_v2(Xform xf, V2 v);; +f32 xform_get_determinant(Xform xf);; +V2 xform_get_scale(Xform xf);; +f32 xform_get_rotation(Xform xf);; -Inline b32 xform_eq(Xform xf1, Xform xf2) -{ - return v2_eq(xf1.og, xf2.og) && v2_eq(xf1.bx, xf2.bx) && v2_eq(xf1.by, xf2.by); -} +b32 xform_eq(Xform xf1, Xform xf2); -Inline Xform xform_from_pos(V2 v) -{ - Xform xf; - xf.bx = V2FromXY(1, 0); - xf.by = V2FromXY(0, 1); - xf.og = v; - return xf; -} - -Inline Xform xform_from_rotation(f32 r) -{ - Xform res; - f32 c = math_cos(r); - f32 s = math_sin(r); - res.bx = V2FromXY(c, s); - res.by = V2FromXY(-s, c); - res.og = V2FromXY(0, 0); - return res; -} - -Inline Xform xform_from_scale(V2 scale) -{ - Xform res; - res.bx = V2FromXY(scale.x, 0); - res.by = V2FromXY(0, scale.y); - res.og = V2FromXY(0, 0); - return res; -} - -Inline Xform xform_from_trs(Trs trs) -{ - Xform xf = XFORM_POS(trs.t); - xf = xform_rotated(xf, trs.r); - xf = xform_scaled(xf, trs.s); - return xf; -} - -Inline Xform xform_from_rect(Rect rect) -{ - V2 half_size = v2_mul(rect.size, 0.5); - Xform xf = ZI; - xf.bx = V2FromXY(rect.size.x, 0); - xf.by = V2FromXY(0, rect.size.y); - xf.og = v2_add(rect.pos, half_size); - return xf; -} - -Inline Xform xform_translated(Xform xf, V2 v) -{ - xf.og = V2FromXY(xf.bx.x * v.x + xf.by.x * v.y + xf.og.x, xf.bx.y * v.x + xf.by.y * v.y + xf.og.y); - return xf; -} - -Inline Xform xform_translated_world(Xform xf, V2 v) -{ - xf.og = v2_add(xf.og, v); - return xf; -} - -Inline Xform xform_rotated(Xform xf, f32 r) -{ - return xform_mul(xf, xform_from_rotation(r)); -} - -Inline Xform xform_rotated_world(Xform xf, f32 r) -{ - return xform_mul(xform_from_rotation(r), xf); -} - -Inline Xform xform_basis_rotated_world(Xform xf, f32 r) -{ - f32 diff = r; - f32 c = math_cos(diff); - f32 s = math_sin(diff); - xf.bx = V2FromXY(xf.bx.x * c - xf.bx.y * s, xf.bx.x * s + xf.bx.y * c); - xf.by = V2FromXY(xf.by.x * c - xf.by.y * s, xf.by.x * s + xf.by.y * c); - return xf; -} - -Inline Xform xform_basis_with_rotation_world(Xform xf, f32 r) -{ - return xform_basis_rotated_world(xf, r - xform_get_rotation(xf)); -} - -Inline Xform xform_scaled(Xform xf, V2 scale) -{ - xf.bx = v2_mul(xf.bx, scale.x); - xf.by = v2_mul(xf.by, scale.y); - return xf; -} - -Inline Xform xform_scaled_world(Xform xf, V2 scale) -{ - Xform res; - res.bx = v2_mul_v2(xf.bx, scale); - res.by = v2_mul_v2(xf.by, scale); - res.og = v2_mul_v2(xf.og, scale); - return res; -} - -Inline Xform xform_lerp(Xform a, Xform b, f32 t) -{ - Xform res; - res.bx = v2_slerp(a.bx, b.bx, t); - res.by = v2_slerp(a.by, b.by, t); - res.og = v2_lerp(a.og, b.og, t); - return res; -} - -Inline Xform xform_invert(Xform xf) -{ - f32 det = xform_get_determinant(xf); - f32 inv_det = 1.0f / det; - - f32 old_bx_x = xf.bx.x; - xf.bx.x = xf.by.y; - xf.by.y = old_bx_x; - - xf.bx = v2_mul_v2(xf.bx, V2FromXY(inv_det, -inv_det)); - xf.by = v2_mul_v2(xf.by, V2FromXY(-inv_det, inv_det)); - - xf.og = xform_basis_mul_v2(xf, v2_neg(xf.og)); - - return xf; -} - -Inline Xform xform_mul(Xform a, Xform b) -{ - Xform res; - res.bx.x = a.bx.x * b.bx.x + a.by.x * b.bx.y; - res.bx.y = a.bx.y * b.bx.x + a.by.y * b.bx.y; - res.by.x = a.bx.x * b.by.x + a.by.x * b.by.y; - res.by.y = a.bx.y * b.by.x + a.by.y * b.by.y; - res.og = xform_mul_v2(a, b.og); - return res; -} - -Inline V2 xform_basis_mul_v2(Xform xf, V2 v) -{ - return V2FromXY( - xf.bx.x * v.x + xf.by.x * v.y, - xf.bx.y * v.x + xf.by.y * v.y - ); -} - -Inline V2 xform_mul_v2(Xform xf, V2 v) -{ - V2 res = xform_basis_mul_v2(xf, v); - res = v2_add(res, xf.og); - return res; -} - -Inline Xform xform_basis(Xform xf) -{ - Xform res = ZI; - res.bx = xf.bx; - res.by = xf.by; - return res; -} - -Inline V2 xform_basis_invert_mul_v2(Xform xf, V2 v) -{ - Xform inv = xform_invert(xf); - V2 res = xform_basis_mul_v2(inv, v); - return res; -} +Xform xform_from_pos(V2 v); +Xform xform_from_rotation(f32 r); +Xform xform_from_scale(V2 scale); +Xform xform_from_trs(Trs trs); +Xform xform_from_rect(Rect rect); +Xform xform_translated(Xform xf, V2 v); +Xform xform_translated_world(Xform xf, V2 v); +Xform xform_rotated(Xform xf, f32 r); +Xform xform_rotated_world(Xform xf, f32 r); +Xform xform_basis_rotated_world(Xform xf, f32 r); +Xform xform_basis_with_rotation_world(Xform xf, f32 r); +Xform xform_scaled(Xform xf, V2 scale); +Xform xform_scaled_world(Xform xf, V2 scale); +Xform xform_lerp(Xform a, Xform b, f32 t); +Xform xform_invert(Xform xf); +Xform xform_mul(Xform a, Xform b); +V2 xform_basis_mul_v2(Xform xf, V2 v); +V2 xform_mul_v2(Xform xf, V2 v); +Xform xform_basis(Xform xf); +V2 xform_basis_invert_mul_v2(Xform xf, V2 v); /* TODO: Get rid of this? Just force caller to use invert manually since it's expensive. */ -Inline V2 xform_invert_mul_v2(Xform xf, V2 v) -{ - Xform inv = xform_invert(xf); - return xform_mul_v2(inv, v); -} +V2 xform_invert_mul_v2(Xform xf, V2 v); -Inline Quad xform_mul_quad(Xform xf, Quad quad) -{ - Quad res; - res.p0 = xform_mul_v2(xf, quad.p0); - res.p1 = xform_mul_v2(xf, quad.p1); - res.p2 = xform_mul_v2(xf, quad.p2); - res.p3 = xform_mul_v2(xf, quad.p3); - return res; -} +Quad xform_mul_quad(Xform xf, Quad quad); +f32 xform_get_determinant(Xform xf); +V2 xform_get_right(Xform xf); +V2 xform_get_left(Xform xf); +V2 xform_get_up(Xform xf); +V2 xform_get_down(Xform xf); +f32 xform_get_rotation(Xform xf); +V2 xform_get_scale(Xform xf); -Inline f32 xform_get_determinant(Xform xf) -{ - return v2_wedge(xf.bx, xf.by); -} +//////////////////////////////// +//~ Quad operations -Inline V2 xform_get_right(Xform xf) -{ - return xf.bx; -} +Quad quad_from_rect(Rect rect); +Quad quad_from_aabb(Aabb aabb); +Quad quad_from_line(V2 start, V2 end, f32 thickness); +Quad quad_from_ray(V2 pos, V2 rel, f32 thickness); +Quad quad_scale(Quad q, f32 s); +Quad quad_round(Quad quad); +Quad quad_floor(Quad quad); -Inline V2 xform_get_left(Xform xf) -{ - return v2_neg(xf.bx); -} +//////////////////////////////// +//~ Polygon operations -Inline V2 xform_get_up(Xform xf) -{ - return v2_neg(xf.by); -} +V2 math_poly_center(V2Array a); -Inline V2 xform_get_down(Xform xf) -{ - return xf.by; -} +//////////////////////////////// +//~ Spring operations -Inline f32 xform_get_rotation(Xform xf) -{ - return v2_angle(xf.bx); -} - -Inline V2 xform_get_scale(Xform xf) -{ - f32 det_sign = math_fsign(xform_get_determinant(xf)); - return V2FromXY(v2_len(xf.bx), det_sign * v2_len(xf.by)); -} - -/* ========================== * - * Quad - * ========================== */ - -Inline Quad quad_from_rect(Rect rect) -{ - Quad res; - res.p0 = V2FromXY(rect.x, rect.y); /* Top left */ - res.p1 = V2FromXY(rect.x + rect.width, rect.y); /* Top right */ - res.p2 = V2FromXY(rect.x + rect.width, rect.y + rect.height); /* Bottom right */ - res.p3 = V2FromXY(rect.x, rect.y + rect.height); /* Bottom left */ - return res; -} - -Inline Quad quad_from_aabb(Aabb aabb) -{ - Quad res; - res.p0 = V2FromXY(aabb.p0.x, aabb.p0.y); /* Top left */ - res.p1 = V2FromXY(aabb.p1.x, aabb.p0.y); /* Top right */ - res.p2 = V2FromXY(aabb.p1.x, aabb.p1.y); /* Bottom right */ - res.p3 = V2FromXY(aabb.p0.x, aabb.p1.y); /* Bottom left */ - return res; -} - -Inline Quad quad_from_line(V2 start, V2 end, f32 thickness) -{ - f32 width = thickness / 2.f; - - V2 dir = v2_norm(v2_sub(end, start)); - V2 dir_perp = v2_perp(dir); - - V2 left = v2_mul(dir_perp, -width); - V2 right = v2_mul(dir_perp, width); - - Quad res; - res.p0 = v2_add(start, left); - res.p1 = v2_add(start, right); - res.p2 = v2_add(end, right); - res.p3 = v2_add(end, left); - return res; -} - -Inline Quad quad_from_ray(V2 pos, V2 rel, f32 thickness) -{ - V2 end = v2_add(pos, rel); - return quad_from_line(pos, end, thickness); -} - -Inline Quad quad_scale(Quad q, f32 s) -{ - q.p0 = v2_mul(q.p0, s); - q.p1 = v2_mul(q.p1, s); - q.p2 = v2_mul(q.p2, s); - q.p3 = v2_mul(q.p3, s); - return q; -} - -Inline Quad quad_round(Quad quad) -{ - Quad res; - res.p0 = v2_round(quad.p0); - res.p1 = v2_round(quad.p1); - res.p2 = v2_round(quad.p2); - res.p3 = v2_round(quad.p3); - return res; -} - -Inline Quad quad_floor(Quad quad) -{ - Quad res; - res.p0 = v2_floor(quad.p0); - res.p1 = v2_floor(quad.p1); - res.p2 = v2_floor(quad.p2); - res.p3 = v2_floor(quad.p3); - return res; -} - -/* ========================== * - * Convex polygon - * ========================== */ - -Inline V2 math_poly_center(V2Array a) -{ - V2 sum = V2FromXY(0, 0); - for (u64 i = 0; i < a.count; ++i) { - sum = v2_add(sum, a.points[i]); - } - return v2_div(sum, a.count); -} - -/* ========================== * - * Spring - * ========================== */ - -/* https://box2d.org/files/ErinCatto_SoftConstraints_GDC2011.pdf */ -Struct(SoftSpring) { - f32 bias_rate; - f32 mass_scale; - f32 impulse_scale; -}; - -Inline SoftSpring math_spring_init(f32 hertz, f32 damping_ratio, f32 dt) -{ - SoftSpring res; - if (hertz == 0.0f) { - res.bias_rate = 0; - res.mass_scale = 1; - res.impulse_scale = 0; - } else { - f32 angular_frequency = TAU * hertz; - f32 a = 2 * damping_ratio + angular_frequency * dt; - f32 b = angular_frequency * a * dt; - f32 c = 1 / (b + 1); - res.bias_rate = angular_frequency / a; - res.mass_scale = b * c; - res.impulse_scale = c; - } - return res; -} +SoftSpring math_spring_init(f32 hertz, f32 damping_ratio, f32 dt); diff --git a/src/collider/collider_core.c b/src/collider/collider_core.c index 6fff05c5..8b6bb397 100644 --- a/src/collider/collider_core.c +++ b/src/collider/collider_core.c @@ -951,7 +951,7 @@ V2Array menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, { V2Array res = { .points = PushDry(arena, V2) }; for (u64 i = 0; i < detail; ++i) { - f32 angle = ((f32)i / detail) * (2 * PI); + f32 angle = ((f32)i / detail) * (2 * Pi); V2 dir = v2_from_angle(angle); CLD_MenkowskiPoint m = get_menkowski_point(shape0, shape1, xf0, xf1, dir); if (res.count == 0 || !v2_eq(m.p, res.points[res.count - 1])) { diff --git a/src/config.h b/src/config.h index d58a7a1d..7f4419c8 100644 --- a/src/config.h +++ b/src/config.h @@ -63,7 +63,7 @@ #if 0 # define SIM_MAX_LINEAR_VELOCITY 500 -# define SIM_MAX_ANGULAR_VELOCITY (TAU * 20) +# define SIM_MAX_ANGULAR_VELOCITY (Tau * 20) #else # define SIM_MAX_LINEAR_VELOCITY F32_INFINITY # define SIM_MAX_ANGULAR_VELOCITY F32_INFINITY diff --git a/src/draw/draw_core.c b/src/draw/draw_core.c index abe37211..8e9e1772 100644 --- a/src/draw/draw_core.c +++ b/src/draw/draw_core.c @@ -11,7 +11,7 @@ D_StartupReceipt draw_startup(F_StartupReceipt *font_sr) __prof; (UNUSED)font_sr; u32 pixel_white = 0xFFFFFFFF; - G.solid_white_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2i32FromXY(1, 1), &pixel_white); + G.solid_white_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32FromXY(1, 1), &pixel_white); return (D_StartupReceipt) { 0 }; } @@ -79,7 +79,7 @@ void draw_circle(G_RenderSig *sig, V2 pos, f32 radius, u32 color, u32 detail) V2 *points = PushArrayNoZero(scratch.arena, V2, detail); for (u32 i = 0; i < detail; ++i) { - f32 angle = ((f32)i / (f32)detail) * TAU; + f32 angle = ((f32)i / (f32)detail) * Tau; V2 p = V2FromXY( radius * math_cos(angle), radius * math_sin(angle) @@ -160,7 +160,7 @@ void draw_circle_line(G_RenderSig *sig, V2 pos, f32 radius, f32 thickness, u32 c V2 *points = PushArrayNoZero(scratch.arena, V2, detail); for (u32 i = 0; i < detail; ++i) { - f32 angle = ((f32)i / (f32)detail) * TAU; + f32 angle = ((f32)i / (f32)detail) * Tau; V2 p = V2FromXY( radius * math_cos(angle), radius * math_sin(angle) @@ -235,7 +235,7 @@ void draw_collider_line(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 t poly.count = detail; poly.points = PushArrayNoZero(scratch.arena, V2, detail); for (u32 i = 0; i < detail; ++i) { - f32 angle = ((f32)i / (f32)detail) * TAU; + f32 angle = ((f32)i / (f32)detail) * Tau; V2 dir = V2FromXY(math_cos(angle), math_sin(angle)); V2 p = collider_get_support_point(&shape, shape_xf, dir).p; poly.points[i] = p; @@ -461,7 +461,7 @@ Rect draw_text(G_RenderSig *sig, D_TextParams params) struct drawable_glyph *tg = &line->glyphs[i]; V2 pos = V2FromXY(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y); V2 size = V2FromXY(tg->width, tg->height); - Xform xf = xform_from_rect(RECT_FROM_V2(pos, size)); + Xform xf = xform_from_rect(RectFromV2(pos, size)); draw_ui_rect(sig, DRAW_UI_RECT_PARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip)); draw_pos.x += tg->advance; diff --git a/src/draw/draw_core.h b/src/draw/draw_core.h index 7028ba43..ad77b182 100644 --- a/src/draw/draw_core.h +++ b/src/draw/draw_core.h @@ -7,7 +7,7 @@ D_StartupReceipt draw_startup(F_StartupReceipt *font_sr); #define DRAW_MATERIAL_PARAMS(...) ((D_MaterialParams) { \ .tint = ColorWhite, \ - .clip = CLIP_ALL, \ + .clip = ClipAll, \ __VA_ARGS__ \ }) @@ -68,7 +68,7 @@ void draw_grid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 lin #define DRAW_UI_RECT_PARAMS(...) ((D_UiRectParams) { \ .tint = ColorWhite, \ - .clip = CLIP_ALL, \ + .clip = ClipAll, \ __VA_ARGS__ \ }) diff --git a/src/editor_include.h b/src/editor_include.h index b9705c28..a392fc20 100644 --- a/src/editor_include.h +++ b/src/editor_include.h @@ -27,4 +27,4 @@ #include "tar/tar.h" #include "ttf/ttf.h" #include "user/user.h" -#include "watch/watch.h" \ No newline at end of file +#include "watch/watch.h" diff --git a/src/font/font_core.c b/src/font/font_core.c index 036b01c2..d9669755 100644 --- a/src/font/font_core.c +++ b/src/font/font_core.c @@ -100,7 +100,7 @@ internal P_JobDef(font_load_asset_job, job) resource_close(&res); /* Send texture to GPU */ - G_Resource *texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2i32FromXY(result.image_width, result.image_height), result.image_pixels); + G_Resource *texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32FromXY(result.image_width, result.image_height), result.image_pixels); /* Allocate store memory */ F_Font *font = 0; diff --git a/src/gp/gp_core.h b/src/gp/gp_core.h index edbac3ea..f752bbd6 100644 --- a/src/gp/gp_core.h +++ b/src/gp/gp_core.h @@ -69,8 +69,8 @@ Struct(G_RenderCmdDesc) Struct(G_RenderParams) { - V2i32 ui_size; - V2i32 render_size; + V2I32 ui_size; + V2I32 render_size; Xform world_to_render_xf; Xform render_to_ui_xf; b32 effects_disabled; @@ -125,9 +125,9 @@ void gp_resource_release(G_Resource *resource); //////////////////////////////// //~ Texture operations -G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void *initial_data); +G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2I32 size, void *initial_data); -V2i32 gp_texture_get_size(G_Resource *texture); +V2I32 gp_texture_get_size(G_Resource *texture); //////////////////////////////// //~ Render operations @@ -147,7 +147,7 @@ G_MemoryInfo gp_query_memory_info(void); //////////////////////////////// //~ Swapchain -G_Swapchain *gp_swapchain_alloc(P_Window *window, V2i32 resolution); +G_Swapchain *gp_swapchain_alloc(P_Window *window, V2I32 resolution); void gp_swapchain_release(G_Swapchain *gp_swapchain); @@ -161,4 +161,4 @@ void gp_swapchain_wait(G_Swapchain *gp_swapchain); /* 1. Clears the backbuffer and ensures it's at size `backbuffer_resolution` * 2. Blits `texture` to the backbuffer using `texture_xf` * 3. Presents the backbuffer */ -void gp_present(G_Swapchain *gp_swapchain, V2i32 backbuffer_resolution, G_Resource *texture, Xform texture_xf, i32 vsync); +void gp_present(G_Swapchain *gp_swapchain, V2I32 backbuffer_resolution, G_Resource *texture, Xform texture_xf, i32 vsync); diff --git a/src/gp/gp_core_dx12.c b/src/gp/gp_core_dx12.c index c34a8b30..de424532 100644 --- a/src/gp/gp_core_dx12.c +++ b/src/gp/gp_core_dx12.c @@ -214,7 +214,7 @@ struct dx12_resource { D3D12_GPU_VIRTUAL_ADDRESS gpu_address; /* NOTE: 0 for textures */ - V2i32 texture_size; + V2I32 texture_size; struct dx12_resource *next_free; }; @@ -229,7 +229,7 @@ struct swapchain { IDXGISwapChain3 *swapchain; HWND hwnd; HANDLE waitable; - V2i32 resolution; + V2I32 resolution; struct swapchain_buffer buffers[DX12_SWAPCHAIN_BUFFER_COUNT]; struct swapchain *next_free; @@ -2204,7 +2204,7 @@ internal P_JobDef(dx12_wait_fence_job, job) * Texture * ========================== */ -G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void *initial_data) +G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2I32 size, void *initial_data) { __prof; if (size.x <= 0 || size.y <= 0) { @@ -2271,7 +2271,7 @@ G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void return (G_Resource *)r; } -V2i32 gp_texture_get_size(G_Resource *resource) +V2I32 gp_texture_get_size(G_Resource *resource) { struct dx12_resource *r = (struct dx12_resource *)resource; return r->texture_size; @@ -2458,7 +2458,7 @@ internal D3D12_INDEX_BUFFER_VIEW ibv_from_command_buffer(struct command_buffer * return ibv; } -internal struct dx12_resource *gbuff_alloc(DXGI_FORMAT format, V2i32 size, D3D12_RESOURCE_STATES initial_state) +internal struct dx12_resource *gbuff_alloc(DXGI_FORMAT format, V2I32 size, D3D12_RESOURCE_STATES initial_state) { __prof; D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_DEFAULT }; @@ -2695,13 +2695,13 @@ G_Resource *gp_run_render(G_RenderSig *gp_render_sig, G_RenderParams params) struct render_sig *rsig = (struct render_sig *)gp_render_sig; ++rsig->frame_index; - V2i32 ui_size = V2i32FromXY(max_i32(params.ui_size.x, 1), max_i32(params.ui_size.y, 1)); - V2i32 render_size = V2i32FromXY(max_i32(params.render_size.x, 1), max_i32(params.render_size.y, 1)); + V2I32 ui_size = V2I32FromXY(max_i32(params.ui_size.x, 1), max_i32(params.ui_size.y, 1)); + V2I32 render_size = V2I32FromXY(max_i32(params.render_size.x, 1), max_i32(params.render_size.y, 1)); Xform world_to_render_xf = params.world_to_render_xf; Xform render_to_ui_xf = params.render_to_ui_xf; - Rect ui_viewport = RECT_FROM_V2(V2FromXY(0, 0), V2FromXY(ui_size.x, ui_size.y)); - Rect render_viewport = RECT_FROM_V2(V2FromXY(0, 0), V2FromXY(render_size.x, render_size.y)); + Rect ui_viewport = RectFromV2(V2FromXY(0, 0), V2FromXY(ui_size.x, ui_size.y)); + Rect render_viewport = RectFromV2(V2FromXY(0, 0), V2FromXY(render_size.x, render_size.y)); /* Allocate render buffers */ @@ -3201,7 +3201,7 @@ internal void swapchain_init_resources(struct swapchain *swapchain) } } -G_Swapchain *gp_swapchain_alloc(P_Window *window, V2i32 resolution) +G_Swapchain *gp_swapchain_alloc(P_Window *window, V2I32 resolution) { HRESULT hr = 0; HWND hwnd = (HWND)P_GetInternalWindowHandle(window); @@ -3282,7 +3282,7 @@ void gp_swapchain_wait(G_Swapchain *gp_swapchain) #endif } -internal struct swapchain_buffer *update_swapchain(struct swapchain *swapchain, V2i32 resolution) +internal struct swapchain_buffer *update_swapchain(struct swapchain *swapchain, V2I32 resolution) { __prof; resolution.x = max_i32(resolution.x, 1); @@ -3360,7 +3360,7 @@ internal void present_blit(struct swapchain_buffer *dst, struct dx12_resource *s ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap }; ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, countof(heaps), heaps); - Rect viewport_rect = RECT_FROM_V2(V2FromXY(0, 0), V2FromXY(swapchain->resolution.x, swapchain->resolution.y)); + Rect viewport_rect = RectFromV2(V2FromXY(0, 0), V2FromXY(swapchain->resolution.x, swapchain->resolution.y)); D3D12_VIEWPORT viewport = viewport_from_rect(viewport_rect); D3D12_RECT scissor = scissor_from_rect(viewport_rect); @@ -3434,7 +3434,7 @@ internal void present_blit(struct swapchain_buffer *dst, struct dx12_resource *s pipeline_scope_end(pipeline_scope); } -void gp_present(G_Swapchain *gp_swapchain, V2i32 backbuffer_resolution, G_Resource *texture, Xform texture_xf, i32 vsync) +void gp_present(G_Swapchain *gp_swapchain, V2I32 backbuffer_resolution, G_Resource *texture, Xform texture_xf, i32 vsync) { __prof; struct swapchain *swapchain = (struct swapchain *)gp_swapchain; diff --git a/src/kernel/kernel_core.h b/src/kernel/kernel_core.h index 75c0648b..d960412c 100644 --- a/src/kernel/kernel_core.h +++ b/src/kernel/kernel_core.h @@ -96,8 +96,8 @@ Inline struct K_float2x3 K_Float2x3FromXform(Xform v) #define DECLS(t, n) t n : n -#define TAU 6.28318530718 -#define PI 3.14159265359 +#define Tau 6.28318530718 +#define Pi 3.14159265359 #define GOLDEN 1.61803398875 diff --git a/src/kernel/kernel_shade.knl b/src/kernel/kernel_shade.knl index 9b8b3fc8..b9e6d164 100644 --- a/src/kernel/kernel_shade.knl +++ b/src/kernel/kernel_shade.knl @@ -19,7 +19,7 @@ float rand_angle(uint2 pos, uint ray_index) { // noise_coord.xy -= sig.camera_offset; uint noise = noise_tex[noise_coord % uint3(K_BLUE_NOISE_TEX_WIDTH, K_BLUE_NOISE_TEX_HEIGHT, K_BLUE_NOISE_TEX_DEPTH)]; - return ((float)noise / (float)0xFFFF) * TAU; + return ((float)noise / (float)0xFFFF) * Tau; } float3 get_light_in_dir(uint2 ray_start, float2 ray_dir) diff --git a/src/platform/platform_snc.c b/src/platform/platform_snc.c index 62996521..dbc93366 100644 --- a/src/platform/platform_snc.c +++ b/src/platform/platform_snc.c @@ -45,7 +45,7 @@ P_Lock P_LockSpinE(P_Mutex *m, i32 spin) { if (spin_cnt < spin) { - ix_pause(); + IxPause(); } else { @@ -92,7 +92,7 @@ P_Lock P_LockSpinS(P_Mutex *m, i32 spin) { if (spin_cnt < spin) { - ix_pause(); + IxPause(); } else { diff --git a/src/platform/platform_win32.c b/src/platform/platform_win32.c index 7a5fea51..9961fe0b 100644 --- a/src/platform/platform_win32.c +++ b/src/platform/platform_win32.c @@ -22,7 +22,7 @@ void P_W32_LockTicketMutex(P_W32_TicketMutex *tm) i64 ticket = Atomic64FetchAdd(&tm->ticket.v, 1); while (Atomic64Fetch(&tm->serving.v) != ticket) { - ix_pause(); + IxPause(); } } @@ -3202,7 +3202,7 @@ void P_SleepPrecise(i64 sleep_time_ns) __profn("Sleep spin"); while (now_ns < target_ns) { - ix_pause(); + IxPause(); now_ns = P_TimeNs(); } } diff --git a/src/sim/sim_core.c b/src/sim/sim_core.c index f687ae51..f72a6beb 100644 --- a/src/sim/sim_core.c +++ b/src/sim/sim_core.c @@ -540,15 +540,15 @@ Snapshot *sim_snapshot_from_closest_tick_gte(Client *client, u64 tick) * Tile * ========================== */ -V2i32 sim_world_tile_index_from_pos(V2 pos) +V2I32 sim_world_tile_index_from_pos(V2 pos) { - V2i32 res = V2i32FromXY(pos.x * SIM_TILES_PER_UNIT_SQRT, pos.y * SIM_TILES_PER_UNIT_SQRT); + V2I32 res = V2I32FromXY(pos.x * SIM_TILES_PER_UNIT_SQRT, pos.y * SIM_TILES_PER_UNIT_SQRT); res.x -= pos.x < 0; res.y -= pos.y < 0; return res; } -V2 sim_pos_from_world_tile_index(V2i32 world_tile_index) +V2 sim_pos_from_world_tile_index(V2I32 world_tile_index) { V2 res = ZI; f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT; @@ -557,9 +557,9 @@ V2 sim_pos_from_world_tile_index(V2i32 world_tile_index) return res; } -V2i32 sim_local_tile_index_from_world_tile_index(V2i32 world_tile_index) +V2I32 sim_local_tile_index_from_world_tile_index(V2I32 world_tile_index) { - V2i32 res = world_tile_index; + V2I32 res = world_tile_index; res.x += res.x < 0; res.y += res.y < 0; res.x = res.x % SIM_TILES_PER_CHUNK_SQRT; @@ -569,17 +569,17 @@ V2i32 sim_local_tile_index_from_world_tile_index(V2i32 world_tile_index) return res; } -V2i32 sim_world_tile_index_from_local_tile_index(V2i32 tile_chunk_index, V2i32 local_tile_index) +V2I32 sim_world_tile_index_from_local_tile_index(V2I32 tile_chunk_index, V2I32 local_tile_index) { - V2i32 res = ZI; + V2I32 res = ZI; res.x = (tile_chunk_index.x * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.x; res.y = (tile_chunk_index.y * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.y; return res; } -V2i32 sim_tile_chunk_index_from_world_tile_index(V2i32 world_tile_index) +V2I32 sim_tile_chunk_index_from_world_tile_index(V2I32 world_tile_index) { - V2i32 res = world_tile_index; + V2I32 res = world_tile_index; res.x += res.x < 0; res.y += res.y < 0; res.x = res.x / SIM_TILES_PER_CHUNK_SQRT; @@ -589,9 +589,9 @@ V2i32 sim_tile_chunk_index_from_world_tile_index(V2i32 world_tile_index) return res; } -void sim_snapshot_set_tile(Snapshot *ss, V2i32 world_tile_index, TileKind tile_kind) +void sim_snapshot_set_tile(Snapshot *ss, V2I32 world_tile_index, TileKind tile_kind) { - V2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index); + V2I32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index); EntId chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index); Ent *chunk_ent = sim_ent_from_id(ss, chunk_id); @@ -602,7 +602,7 @@ void sim_snapshot_set_tile(Snapshot *ss, V2i32 world_tile_index, TileKind tile_k chunk_ent->tile_chunk_index = chunk_index; } - V2i32 local_index = sim_local_tile_index_from_world_tile_index(world_tile_index); + V2I32 local_index = sim_local_tile_index_from_world_tile_index(world_tile_index); chunk_ent->tile_chunk_tiles[local_index.x + (local_index.y * SIM_TILES_PER_CHUNK_SQRT)] = tile_kind; } diff --git a/src/sim/sim_core.h b/src/sim/sim_core.h index 5d38666f..88823373 100644 --- a/src/sim/sim_core.h +++ b/src/sim/sim_core.h @@ -233,12 +233,12 @@ Snapshot *sim_snapshot_from_closest_tick_lte(Client *client, u64 tick); Snapshot *sim_snapshot_from_closest_tick_gte(Client *client, u64 tick); /* Tile */ -V2i32 sim_world_tile_index_from_pos(V2 pos); -V2 sim_pos_from_world_tile_index(V2i32 world_tile_index); -V2i32 sim_local_tile_index_from_world_tile_index(V2i32 world_tile_index); -V2i32 sim_world_tile_index_from_local_tile_index(V2i32 tile_chunk_index, V2i32 local_tile_index); -V2i32 sim_tile_chunk_index_from_world_tile_index(V2i32 world_tile_index); -void sim_snapshot_set_tile(Snapshot *ss, V2i32 world_tile_index, TileKind tile_kind); +V2I32 sim_world_tile_index_from_pos(V2 pos); +V2 sim_pos_from_world_tile_index(V2I32 world_tile_index); +V2I32 sim_local_tile_index_from_world_tile_index(V2I32 world_tile_index); +V2I32 sim_world_tile_index_from_local_tile_index(V2I32 tile_chunk_index, V2I32 local_tile_index); +V2I32 sim_tile_chunk_index_from_world_tile_index(V2I32 world_tile_index); +void sim_snapshot_set_tile(Snapshot *ss, V2I32 world_tile_index, TileKind tile_kind); /* Lerp */ Snapshot *sim_snapshot_alloc_from_lerp(Client *client, Snapshot *ss0, Snapshot *ss1, f64 blend); diff --git a/src/sim/sim_ent.c b/src/sim/sim_ent.c index fb0e3476..a0d27005 100644 --- a/src/sim/sim_ent.c +++ b/src/sim/sim_ent.c @@ -289,7 +289,7 @@ EntId sim_ent_collision_debug_id_from_ids(EntId player_id, EntId id0, EntId id1) } /* Returns the deterministic id of the tile chunk that should be produced at chunk pos */ -EntId sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_index) +EntId sim_ent_tile_chunk_id_from_tile_chunk_index(V2I32 chunk_index) { EntId res = ZI; res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID; @@ -559,21 +559,21 @@ void sim_ent_apply_torque(Ent *ent, f32 torque) * Tile * ========================== */ -Ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2i32 chunk_index) +Ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2I32 chunk_index) { EntId chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index); Ent *chunk_ent = sim_ent_from_id(ss, chunk_id); return chunk_ent; } -Ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, V2i32 world_tile_index) +Ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, V2I32 world_tile_index) { - V2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index); + V2I32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index); Ent *chunk_ent = sim_tile_chunk_from_chunk_index(ss, chunk_index); return chunk_ent; } -TileKind sim_get_chunk_tile(Ent *chunk_ent, V2i32 local_tile_index) +TileKind sim_get_chunk_tile(Ent *chunk_ent, V2I32 local_tile_index) { TileKind res = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)]; return res; diff --git a/src/sim/sim_ent.h b/src/sim/sim_ent.h index 3b887c35..41108626 100644 --- a/src/sim/sim_ent.h +++ b/src/sim/sim_ent.h @@ -157,7 +157,7 @@ Struct(Ent) { /* FIXME: Move out of here */ u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT]; - V2i32 tile_chunk_index; + V2I32 tile_chunk_index; /* ====================================================================== */ /* Client */ @@ -508,7 +508,7 @@ Ent *sim_ent_from_id(Snapshot *ss, EntId id); EntId sim_ent_random_id(void); EntId sim_ent_contact_constraint_id_from_contacting_ids(EntId player_id, EntId id0, EntId id1); EntId sim_ent_collision_debug_id_from_ids(EntId player_id, EntId id0, EntId id1); -EntId sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_start); +EntId sim_ent_tile_chunk_id_from_tile_chunk_index(V2I32 chunk_start); /* Query */ Ent *sim_ent_find_first_match_one(Snapshot *ss, EntProp prop); @@ -534,9 +534,9 @@ void sim_ent_apply_angular_impulse(Ent *ent, f32 impulse); void sim_ent_apply_torque(Ent *ent, f32 torque); /* Tile */ -Ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2i32 chunk_index); -Ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, V2i32 world_tile_index); -TileKind sim_get_chunk_tile(Ent *chunk_ent, V2i32 local_tile_index); +Ent *sim_tile_chunk_from_chunk_index(Snapshot *ss, V2I32 chunk_index); +Ent *sim_tile_chunk_from_world_tile_index(Snapshot *ss, V2I32 world_tile_index); +TileKind sim_get_chunk_tile(Ent *chunk_ent, V2I32 local_tile_index); /* Lerp */ void sim_ent_lerp(Ent *e, Ent *e0, Ent *e1, f64 blend); diff --git a/src/sim/sim_space.c b/src/sim/sim_space.c index 909d0f84..e90e0e44 100644 --- a/src/sim/sim_space.c +++ b/src/sim/sim_space.c @@ -69,16 +69,16 @@ Space *space_from_entry(SpaceEntry *entry) * Cell * ========================== */ -internal V2i32 world_to_cell_coords(f32 cell_size, V2 world_pos) +internal V2I32 world_to_cell_coords(f32 cell_size, V2 world_pos) { f32 x = world_pos.x; f32 y = world_pos.y; x = (x + ((x >= 0) - (x < 0)) * cell_size) / cell_size; y = (y + ((y >= 0) - (y < 0)) * cell_size) / cell_size; - return V2i32FromXY((i32)x, (i32)y); + return V2I32FromXY((i32)x, (i32)y); } -internal i32 cell_coords_to_bin_index(Space *space, V2i32 cell_pos) +internal i32 cell_coords_to_bin_index(Space *space, V2I32 cell_pos) { i32 num_bins_sqrt = space->num_bins_sqrt; @@ -100,7 +100,7 @@ internal i32 cell_coords_to_bin_index(Space *space, V2i32 cell_pos) return bin_index; } -SpaceCell *space_get_cell(Space *space, V2i32 cell_pos) +SpaceCell *space_get_cell(Space *space, V2I32 cell_pos) { i32 bin_index = cell_coords_to_bin_index(space, cell_pos); SpaceCellBin *bin = &space->bins[bin_index]; @@ -114,7 +114,7 @@ SpaceCell *space_get_cell(Space *space, V2i32 cell_pos) return res; } -internal void space_cell_node_alloc(V2i32 cell_pos, SpaceEntry *entry) +internal void space_cell_node_alloc(V2I32 cell_pos, SpaceEntry *entry) { Space *space = space_from_entry(entry); i32 bin_index = cell_coords_to_bin_index(space, cell_pos); @@ -311,22 +311,22 @@ void space_entry_update_aabb(SpaceEntry *entry, Aabb new_aabb) Space *space = space_from_entry(entry); f32 cell_size = space->cell_size; - V2i32 old_cell_p0 = V2i32FromXY(0, 0); - V2i32 old_cell_p1 = V2i32FromXY(0, 0); + V2I32 old_cell_p0 = V2I32FromXY(0, 0); + V2I32 old_cell_p1 = V2I32FromXY(0, 0); if (entry->first_node) { Aabb old_aabb = entry->aabb; old_cell_p0 = world_to_cell_coords(cell_size, old_aabb.p0); old_cell_p1 = world_to_cell_coords(cell_size, old_aabb.p1); } - V2i32 new_cell_p0 = world_to_cell_coords(cell_size, new_aabb.p0); - V2i32 new_cell_p1 = world_to_cell_coords(cell_size, new_aabb.p1); + V2I32 new_cell_p0 = world_to_cell_coords(cell_size, new_aabb.p0); + V2I32 new_cell_p1 = world_to_cell_coords(cell_size, new_aabb.p1); /* Release outdated nodes */ SpaceCellNode *n = entry->first_node; while (n) { SpaceCell *cell = n->cell; - V2i32 cell_pos = cell->pos; + V2I32 cell_pos = cell->pos; if (cell_pos.x < new_cell_p0.x || cell_pos.x > new_cell_p1.x || cell_pos.y < new_cell_p0.y || cell_pos.y > new_cell_p1.y) { /* Cell is outside of new AABB */ SpaceCellNode *next = n->next_in_entry; @@ -342,7 +342,7 @@ void space_entry_update_aabb(SpaceEntry *entry, Aabb new_aabb) for (i32 x = new_cell_p0.x; x <= new_cell_p1.x; ++x) { if (x != 0 && y != 0 && (x < old_cell_p0.x || x > old_cell_p1.x || y < old_cell_p0.y || y > old_cell_p1.y)) { /* Cell is outside of old AABB */ - space_cell_node_alloc(V2i32FromXY(x, y), entry); + space_cell_node_alloc(V2I32FromXY(x, y), entry); } } } @@ -364,7 +364,7 @@ SpaceIter space_iter_begin_aabb(Space *space, Aabb aabb) iter.cell_end = world_to_cell_coords(cell_size, aabb.p1); if (iter.cell_start.x > iter.cell_end.x || iter.cell_start.y > iter.cell_end.y) { /* Swap cell_start & cell_end */ - V2i32 tmp = iter.cell_start; + V2I32 tmp = iter.cell_start; iter.cell_start = iter.cell_end; iter.cell_end = tmp; } @@ -381,9 +381,9 @@ SpaceEntry *space_iter_next(SpaceIter *iter) { Space *space = iter->space; Aabb iter_aabb = iter->aabb; - V2i32 cell_start = iter->cell_start; - V2i32 cell_end = iter->cell_end; - V2i32 cell_cur = iter->cell_cur; + V2I32 cell_start = iter->cell_start; + V2I32 cell_end = iter->cell_end; + V2I32 cell_cur = iter->cell_cur; i32 span = cell_end.x - cell_start.x; SpaceCellNode *next_node = 0; diff --git a/src/sim/sim_space.h b/src/sim/sim_space.h index e36464d2..72bc35c9 100644 --- a/src/sim/sim_space.h +++ b/src/sim/sim_space.h @@ -42,7 +42,7 @@ typedef struct SpaceCellBin SpaceCellBin; typedef struct SpaceCell SpaceCell; struct SpaceCell { b32 valid; - V2i32 pos; + V2I32 pos; SpaceCellNode *first_node; SpaceCellNode *last_node; @@ -82,9 +82,9 @@ typedef struct SpaceIter SpaceIter; struct SpaceIter { Aabb aabb; Space *space; - V2i32 cell_start; - V2i32 cell_end; - V2i32 cell_cur; + V2I32 cell_start; + V2I32 cell_end; + V2I32 cell_cur; SpaceCellNode *prev; }; @@ -124,7 +124,7 @@ Space *space_from_entry(SpaceEntry *entry); * Cell * ========================== */ -SpaceCell *space_get_cell(Space *space, V2i32 cell_pos); +SpaceCell *space_get_cell(Space *space, V2I32 cell_pos); /* ========================== * * Entry diff --git a/src/sim/sim_step.c b/src/sim/sim_step.c index 87de73d2..dfe6e838 100644 --- a/src/sim/sim_step.c +++ b/src/sim/sim_step.c @@ -114,7 +114,7 @@ internal Ent *test_spawn_employee(Ent *parent) //V2 size = V2FromXY(0.5, 0.25); V2 size = V2FromXY(1.0, 1.0); - //f32 r = PI / 4; + //f32 r = Pi / 4; f32 r = 0; { @@ -262,7 +262,7 @@ internal void test_spawn_entities2(Ent *parent, V2 pos) //e->sprite_tint = Alpha32F(ColorWhite, 1); sim_ent_enable_prop(e, SEPROP_SOLID); - Quad collider_quad = quad_from_rect(RECT(-0.5, -0.5, 1, 1)); + Quad collider_quad = quad_from_rect(RectFromScalar(-0.5, -0.5, 1, 1)); e->local_collider = collider_from_quad(collider_quad); sim_ent_enable_prop(e, SEPROP_LIGHT_TEST); @@ -292,7 +292,7 @@ internal void test_spawn_entities2(Ent *parent, V2 pos) { Ent *e = sim_ent_alloc_sync_src(parent); - f32 r = PI / 4; + f32 r = Pi / 4; V2 size = V2FromXY(0.5, 0.25); Xform xf = XFORM_TRS(.t = pos, .r = r, .s = size); sim_ent_set_xform(e, xf); @@ -331,7 +331,7 @@ internal void test_spawn_entities3(Ent *parent, V2 pos) e->sprite_tint = ColorRed; sim_ent_enable_prop(e, SEPROP_SOLID); - Quad collider_quad = quad_from_rect(RECT(-0.5, -0.5, 1, 1)); + Quad collider_quad = quad_from_rect(RectFromScalar(-0.5, -0.5, 1, 1)); e->local_collider = collider_from_quad(collider_quad); } } @@ -365,7 +365,7 @@ internal void test_spawn_tile(Snapshot *world, V2 world_pos) i32 sign_x = (world_pos.x >= 0) - (world_pos.x < 0); i32 sign_y = (world_pos.y >= 0) - (world_pos.y < 0); - V2i32 tile_index = V2i32FromXY(world_pos.x * SIM_TILES_PER_UNIT_SQRT, world_pos.y * SIM_TILES_PER_UNIT_SQRT); + V2I32 tile_index = V2I32FromXY(world_pos.x * SIM_TILES_PER_UNIT_SQRT, world_pos.y * SIM_TILES_PER_UNIT_SQRT); world_pos.x -= sign_x < 0; world_pos.y -= sign_y < 0; @@ -389,10 +389,10 @@ internal void test_spawn_tile(Snapshot *world, V2 world_pos) } sim_ent_enable_prop(e, SEPROP_SOLID); - Quad collider_quad = quad_from_rect(RECT(-tile_size.x / 2, -tile_size.y / 2, tile_size.y, tile_size.y)); + Quad collider_quad = quad_from_rect(RectFromScalar(-tile_size.x / 2, -tile_size.y / 2, tile_size.y, tile_size.y)); e->local_collider = collider_from_quad(collider_quad); #else - V2i32 tile_index = sim_world_tile_index_from_pos(world_pos); + V2I32 tile_index = sim_world_tile_index_from_pos(world_pos); sim_snapshot_set_tile(world, tile_index, SIM_TILE_KIND_WALL); #endif } @@ -467,8 +467,8 @@ internal void test_generate_walls(Snapshot *world) } struct wall_node { - V2i32 start; - V2i32 end; + V2I32 start; + V2I32 end; i32 wall_dir; /* = 0 up, 1 = right, 2 = down, 3 = left */ struct wall_node *next; }; @@ -483,9 +483,9 @@ internal void test_generate_walls(Snapshot *world) /* Generate horizontal wall nodes */ for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) { Ent *chunk = x_sorted_tile_chunks[sorted_index]; - V2i32 chunk_index = chunk->tile_chunk_index; - Ent *top_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x, chunk_index.y - 1)); - Ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x, chunk_index.y + 1)); + V2I32 chunk_index = chunk->tile_chunk_index; + Ent *top_chunk = sim_tile_chunk_from_chunk_index(world, V2I32FromXY(chunk_index.x, chunk_index.y - 1)); + Ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, V2I32FromXY(chunk_index.x, chunk_index.y + 1)); /* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */ i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid; i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1; @@ -497,17 +497,17 @@ internal void test_generate_walls(Snapshot *world) i32 desired_wall_dir = -1; TileKind tile = SIM_TILE_KIND_NONE; if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) { - tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x, tile_y)); + tile = sim_get_chunk_tile(chunk, V2I32FromXY(tile_x, tile_y)); } if (tile_x < SIM_TILES_PER_CHUNK_SQRT) { TileKind top_tile = SIM_TILE_KIND_NONE; if (tile_y == 0) { if (top_chunk->valid) { - V2i32 top_tile_local_index = V2i32FromXY(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1); + V2I32 top_tile_local_index = V2I32FromXY(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1); top_tile = sim_get_chunk_tile(top_chunk, top_tile_local_index); } } else { - top_tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x, tile_y - 1)); + top_tile = sim_get_chunk_tile(chunk, V2I32FromXY(tile_x, tile_y - 1)); } if (tile == SIM_TILE_KIND_WALL) { /* Process wall tile */ @@ -524,8 +524,8 @@ internal void test_generate_walls(Snapshot *world) /* Stop wall */ if (wall_dir >= 0 && desired_wall_dir != wall_dir) { - V2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2i32FromXY(wall_start, tile_y)); - V2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2i32FromXY(wall_end, tile_y)); + V2I32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32FromXY(wall_start, tile_y)); + V2I32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32FromXY(wall_end, tile_y)); struct wall_node *node = 0; if (wall_start == 0) { u64 start_hash = rand_u64_from_seed(*(u64 *)&start); @@ -572,9 +572,9 @@ internal void test_generate_walls(Snapshot *world) /* Generate vertical wall nodes */ for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) { Ent *chunk = y_sorted_tile_chunks[sorted_index]; - V2i32 chunk_index = chunk->tile_chunk_index; - Ent *left_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x - 1, chunk_index.y)); - Ent *right_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x + 1, chunk_index.y)); + V2I32 chunk_index = chunk->tile_chunk_index; + Ent *left_chunk = sim_tile_chunk_from_chunk_index(world, V2I32FromXY(chunk_index.x - 1, chunk_index.y)); + Ent *right_chunk = sim_tile_chunk_from_chunk_index(world, V2I32FromXY(chunk_index.x + 1, chunk_index.y)); /* If there's no chunk to the right of this one, then do an extra iteration (since walls are created on the left of each tile) */ i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + 1; i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + !right_chunk->valid; @@ -586,18 +586,18 @@ internal void test_generate_walls(Snapshot *world) i32 desired_wall_dir = -1; TileKind tile = SIM_TILE_KIND_NONE; if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) { - tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x, tile_y)); + tile = sim_get_chunk_tile(chunk, V2I32FromXY(tile_x, tile_y)); } if (tile_y < SIM_TILES_PER_CHUNK_SQRT) { TileKind left_tile = SIM_TILE_KIND_NONE; if (tile_x == 0) { if (left_chunk->valid) { - V2i32 left_tile_local_index = V2i32FromXY(SIM_TILES_PER_CHUNK_SQRT - 1, tile_y); + V2I32 left_tile_local_index = V2I32FromXY(SIM_TILES_PER_CHUNK_SQRT - 1, tile_y); left_tile = sim_get_chunk_tile(left_chunk, left_tile_local_index); } } else { - left_tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x - 1, tile_y)); + left_tile = sim_get_chunk_tile(chunk, V2I32FromXY(tile_x - 1, tile_y)); } if (tile == SIM_TILE_KIND_WALL) { /* Process wall tile */ @@ -614,8 +614,8 @@ internal void test_generate_walls(Snapshot *world) /* Stop wall */ if (wall_dir >= 0 && desired_wall_dir != wall_dir) { - V2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2i32FromXY(tile_x, wall_start)); - V2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2i32FromXY(tile_x, wall_end)); + V2I32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32FromXY(tile_x, wall_start)); + V2I32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32FromXY(tile_x, wall_end)); struct wall_node *node = 0; if (wall_start == 0) { u64 start_hash = rand_u64_from_seed(*(u64 *)&start); @@ -748,7 +748,7 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) /* Create test blood */ /* TODO: Remove this */ { - Xform xf = XFORM_TRS(.t = point, .r = rand_f64_from_state(&step_ctx->rand, 0, TAU)); + Xform xf = XFORM_TRS(.t = point, .r = rand_f64_from_state(&step_ctx->rand, 0, Tau)); Ent *decal = sim_ent_alloc_sync_src(root); decal->sprite = sprite_tag_from_path(LIT("sprite/blood.ase")); decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f); @@ -1209,7 +1209,7 @@ void sim_step(SimStepCtx *ctx) V2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT); V2 dir = v2_mul_v2(sprite_size, slice.dir); - f32 rot = v2_angle(dir) + PI / 2; + f32 rot = v2_angle(dir) + Pi / 2; Xform xf = XFORM_IDENT; xf = xform_rotated(xf, -rot); @@ -1284,7 +1284,7 @@ void sim_step(SimStepCtx *ctx) Xform xf = sim_ent_get_local_xform(ent); xf.og = attach_pos; - xf = xform_basis_with_rotation_world(xf, v2_angle(attach_dir) + PI / 2); + xf = xform_basis_with_rotation_world(xf, v2_angle(attach_dir) + Pi / 2); sim_ent_set_local_xform(ent, xf); } @@ -1590,7 +1590,7 @@ void sim_step(SimStepCtx *ctx) f32 final_hold_angle_btw_ent_and_focus = v2_angle_from_dirs(hold_ent_dir, hold_dir); f32 final_focus_angle_btw_ent_and_hold = math_asin((math_sin(final_hold_angle_btw_ent_and_focus) * hold_ent_len) / focus_ent_len); - f32 final_ent_angle_btw_focus_and_hold = PI - (final_focus_angle_btw_ent_and_hold + final_hold_angle_btw_ent_and_focus); + f32 final_ent_angle_btw_focus_and_hold = Pi - (final_focus_angle_btw_ent_and_hold + final_hold_angle_btw_ent_and_focus); new_angle = math_unwind_angle(v2_angle_from_dirs(V2FromXY(0, -1), v2_sub(focus_pos, ent_pos)) + final_ent_angle_btw_focus_and_hold - forward_hold_angle_offset); } @@ -1776,7 +1776,7 @@ void sim_step(SimStepCtx *ctx) } #endif - Xform xf = XFORM_TRS(.t = pos, .r = v2_angle(vel) + PI / 2); + Xform xf = XFORM_TRS(.t = pos, .r = v2_angle(vel) + Pi / 2); sim_ent_set_xform(ent, xf); sim_ent_enable_prop(ent, SEPROP_KINEMATIC); diff --git a/src/sprite/sprite_core.c b/src/sprite/sprite_core.c index 7743d4a5..309daf7f 100644 --- a/src/sprite/sprite_core.c +++ b/src/sprite/sprite_core.c @@ -206,7 +206,7 @@ S_StartupReceipt sprite_startup(void) u32 width = 64; u32 height = 64; u32 *pixels = generate_purple_black_image(scratch.arena, width, height); - G.nil_texture->gp_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2i32FromXY(width, height), pixels); + G.nil_texture->gp_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32FromXY(width, height), pixels); EndScratch(scratch); } @@ -353,7 +353,7 @@ internal void cache_entry_load_texture(struct cache_ref ref, S_Tag tag) e->texture->height = decoded.height; e->texture->valid = 1; e->texture->loaded = 1; - e->texture->gp_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB, 0, V2i32FromXY(decoded.width, decoded.height), decoded.pixels); + e->texture->gp_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB, 0, V2I32FromXY(decoded.width, decoded.height), decoded.pixels); /* TODO: Query gpu for more accurate texture size in VRAM */ memory_size += (decoded.width * decoded.height) * sizeof(*decoded.pixels); success = 1; @@ -530,8 +530,8 @@ internal S_Sheet init_sheet_from_ase_result(Arena *arena, Ase_DecodedSheet ase) f32 height = y2 - y1; /* Rect */ - Rect rect_px = RECT(x1_px, y1_px, width_px, height_px); - Rect rect = RECT(x1, y1, width, height); + Rect rect_px = RectFromScalar(x1_px, y1_px, width_px, height_px); + Rect rect = RectFromScalar(x1, y1, width, height); /* Center */ V2 center_px = V2FromXY(x1_px + (width_px * 0.5f), y1_px + (height_px * 0.5f)); V2 center = V2FromXY(x1 + (width * 0.5f), y1 + (height * 0.5f)); @@ -992,7 +992,7 @@ internal void *data_from_tag_internal(S_Scope *scope, S_Tag tag, enum cache_entr /* Spinlock until result is ready */ if (await && state != CACHE_ENTRY_STATE_LOADED) { while (Atomic32Fetch(&ref.e->state) != CACHE_ENTRY_STATE_LOADED) { - ix_pause(); + IxPause(); } } @@ -1047,7 +1047,7 @@ S_SheetFrame sprite_sheet_get_frame(S_Sheet *sheet, u32 index) S_SheetFrame res = ZI; res.index = 0; res.duration = 0.1; - res.clip = CLIP_ALL; + res.clip = ClipAll; return res; } diff --git a/src/user/user_core.c b/src/user/user_core.c index 732844a1..577a1fbb 100644 --- a/src/user/user_core.c +++ b/src/user/user_core.c @@ -229,7 +229,7 @@ struct user_startup_receipt user_startup(F_StartupReceipt *font_sr, P_RegisterLogCallback(debug_console_log_callback, P_LogLevel_Debug); G.window = P_AllocWindow(); - G.swapchain = gp_swapchain_alloc(G.window, V2i32FromXY(100, 100)); + G.swapchain = gp_swapchain_alloc(G.window, V2I32FromXY(100, 100)); P_ShowWindow(G.window); /* Start jobs */ @@ -270,7 +270,7 @@ internal void debug_draw_xform(Xform xf, u32 color_x, u32 color_y) draw_arrow_ray(G.render_sig, pos, y_ray, thickness, arrowhead_len, color_y); //u32 color_quad = Rgba32F(0, 1, 1, 0.3); - //Quad quad = quad_from_rect(RECT(0, 0, 1, -1)); + //Quad quad = quad_from_rect(RectFromScalar(0, 0, 1, -1)); //quad = xform_mul_quad(xf, quad_scale(quad, 0.075f)); //draw_quad(G.render_sig, quad, color); } @@ -846,8 +846,8 @@ internal void user_update(P_Window *window) if (shake > 0) { u64 angle_seed0 = ent->id.uid.lo + (u64)(G.ss_blended->sim_time_ns / frequency_ns); u64 angle_seed1 = angle_seed0 + 1; - f32 angle0 = rand_f64_from_seed(angle_seed0, 0, TAU); - f32 angle1 = rand_f64_from_seed(angle_seed1, 0, TAU); + f32 angle0 = rand_f64_from_seed(angle_seed0, 0, Tau); + f32 angle1 = rand_f64_from_seed(angle_seed1, 0, Tau); V2 vec0 = v2_with_len(v2_from_angle(angle0), shake); /* NOTE: vec1 not completely accurate since shake can change between frames, it's just a prediction */ @@ -1031,7 +1031,7 @@ internal void user_update(P_Window *window) V2 size = xform_basis_invert_mul_v2(G.world_to_render_xf, G.render_size); u32 color0 = Rgba32F(0.17f, 0.17f, 0.17f, 1.f); u32 color1 = Rgba32F(0.15f, 0.15f, 0.15f, 1.f); - draw_grid(G.render_sig, xform_from_rect(RECT_FROM_V2(pos, size)), color0, color1, Rgba32(0x3f, 0x3f, 0x3f, 0xFF), ColorRed, ColorGreen, thickness, spacing, offset); + draw_grid(G.render_sig, xform_from_rect(RectFromV2(pos, size)), color0, color1, Rgba32(0x3f, 0x3f, 0x3f, 0xFF), ColorRed, ColorGreen, thickness, spacing, offset); } #if 0 @@ -1070,7 +1070,7 @@ internal void user_update(P_Window *window) for (u64 entry_index = 0; entry_index < G.tile_cache.num_reserved_entries; ++entry_index) { struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index]; if (entry->valid) { - V2i32 chunk_pos = entry->pos; + V2I32 chunk_pos = entry->pos; Ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos); if (entry->applied_dirty_gen != chunk_ent->dirty_gen) { entry->applied_dirty_gen = chunk_ent->dirty_gen; @@ -1094,7 +1094,7 @@ internal void user_update(P_Window *window) for (u64 entry_index = 0; entry_index < G.tile_cache.num_reserved_entries; ++entry_index) { struct tile_cache_entry *entry = &G.tile_cache.entries[entry_index]; if (entry->valid) { - V2i32 chunk_pos = entry->pos; + V2I32 chunk_pos = entry->pos; Ent *chunk_ent = sim_ent_from_chunk_pos(chunk_pos); if (entry->applied_dirty_gen != chunk_ent->dirty_gen) { entry->applied_dirty_gen = chunk_ent->dirty_gen; @@ -1104,14 +1104,14 @@ internal void user_update(P_Window *window) * [L ] X [R ] * [BL] [B] [BR] */ - V2i32 chunk_pos_tl = V2i32FromXY(chunk_pos.x - 1, chunk_pos.y - 1); - V2i32 chunk_pos_t = V2i32FromXY(chunk_pos.x, chunk_pos.y - 1); - V2i32 chunk_pos_tr = V2i32FromXY(chunk_pos.x + 1, chunk_pos.y - 1); - V2i32 chunk_pos_l = V2i32FromXY(chunk_pos.x - 1, chunk_pos.y); - V2i32 chunk_pos_r = V2i32FromXY(chunk_pos.x + 1, chunk_pos.y); - V2i32 chunk_pos_bl = V2i32FromXY(chunk_pos.x - 1, chunk_pos.y + 1); - V2i32 chunk_pos_b = V2i32FromXY(chunk_pos.x, chunk_pos.y + 1); - V2i32 chunk_pos_br = V2i32FromXY(chunk_pos.x + 1, chunk_pos.y + 1); + V2I32 chunk_pos_tl = V2I32FromXY(chunk_pos.x - 1, chunk_pos.y - 1); + V2I32 chunk_pos_t = V2I32FromXY(chunk_pos.x, chunk_pos.y - 1); + V2I32 chunk_pos_tr = V2I32FromXY(chunk_pos.x + 1, chunk_pos.y - 1); + V2I32 chunk_pos_l = V2I32FromXY(chunk_pos.x - 1, chunk_pos.y); + V2I32 chunk_pos_r = V2I32FromXY(chunk_pos.x + 1, chunk_pos.y); + V2I32 chunk_pos_bl = V2I32FromXY(chunk_pos.x - 1, chunk_pos.y + 1); + V2I32 chunk_pos_b = V2I32FromXY(chunk_pos.x, chunk_pos.y + 1); + V2I32 chunk_pos_br = V2I32FromXY(chunk_pos.x + 1, chunk_pos.y + 1); Ent *chunk_ent_tl = sim_ent_from_chunk_pos(chunk_pos_tl); Ent *chunk_ent_t = sim_ent_from_chunk_pos(chunk_pos_t); Ent *chunk_ent_tr = sim_ent_from_chunk_pos(chunk_pos_tr); @@ -1240,20 +1240,20 @@ internal void user_update(P_Window *window) /* Draw tiles */ /* TODO: Something better */ if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) { - V2i32 chunk_index = ent->tile_chunk_index; + V2I32 chunk_index = ent->tile_chunk_index; S_Tag tile_sprite = sprite_tag_from_path(LIT("sprite/tile.ase")); S_Texture *tile_texture = sprite_texture_from_tag_async(sprite_frame_scope, tile_sprite); if (tile_texture->loaded) { f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT; for (i32 tile_y = 0; tile_y < SIM_TILES_PER_CHUNK_SQRT; ++tile_y) { for (i32 tile_x = 0; tile_x < SIM_TILES_PER_CHUNK_SQRT; ++tile_x) { - V2i32 local_tile_index = V2i32FromXY(tile_x, tile_y); + V2I32 local_tile_index = V2I32FromXY(tile_x, tile_y); TileKind tile = ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)]; //if (tile > -1) { if (tile == SIM_TILE_KIND_WALL) { - V2i32 world_tile_index = sim_world_tile_index_from_local_tile_index(chunk_index, local_tile_index); + V2I32 world_tile_index = sim_world_tile_index_from_local_tile_index(chunk_index, local_tile_index); V2 pos = sim_pos_from_world_tile_index(world_tile_index); - Xform tile_xf = xform_from_rect(RECT_FROM_V2(pos, V2FromXY(tile_size, tile_size))); + Xform tile_xf = xform_from_rect(RectFromV2(pos, V2FromXY(tile_size, tile_size))); D_MaterialParams params = DRAW_MATERIAL_PARAMS(.xf = tile_xf, .texture = tile_texture->gp_texture, .is_light = 1, .light_emittance = V3FromXYZ(0, 0, 0)); draw_material(G.render_sig, params); } @@ -1678,7 +1678,7 @@ internal void user_update(P_Window *window) f32 thickness = 3; Xform quad_xf = xform_mul(xf, ent->camera_quad_xform); - Quad quad = xform_mul_quad(quad_xf, QUAD_UNIT_SQUARE_CENTERED); + Quad quad = xform_mul_quad(quad_xf, QuadUnitSquareCentered); quad = xform_mul_quad(G.world_to_ui_xf, quad); draw_quad_line(G.render_sig, quad, thickness, color); @@ -1710,7 +1710,7 @@ internal void user_update(P_Window *window) } else { S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, sprite_tag_from_path(LIT("sprite/crosshair.ase"))); V2 size = V2FromXY(t->width, t->height); - Rect cursor_clip = RECT_FROM_V2(G.ui_screen_offset, G.ui_size); + Rect cursor_clip = RectFromV2(G.ui_screen_offset, G.ui_size); cursor_clip.pos = v2_add(cursor_clip.pos, v2_mul(size, 0.5f)); cursor_clip.pos = v2_add(cursor_clip.pos, V2FromXY(1, 1)); cursor_clip.size = v2_sub(cursor_clip.size, size); @@ -1975,15 +1975,15 @@ internal void user_update(P_Window *window) text.len += string_format(temp.arena, LIT("cursor world: %F, %F"), FMT_FLOAT(world_cursor.x), FMT_FLOAT(world_cursor.y)).len; text.len += string_copy(temp.arena, LIT("\n")).len; - V2i32 world_tile_cursor = sim_world_tile_index_from_pos(world_cursor); + V2I32 world_tile_cursor = sim_world_tile_index_from_pos(world_cursor); text.len += string_format(temp.arena, LIT("cursor world tile: %F, %F"), FMT_SINT(world_tile_cursor.x), FMT_SINT(world_tile_cursor.y)).len; text.len += string_copy(temp.arena, LIT("\n")).len; - V2i32 local_tile_cursor = sim_local_tile_index_from_world_tile_index(world_tile_cursor); + V2I32 local_tile_cursor = sim_local_tile_index_from_world_tile_index(world_tile_cursor); text.len += string_format(temp.arena, LIT("cursor local tile: %F, %F"), FMT_SINT(local_tile_cursor.x), FMT_SINT(local_tile_cursor.y)).len; text.len += string_copy(temp.arena, LIT("\n")).len; - V2i32 tile_chunk_cursor = sim_tile_chunk_index_from_world_tile_index(world_tile_cursor); + V2I32 tile_chunk_cursor = sim_tile_chunk_index_from_world_tile_index(world_tile_cursor); text.len += string_format(temp.arena, LIT("cursor tile chunk: %F, %F"), FMT_SINT(tile_chunk_cursor.x), FMT_SINT(tile_chunk_cursor.y)).len; text.len += string_copy(temp.arena, LIT("\n")).len; text.len += string_copy(temp.arena, LIT("\n")).len; @@ -2052,9 +2052,9 @@ internal void user_update(P_Window *window) { __profn("Render"); - V2i32 world_resolution = v2_round_to_int(G.render_size); - V2i32 user_resolution = v2_round_to_int(G.ui_size); - V2i32 backbuffer_resolution = v2_round_to_int(G.screen_size); + V2I32 world_resolution = v2_round_to_int(G.render_size); + V2I32 user_resolution = v2_round_to_int(G.ui_size); + V2I32 backbuffer_resolution = v2_round_to_int(G.screen_size); /* Draw world to user texture */ G_Resource *render_texture = 0;