From e1eb6203c45557b8c4f623b2401445ba90fce87a Mon Sep 17 00:00:00 2001 From: doylet Date: Sat, 28 Jun 2025 20:53:35 +1000 Subject: [PATCH] Fix single header build --- Single_Header/dn_single_header.cpp | 10357 +++------------------------ Single_Header/dn_single_header.h | 2788 ++----- Source/.gitignore | 6 + Source/Base/dn_base_containers.h | 2 + Source/_clang-format | 458 ++ build.bat | 11 +- single_header_generator.cpp | 5 +- 7 files changed, 2028 insertions(+), 11599 deletions(-) create mode 100644 Source/.gitignore create mode 100644 Source/_clang-format diff --git a/Single_Header/dn_single_header.cpp b/Single_Header/dn_single_header.cpp index 1dd7b34..91ca177 100644 --- a/Single_Header/dn_single_header.cpp +++ b/Single_Header/dn_single_header.cpp @@ -1,4 +1,4 @@ -// Generated by the DN single header generator 2025-06-27 16:54:49 +// Generated by the DN single header generator 2025-06-28 20:52:01 #define DN_BASE_INC_CPP @@ -12974,9513 +12974,1292 @@ DN_API DN_F32 DN_Lerp_F32(DN_F32 a, DN_F32 t, DN_F32 b) DN_F32 result = a + ((b - a) * t); return result; } -#define DN_MATH_CPP +#define DN_ASYNC_CPP -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_V2I32 -DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator!=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2I32 operator+(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator-=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2I32 &operator+=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2I32 DN_V2I32_Min(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Max(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -// NOTE: DN_V2U16 -DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2U16 operator-(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2U16 operator+(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator-=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -// NOTE: DN_V2 -DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator-(DN_V2F32 lhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} +// DN: Single header generator commented out this header => #include "../dn_base_inc.h" +// DN: Single header generator commented out this header => #include "../dn_os_inc.h" +// DN: Single header generator commented out this header => #include "dn_async.h" +#if !defined(DN_ASYNC_H) +#define DN_ASYNC_H -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 DN_V2F32_Min(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Max(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Abs(DN_V2F32 a) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -DN_API DN_F32 DN_V2F32_Dot(DN_V2F32 a, DN_V2F32 b) -{ - // NOTE: Scalar projection of B onto A ///////////////////////////////////////////////////////// - // - // Scalar projection calculates the signed distance between `b` and `a` - // where `a` is a unit vector then, the dot product calculates the projection - // of `b` onto the infinite line that the direction of `a` represents. This - // calculation is the signed distance. - // - // signed_distance = dot_product(a, b) = (a.x * b.x) + (a.y * b.y) - // - // Y - // ^ b - // | /| - // | / | - // | / | - // | / | Projection - // | / | - // |/ V - // +--->--------> X - // . a . - // . . - // |------| <- Calculated signed distance - // - // The signed-ness of the result indicates the relationship: - // - // Distance <0 means `b` is behind `a` - // Distance >0 means `b` is in-front of `a` - // Distance ==0 means `b` is perpendicular to `a` - // - // If `a` is not normalized then the signed-ness of the result still holds - // however result no longer represents the actual distance between the - // 2 objects. One of the vectors must be normalised (e.g. turned into a unit - // vector). - // - // NOTE: DN_V projection ///////////////////////////////////////////////////////////////////// - // - // DN_V projection calculates the exact X,Y coordinates of where `b` meets - // `a` when it was projected. This is calculated by multipying the - // 'scalar projection' result by the unit vector of `a` - // - // vector_projection = a * signed_distance = a * dot_product(a, b) +// DN: Single header generator commented out this header => #include "../dn_base_inc.h" +// DN: Single header generator commented out this header => #include "../dn_os_inc.h" - DN_F32 result = (a.x * b.x) + (a.y * b.y); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - // NOTE: Pythagoras's theorem (a^2 + b^2 = c^2) without the square root - DN_F32 a = rhs.x - lhs.x; - DN_F32 b = rhs.y - lhs.y; - DN_F32 c_squared = DN_Squared(a) + DN_Squared(b); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) +enum DN_ASYNCPriority { - DN_F32 result_squared = DN_V2F32_LengthSq_V2x2(lhs, rhs); - DN_F32 result = DN_SqrtF32(result_squared); - return result; -} + DN_ASYNCPriority_Low, + DN_ASYNCPriority_High, + DN_ASYNCPriority_Count, +}; -DN_API DN_F32 DN_V2F32_LengthSq(DN_V2F32 lhs) +struct DN_ASYNCCore { - // NOTE: Pythagoras's theorem without the square root - DN_F32 c_squared = DN_Squared(lhs.x) + DN_Squared(lhs.y); - DN_F32 result = c_squared; - return result; -} + DN_OSMutex ring_mutex; + DN_OSConditionVariable ring_write_cv; + DN_OSSemaphore worker_sem; + DN_Ring ring; + DN_OSThread *threads; + DN_U32 thread_count; + DN_U32 busy_threads; + DN_U32 join_threads; +}; -DN_API DN_F32 DN_V2F32_Length(DN_V2F32 lhs) -{ - DN_F32 c_squared = DN_V2F32_LengthSq(lhs); - DN_F32 result = DN_SqrtF32(c_squared); - return result; -} +typedef void(DN_ASYNCWorkFunc)(void *input); -DN_API DN_V2F32 DN_V2F32_Normalise(DN_V2F32 a) +struct DN_ASYNCWork { - DN_F32 length = DN_V2F32_Length(a); - DN_V2F32 result = a / length; - return result; -} + DN_ASYNCWorkFunc *func; + void *input; + void *output; +}; -DN_API DN_V2F32 DN_V2F32_Perpendicular(DN_V2F32 a) +struct DN_ASYNCJob { - // NOTE: Matrix form of a 2D vector can be defined as - // - // x' = x cos(t) - y sin(t) - // y' = x sin(t) + y cos(t) - // - // Calculate a line perpendicular to a vector means rotating the vector by - // 90 degrees - // - // x' = x cos(90) - y sin(90) - // y' = x sin(90) + y cos(90) - // - // Where `cos(90) = 0` and `sin(90) = 1` then, - // - // x' = -y - // y' = +x - - DN_V2F32 result = DN_V2F32_Init2N(-a.y, a.x); - return result; -} + DN_ASYNCWork work; + DN_OSSemaphore completion_sem; +}; -DN_API DN_V2F32 DN_V2F32_Reflect(DN_V2F32 in, DN_V2F32 surface) +struct DN_ASYNCTask { - DN_V2F32 normal = DN_V2F32_Perpendicular(surface); - DN_V2F32 normal_norm = DN_V2F32_Normalise(normal); - DN_F32 signed_dist = DN_V2F32_Dot(in, normal_norm); - DN_V2F32 result = DN_V2F32_Init2N(in.x, in.y + (-signed_dist * 2.f)); - return result; -} + DN_ASYNCWork work; +}; -DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) -{ - DN_F32 result = a.w * a.h; - return result; -} -#endif // !defined(DN_NO_V2) +DN_API void DN_ASYNC_Init (DN_ASYNCCore *async, char *base, DN_USize base_size, DN_OSThread *threads, DN_U32 threads_size); +DN_API void DN_ASYNC_Deinit (DN_ASYNCCore *async); +DN_API bool DN_ASYNC_QueueWork(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms); +DN_API DN_OSSemaphore DN_ASYNC_QueueTask(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms); +DN_API void DN_ASYNC_WaitTask (DN_OSSemaphore *sem, DN_U32 timeout_ms); -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z); - return result; -} - -DN_API bool operator>=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z); - return result; -} +#endif // DN_ASYNC_H -DN_API bool operator<=(DN_V3F32 lhs, DN_V3F32 rhs) +static DN_I32 DN_ASYNC_ThreadEntryPoint_(DN_OSThread *thread) { - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z); - return result; -} - -DN_API bool operator<(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z); - return result; -} - -DN_API bool operator>(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(-lhs.x, -lhs.y, -lhs.z); - return result; -} - -DN_API DN_V3F32 operator+(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator-=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V3F32 &operator+=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V3_LengthSq(DN_V3F32 a) -{ - DN_F32 result = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - return result; -} - -DN_API DN_F32 DN_V3_Length(DN_V3F32 a) -{ - DN_F32 length_sq = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - DN_F32 result = DN_SqrtF32(length_sq); - return result; -} - -DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) -{ - DN_F32 length = DN_V3_Length(a); - DN_V3F32 result = a / length; - return result; -} -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.w == rhs.w); - return result; -} - -DN_API bool operator!=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z) && (lhs.w >= rhs.w); - return result; -} - -DN_API bool operator<=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z) && (lhs.w <= rhs.w); - return result; -} - -DN_API bool operator<(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z) && (lhs.w < rhs.w); - return result; -} - -DN_API bool operator>(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z) && (lhs.w > rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(-lhs.x, -lhs.y, -lhs.z, -lhs.w); - return result; -} - -DN_API DN_V4F32 operator+(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, int32_t rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator/(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); - return result; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator-=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V4F32 &operator+=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) -{ - DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); - return result; -} -#endif // !defined(DN_NO_V4) - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_M4 DN_M4_Identity() -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_ScaleF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Scale(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {xyz.x, 0, 0, 0}, - {0, xyz.y, 0, 0}, - {0, 0, xyz.z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_TranslateF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Translate(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {xyz.x, xyz.y, xyz.z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Transpose(DN_M4 mat) -{ - DN_M4 result = {}; - for (int col = 0; col < 4; col++) - for (int row = 0; row < 4; row++) - result.columns[col][row] = mat.columns[row][col]; - return result; -} - -DN_API DN_M4 DN_M4_Rotate(DN_V3F32 axis01, DN_F32 radians) -{ - DN_AssertF(DN_Abs(DN_V3_Length(axis01) - 1.f) <= 0.01f, - "Rotation axis must be normalised, length = %f", - DN_V3_Length(axis01)); - - DN_F32 sin = DN_SinF32(radians); - DN_F32 cos = DN_CosF32(radians); - DN_F32 one_minus_cos = 1.f - cos; - - DN_F32 x = axis01.x; - DN_F32 y = axis01.y; - DN_F32 z = axis01.z; - DN_F32 x2 = DN_Squared(x); - DN_F32 y2 = DN_Squared(y); - DN_F32 z2 = DN_Squared(z); - - DN_M4 result = - { - { - {cos + x2 * one_minus_cos, y * x * one_minus_cos + z * sin, z * x * one_minus_cos - y * sin, 0}, // Col 1 - {x * y * one_minus_cos - z * sin, cos + y2 * one_minus_cos, z * y * one_minus_cos + x * sin, 0}, // Col 2 - {x * z * one_minus_cos + y * sin, y * z * one_minus_cos - x * sin, cos + z2 * one_minus_cos, 0}, // Col 3 - {0, 0, 0, 1}, // Col 4 - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Orthographic(DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far) -{ - // NOTE: Here is the matrix in column major for readability. Below it's - // transposed due to how you have to declare column major matrices in C/C++. - // - // m = [2/r-l, 0, 0, -1*(r+l)/(r-l)] - // [0, 2/t-b, 0, 1*(t+b)/(t-b)] - // [0, 0, -2/f-n, -1*(f+n)/(f-n)] - // [0, 0, 0, 1 ] - - DN_M4 result = - { - { - {2.f / (right - left), 0.f, 0.f, 0.f}, - {0.f, 2.f / (top - bottom), 0.f, 0.f}, - {0.f, 0.f, -2.f / (z_far - z_near), 0.f}, - {(-1.f * (right + left)) / (right - left), (-1.f * (top + bottom)) / (top - bottom), (-1.f * (z_far + z_near)) / (z_far - z_near), 1.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Perspective(DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far) -{ - DN_F32 tan_fov = DN_TanF32(fov / 2.f); - DN_M4 result = - { - { - {1.f / (aspect * tan_fov), 0.f, 0.f, 0.f}, - {0, 1.f / tan_fov, 0.f, 0.f}, - {0.f, 0.f, (z_near + z_far) / (z_near - z_far), -1.f}, - {0.f, 0.f, (2.f * z_near * z_far) / (z_near - z_far), 0.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Add(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Sub(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Mul(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) { - for (int row = 0; row < 4; row++) { - DN_F32 sum = 0; - for (int f32_it = 0; f32_it < 4; f32_it++) - sum += lhs.columns[f32_it][row] * rhs.columns[col][f32_it]; - - result.columns[col][row] = sum; - } - } - return result; -} - -DN_API DN_M4 DN_M4_Div(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_AddF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs; - return result; -} - -DN_API DN_M4 DN_M4_SubF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs; - return result; -} - -DN_API DN_M4 DN_M4_MulF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] * rhs; - return result; -} - -DN_API DN_M4 DN_M4_DivF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs; - return result; -} - - #if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString(DN_M4 mat) -{ - DN_FStr8<256> result = {}; - for (int row = 0; row < 4; row++) { - for (int it = 0; it < 4; it++) { - if (it == 0) - DN_FStr8_Add(&result, DN_STR8("|")); - DN_FStr8_AddF(&result, "%.5f", mat.columns[it][row]); - if (it != 3) - DN_FStr8_Add(&result, DN_STR8(", ")); - else - DN_FStr8_Add(&result, DN_STR8("|\n")); - } - } - - return result; -} - #endif -#endif // !defined(DN_M4) - -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) -{ - bool result = DN_Memcmp(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ArrayCountU(lhs.e)) == 0; - return result; -} - -DN_API bool operator!=(DN_M2x3 const &lhs, DN_M2x3 const &rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API DN_M2x3 DN_M2x3_Identity() -{ - DN_M2x3 result = { - { - 1, - 0, - 0, - 0, - 1, - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset) -{ - DN_M2x3 result = { - { - 1, - 0, - offset.x, - 0, - 1, - offset.y, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) -{ - DN_M2x3 result = { - { - scale.x, - 0, - 0, - 0, - scale.y, - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Rotate(DN_F32 radians) -{ - DN_M2x3 result = { - { - DN_CosF32(radians), - DN_SinF32(radians), - 0, - -DN_SinF32(radians), - DN_CosF32(radians), - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Mul(DN_M2x3 m1, DN_M2x3 m2) -{ - // NOTE: Ordinarily you can't multiply M2x3 with M2x3 because column count - // (3) != row count (2). We pretend we have two 3x3 matrices with the last - // row set to [0 0 1] and perform a 3x3 matrix multiply. - // - // | (0)a (1)b (2)c | | (0)g (1)h (2)i | - // | (3)d (4)e (5)f | x | (3)j (4)k (5)l | - // | (6)0 (7)0 (8)1 | | (6)0 (7)0 (8)1 | - - DN_M2x3 result = { - { - m1.e[0] * m2.e[0] + m1.e[1] * m2.e[3], // a*g + b*j + c*0[omitted], - m1.e[0] * m2.e[1] + m1.e[1] * m2.e[4], // a*h + b*k + c*0[omitted], - m1.e[0] * m2.e[2] + m1.e[1] * m2.e[5] + m1.e[2], // a*i + b*l + c*1, + DN_OS_ThreadSetName(DN_FStr8_ToStr8(&thread->name)); + DN_ASYNCCore *async = DN_CAST(DN_ASYNCCore *) thread->user_context; + DN_Ring *ring = &async->ring; + for (;;) { + DN_OS_SemaphoreWait(&async->worker_sem, UINT32_MAX); + if (async->join_threads) + break; - m1.e[3] * m2.e[0] + m1.e[4] * m2.e[3], // d*g + e*j + f*0[omitted], - m1.e[3] * m2.e[1] + m1.e[4] * m2.e[4], // d*h + e*k + f*0[omitted], - m1.e[3] * m2.e[2] + m1.e[4] * m2.e[5] + m1.e[5], // d*i + e*l + f*1, + DN_ASYNCJob job = {}; + for (DN_OS_MutexScope(&async->ring_mutex)) { + if (DN_Ring_HasData(ring, sizeof(job))) { + DN_Ring_Read(ring, &job, sizeof(job)); + break; } - }; + } - return result; + if (job.work.func) { + DN_OS_ConditionVariableBroadcast(&async->ring_write_cv); // Resume any blocked ring write(s) + + DN_Atomic_AddU32(&async->busy_threads, 1); + job.work.func(job.work.input); + DN_Atomic_SubU32(&async->busy_threads, 1); + + if (job.completion_sem.handle != 0) + DN_OS_SemaphoreIncrement(&job.completion_sem, 1); + } + } + + return 0; } -DN_API DN_V2F32 DN_M2x3_Mul2F32(DN_M2x3 m1, DN_F32 x, DN_F32 y) +DN_API void DN_ASYNC_Init(DN_ASYNCCore *async, char *base, DN_USize base_size, DN_OSThread *threads, DN_U32 threads_size) { - // NOTE: Ordinarily you can't multiply M2x3 with V2 because column count (3) - // != row count (2). We pretend we have a V3 with `z` set to `1`. - // - // | (0)a (1)b (2)c | | x | - // | (3)d (4)e (5)f | x | y | - // | 1 | + DN_Assert(async); + async->ring.size = base_size; + async->ring.base = base; + async->ring_mutex = DN_OS_MutexInit(); + async->ring_write_cv = DN_OS_ConditionVariableInit(); + async->worker_sem = DN_OS_SemaphoreInit(0); + async->thread_count = threads_size; + async->threads = threads; + for (DN_ForIndexU(index, async->thread_count)) { + DN_OSThread *thread = async->threads + index; + thread->name = DN_FStr8_InitF<64>("ASYNC W%zu", index); + DN_OS_ThreadInit(thread, DN_ASYNC_ThreadEntryPoint_, async); + } +} - DN_V2F32 result = { - { - m1.e[0] * x + m1.e[1] * y + m1.e[2], // a*x + b*y + c*1 - m1.e[3] * x + m1.e[4] * y + m1.e[5], // d*x + e*y + f*1 +DN_API void DN_ASYNC_Deinit(DN_ASYNCCore *async) +{ + DN_Assert(async); + DN_Atomic_SetValue32(&async->join_threads, true); + DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count); + for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count)) + DN_OS_ThreadDeinit(it.data); +} + + +static bool DN_ASYNC_QueueJob_(DN_ASYNCCore *async, DN_ASYNCJob const *job, DN_U64 wait_time_ms) { + DN_U64 end_time_ms = DN_OS_DateUnixTimeMs() + wait_time_ms; + bool result = false; + for (DN_OS_MutexScope(&async->ring_mutex)) { + for (;;) { + if (DN_Ring_HasSpace(&async->ring, sizeof(*job))) { + DN_Ring_WriteStruct(&async->ring, job); + result = true; + break; } - }; - return result; -} - -DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) -{ - DN_V2F32 result = DN_M2x3_Mul2F32(m1, v2.x, v2.y); - return result; -} - -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(const DN_Rect &lhs, const DN_Rect &rhs) -{ - bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); - return result; -} - -DN_API DN_V2F32 DN_Rect_Center(DN_Rect rect) -{ - DN_V2F32 result = rect.pos + (rect.size * .5f); - return result; -} - -DN_API bool DN_Rect_ContainsPoint(DN_Rect rect, DN_V2F32 p) -{ - DN_V2F32 min = rect.pos; - DN_V2F32 max = rect.pos + rect.size; - bool result = (p.x >= min.x && p.x <= max.x && p.y >= min.y && p.y <= max.y); - return result; -} - -DN_API bool DN_Rect_ContainsRect(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (b_min >= a_min && b_max <= a_max); - return result; -} - -DN_API DN_Rect DN_Rect_Expand(DN_Rect a, DN_F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API DN_Rect DN_Rect_ExpandV2(DN_Rect a, DN_V2F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API bool DN_Rect_Intersects(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (a_min.x <= b_max.x && a_max.x >= b_min.x) && - (a_min.y <= b_max.y && a_max.y >= b_min.y); - return result; -} - -DN_API DN_Rect DN_Rect_Intersection(DN_Rect a, DN_Rect b) -{ - DN_Rect result = DN_Rect_Init2V2(a.pos, DN_V2F32_Init1N(0)); - if (DN_Rect_Intersects(a, b)) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min = {}; - DN_V2F32 max = {}; - min.x = DN_Max(a_min.x, b_min.x); - min.y = DN_Max(a_min.y, b_min.y); - max.x = DN_Min(a_max.x, b_max.x); - max.y = DN_Min(a_max.y, b_max.y); - result = DN_Rect_Init2V2(min, max - min); - } - return result; -} - -DN_API DN_Rect DN_Rect_Union(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min, max; - min.x = DN_Min(a_min.x, b_min.x); - min.y = DN_Min(a_min.y, b_min.y); - max.x = DN_Max(a_max.x, b_max.x); - max.y = DN_Max(a_max.y, b_max.y); - DN_Rect result = DN_Rect_Init2V2(min, max - min); - return result; -} - -DN_API DN_RectMinMax DN_Rect_MinMax(DN_Rect a) -{ - DN_RectMinMax result = {}; - result.min = a.pos; - result.max = a.pos + a.size; - return result; -} - -DN_API DN_F32 DN_Rect_Area(DN_Rect a) -{ - DN_F32 result = a.size.w * a.size.h; - return result; -} - -DN_API DN_Rect DN_Rect_CutLeftClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_max_x = min_x + amount; - if (clip) - result_max_x = DN_Min(result_max_x, max_x); - DN_Rect result = DN_Rect_Init4N(min_x, rect->pos.y, result_max_x - min_x, rect->size.h); - rect->pos.x = result_max_x; - rect->size.w = max_x - result_max_x; - return result; -} - -DN_API DN_Rect DN_Rect_CutRightClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_min_x = max_x - amount; - if (clip) - result_min_x = DN_Max(result_min_x, 0); - DN_Rect result = DN_Rect_Init4N(result_min_x, rect->pos.y, max_x - result_min_x, rect->size.h); - rect->size.w = result_min_x - min_x; - return result; -} - -DN_API DN_Rect DN_Rect_CutTopClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_max_y = min_y + amount; - if (clip) - result_max_y = DN_Min(result_max_y, max_y); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, min_y, rect->size.w, result_max_y - min_y); - rect->pos.y = result_max_y; - rect->size.h = max_y - result_max_y; - return result; -} - -DN_API DN_Rect DN_Rect_CutBottomClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_min_y = max_y - amount; - if (clip) - result_min_y = DN_Max(result_min_y, 0); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, result_min_y, rect->size.w, max_y - result_min_y); - rect->size.h = result_min_y - min_y; - return result; -} - -DN_API DN_Rect DN_RectCut_Cut(DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip) -{ - DN_Rect result = {}; - if (rect_cut.rect) { - switch (rect_cut.side) { - case DN_RectCutSide_Left: result = DN_Rect_CutLeftClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Right: result = DN_Rect_CutRightClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Top: result = DN_Rect_CutTopClip(rect_cut.rect, size.h, clip); break; - case DN_RectCutSide_Bottom: result = DN_Rect_CutBottomClip(rect_cut.rect, size.h, clip); break; - } - } - return result; -} - -DN_API DN_V2F32 DN_Rect_InterpolatedPoint(DN_Rect rect, DN_V2F32 t01) -{ - DN_V2F32 result = DN_V2F32_Init2N(rect.pos.w + (rect.size.w * t01.x), - rect.pos.h + (rect.size.h * t01.y)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 1)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 1)); - return result; -} -#endif // !defined(DN_NO_RECT) - -// NOTE: Raycast /////////////////////////////////////////////////////////////////////////////////// - -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) -{ - // NOTE: Parametric equation of a line - // - // p = o + (t*d) - // - // - o is the starting 2d point - // - d is the direction of the line - // - t is a scalar that scales along the direction of the point - // - // To determine if a ray intersections a ray, we want to solve - // - // (o_a + (t_a * d_a)) = (o_b + (t_b * d_b)) - // - // Where '_a' and '_b' represent the 1st and 2nd point's origin, direction - // and 't' components respectively. This is 2 equations with 2 unknowns - // (`t_a` and `t_b`) which we can solve for by expressing the equation in - // terms of `t_a` and `t_b`. - // - // Working that math out produces the formula below for 't'. - - DN_RaycastLineIntersectV2Result result = {}; - DN_F32 denominator = ((dir_b.y * dir_a.x) - (dir_b.x * dir_a.y)); - if (denominator != 0.0f) { - result.t_a = (((origin_a.y - origin_b.y) * dir_b.x) + ((origin_b.x - origin_a.x) * dir_b.y)) / denominator; - result.t_b = (((origin_a.y - origin_b.y) * dir_a.x) + ((origin_b.x - origin_a.x) * dir_a.y)) / denominator; - result.hit = true; - } - return result; -} - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) -{ - DN_V2F32 result = {}; - result.x = a.x + ((b.x - a.x) * t); - result.y = a.y + ((b.y - a.y) * t); - return result; -} - -DN_API DN_F32 DN_Lerp_F32(DN_F32 a, DN_F32 t, DN_F32 b) -{ - DN_F32 result = a + ((b - a) * t); - return result; -} -#define DN_MATH_CPP - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_V2I32 -DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator!=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2I32 operator+(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator-=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2I32 &operator+=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2I32 DN_V2I32_Min(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Max(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -// NOTE: DN_V2U16 -DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2U16 operator-(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2U16 operator+(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator-=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -// NOTE: DN_V2 -DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator-(DN_V2F32 lhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 DN_V2F32_Min(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Max(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Abs(DN_V2F32 a) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -DN_API DN_F32 DN_V2F32_Dot(DN_V2F32 a, DN_V2F32 b) -{ - // NOTE: Scalar projection of B onto A ///////////////////////////////////////////////////////// - // - // Scalar projection calculates the signed distance between `b` and `a` - // where `a` is a unit vector then, the dot product calculates the projection - // of `b` onto the infinite line that the direction of `a` represents. This - // calculation is the signed distance. - // - // signed_distance = dot_product(a, b) = (a.x * b.x) + (a.y * b.y) - // - // Y - // ^ b - // | /| - // | / | - // | / | - // | / | Projection - // | / | - // |/ V - // +--->--------> X - // . a . - // . . - // |------| <- Calculated signed distance - // - // The signed-ness of the result indicates the relationship: - // - // Distance <0 means `b` is behind `a` - // Distance >0 means `b` is in-front of `a` - // Distance ==0 means `b` is perpendicular to `a` - // - // If `a` is not normalized then the signed-ness of the result still holds - // however result no longer represents the actual distance between the - // 2 objects. One of the vectors must be normalised (e.g. turned into a unit - // vector). - // - // NOTE: DN_V projection ///////////////////////////////////////////////////////////////////// - // - // DN_V projection calculates the exact X,Y coordinates of where `b` meets - // `a` when it was projected. This is calculated by multipying the - // 'scalar projection' result by the unit vector of `a` - // - // vector_projection = a * signed_distance = a * dot_product(a, b) - - DN_F32 result = (a.x * b.x) + (a.y * b.y); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - // NOTE: Pythagoras's theorem (a^2 + b^2 = c^2) without the square root - DN_F32 a = rhs.x - lhs.x; - DN_F32 b = rhs.y - lhs.y; - DN_F32 c_squared = DN_Squared(a) + DN_Squared(b); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_F32 result_squared = DN_V2F32_LengthSq_V2x2(lhs, rhs); - DN_F32 result = DN_SqrtF32(result_squared); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq(DN_V2F32 lhs) -{ - // NOTE: Pythagoras's theorem without the square root - DN_F32 c_squared = DN_Squared(lhs.x) + DN_Squared(lhs.y); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length(DN_V2F32 lhs) -{ - DN_F32 c_squared = DN_V2F32_LengthSq(lhs); - DN_F32 result = DN_SqrtF32(c_squared); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Normalise(DN_V2F32 a) -{ - DN_F32 length = DN_V2F32_Length(a); - DN_V2F32 result = a / length; - return result; -} - -DN_API DN_V2F32 DN_V2F32_Perpendicular(DN_V2F32 a) -{ - // NOTE: Matrix form of a 2D vector can be defined as - // - // x' = x cos(t) - y sin(t) - // y' = x sin(t) + y cos(t) - // - // Calculate a line perpendicular to a vector means rotating the vector by - // 90 degrees - // - // x' = x cos(90) - y sin(90) - // y' = x sin(90) + y cos(90) - // - // Where `cos(90) = 0` and `sin(90) = 1` then, - // - // x' = -y - // y' = +x - - DN_V2F32 result = DN_V2F32_Init2N(-a.y, a.x); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Reflect(DN_V2F32 in, DN_V2F32 surface) -{ - DN_V2F32 normal = DN_V2F32_Perpendicular(surface); - DN_V2F32 normal_norm = DN_V2F32_Normalise(normal); - DN_F32 signed_dist = DN_V2F32_Dot(in, normal_norm); - DN_V2F32 result = DN_V2F32_Init2N(in.x, in.y + (-signed_dist * 2.f)); - return result; -} - -DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) -{ - DN_F32 result = a.w * a.h; - return result; -} -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z); - return result; -} - -DN_API bool operator>=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z); - return result; -} - -DN_API bool operator<=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z); - return result; -} - -DN_API bool operator<(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z); - return result; -} - -DN_API bool operator>(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(-lhs.x, -lhs.y, -lhs.z); - return result; -} - -DN_API DN_V3F32 operator+(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator-=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V3F32 &operator+=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V3_LengthSq(DN_V3F32 a) -{ - DN_F32 result = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - return result; -} - -DN_API DN_F32 DN_V3_Length(DN_V3F32 a) -{ - DN_F32 length_sq = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - DN_F32 result = DN_SqrtF32(length_sq); - return result; -} - -DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) -{ - DN_F32 length = DN_V3_Length(a); - DN_V3F32 result = a / length; - return result; -} -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.w == rhs.w); - return result; -} - -DN_API bool operator!=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z) && (lhs.w >= rhs.w); - return result; -} - -DN_API bool operator<=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z) && (lhs.w <= rhs.w); - return result; -} - -DN_API bool operator<(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z) && (lhs.w < rhs.w); - return result; -} - -DN_API bool operator>(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z) && (lhs.w > rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(-lhs.x, -lhs.y, -lhs.z, -lhs.w); - return result; -} - -DN_API DN_V4F32 operator+(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, int32_t rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator/(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); - return result; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator-=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V4F32 &operator+=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) -{ - DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); - return result; -} -#endif // !defined(DN_NO_V4) - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_M4 DN_M4_Identity() -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_ScaleF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Scale(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {xyz.x, 0, 0, 0}, - {0, xyz.y, 0, 0}, - {0, 0, xyz.z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_TranslateF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Translate(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {xyz.x, xyz.y, xyz.z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Transpose(DN_M4 mat) -{ - DN_M4 result = {}; - for (int col = 0; col < 4; col++) - for (int row = 0; row < 4; row++) - result.columns[col][row] = mat.columns[row][col]; - return result; -} - -DN_API DN_M4 DN_M4_Rotate(DN_V3F32 axis01, DN_F32 radians) -{ - DN_AssertF(DN_Abs(DN_V3_Length(axis01) - 1.f) <= 0.01f, - "Rotation axis must be normalised, length = %f", - DN_V3_Length(axis01)); - - DN_F32 sin = DN_SinF32(radians); - DN_F32 cos = DN_CosF32(radians); - DN_F32 one_minus_cos = 1.f - cos; - - DN_F32 x = axis01.x; - DN_F32 y = axis01.y; - DN_F32 z = axis01.z; - DN_F32 x2 = DN_Squared(x); - DN_F32 y2 = DN_Squared(y); - DN_F32 z2 = DN_Squared(z); - - DN_M4 result = - { - { - {cos + x2 * one_minus_cos, y * x * one_minus_cos + z * sin, z * x * one_minus_cos - y * sin, 0}, // Col 1 - {x * y * one_minus_cos - z * sin, cos + y2 * one_minus_cos, z * y * one_minus_cos + x * sin, 0}, // Col 2 - {x * z * one_minus_cos + y * sin, y * z * one_minus_cos - x * sin, cos + z2 * one_minus_cos, 0}, // Col 3 - {0, 0, 0, 1}, // Col 4 - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Orthographic(DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far) -{ - // NOTE: Here is the matrix in column major for readability. Below it's - // transposed due to how you have to declare column major matrices in C/C++. - // - // m = [2/r-l, 0, 0, -1*(r+l)/(r-l)] - // [0, 2/t-b, 0, 1*(t+b)/(t-b)] - // [0, 0, -2/f-n, -1*(f+n)/(f-n)] - // [0, 0, 0, 1 ] - - DN_M4 result = - { - { - {2.f / (right - left), 0.f, 0.f, 0.f}, - {0.f, 2.f / (top - bottom), 0.f, 0.f}, - {0.f, 0.f, -2.f / (z_far - z_near), 0.f}, - {(-1.f * (right + left)) / (right - left), (-1.f * (top + bottom)) / (top - bottom), (-1.f * (z_far + z_near)) / (z_far - z_near), 1.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Perspective(DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far) -{ - DN_F32 tan_fov = DN_TanF32(fov / 2.f); - DN_M4 result = - { - { - {1.f / (aspect * tan_fov), 0.f, 0.f, 0.f}, - {0, 1.f / tan_fov, 0.f, 0.f}, - {0.f, 0.f, (z_near + z_far) / (z_near - z_far), -1.f}, - {0.f, 0.f, (2.f * z_near * z_far) / (z_near - z_far), 0.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Add(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Sub(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Mul(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) { - for (int row = 0; row < 4; row++) { - DN_F32 sum = 0; - for (int f32_it = 0; f32_it < 4; f32_it++) - sum += lhs.columns[f32_it][row] * rhs.columns[col][f32_it]; - - result.columns[col][row] = sum; - } - } - return result; -} - -DN_API DN_M4 DN_M4_Div(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_AddF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs; - return result; -} - -DN_API DN_M4 DN_M4_SubF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs; - return result; -} - -DN_API DN_M4 DN_M4_MulF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] * rhs; - return result; -} - -DN_API DN_M4 DN_M4_DivF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs; - return result; -} - - #if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString(DN_M4 mat) -{ - DN_FStr8<256> result = {}; - for (int row = 0; row < 4; row++) { - for (int it = 0; it < 4; it++) { - if (it == 0) - DN_FStr8_Add(&result, DN_STR8("|")); - DN_FStr8_AddF(&result, "%.5f", mat.columns[it][row]); - if (it != 3) - DN_FStr8_Add(&result, DN_STR8(", ")); - else - DN_FStr8_Add(&result, DN_STR8("|\n")); + DN_OS_ConditionVariableWaitUntil(&async->ring_write_cv, &async->ring_mutex, end_time_ms); + if (DN_OS_DateUnixTimeMs() >= end_time_ms) + break; } } - return result; -} - #endif -#endif // !defined(DN_M4) + if (result) + DN_OS_SemaphoreIncrement(&async->worker_sem, 1); // Flag that a job is available -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) -{ - bool result = DN_Memcmp(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ArrayCountU(lhs.e)) == 0; return result; } -DN_API bool operator!=(DN_M2x3 const &lhs, DN_M2x3 const &rhs) +DN_API bool DN_ASYNC_QueueWork(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms) { - bool result = !(lhs == rhs); + DN_ASYNCJob job = {}; + job.work.func = func; + job.work.input = input; + bool result = DN_ASYNC_QueueJob_(async, &job, wait_time_ms); return result; } -DN_API DN_M2x3 DN_M2x3_Identity() +DN_API DN_OSSemaphore DN_ASYNC_QueueTask(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms) { - DN_M2x3 result = { - { - 1, - 0, - 0, - 0, - 1, - 0, - } - }; + DN_OSSemaphore result = DN_OS_SemaphoreInit(0); + DN_ASYNCJob job = {}; + job.work.func = func; + job.work.input = input; + job.completion_sem = result; + DN_ASYNC_QueueJob_(async, &job, wait_time_ms); return result; } -DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset) +DN_API void DN_ASYNC_WaitTask(DN_OSSemaphore *sem, DN_U32 timeout_ms) { - DN_M2x3 result = { - { - 1, - 0, - offset.x, - 0, - 1, - offset.y, - } - }; + DN_OS_SemaphoreWait(sem, timeout_ms); + DN_OS_SemaphoreDeinit(sem); +} + +DN_API void DN_BinPack_U64(DN_BinPack *pack, DN_BinPackMode mode, DN_U64 *item) +{ + DN_U64 const VALUE_MASK = 0b0111'1111; + DN_U8 const CONTINUE_BIT = 0b1000'0000; + + if (mode == DN_BinPackMode_Serialise) { + DN_U64 it = *item; + do { + DN_U8 write_value = DN_CAST(DN_U8)(it & VALUE_MASK); + it >>= 7; + if (it) + write_value |= CONTINUE_BIT; + DN_Str8Builder_AppendBytesCopy(&pack->writer, &write_value, sizeof(write_value)); + } while (it); + } else { + *item = 0; + DN_USize bits_read = 0; + for (DN_U8 src = CONTINUE_BIT; (src & CONTINUE_BIT) && bits_read < 64; bits_read += 7) { + src = pack->read.data[pack->read_index++]; + DN_U8 masked_src = src & VALUE_MASK; + *item |= (DN_CAST(DN_U64) masked_src << bits_read); + } + } +} + +DN_API void DN_BinPack_VarInt_(DN_BinPack *pack, DN_BinPackMode mode, void *item, DN_USize size) +{ + DN_U64 value = 0; + DN_AssertF(size <= sizeof(value), + "An item larger than 64 bits (%zu) is trying to be packed as a variable integer which is not supported", + size * 8); + + if (mode == DN_BinPackMode_Serialise) // Read `item` into U64 `value` + DN_Memcpy(&value, item, size); + + DN_BinPack_U64(pack, mode, &value); + + if (mode == DN_BinPackMode_Deserialise) // Write U64 `value` into `item` + DN_Memcpy(item, &value, size); +} + +DN_API void DN_BinPack_U32(DN_BinPack *pack, DN_BinPackMode mode, DN_U32 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_U16(DN_BinPack *pack, DN_BinPackMode mode, DN_U16 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_U8(DN_BinPack *pack, DN_BinPackMode mode, DN_U8 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_I64(DN_BinPack *pack, DN_BinPackMode mode, DN_I64 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_I32(DN_BinPack *pack, DN_BinPackMode mode, DN_I32 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_I16(DN_BinPack *pack, DN_BinPackMode mode, DN_I16 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_I8(DN_BinPack *pack, DN_BinPackMode mode, DN_I8 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_F64(DN_BinPack *pack, DN_BinPackMode mode, DN_F64 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_F32(DN_BinPack *pack, DN_BinPackMode mode, DN_F32 *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +#if defined(DN_MATH_H) +DN_API void DN_BinPack_V2(DN_BinPack *pack, DN_BinPackMode mode, DN_V2F32 *item) +{ + DN_BinPack_F32(pack, mode, &item->x); + DN_BinPack_F32(pack, mode, &item->y); +} + +DN_API void DN_BinPack_V4(DN_BinPack *pack, DN_BinPackMode mode, DN_V4F32 *item) +{ + DN_BinPack_F32(pack, mode, &item->x); + DN_BinPack_F32(pack, mode, &item->y); + DN_BinPack_F32(pack, mode, &item->z); + DN_BinPack_F32(pack, mode, &item->w); +} +#endif + +DN_API void DN_BinPack_Bool(DN_BinPack *pack, DN_BinPackMode mode, bool *item) +{ + DN_BinPack_VarInt_(pack, mode, item, sizeof(*item)); +} + +DN_API void DN_BinPack_Str8(DN_BinPack *pack, DN_Arena *arena, DN_BinPackMode mode, DN_Str8 *string) +{ + DN_BinPack_VarInt_(pack, mode, &string->size, sizeof(string->size)); + if (mode == DN_BinPackMode_Serialise) { + DN_Str8Builder_AppendBytesCopy(&pack->writer, string->data, string->size); + } else { + DN_Str8 src = DN_Str8_Slice(pack->read, pack->read_index, string->size); + *string = DN_Str8_Copy(arena, src); + pack->read_index += src.size; + } +} + +DN_API void DN_BinPack_Str8Pool(DN_BinPack *pack, DN_Pool *pool, DN_BinPackMode mode, DN_Str8 *string) +{ + DN_BinPack_VarInt_(pack, mode, &string->size, sizeof(string->size)); + if (mode == DN_BinPackMode_Serialise) { + DN_Str8Builder_AppendBytesCopy(&pack->writer, string->data, string->size); + } else { + DN_Str8 src = DN_Str8_Slice(pack->read, pack->read_index, string->size); + *string = DN_Pool_AllocStr8Copy(pool, src); + pack->read_index += src.size; + } +} + +template +DN_API void DN_BinPack_FStr8(DN_BinPack *pack, DN_BinPackMode mode, DN_FStr8 *string) +{ + DN_BinPack_VarInt_(pack, mode, &string->size, sizeof(string->size)); + if (mode == DN_BinPackMode_Serialise) { + DN_Str8Builder_AppendBytesCopy(&pack->writer, string->data, string->size); + } else { + DN_Str8 src = DN_Str8_Slice(pack->read, pack->read_index, string->size); + *string = DN_FStr8_InitF("%.*s", DN_STR_FMT(src)); + pack->read_index += src.size; + } +} + +DN_API void DN_BinPack_Bytes(DN_BinPack *pack, DN_Arena *arena, DN_BinPackMode mode, void **ptr, DN_USize *size) +{ + DN_Str8 string = DN_Str8_Init(*ptr, *size); + DN_BinPack_Str8(pack, arena, mode, &string); + *ptr = string.data; + *size = string.size; +} + +DN_API void DN_BinPack_CArray(DN_BinPack *pack, DN_BinPackMode mode, void *ptr, DN_USize size) +{ + DN_BinPack_VarInt_(pack, mode, &size, sizeof(size)); + if (mode == DN_BinPackMode_Serialise) { + DN_Str8Builder_AppendBytesCopy(&pack->writer, ptr, size); + } else { + DN_Str8 src = DN_Str8_Slice(pack->read, pack->read_index, size); + DN_Assert(src.size == size); + DN_Memcpy(ptr, src.data, DN_Min(src.size, size)); + pack->read_index += src.size; + } +} + +DN_API DN_Str8 DN_BinPack_Build(DN_BinPack const *pack, DN_Arena *arena) +{ + DN_Str8 result = DN_Str8Builder_Build(&pack->writer, arena); + return result; +} +// DN: Single header generator commented out this header => #include "dn_csv.h" +#if !defined(DN_CSV_H) +#define DN_CSV_H + +enum DN_CSVSerialise +{ + DN_CSVSerialise_Read, + DN_CSVSerialise_Write, +}; + +struct DN_CSVTokeniser +{ + bool bad; + DN_Str8 string; + char delimiter; + char const *it; + bool end_of_line; +}; + +struct DN_CSVPack +{ + DN_Str8Builder write_builder; + DN_USize write_column; + DN_CSVTokeniser read_tokeniser; +}; + +#endif // !defined(DN_CSV_H) + +static DN_CSVTokeniser DN_CSV_TokeniserInit(DN_Str8 string, char delimiter) +{ + DN_CSVTokeniser result = {}; + result.string = string; + result.delimiter = delimiter; return result; } -DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) +static bool DN_CSV_TokeniserValid(DN_CSVTokeniser *tokeniser) { - DN_M2x3 result = { - { - scale.x, - 0, - 0, - 0, - scale.y, - 0, - } - }; + bool result = tokeniser && !tokeniser->bad; return result; } -DN_API DN_M2x3 DN_M2x3_Rotate(DN_F32 radians) +static bool DN_CSV_TokeniserNextRow(DN_CSVTokeniser *tokeniser) { - DN_M2x3 result = { - { - DN_CosF32(radians), - DN_SinF32(radians), - 0, - -DN_SinF32(radians), - DN_CosF32(radians), - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Mul(DN_M2x3 m1, DN_M2x3 m2) -{ - // NOTE: Ordinarily you can't multiply M2x3 with M2x3 because column count - // (3) != row count (2). We pretend we have two 3x3 matrices with the last - // row set to [0 0 1] and perform a 3x3 matrix multiply. - // - // | (0)a (1)b (2)c | | (0)g (1)h (2)i | - // | (3)d (4)e (5)f | x | (3)j (4)k (5)l | - // | (6)0 (7)0 (8)1 | | (6)0 (7)0 (8)1 | - - DN_M2x3 result = { - { - m1.e[0] * m2.e[0] + m1.e[1] * m2.e[3], // a*g + b*j + c*0[omitted], - m1.e[0] * m2.e[1] + m1.e[1] * m2.e[4], // a*h + b*k + c*0[omitted], - m1.e[0] * m2.e[2] + m1.e[1] * m2.e[5] + m1.e[2], // a*i + b*l + c*1, - - m1.e[3] * m2.e[0] + m1.e[4] * m2.e[3], // d*g + e*j + f*0[omitted], - m1.e[3] * m2.e[1] + m1.e[4] * m2.e[4], // d*h + e*k + f*0[omitted], - m1.e[3] * m2.e[2] + m1.e[4] * m2.e[5] + m1.e[5], // d*i + e*l + f*1, + bool result = false; + if (DN_CSV_TokeniserValid(tokeniser) && DN_Str8_HasData(tokeniser->string)) { + // NOTE: First time querying row iterator is nil, let tokeniser advance + if (tokeniser->it) { + // NOTE: Only advance the tokeniser if we're at the end of the line and + // there's more to tokenise. + char const *end = tokeniser->string.data + tokeniser->string.size; + if (tokeniser->it != end && tokeniser->end_of_line) { + tokeniser->end_of_line = false; + result = true; } - }; - - return result; -} - -DN_API DN_V2F32 DN_M2x3_Mul2F32(DN_M2x3 m1, DN_F32 x, DN_F32 y) -{ - // NOTE: Ordinarily you can't multiply M2x3 with V2 because column count (3) - // != row count (2). We pretend we have a V3 with `z` set to `1`. - // - // | (0)a (1)b (2)c | | x | - // | (3)d (4)e (5)f | x | y | - // | 1 | - - DN_V2F32 result = { - { - m1.e[0] * x + m1.e[1] * y + m1.e[2], // a*x + b*y + c*1 - m1.e[3] * x + m1.e[4] * y + m1.e[5], // d*x + e*y + f*1 - } - }; - return result; -} - -DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) -{ - DN_V2F32 result = DN_M2x3_Mul2F32(m1, v2.x, v2.y); - return result; -} - -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(const DN_Rect &lhs, const DN_Rect &rhs) -{ - bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); - return result; -} - -DN_API DN_V2F32 DN_Rect_Center(DN_Rect rect) -{ - DN_V2F32 result = rect.pos + (rect.size * .5f); - return result; -} - -DN_API bool DN_Rect_ContainsPoint(DN_Rect rect, DN_V2F32 p) -{ - DN_V2F32 min = rect.pos; - DN_V2F32 max = rect.pos + rect.size; - bool result = (p.x >= min.x && p.x <= max.x && p.y >= min.y && p.y <= max.y); - return result; -} - -DN_API bool DN_Rect_ContainsRect(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (b_min >= a_min && b_max <= a_max); - return result; -} - -DN_API DN_Rect DN_Rect_Expand(DN_Rect a, DN_F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API DN_Rect DN_Rect_ExpandV2(DN_Rect a, DN_V2F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API bool DN_Rect_Intersects(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (a_min.x <= b_max.x && a_max.x >= b_min.x) && - (a_min.y <= b_max.y && a_max.y >= b_min.y); - return result; -} - -DN_API DN_Rect DN_Rect_Intersection(DN_Rect a, DN_Rect b) -{ - DN_Rect result = DN_Rect_Init2V2(a.pos, DN_V2F32_Init1N(0)); - if (DN_Rect_Intersects(a, b)) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min = {}; - DN_V2F32 max = {}; - min.x = DN_Max(a_min.x, b_min.x); - min.y = DN_Max(a_min.y, b_min.y); - max.x = DN_Min(a_max.x, b_max.x); - max.y = DN_Min(a_max.y, b_max.y); - result = DN_Rect_Init2V2(min, max - min); - } - return result; -} - -DN_API DN_Rect DN_Rect_Union(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min, max; - min.x = DN_Min(a_min.x, b_min.x); - min.y = DN_Min(a_min.y, b_min.y); - max.x = DN_Max(a_max.x, b_max.x); - max.y = DN_Max(a_max.y, b_max.y); - DN_Rect result = DN_Rect_Init2V2(min, max - min); - return result; -} - -DN_API DN_RectMinMax DN_Rect_MinMax(DN_Rect a) -{ - DN_RectMinMax result = {}; - result.min = a.pos; - result.max = a.pos + a.size; - return result; -} - -DN_API DN_F32 DN_Rect_Area(DN_Rect a) -{ - DN_F32 result = a.size.w * a.size.h; - return result; -} - -DN_API DN_Rect DN_Rect_CutLeftClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_max_x = min_x + amount; - if (clip) - result_max_x = DN_Min(result_max_x, max_x); - DN_Rect result = DN_Rect_Init4N(min_x, rect->pos.y, result_max_x - min_x, rect->size.h); - rect->pos.x = result_max_x; - rect->size.w = max_x - result_max_x; - return result; -} - -DN_API DN_Rect DN_Rect_CutRightClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_min_x = max_x - amount; - if (clip) - result_min_x = DN_Max(result_min_x, 0); - DN_Rect result = DN_Rect_Init4N(result_min_x, rect->pos.y, max_x - result_min_x, rect->size.h); - rect->size.w = result_min_x - min_x; - return result; -} - -DN_API DN_Rect DN_Rect_CutTopClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_max_y = min_y + amount; - if (clip) - result_max_y = DN_Min(result_max_y, max_y); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, min_y, rect->size.w, result_max_y - min_y); - rect->pos.y = result_max_y; - rect->size.h = max_y - result_max_y; - return result; -} - -DN_API DN_Rect DN_Rect_CutBottomClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_min_y = max_y - amount; - if (clip) - result_min_y = DN_Max(result_min_y, 0); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, result_min_y, rect->size.w, max_y - result_min_y); - rect->size.h = result_min_y - min_y; - return result; -} - -DN_API DN_Rect DN_RectCut_Cut(DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip) -{ - DN_Rect result = {}; - if (rect_cut.rect) { - switch (rect_cut.side) { - case DN_RectCutSide_Left: result = DN_Rect_CutLeftClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Right: result = DN_Rect_CutRightClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Top: result = DN_Rect_CutTopClip(rect_cut.rect, size.h, clip); break; - case DN_RectCutSide_Bottom: result = DN_Rect_CutBottomClip(rect_cut.rect, size.h, clip); break; - } - } - return result; -} - -DN_API DN_V2F32 DN_Rect_InterpolatedPoint(DN_Rect rect, DN_V2F32 t01) -{ - DN_V2F32 result = DN_V2F32_Init2N(rect.pos.w + (rect.size.w * t01.x), - rect.pos.h + (rect.size.h * t01.y)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 1)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 1)); - return result; -} -#endif // !defined(DN_NO_RECT) - -// NOTE: Raycast /////////////////////////////////////////////////////////////////////////////////// - -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) -{ - // NOTE: Parametric equation of a line - // - // p = o + (t*d) - // - // - o is the starting 2d point - // - d is the direction of the line - // - t is a scalar that scales along the direction of the point - // - // To determine if a ray intersections a ray, we want to solve - // - // (o_a + (t_a * d_a)) = (o_b + (t_b * d_b)) - // - // Where '_a' and '_b' represent the 1st and 2nd point's origin, direction - // and 't' components respectively. This is 2 equations with 2 unknowns - // (`t_a` and `t_b`) which we can solve for by expressing the equation in - // terms of `t_a` and `t_b`. - // - // Working that math out produces the formula below for 't'. - - DN_RaycastLineIntersectV2Result result = {}; - DN_F32 denominator = ((dir_b.y * dir_a.x) - (dir_b.x * dir_a.y)); - if (denominator != 0.0f) { - result.t_a = (((origin_a.y - origin_b.y) * dir_b.x) + ((origin_b.x - origin_a.x) * dir_b.y)) / denominator; - result.t_b = (((origin_a.y - origin_b.y) * dir_a.x) + ((origin_b.x - origin_a.x) * dir_a.y)) / denominator; - result.hit = true; - } - return result; -} - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) -{ - DN_V2F32 result = {}; - result.x = a.x + ((b.x - a.x) * t); - result.y = a.y + ((b.y - a.y) * t); - return result; -} - -DN_API DN_F32 DN_Lerp_F32(DN_F32 a, DN_F32 t, DN_F32 b) -{ - DN_F32 result = a + ((b - a) * t); - return result; -} -#define DN_MATH_CPP - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_V2I32 -DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator!=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2I32 operator+(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator-=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2I32 &operator+=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2I32 DN_V2I32_Min(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Max(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -// NOTE: DN_V2U16 -DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2U16 operator-(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2U16 operator+(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator-=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -// NOTE: DN_V2 -DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator-(DN_V2F32 lhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 DN_V2F32_Min(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Max(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Abs(DN_V2F32 a) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -DN_API DN_F32 DN_V2F32_Dot(DN_V2F32 a, DN_V2F32 b) -{ - // NOTE: Scalar projection of B onto A ///////////////////////////////////////////////////////// - // - // Scalar projection calculates the signed distance between `b` and `a` - // where `a` is a unit vector then, the dot product calculates the projection - // of `b` onto the infinite line that the direction of `a` represents. This - // calculation is the signed distance. - // - // signed_distance = dot_product(a, b) = (a.x * b.x) + (a.y * b.y) - // - // Y - // ^ b - // | /| - // | / | - // | / | - // | / | Projection - // | / | - // |/ V - // +--->--------> X - // . a . - // . . - // |------| <- Calculated signed distance - // - // The signed-ness of the result indicates the relationship: - // - // Distance <0 means `b` is behind `a` - // Distance >0 means `b` is in-front of `a` - // Distance ==0 means `b` is perpendicular to `a` - // - // If `a` is not normalized then the signed-ness of the result still holds - // however result no longer represents the actual distance between the - // 2 objects. One of the vectors must be normalised (e.g. turned into a unit - // vector). - // - // NOTE: DN_V projection ///////////////////////////////////////////////////////////////////// - // - // DN_V projection calculates the exact X,Y coordinates of where `b` meets - // `a` when it was projected. This is calculated by multipying the - // 'scalar projection' result by the unit vector of `a` - // - // vector_projection = a * signed_distance = a * dot_product(a, b) - - DN_F32 result = (a.x * b.x) + (a.y * b.y); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - // NOTE: Pythagoras's theorem (a^2 + b^2 = c^2) without the square root - DN_F32 a = rhs.x - lhs.x; - DN_F32 b = rhs.y - lhs.y; - DN_F32 c_squared = DN_Squared(a) + DN_Squared(b); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_F32 result_squared = DN_V2F32_LengthSq_V2x2(lhs, rhs); - DN_F32 result = DN_SqrtF32(result_squared); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq(DN_V2F32 lhs) -{ - // NOTE: Pythagoras's theorem without the square root - DN_F32 c_squared = DN_Squared(lhs.x) + DN_Squared(lhs.y); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length(DN_V2F32 lhs) -{ - DN_F32 c_squared = DN_V2F32_LengthSq(lhs); - DN_F32 result = DN_SqrtF32(c_squared); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Normalise(DN_V2F32 a) -{ - DN_F32 length = DN_V2F32_Length(a); - DN_V2F32 result = a / length; - return result; -} - -DN_API DN_V2F32 DN_V2F32_Perpendicular(DN_V2F32 a) -{ - // NOTE: Matrix form of a 2D vector can be defined as - // - // x' = x cos(t) - y sin(t) - // y' = x sin(t) + y cos(t) - // - // Calculate a line perpendicular to a vector means rotating the vector by - // 90 degrees - // - // x' = x cos(90) - y sin(90) - // y' = x sin(90) + y cos(90) - // - // Where `cos(90) = 0` and `sin(90) = 1` then, - // - // x' = -y - // y' = +x - - DN_V2F32 result = DN_V2F32_Init2N(-a.y, a.x); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Reflect(DN_V2F32 in, DN_V2F32 surface) -{ - DN_V2F32 normal = DN_V2F32_Perpendicular(surface); - DN_V2F32 normal_norm = DN_V2F32_Normalise(normal); - DN_F32 signed_dist = DN_V2F32_Dot(in, normal_norm); - DN_V2F32 result = DN_V2F32_Init2N(in.x, in.y + (-signed_dist * 2.f)); - return result; -} - -DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) -{ - DN_F32 result = a.w * a.h; - return result; -} -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z); - return result; -} - -DN_API bool operator>=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z); - return result; -} - -DN_API bool operator<=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z); - return result; -} - -DN_API bool operator<(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z); - return result; -} - -DN_API bool operator>(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(-lhs.x, -lhs.y, -lhs.z); - return result; -} - -DN_API DN_V3F32 operator+(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator-=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V3F32 &operator+=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V3_LengthSq(DN_V3F32 a) -{ - DN_F32 result = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - return result; -} - -DN_API DN_F32 DN_V3_Length(DN_V3F32 a) -{ - DN_F32 length_sq = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - DN_F32 result = DN_SqrtF32(length_sq); - return result; -} - -DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) -{ - DN_F32 length = DN_V3_Length(a); - DN_V3F32 result = a / length; - return result; -} -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.w == rhs.w); - return result; -} - -DN_API bool operator!=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z) && (lhs.w >= rhs.w); - return result; -} - -DN_API bool operator<=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z) && (lhs.w <= rhs.w); - return result; -} - -DN_API bool operator<(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z) && (lhs.w < rhs.w); - return result; -} - -DN_API bool operator>(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z) && (lhs.w > rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(-lhs.x, -lhs.y, -lhs.z, -lhs.w); - return result; -} - -DN_API DN_V4F32 operator+(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, int32_t rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator/(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); - return result; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator-=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V4F32 &operator+=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) -{ - DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); - return result; -} -#endif // !defined(DN_NO_V4) - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_M4 DN_M4_Identity() -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_ScaleF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Scale(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {xyz.x, 0, 0, 0}, - {0, xyz.y, 0, 0}, - {0, 0, xyz.z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_TranslateF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Translate(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {xyz.x, xyz.y, xyz.z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Transpose(DN_M4 mat) -{ - DN_M4 result = {}; - for (int col = 0; col < 4; col++) - for (int row = 0; row < 4; row++) - result.columns[col][row] = mat.columns[row][col]; - return result; -} - -DN_API DN_M4 DN_M4_Rotate(DN_V3F32 axis01, DN_F32 radians) -{ - DN_AssertF(DN_Abs(DN_V3_Length(axis01) - 1.f) <= 0.01f, - "Rotation axis must be normalised, length = %f", - DN_V3_Length(axis01)); - - DN_F32 sin = DN_SinF32(radians); - DN_F32 cos = DN_CosF32(radians); - DN_F32 one_minus_cos = 1.f - cos; - - DN_F32 x = axis01.x; - DN_F32 y = axis01.y; - DN_F32 z = axis01.z; - DN_F32 x2 = DN_Squared(x); - DN_F32 y2 = DN_Squared(y); - DN_F32 z2 = DN_Squared(z); - - DN_M4 result = - { - { - {cos + x2 * one_minus_cos, y * x * one_minus_cos + z * sin, z * x * one_minus_cos - y * sin, 0}, // Col 1 - {x * y * one_minus_cos - z * sin, cos + y2 * one_minus_cos, z * y * one_minus_cos + x * sin, 0}, // Col 2 - {x * z * one_minus_cos + y * sin, y * z * one_minus_cos - x * sin, cos + z2 * one_minus_cos, 0}, // Col 3 - {0, 0, 0, 1}, // Col 4 - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Orthographic(DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far) -{ - // NOTE: Here is the matrix in column major for readability. Below it's - // transposed due to how you have to declare column major matrices in C/C++. - // - // m = [2/r-l, 0, 0, -1*(r+l)/(r-l)] - // [0, 2/t-b, 0, 1*(t+b)/(t-b)] - // [0, 0, -2/f-n, -1*(f+n)/(f-n)] - // [0, 0, 0, 1 ] - - DN_M4 result = - { - { - {2.f / (right - left), 0.f, 0.f, 0.f}, - {0.f, 2.f / (top - bottom), 0.f, 0.f}, - {0.f, 0.f, -2.f / (z_far - z_near), 0.f}, - {(-1.f * (right + left)) / (right - left), (-1.f * (top + bottom)) / (top - bottom), (-1.f * (z_far + z_near)) / (z_far - z_near), 1.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Perspective(DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far) -{ - DN_F32 tan_fov = DN_TanF32(fov / 2.f); - DN_M4 result = - { - { - {1.f / (aspect * tan_fov), 0.f, 0.f, 0.f}, - {0, 1.f / tan_fov, 0.f, 0.f}, - {0.f, 0.f, (z_near + z_far) / (z_near - z_far), -1.f}, - {0.f, 0.f, (2.f * z_near * z_far) / (z_near - z_far), 0.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Add(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Sub(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Mul(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) { - for (int row = 0; row < 4; row++) { - DN_F32 sum = 0; - for (int f32_it = 0; f32_it < 4; f32_it++) - sum += lhs.columns[f32_it][row] * rhs.columns[col][f32_it]; - - result.columns[col][row] = sum; - } - } - return result; -} - -DN_API DN_M4 DN_M4_Div(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_AddF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs; - return result; -} - -DN_API DN_M4 DN_M4_SubF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs; - return result; -} - -DN_API DN_M4 DN_M4_MulF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] * rhs; - return result; -} - -DN_API DN_M4 DN_M4_DivF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs; - return result; -} - - #if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString(DN_M4 mat) -{ - DN_FStr8<256> result = {}; - for (int row = 0; row < 4; row++) { - for (int it = 0; it < 4; it++) { - if (it == 0) - DN_FStr8_Add(&result, DN_STR8("|")); - DN_FStr8_AddF(&result, "%.5f", mat.columns[it][row]); - if (it != 3) - DN_FStr8_Add(&result, DN_STR8(", ")); - else - DN_FStr8_Add(&result, DN_STR8("|\n")); } } return result; } - #endif -#endif // !defined(DN_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) +static DN_Str8 DN_CSV_TokeniserNextField(DN_CSVTokeniser *tokeniser) { - bool result = DN_Memcmp(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ArrayCountU(lhs.e)) == 0; - return result; -} + DN_Str8 result = {}; + if (!DN_CSV_TokeniserValid(tokeniser)) + return result; -DN_API bool operator!=(DN_M2x3 const &lhs, DN_M2x3 const &rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API DN_M2x3 DN_M2x3_Identity() -{ - DN_M2x3 result = { - { - 1, - 0, - 0, - 0, - 1, - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset) -{ - DN_M2x3 result = { - { - 1, - 0, - offset.x, - 0, - 1, - offset.y, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) -{ - DN_M2x3 result = { - { - scale.x, - 0, - 0, - 0, - scale.y, - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Rotate(DN_F32 radians) -{ - DN_M2x3 result = { - { - DN_CosF32(radians), - DN_SinF32(radians), - 0, - -DN_SinF32(radians), - DN_CosF32(radians), - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Mul(DN_M2x3 m1, DN_M2x3 m2) -{ - // NOTE: Ordinarily you can't multiply M2x3 with M2x3 because column count - // (3) != row count (2). We pretend we have two 3x3 matrices with the last - // row set to [0 0 1] and perform a 3x3 matrix multiply. - // - // | (0)a (1)b (2)c | | (0)g (1)h (2)i | - // | (3)d (4)e (5)f | x | (3)j (4)k (5)l | - // | (6)0 (7)0 (8)1 | | (6)0 (7)0 (8)1 | - - DN_M2x3 result = { - { - m1.e[0] * m2.e[0] + m1.e[1] * m2.e[3], // a*g + b*j + c*0[omitted], - m1.e[0] * m2.e[1] + m1.e[1] * m2.e[4], // a*h + b*k + c*0[omitted], - m1.e[0] * m2.e[2] + m1.e[1] * m2.e[5] + m1.e[2], // a*i + b*l + c*1, - - m1.e[3] * m2.e[0] + m1.e[4] * m2.e[3], // d*g + e*j + f*0[omitted], - m1.e[3] * m2.e[1] + m1.e[4] * m2.e[4], // d*h + e*k + f*0[omitted], - m1.e[3] * m2.e[2] + m1.e[4] * m2.e[5] + m1.e[5], // d*i + e*l + f*1, - } - }; - - return result; -} - -DN_API DN_V2F32 DN_M2x3_Mul2F32(DN_M2x3 m1, DN_F32 x, DN_F32 y) -{ - // NOTE: Ordinarily you can't multiply M2x3 with V2 because column count (3) - // != row count (2). We pretend we have a V3 with `z` set to `1`. - // - // | (0)a (1)b (2)c | | x | - // | (3)d (4)e (5)f | x | y | - // | 1 | - - DN_V2F32 result = { - { - m1.e[0] * x + m1.e[1] * y + m1.e[2], // a*x + b*y + c*1 - m1.e[3] * x + m1.e[4] * y + m1.e[5], // d*x + e*y + f*1 - } - }; - return result; -} - -DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) -{ - DN_V2F32 result = DN_M2x3_Mul2F32(m1, v2.x, v2.y); - return result; -} - -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(const DN_Rect &lhs, const DN_Rect &rhs) -{ - bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); - return result; -} - -DN_API DN_V2F32 DN_Rect_Center(DN_Rect rect) -{ - DN_V2F32 result = rect.pos + (rect.size * .5f); - return result; -} - -DN_API bool DN_Rect_ContainsPoint(DN_Rect rect, DN_V2F32 p) -{ - DN_V2F32 min = rect.pos; - DN_V2F32 max = rect.pos + rect.size; - bool result = (p.x >= min.x && p.x <= max.x && p.y >= min.y && p.y <= max.y); - return result; -} - -DN_API bool DN_Rect_ContainsRect(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (b_min >= a_min && b_max <= a_max); - return result; -} - -DN_API DN_Rect DN_Rect_Expand(DN_Rect a, DN_F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API DN_Rect DN_Rect_ExpandV2(DN_Rect a, DN_V2F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API bool DN_Rect_Intersects(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (a_min.x <= b_max.x && a_max.x >= b_min.x) && - (a_min.y <= b_max.y && a_max.y >= b_min.y); - return result; -} - -DN_API DN_Rect DN_Rect_Intersection(DN_Rect a, DN_Rect b) -{ - DN_Rect result = DN_Rect_Init2V2(a.pos, DN_V2F32_Init1N(0)); - if (DN_Rect_Intersects(a, b)) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min = {}; - DN_V2F32 max = {}; - min.x = DN_Max(a_min.x, b_min.x); - min.y = DN_Max(a_min.y, b_min.y); - max.x = DN_Min(a_max.x, b_max.x); - max.y = DN_Min(a_max.y, b_max.y); - result = DN_Rect_Init2V2(min, max - min); + if (!DN_Str8_HasData(tokeniser->string)) { + tokeniser->bad = true; + return result; } - return result; -} -DN_API DN_Rect DN_Rect_Union(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min, max; - min.x = DN_Min(a_min.x, b_min.x); - min.y = DN_Min(a_min.y, b_min.y); - max.x = DN_Max(a_max.x, b_max.x); - max.y = DN_Max(a_max.y, b_max.y); - DN_Rect result = DN_Rect_Init2V2(min, max - min); - return result; -} - -DN_API DN_RectMinMax DN_Rect_MinMax(DN_Rect a) -{ - DN_RectMinMax result = {}; - result.min = a.pos; - result.max = a.pos + a.size; - return result; -} - -DN_API DN_F32 DN_Rect_Area(DN_Rect a) -{ - DN_F32 result = a.size.w * a.size.h; - return result; -} - -DN_API DN_Rect DN_Rect_CutLeftClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_max_x = min_x + amount; - if (clip) - result_max_x = DN_Min(result_max_x, max_x); - DN_Rect result = DN_Rect_Init4N(min_x, rect->pos.y, result_max_x - min_x, rect->size.h); - rect->pos.x = result_max_x; - rect->size.w = max_x - result_max_x; - return result; -} - -DN_API DN_Rect DN_Rect_CutRightClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_min_x = max_x - amount; - if (clip) - result_min_x = DN_Max(result_min_x, 0); - DN_Rect result = DN_Rect_Init4N(result_min_x, rect->pos.y, max_x - result_min_x, rect->size.h); - rect->size.w = result_min_x - min_x; - return result; -} - -DN_API DN_Rect DN_Rect_CutTopClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_max_y = min_y + amount; - if (clip) - result_max_y = DN_Min(result_max_y, max_y); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, min_y, rect->size.w, result_max_y - min_y); - rect->pos.y = result_max_y; - rect->size.h = max_y - result_max_y; - return result; -} - -DN_API DN_Rect DN_Rect_CutBottomClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_min_y = max_y - amount; - if (clip) - result_min_y = DN_Max(result_min_y, 0); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, result_min_y, rect->size.w, max_y - result_min_y); - rect->size.h = result_min_y - min_y; - return result; -} - -DN_API DN_Rect DN_RectCut_Cut(DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip) -{ - DN_Rect result = {}; - if (rect_cut.rect) { - switch (rect_cut.side) { - case DN_RectCutSide_Left: result = DN_Rect_CutLeftClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Right: result = DN_Rect_CutRightClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Top: result = DN_Rect_CutTopClip(rect_cut.rect, size.h, clip); break; - case DN_RectCutSide_Bottom: result = DN_Rect_CutBottomClip(rect_cut.rect, size.h, clip); break; - } + // NOTE: First time tokeniser is invoked with a string, set up initial state. + char const *string_end = tokeniser->string.data + tokeniser->string.size; + if (!tokeniser->it) { + tokeniser->it = tokeniser->string.data; + // NOTE: Skip any leading new lines + while (tokeniser->it[0] == '\n' || tokeniser->it[0] == '\r') + if (++tokeniser->it == string_end) + break; } - return result; -} -DN_API DN_V2F32 DN_Rect_InterpolatedPoint(DN_Rect rect, DN_V2F32 t01) -{ - DN_V2F32 result = DN_V2F32_Init2N(rect.pos.w + (rect.size.w * t01.x), - rect.pos.h + (rect.size.h * t01.y)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 1)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 1)); - return result; -} -#endif // !defined(DN_NO_RECT) - -// NOTE: Raycast /////////////////////////////////////////////////////////////////////////////////// - -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) -{ - // NOTE: Parametric equation of a line - // - // p = o + (t*d) - // - // - o is the starting 2d point - // - d is the direction of the line - // - t is a scalar that scales along the direction of the point - // - // To determine if a ray intersections a ray, we want to solve - // - // (o_a + (t_a * d_a)) = (o_b + (t_b * d_b)) - // - // Where '_a' and '_b' represent the 1st and 2nd point's origin, direction - // and 't' components respectively. This is 2 equations with 2 unknowns - // (`t_a` and `t_b`) which we can solve for by expressing the equation in - // terms of `t_a` and `t_b`. - // - // Working that math out produces the formula below for 't'. - - DN_RaycastLineIntersectV2Result result = {}; - DN_F32 denominator = ((dir_b.y * dir_a.x) - (dir_b.x * dir_a.y)); - if (denominator != 0.0f) { - result.t_a = (((origin_a.y - origin_b.y) * dir_b.x) + ((origin_b.x - origin_a.x) * dir_b.y)) / denominator; - result.t_b = (((origin_a.y - origin_b.y) * dir_a.x) + ((origin_b.x - origin_a.x) * dir_a.y)) / denominator; - result.hit = true; - } - return result; -} - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) -{ - DN_V2F32 result = {}; - result.x = a.x + ((b.x - a.x) * t); - result.y = a.y + ((b.y - a.y) * t); - return result; -} - -DN_API DN_F32 DN_Lerp_F32(DN_F32 a, DN_F32 t, DN_F32 b) -{ - DN_F32 result = a + ((b - a) * t); - return result; -} -#define DN_MATH_CPP - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_V2I32 -DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator!=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2I32 operator+(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator-=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2I32 &operator+=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2I32 DN_V2I32_Min(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Max(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -// NOTE: DN_V2U16 -DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2U16 operator-(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2U16 operator+(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator-=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -// NOTE: DN_V2 -DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator-(DN_V2F32 lhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 DN_V2F32_Min(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Max(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Abs(DN_V2F32 a) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -DN_API DN_F32 DN_V2F32_Dot(DN_V2F32 a, DN_V2F32 b) -{ - // NOTE: Scalar projection of B onto A ///////////////////////////////////////////////////////// - // - // Scalar projection calculates the signed distance between `b` and `a` - // where `a` is a unit vector then, the dot product calculates the projection - // of `b` onto the infinite line that the direction of `a` represents. This - // calculation is the signed distance. - // - // signed_distance = dot_product(a, b) = (a.x * b.x) + (a.y * b.y) - // - // Y - // ^ b - // | /| - // | / | - // | / | - // | / | Projection - // | / | - // |/ V - // +--->--------> X - // . a . - // . . - // |------| <- Calculated signed distance - // - // The signed-ness of the result indicates the relationship: - // - // Distance <0 means `b` is behind `a` - // Distance >0 means `b` is in-front of `a` - // Distance ==0 means `b` is perpendicular to `a` - // - // If `a` is not normalized then the signed-ness of the result still holds - // however result no longer represents the actual distance between the - // 2 objects. One of the vectors must be normalised (e.g. turned into a unit - // vector). - // - // NOTE: DN_V projection ///////////////////////////////////////////////////////////////////// - // - // DN_V projection calculates the exact X,Y coordinates of where `b` meets - // `a` when it was projected. This is calculated by multipying the - // 'scalar projection' result by the unit vector of `a` - // - // vector_projection = a * signed_distance = a * dot_product(a, b) - - DN_F32 result = (a.x * b.x) + (a.y * b.y); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - // NOTE: Pythagoras's theorem (a^2 + b^2 = c^2) without the square root - DN_F32 a = rhs.x - lhs.x; - DN_F32 b = rhs.y - lhs.y; - DN_F32 c_squared = DN_Squared(a) + DN_Squared(b); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_F32 result_squared = DN_V2F32_LengthSq_V2x2(lhs, rhs); - DN_F32 result = DN_SqrtF32(result_squared); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq(DN_V2F32 lhs) -{ - // NOTE: Pythagoras's theorem without the square root - DN_F32 c_squared = DN_Squared(lhs.x) + DN_Squared(lhs.y); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length(DN_V2F32 lhs) -{ - DN_F32 c_squared = DN_V2F32_LengthSq(lhs); - DN_F32 result = DN_SqrtF32(c_squared); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Normalise(DN_V2F32 a) -{ - DN_F32 length = DN_V2F32_Length(a); - DN_V2F32 result = a / length; - return result; -} - -DN_API DN_V2F32 DN_V2F32_Perpendicular(DN_V2F32 a) -{ - // NOTE: Matrix form of a 2D vector can be defined as - // - // x' = x cos(t) - y sin(t) - // y' = x sin(t) + y cos(t) - // - // Calculate a line perpendicular to a vector means rotating the vector by - // 90 degrees - // - // x' = x cos(90) - y sin(90) - // y' = x sin(90) + y cos(90) - // - // Where `cos(90) = 0` and `sin(90) = 1` then, - // - // x' = -y - // y' = +x - - DN_V2F32 result = DN_V2F32_Init2N(-a.y, a.x); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Reflect(DN_V2F32 in, DN_V2F32 surface) -{ - DN_V2F32 normal = DN_V2F32_Perpendicular(surface); - DN_V2F32 normal_norm = DN_V2F32_Normalise(normal); - DN_F32 signed_dist = DN_V2F32_Dot(in, normal_norm); - DN_V2F32 result = DN_V2F32_Init2N(in.x, in.y + (-signed_dist * 2.f)); - return result; -} - -DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) -{ - DN_F32 result = a.w * a.h; - return result; -} -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z); - return result; -} - -DN_API bool operator>=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z); - return result; -} - -DN_API bool operator<=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z); - return result; -} - -DN_API bool operator<(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z); - return result; -} - -DN_API bool operator>(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(-lhs.x, -lhs.y, -lhs.z); - return result; -} - -DN_API DN_V3F32 operator+(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator-=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V3F32 &operator+=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V3_LengthSq(DN_V3F32 a) -{ - DN_F32 result = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - return result; -} - -DN_API DN_F32 DN_V3_Length(DN_V3F32 a) -{ - DN_F32 length_sq = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - DN_F32 result = DN_SqrtF32(length_sq); - return result; -} - -DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) -{ - DN_F32 length = DN_V3_Length(a); - DN_V3F32 result = a / length; - return result; -} -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.w == rhs.w); - return result; -} - -DN_API bool operator!=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z) && (lhs.w >= rhs.w); - return result; -} - -DN_API bool operator<=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z) && (lhs.w <= rhs.w); - return result; -} - -DN_API bool operator<(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z) && (lhs.w < rhs.w); - return result; -} - -DN_API bool operator>(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z) && (lhs.w > rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(-lhs.x, -lhs.y, -lhs.z, -lhs.w); - return result; -} - -DN_API DN_V4F32 operator+(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, int32_t rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator/(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); - return result; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator-=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V4F32 &operator+=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) -{ - DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); - return result; -} -#endif // !defined(DN_NO_V4) - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_M4 DN_M4_Identity() -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_ScaleF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Scale(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {xyz.x, 0, 0, 0}, - {0, xyz.y, 0, 0}, - {0, 0, xyz.z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_TranslateF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Translate(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {xyz.x, xyz.y, xyz.z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Transpose(DN_M4 mat) -{ - DN_M4 result = {}; - for (int col = 0; col < 4; col++) - for (int row = 0; row < 4; row++) - result.columns[col][row] = mat.columns[row][col]; - return result; -} - -DN_API DN_M4 DN_M4_Rotate(DN_V3F32 axis01, DN_F32 radians) -{ - DN_AssertF(DN_Abs(DN_V3_Length(axis01) - 1.f) <= 0.01f, - "Rotation axis must be normalised, length = %f", - DN_V3_Length(axis01)); - - DN_F32 sin = DN_SinF32(radians); - DN_F32 cos = DN_CosF32(radians); - DN_F32 one_minus_cos = 1.f - cos; - - DN_F32 x = axis01.x; - DN_F32 y = axis01.y; - DN_F32 z = axis01.z; - DN_F32 x2 = DN_Squared(x); - DN_F32 y2 = DN_Squared(y); - DN_F32 z2 = DN_Squared(z); - - DN_M4 result = - { - { - {cos + x2 * one_minus_cos, y * x * one_minus_cos + z * sin, z * x * one_minus_cos - y * sin, 0}, // Col 1 - {x * y * one_minus_cos - z * sin, cos + y2 * one_minus_cos, z * y * one_minus_cos + x * sin, 0}, // Col 2 - {x * z * one_minus_cos + y * sin, y * z * one_minus_cos - x * sin, cos + z2 * one_minus_cos, 0}, // Col 3 - {0, 0, 0, 1}, // Col 4 - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Orthographic(DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far) -{ - // NOTE: Here is the matrix in column major for readability. Below it's - // transposed due to how you have to declare column major matrices in C/C++. - // - // m = [2/r-l, 0, 0, -1*(r+l)/(r-l)] - // [0, 2/t-b, 0, 1*(t+b)/(t-b)] - // [0, 0, -2/f-n, -1*(f+n)/(f-n)] - // [0, 0, 0, 1 ] - - DN_M4 result = - { - { - {2.f / (right - left), 0.f, 0.f, 0.f}, - {0.f, 2.f / (top - bottom), 0.f, 0.f}, - {0.f, 0.f, -2.f / (z_far - z_near), 0.f}, - {(-1.f * (right + left)) / (right - left), (-1.f * (top + bottom)) / (top - bottom), (-1.f * (z_far + z_near)) / (z_far - z_near), 1.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Perspective(DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far) -{ - DN_F32 tan_fov = DN_TanF32(fov / 2.f); - DN_M4 result = - { - { - {1.f / (aspect * tan_fov), 0.f, 0.f, 0.f}, - {0, 1.f / tan_fov, 0.f, 0.f}, - {0.f, 0.f, (z_near + z_far) / (z_near - z_far), -1.f}, - {0.f, 0.f, (2.f * z_near * z_far) / (z_near - z_far), 0.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Add(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Sub(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Mul(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) { - for (int row = 0; row < 4; row++) { - DN_F32 sum = 0; - for (int f32_it = 0; f32_it < 4; f32_it++) - sum += lhs.columns[f32_it][row] * rhs.columns[col][f32_it]; - - result.columns[col][row] = sum; - } - } - return result; -} - -DN_API DN_M4 DN_M4_Div(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_AddF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs; - return result; -} - -DN_API DN_M4 DN_M4_SubF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs; - return result; -} - -DN_API DN_M4 DN_M4_MulF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] * rhs; - return result; -} - -DN_API DN_M4 DN_M4_DivF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs; - return result; -} - - #if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString(DN_M4 mat) -{ - DN_FStr8<256> result = {}; - for (int row = 0; row < 4; row++) { - for (int it = 0; it < 4; it++) { - if (it == 0) - DN_FStr8_Add(&result, DN_STR8("|")); - DN_FStr8_AddF(&result, "%.5f", mat.columns[it][row]); - if (it != 3) - DN_FStr8_Add(&result, DN_STR8(", ")); - else - DN_FStr8_Add(&result, DN_STR8("|\n")); + // NOTE: Tokeniser pointing at end, no more valid data to parse. + if (tokeniser->it == string_end) + return result; + + // NOTE: Scan forward until the next control character. + // 1. '"' Double quoted field, extract everything between the quotes. + // 2. tokeniser->delimiter End of the field, extract everything leading up to the delimiter. + // 3. '\n' Last field in record, extract everything leading up the the new line. + char const *begin = tokeniser->it; + while (tokeniser->it != string_end && (tokeniser->it[0] != '"' && + tokeniser->it[0] != tokeniser->delimiter && + tokeniser->it[0] != '\n')) + tokeniser->it++; + + bool quoted_field = (tokeniser->it != string_end) && tokeniser->it[0] == '"'; + if (quoted_field) { + begin = ++tokeniser->it; // Begin after the quote + + // NOTE: Scan forward until the next '"' which marks the end + // of the field unless it is escaped by another '"'. + find_next_quote: + while (tokeniser->it != string_end && tokeniser->it[0] != '"') + tokeniser->it++; + + // NOTE: If we encounter a '"' right after, the quotes were escaped + // and we need to skip to the next instance of a '"'. + if (tokeniser->it != string_end && tokeniser->it + 1 != string_end && tokeniser->it[1] == '"') { + tokeniser->it += 2; + goto find_next_quote; } } - return result; -} - #endif -#endif // !defined(DN_M4) + // NOTE: Mark the end of the field + char const *end = tokeniser->it; + tokeniser->end_of_line = tokeniser->it == string_end || end[0] == '\n'; -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) -{ - bool result = DN_Memcmp(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ArrayCountU(lhs.e)) == 0; + // NOTE: In files with \r\n style new lines ensure that we don't include + // the \r byte in the CSV field we produce. + if (end != string_end && end[0] == '\n') { + DN_Assert((uintptr_t)(end - 1) > (uintptr_t)tokeniser->string.data && + "Internal error: The string iterator is pointing behind the start of the string we're reading"); + if (end[-1] == '\r') + end = end - 1; + } + + // NOTE: Quoted fields may have whitespace after the closing quote, we skip + // until we reach the field terminator. + if (quoted_field) + while (tokeniser->it != string_end && (tokeniser->it[0] != tokeniser->delimiter && + tokeniser->it[0] != '\n')) + tokeniser->it++; + + // NOTE: Advance the tokeniser past the field terminator. + if (tokeniser->it != string_end) + tokeniser->it++; + + // NOTE: Generate the record + result.data = DN_CAST(char *) begin; + result.size = DN_CAST(int)(end - begin); return result; } -DN_API bool operator!=(DN_M2x3 const &lhs, DN_M2x3 const &rhs) +static DN_Str8 DN_CSV_TokeniserNextColumn(DN_CSVTokeniser *tokeniser) { - bool result = !(lhs == rhs); + DN_Str8 result = {}; + if (!DN_CSV_TokeniserValid(tokeniser)) + return result; + + // NOTE: End of line, the user must explicitly advance to the next row + if (tokeniser->end_of_line) + return result; + + // NOTE: Advance tokeniser to the next field in the row + result = DN_CSV_TokeniserNextField(tokeniser); return result; } -DN_API DN_M2x3 DN_M2x3_Identity() +static void DN_CSV_TokeniserSkipLine(DN_CSVTokeniser *tokeniser) { - DN_M2x3 result = { - { - 1, - 0, - 0, - 0, - 1, - 0, - } - }; - return result; + while (DN_CSV_TokeniserValid(tokeniser) && !tokeniser->end_of_line) + DN_CSV_TokeniserNextColumn(tokeniser); + DN_CSV_TokeniserNextRow(tokeniser); } -DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset) +static int DN_CSV_TokeniserNextN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size, bool column_iterator) { - DN_M2x3 result = { - { - 1, - 0, - offset.x, - 0, - 1, - offset.y, - } - }; - return result; -} + if (!DN_CSV_TokeniserValid(tokeniser) || !fields || fields_size <= 0) + return 0; -DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) -{ - DN_M2x3 result = { - { - scale.x, - 0, - 0, - 0, - scale.y, - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Rotate(DN_F32 radians) -{ - DN_M2x3 result = { - { - DN_CosF32(radians), - DN_SinF32(radians), - 0, - -DN_SinF32(radians), - DN_CosF32(radians), - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Mul(DN_M2x3 m1, DN_M2x3 m2) -{ - // NOTE: Ordinarily you can't multiply M2x3 with M2x3 because column count - // (3) != row count (2). We pretend we have two 3x3 matrices with the last - // row set to [0 0 1] and perform a 3x3 matrix multiply. - // - // | (0)a (1)b (2)c | | (0)g (1)h (2)i | - // | (3)d (4)e (5)f | x | (3)j (4)k (5)l | - // | (6)0 (7)0 (8)1 | | (6)0 (7)0 (8)1 | - - DN_M2x3 result = { - { - m1.e[0] * m2.e[0] + m1.e[1] * m2.e[3], // a*g + b*j + c*0[omitted], - m1.e[0] * m2.e[1] + m1.e[1] * m2.e[4], // a*h + b*k + c*0[omitted], - m1.e[0] * m2.e[2] + m1.e[1] * m2.e[5] + m1.e[2], // a*i + b*l + c*1, - - m1.e[3] * m2.e[0] + m1.e[4] * m2.e[3], // d*g + e*j + f*0[omitted], - m1.e[3] * m2.e[1] + m1.e[4] * m2.e[4], // d*h + e*k + f*0[omitted], - m1.e[3] * m2.e[2] + m1.e[4] * m2.e[5] + m1.e[5], // d*i + e*l + f*1, - } - }; + int result = 0; + for (; result < fields_size; result++) { + fields[result] = column_iterator ? DN_CSV_TokeniserNextColumn(tokeniser) : DN_CSV_TokeniserNextField(tokeniser); + if (!DN_CSV_TokeniserValid(tokeniser) || !DN_Str8_HasData(fields[result])) + break; + } return result; } -DN_API DN_V2F32 DN_M2x3_Mul2F32(DN_M2x3 m1, DN_F32 x, DN_F32 y) +DN_MSVC_WARNING_PUSH +DN_MSVC_WARNING_DISABLE(4505) // 'x': unreferenced function with internal linkage has been removed +static int DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size) { - // NOTE: Ordinarily you can't multiply M2x3 with V2 because column count (3) - // != row count (2). We pretend we have a V3 with `z` set to `1`. - // - // | (0)a (1)b (2)c | | x | - // | (3)d (4)e (5)f | x | y | - // | 1 | - - DN_V2F32 result = { - { - m1.e[0] * x + m1.e[1] * y + m1.e[2], // a*x + b*y + c*1 - m1.e[3] * x + m1.e[4] * y + m1.e[5], // d*x + e*y + f*1 - } - }; + int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, true /*column_iterator*/); return result; } -DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) +static int DN_CSV_TokeniserNextFieldN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size) { - DN_V2F32 result = DN_M2x3_Mul2F32(m1, v2.x, v2.y); + int result = DN_CSV_TokeniserNextN(tokeniser, fields, fields_size, false /*column_iterator*/); return result; } -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(const DN_Rect &lhs, const DN_Rect &rhs) +static void DN_CSV_TokeniserSkipLineN(DN_CSVTokeniser *tokeniser, int count) { - bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); - return result; + for (int i = 0; i < count && DN_CSV_TokeniserValid(tokeniser); i++) + DN_CSV_TokeniserSkipLine(tokeniser); } -DN_API DN_V2F32 DN_Rect_Center(DN_Rect rect) +static void DN_CSV_PackU64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *value) { - DN_V2F32 result = rect.pos + (rect.size * .5f); - return result; + if (serialise == DN_CSVSerialise_Read) { + DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser); + DN_Str8ToU64Result to_u64 = DN_Str8_ToU64(csv_value, 0); + DN_Assert(to_u64.success); + *value = to_u64.value; + } else { + DN_Str8Builder_AppendF(&pack->write_builder, "%s%" PRIu64, pack->write_column++ ? "," : "", *value); + } } -DN_API bool DN_Rect_ContainsPoint(DN_Rect rect, DN_V2F32 p) +static void DN_CSV_PackI64(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *value) { - DN_V2F32 min = rect.pos; - DN_V2F32 max = rect.pos + rect.size; - bool result = (p.x >= min.x && p.x <= max.x && p.y >= min.y && p.y <= max.y); - return result; + if (serialise == DN_CSVSerialise_Read) { + DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser); + DN_Str8ToI64Result to_i64 = DN_Str8_ToI64(csv_value, 0); + DN_Assert(to_i64.success); + *value = to_i64.value; + } else { + DN_Str8Builder_AppendF(&pack->write_builder, "%s%" PRIu64, pack->write_column++ ? "," : "", *value); + } } -DN_API bool DN_Rect_ContainsRect(DN_Rect a, DN_Rect b) +static void DN_CSV_PackI32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *value) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (b_min >= a_min && b_max <= a_max); - return result; + DN_I64 u64 = *value; + DN_CSV_PackI64(pack, serialise, &u64); + if (serialise == DN_CSVSerialise_Read) + *value = DN_SaturateCastI64ToI32(u64); } -DN_API DN_Rect DN_Rect_Expand(DN_Rect a, DN_F32 amount) +static void DN_CSV_PackI16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *value) { - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; + DN_I64 u64 = *value; + DN_CSV_PackI64(pack, serialise, &u64); + if (serialise == DN_CSVSerialise_Read) + *value = DN_SaturateCastI64ToI16(u64); } -DN_API DN_Rect DN_Rect_ExpandV2(DN_Rect a, DN_V2F32 amount) +static void DN_CSV_PackI8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *value) { - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; + DN_I64 u64 = *value; + DN_CSV_PackI64(pack, serialise, &u64); + if (serialise == DN_CSVSerialise_Read) + *value = DN_SaturateCastI64ToI8(u64); } -DN_API bool DN_Rect_Intersects(DN_Rect a, DN_Rect b) + +static void DN_CSV_PackU32(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (a_min.x <= b_max.x && a_max.x >= b_min.x) && - (a_min.y <= b_max.y && a_max.y >= b_min.y); - return result; + DN_U64 u64 = *value; + DN_CSV_PackU64(pack, serialise, &u64); + if (serialise == DN_CSVSerialise_Read) + *value = DN_SaturateCastU64ToU32(u64); } -DN_API DN_Rect DN_Rect_Intersection(DN_Rect a, DN_Rect b) +static void DN_CSV_PackU16(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *value) { - DN_Rect result = DN_Rect_Init2V2(a.pos, DN_V2F32_Init1N(0)); - if (DN_Rect_Intersects(a, b)) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; + DN_U64 u64 = *value; + DN_CSV_PackU64(pack, serialise, &u64); + if (serialise == DN_CSVSerialise_Read) + *value = DN_SaturateCastU64ToU16(u64); +} - DN_V2F32 min = {}; - DN_V2F32 max = {}; - min.x = DN_Max(a_min.x, b_min.x); - min.y = DN_Max(a_min.y, b_min.y); - max.x = DN_Min(a_max.x, b_max.x); - max.y = DN_Min(a_max.y, b_max.y); - result = DN_Rect_Init2V2(min, max - min); +static void DN_CSV_PackBoolAsU64(DN_CSVPack *pack, DN_CSVSerialise serialise, bool *value) +{ + DN_U64 u64 = *value; + DN_CSV_PackU64(pack, serialise, &u64); + if (serialise == DN_CSVSerialise_Read) + *value = u64 ? 1 : 0; +} + +static void DN_CSV_PackStr8(DN_CSVPack *pack, DN_CSVSerialise serialise, DN_Str8 *str8, DN_Arena *arena) +{ + if (serialise == DN_CSVSerialise_Read) { + DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser); + *str8 = DN_Str8_Copy(arena, csv_value); + } else { + DN_Str8Builder_AppendF(&pack->write_builder, "%s%.*s", pack->write_column++ ? "," : "", DN_STR_FMT(*str8)); + } +} + +static void DN_CSV_PackBuffer(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size) +{ + if (serialise == DN_CSVSerialise_Read) { + DN_Str8 csv_value = DN_CSV_TokeniserNextColumn(&pack->read_tokeniser); + *size = DN_Min(*size, csv_value.size); + DN_Memcpy(dest, csv_value.data, *size); + } else { + DN_Str8Builder_AppendF(&pack->write_builder, "%s%.*s", pack->write_column++ ? "," : "", DN_CAST(int)(*size), dest); + } +} + +static void DN_CSV_PackBufferWithMax(DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size, size_t max) +{ + if (serialise == DN_CSVSerialise_Read) + *size = max; + DN_CSV_PackBuffer(pack, serialise, dest, size); +} + +static bool DN_CSV_PackNewLine(DN_CSVPack *pack, DN_CSVSerialise serialise) +{ + bool result = true; + if (serialise == DN_CSVSerialise_Read) { + result = DN_CSV_TokeniserNextRow(&pack->read_tokeniser); + } else { + pack->write_column = 0; + result = DN_Str8Builder_AppendRef(&pack->write_builder, DN_STR8("\n")); } return result; } +DN_MSVC_WARNING_POP +#define DN_HASH_CPP -DN_API DN_Rect DN_Rect_Union(DN_Rect a, DN_Rect b) +/* +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// $$\ $$\ $$$$$$\ $$$$$$\ $$\ $$\ +// $$ | $$ |$$ __$$\ $$ __$$\ $$ | $$ | +// $$ | $$ |$$ / $$ |$$ / \__|$$ | $$ | +// $$$$$$$$ |$$$$$$$$ |\$$$$$$\ $$$$$$$$ | +// $$ __$$ |$$ __$$ | \____$$\ $$ __$$ | +// $$ | $$ |$$ | $$ |$$\ $$ |$$ | $$ | +// $$ | $$ |$$ | $$ |\$$$$$$ |$$ | $$ | +// \__| \__|\__| \__| \______/ \__| \__| +// +// dn_hash.cpp +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + +// NOTE: DN_FNV1A ////////////////////////////////////////////////////////////////////////////////// +// Default values recommended by: http://isthe.com/chongo/tech/comp/fnv/ +DN_API uint32_t DN_FNV1A32_Iterate(void const *bytes, DN_USize size, uint32_t hash) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min, max; - min.x = DN_Min(a_min.x, b_min.x); - min.y = DN_Min(a_min.y, b_min.y); - max.x = DN_Max(a_max.x, b_max.x); - max.y = DN_Max(a_max.y, b_max.y); - DN_Rect result = DN_Rect_Init2V2(min, max - min); - return result; + auto buffer = DN_CAST(uint8_t const *)bytes; + for (DN_USize i = 0; i < size; i++) + hash = (buffer[i] ^ hash) * 16777619 /*FNV Prime*/; + return hash; } -DN_API DN_RectMinMax DN_Rect_MinMax(DN_Rect a) +DN_API uint32_t DN_FNV1A32_Hash(void const *bytes, DN_USize size) { - DN_RectMinMax result = {}; - result.min = a.pos; - result.max = a.pos + a.size; - return result; + uint32_t result = DN_FNV1A32_Iterate(bytes, size, DN_FNV1A32_SEED); + return result; } -DN_API DN_F32 DN_Rect_Area(DN_Rect a) +DN_API uint64_t DN_FNV1A64_Iterate(void const *bytes, DN_USize size, uint64_t hash) { - DN_F32 result = a.size.w * a.size.h; - return result; + auto buffer = DN_CAST(uint8_t const *)bytes; + for (DN_USize i = 0; i < size; i++) + hash = (buffer[i] ^ hash) * 1099511628211 /*FNV Prime*/; + return hash; } -DN_API DN_Rect DN_Rect_CutLeftClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) +DN_API uint64_t DN_FNV1A64_Hash(void const *bytes, DN_USize size) { - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_max_x = min_x + amount; - if (clip) - result_max_x = DN_Min(result_max_x, max_x); - DN_Rect result = DN_Rect_Init4N(min_x, rect->pos.y, result_max_x - min_x, rect->size.h); - rect->pos.x = result_max_x; - rect->size.w = max_x - result_max_x; - return result; + uint64_t result = DN_FNV1A64_Iterate(bytes, size, DN_FNV1A64_SEED); + return result; } -DN_API DN_Rect DN_Rect_CutRightClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) +// NOTE: DN_MurmurHash3 //////////////////////////////////////////////////////////////////////////// +#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL) + #define DN_MMH3_ROTL32(x, y) _rotl(x, y) + #define DN_MMH3_ROTL64(x, y) _rotl64(x, y) +#else + #define DN_MMH3_ROTL32(x, y) ((x) << (y)) | ((x) >> (32 - (y))) + #define DN_MMH3_ROTL64(x, y) ((x) << (y)) | ((x) >> (64 - (y))) +#endif + +//----------------------------------------------------------------------------- +// Block read - if your platform needs to do endian-swapping or can only +// handle aligned reads, do the conversion here + +DN_FORCE_INLINE uint32_t DN_MurmurHash3_GetBlock32(uint32_t const *p, int i) { - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_min_x = max_x - amount; - if (clip) - result_min_x = DN_Max(result_min_x, 0); - DN_Rect result = DN_Rect_Init4N(result_min_x, rect->pos.y, max_x - result_min_x, rect->size.h); - rect->size.w = result_min_x - min_x; - return result; + return p[i]; } -DN_API DN_Rect DN_Rect_CutTopClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) +DN_FORCE_INLINE uint64_t DN_MurmurHash3_GetBlock64(uint64_t const *p, int i) { - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_max_y = min_y + amount; - if (clip) - result_max_y = DN_Min(result_max_y, max_y); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, min_y, rect->size.w, result_max_y - min_y); - rect->pos.y = result_max_y; - rect->size.h = max_y - result_max_y; - return result; + return p[i]; } -DN_API DN_Rect DN_Rect_CutBottomClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) +//----------------------------------------------------------------------------- +// Finalization mix - force all bits of a hash block to avalanche + +DN_FORCE_INLINE uint32_t DN_MurmurHash3_FMix32(uint32_t h) { - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_min_y = max_y - amount; - if (clip) - result_min_y = DN_Max(result_min_y, 0); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, result_min_y, rect->size.w, max_y - result_min_y); - rect->size.h = result_min_y - min_y; - return result; + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; } -DN_API DN_Rect DN_RectCut_Cut(DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip) +DN_FORCE_INLINE uint64_t DN_MurmurHash3_FMix64(uint64_t k) { - DN_Rect result = {}; - if (rect_cut.rect) { - switch (rect_cut.side) { - case DN_RectCutSide_Left: result = DN_Rect_CutLeftClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Right: result = DN_Rect_CutRightClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Top: result = DN_Rect_CutTopClip(rect_cut.rect, size.h, clip); break; - case DN_RectCutSide_Bottom: result = DN_Rect_CutBottomClip(rect_cut.rect, size.h, clip); break; + k ^= k >> 33; + k *= 0xff51afd7ed558ccd; + k ^= k >> 33; + k *= 0xc4ceb9fe1a85ec53; + k ^= k >> 33; + return k; +} + +DN_API uint32_t DN_MurmurHash3_x86U32(void const *key, int len, uint32_t seed) +{ + const uint8_t *data = (const uint8_t *)key; + const int nblocks = len / 4; + + uint32_t h1 = seed; + + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + //---------- + // body + + const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4); + + for (int i = -nblocks; i; i++) + { + uint32_t k1 = DN_MurmurHash3_GetBlock32(blocks, i); + + k1 *= c1; + k1 = DN_MMH3_ROTL32(k1, 15); + k1 *= c2; + + h1 ^= k1; + h1 = DN_MMH3_ROTL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; } - } - return result; -} - -DN_API DN_V2F32 DN_Rect_InterpolatedPoint(DN_Rect rect, DN_V2F32 t01) -{ - DN_V2F32 result = DN_V2F32_Init2N(rect.pos.w + (rect.size.w * t01.x), - rect.pos.h + (rect.size.h * t01.y)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 1)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 1)); - return result; -} -#endif // !defined(DN_NO_RECT) - -// NOTE: Raycast /////////////////////////////////////////////////////////////////////////////////// - -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) -{ - // NOTE: Parametric equation of a line - // - // p = o + (t*d) - // - // - o is the starting 2d point - // - d is the direction of the line - // - t is a scalar that scales along the direction of the point - // - // To determine if a ray intersections a ray, we want to solve - // - // (o_a + (t_a * d_a)) = (o_b + (t_b * d_b)) - // - // Where '_a' and '_b' represent the 1st and 2nd point's origin, direction - // and 't' components respectively. This is 2 equations with 2 unknowns - // (`t_a` and `t_b`) which we can solve for by expressing the equation in - // terms of `t_a` and `t_b`. - // - // Working that math out produces the formula below for 't'. - - DN_RaycastLineIntersectV2Result result = {}; - DN_F32 denominator = ((dir_b.y * dir_a.x) - (dir_b.x * dir_a.y)); - if (denominator != 0.0f) { - result.t_a = (((origin_a.y - origin_b.y) * dir_b.x) + ((origin_b.x - origin_a.x) * dir_b.y)) / denominator; - result.t_b = (((origin_a.y - origin_b.y) * dir_a.x) + ((origin_b.x - origin_a.x) * dir_a.y)) / denominator; - result.hit = true; - } - return result; -} - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) -{ - DN_V2F32 result = {}; - result.x = a.x + ((b.x - a.x) * t); - result.y = a.y + ((b.y - a.y) * t); - return result; -} - -DN_API DN_F32 DN_Lerp_F32(DN_F32 a, DN_F32 t, DN_F32 b) -{ - DN_F32 result = a + ((b - a) * t); - return result; -} -#define DN_MATH_CPP - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_V2I32 -DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator!=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} -DN_API bool operator>=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} + //---------- + // tail -DN_API bool operator<=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} + const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); -DN_API bool operator<(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} + uint32_t k1 = 0; -DN_API bool operator>(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} + switch (len & 3) + { + case 3: + k1 ^= tail[2] << 16; + case 2: + k1 ^= tail[1] << 8; + case 1: + k1 ^= tail[0]; + k1 *= c1; + k1 = DN_MMH3_ROTL32(k1, 15); + k1 *= c2; + h1 ^= k1; + }; -DN_API DN_V2I32 operator-(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} + //---------- + // finalization -DN_API DN_V2I32 operator-(DN_V2I32 lhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(-lhs.x, -lhs.y); - return result; -} + h1 ^= len; -DN_API DN_V2I32 operator+(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} + h1 = DN_MurmurHash3_FMix32(h1); -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; + return h1; } -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_F32 rhs) +DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128(void const *key, int len, uint32_t seed) { - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} + const uint8_t *data = (const uint8_t *)key; + const int nblocks = len / 16; -DN_API DN_V2I32 operator*(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} + uint64_t h1 = seed; + uint64_t h2 = seed; -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} + const uint64_t c1 = 0x87c37b91114253d5; + const uint64_t c2 = 0x4cf5ad432745937f; -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} + //---------- + // body -DN_API DN_V2I32 operator/(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} + const uint64_t *blocks = (const uint64_t *)(data); -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} + for (int i = 0; i < nblocks; i++) + { + uint64_t k1 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 0); + uint64_t k2 = DN_MurmurHash3_GetBlock64(blocks, i * 2 + 1); -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} + k1 *= c1; + k1 = DN_MMH3_ROTL64(k1, 31); + k1 *= c2; + h1 ^= k1; -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator-=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2I32 &operator+=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2I32 DN_V2I32_Min(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Max(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -// NOTE: DN_V2U16 -DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2U16 operator-(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2U16 operator+(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} + h1 = DN_MMH3_ROTL64(h1, 27); + h1 += h2; + h1 = h1 * 5 + 0x52dce729; -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator-=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -// NOTE: DN_V2 -DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator-(DN_V2F32 lhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 DN_V2F32_Min(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Max(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Abs(DN_V2F32 a) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -DN_API DN_F32 DN_V2F32_Dot(DN_V2F32 a, DN_V2F32 b) -{ - // NOTE: Scalar projection of B onto A ///////////////////////////////////////////////////////// - // - // Scalar projection calculates the signed distance between `b` and `a` - // where `a` is a unit vector then, the dot product calculates the projection - // of `b` onto the infinite line that the direction of `a` represents. This - // calculation is the signed distance. - // - // signed_distance = dot_product(a, b) = (a.x * b.x) + (a.y * b.y) - // - // Y - // ^ b - // | /| - // | / | - // | / | - // | / | Projection - // | / | - // |/ V - // +--->--------> X - // . a . - // . . - // |------| <- Calculated signed distance - // - // The signed-ness of the result indicates the relationship: - // - // Distance <0 means `b` is behind `a` - // Distance >0 means `b` is in-front of `a` - // Distance ==0 means `b` is perpendicular to `a` - // - // If `a` is not normalized then the signed-ness of the result still holds - // however result no longer represents the actual distance between the - // 2 objects. One of the vectors must be normalised (e.g. turned into a unit - // vector). - // - // NOTE: DN_V projection ///////////////////////////////////////////////////////////////////// - // - // DN_V projection calculates the exact X,Y coordinates of where `b` meets - // `a` when it was projected. This is calculated by multipying the - // 'scalar projection' result by the unit vector of `a` - // - // vector_projection = a * signed_distance = a * dot_product(a, b) - - DN_F32 result = (a.x * b.x) + (a.y * b.y); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - // NOTE: Pythagoras's theorem (a^2 + b^2 = c^2) without the square root - DN_F32 a = rhs.x - lhs.x; - DN_F32 b = rhs.y - lhs.y; - DN_F32 c_squared = DN_Squared(a) + DN_Squared(b); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_F32 result_squared = DN_V2F32_LengthSq_V2x2(lhs, rhs); - DN_F32 result = DN_SqrtF32(result_squared); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq(DN_V2F32 lhs) -{ - // NOTE: Pythagoras's theorem without the square root - DN_F32 c_squared = DN_Squared(lhs.x) + DN_Squared(lhs.y); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length(DN_V2F32 lhs) -{ - DN_F32 c_squared = DN_V2F32_LengthSq(lhs); - DN_F32 result = DN_SqrtF32(c_squared); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Normalise(DN_V2F32 a) -{ - DN_F32 length = DN_V2F32_Length(a); - DN_V2F32 result = a / length; - return result; -} - -DN_API DN_V2F32 DN_V2F32_Perpendicular(DN_V2F32 a) -{ - // NOTE: Matrix form of a 2D vector can be defined as - // - // x' = x cos(t) - y sin(t) - // y' = x sin(t) + y cos(t) - // - // Calculate a line perpendicular to a vector means rotating the vector by - // 90 degrees - // - // x' = x cos(90) - y sin(90) - // y' = x sin(90) + y cos(90) - // - // Where `cos(90) = 0` and `sin(90) = 1` then, - // - // x' = -y - // y' = +x - - DN_V2F32 result = DN_V2F32_Init2N(-a.y, a.x); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Reflect(DN_V2F32 in, DN_V2F32 surface) -{ - DN_V2F32 normal = DN_V2F32_Perpendicular(surface); - DN_V2F32 normal_norm = DN_V2F32_Normalise(normal); - DN_F32 signed_dist = DN_V2F32_Dot(in, normal_norm); - DN_V2F32 result = DN_V2F32_Init2N(in.x, in.y + (-signed_dist * 2.f)); - return result; -} - -DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) -{ - DN_F32 result = a.w * a.h; - return result; -} -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z); - return result; -} - -DN_API bool operator>=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z); - return result; -} - -DN_API bool operator<=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z); - return result; -} - -DN_API bool operator<(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z); - return result; -} - -DN_API bool operator>(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(-lhs.x, -lhs.y, -lhs.z); - return result; -} - -DN_API DN_V3F32 operator+(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator-=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V3F32 &operator+=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V3_LengthSq(DN_V3F32 a) -{ - DN_F32 result = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - return result; -} - -DN_API DN_F32 DN_V3_Length(DN_V3F32 a) -{ - DN_F32 length_sq = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - DN_F32 result = DN_SqrtF32(length_sq); - return result; -} - -DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) -{ - DN_F32 length = DN_V3_Length(a); - DN_V3F32 result = a / length; - return result; -} -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.w == rhs.w); - return result; -} - -DN_API bool operator!=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z) && (lhs.w >= rhs.w); - return result; -} - -DN_API bool operator<=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z) && (lhs.w <= rhs.w); - return result; -} - -DN_API bool operator<(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z) && (lhs.w < rhs.w); - return result; -} - -DN_API bool operator>(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z) && (lhs.w > rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(-lhs.x, -lhs.y, -lhs.z, -lhs.w); - return result; -} - -DN_API DN_V4F32 operator+(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, int32_t rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator/(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); - return result; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator-=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V4F32 &operator+=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) -{ - DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); - return result; -} -#endif // !defined(DN_NO_V4) - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_M4 DN_M4_Identity() -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_ScaleF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Scale(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {xyz.x, 0, 0, 0}, - {0, xyz.y, 0, 0}, - {0, 0, xyz.z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_TranslateF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Translate(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {xyz.x, xyz.y, xyz.z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Transpose(DN_M4 mat) -{ - DN_M4 result = {}; - for (int col = 0; col < 4; col++) - for (int row = 0; row < 4; row++) - result.columns[col][row] = mat.columns[row][col]; - return result; -} - -DN_API DN_M4 DN_M4_Rotate(DN_V3F32 axis01, DN_F32 radians) -{ - DN_AssertF(DN_Abs(DN_V3_Length(axis01) - 1.f) <= 0.01f, - "Rotation axis must be normalised, length = %f", - DN_V3_Length(axis01)); - - DN_F32 sin = DN_SinF32(radians); - DN_F32 cos = DN_CosF32(radians); - DN_F32 one_minus_cos = 1.f - cos; - - DN_F32 x = axis01.x; - DN_F32 y = axis01.y; - DN_F32 z = axis01.z; - DN_F32 x2 = DN_Squared(x); - DN_F32 y2 = DN_Squared(y); - DN_F32 z2 = DN_Squared(z); - - DN_M4 result = - { - { - {cos + x2 * one_minus_cos, y * x * one_minus_cos + z * sin, z * x * one_minus_cos - y * sin, 0}, // Col 1 - {x * y * one_minus_cos - z * sin, cos + y2 * one_minus_cos, z * y * one_minus_cos + x * sin, 0}, // Col 2 - {x * z * one_minus_cos + y * sin, y * z * one_minus_cos - x * sin, cos + z2 * one_minus_cos, 0}, // Col 3 - {0, 0, 0, 1}, // Col 4 - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Orthographic(DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far) -{ - // NOTE: Here is the matrix in column major for readability. Below it's - // transposed due to how you have to declare column major matrices in C/C++. - // - // m = [2/r-l, 0, 0, -1*(r+l)/(r-l)] - // [0, 2/t-b, 0, 1*(t+b)/(t-b)] - // [0, 0, -2/f-n, -1*(f+n)/(f-n)] - // [0, 0, 0, 1 ] - - DN_M4 result = - { - { - {2.f / (right - left), 0.f, 0.f, 0.f}, - {0.f, 2.f / (top - bottom), 0.f, 0.f}, - {0.f, 0.f, -2.f / (z_far - z_near), 0.f}, - {(-1.f * (right + left)) / (right - left), (-1.f * (top + bottom)) / (top - bottom), (-1.f * (z_far + z_near)) / (z_far - z_near), 1.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Perspective(DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far) -{ - DN_F32 tan_fov = DN_TanF32(fov / 2.f); - DN_M4 result = - { - { - {1.f / (aspect * tan_fov), 0.f, 0.f, 0.f}, - {0, 1.f / tan_fov, 0.f, 0.f}, - {0.f, 0.f, (z_near + z_far) / (z_near - z_far), -1.f}, - {0.f, 0.f, (2.f * z_near * z_far) / (z_near - z_far), 0.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Add(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Sub(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Mul(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) { - for (int row = 0; row < 4; row++) { - DN_F32 sum = 0; - for (int f32_it = 0; f32_it < 4; f32_it++) - sum += lhs.columns[f32_it][row] * rhs.columns[col][f32_it]; + k2 *= c2; + k2 = DN_MMH3_ROTL64(k2, 33); + k2 *= c1; + h2 ^= k2; - result.columns[col][row] = sum; + h2 = DN_MMH3_ROTL64(h2, 31); + h2 += h1; + h2 = h2 * 5 + 0x38495ab5; } + + //---------- + // tail + + const uint8_t *tail = (const uint8_t *)(data + nblocks * 16); + + uint64_t k1 = 0; + uint64_t k2 = 0; + + switch (len & 15) + { + case 15: + k2 ^= ((uint64_t)tail[14]) << 48; + case 14: + k2 ^= ((uint64_t)tail[13]) << 40; + case 13: + k2 ^= ((uint64_t)tail[12]) << 32; + case 12: + k2 ^= ((uint64_t)tail[11]) << 24; + case 11: + k2 ^= ((uint64_t)tail[10]) << 16; + case 10: + k2 ^= ((uint64_t)tail[9]) << 8; + case 9: + k2 ^= ((uint64_t)tail[8]) << 0; + k2 *= c2; + k2 = DN_MMH3_ROTL64(k2, 33); + k2 *= c1; + h2 ^= k2; + + case 8: + k1 ^= ((uint64_t)tail[7]) << 56; + case 7: + k1 ^= ((uint64_t)tail[6]) << 48; + case 6: + k1 ^= ((uint64_t)tail[5]) << 40; + case 5: + k1 ^= ((uint64_t)tail[4]) << 32; + case 4: + k1 ^= ((uint64_t)tail[3]) << 24; + case 3: + k1 ^= ((uint64_t)tail[2]) << 16; + case 2: + k1 ^= ((uint64_t)tail[1]) << 8; + case 1: + k1 ^= ((uint64_t)tail[0]) << 0; + k1 *= c1; + k1 = DN_MMH3_ROTL64(k1, 31); + k1 *= c2; + h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; + h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = DN_MurmurHash3_FMix64(h1); + h2 = DN_MurmurHash3_FMix64(h2); + + h1 += h2; + h2 += h1; + + DN_MurmurHash3 result = {}; + result.e[0] = h1; + result.e[1] = h2; + return result; +} +#define DN_HELPERS_CPP + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// $$\ $$\ $$$$$$$$\ $$\ $$$$$$$\ $$$$$$$$\ $$$$$$$\ $$$$$$\ +// $$ | $$ |$$ _____|$$ | $$ __$$\ $$ _____|$$ __$$\ $$ __$$\ +// $$ | $$ |$$ | $$ | $$ | $$ |$$ | $$ | $$ |$$ / \__| +// $$$$$$$$ |$$$$$\ $$ | $$$$$$$ |$$$$$\ $$$$$$$ |\$$$$$$\ +// $$ __$$ |$$ __| $$ | $$ ____/ $$ __| $$ __$$< \____$$\ +// $$ | $$ |$$ | $$ | $$ | $$ | $$ | $$ |$$\ $$ | +// $$ | $$ |$$$$$$$$\ $$$$$$$$\ $$ | $$$$$$$$\ $$ | $$ |\$$$$$$ | +// \__| \__|\________|\________|\__| \________|\__| \__| \______/ +// +// dn_helpers.cpp +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + +// NOTE: DN_PCG32 ////////////////////////////////////////////////////////////////////////////////// +#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL +#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL + +DN_API DN_PCG32 DN_PCG32_Init(uint64_t seed) +{ + DN_PCG32 result = {}; + DN_PCG32_Next(&result); + result.state += seed; + DN_PCG32_Next(&result); + return result; +} + +DN_API uint32_t DN_PCG32_Next(DN_PCG32 *rng) +{ + uint64_t state = rng->state; + rng->state = state * DN_PCG_DEFAULT_MULTIPLIER_64 + DN_PCG_DEFAULT_INCREMENT_64; + + // XSH-RR + uint32_t value = (uint32_t)((state ^ (state >> 18)) >> 27); + int rot = state >> 59; + return rot ? (value >> rot) | (value << (32 - rot)) : value; +} + +DN_API uint64_t DN_PCG32_Next64(DN_PCG32 *rng) +{ + uint64_t value = DN_PCG32_Next(rng); + value <<= 32; + value |= DN_PCG32_Next(rng); + return value; +} + +DN_API uint32_t DN_PCG32_Range(DN_PCG32 *rng, uint32_t low, uint32_t high) +{ + uint32_t bound = high - low; + uint32_t threshold = -(int32_t)bound % bound; + + for (;;) { + uint32_t r = DN_PCG32_Next(rng); + if (r >= threshold) + return low + (r % bound); } - return result; } -DN_API DN_M4 DN_M4_Div(DN_M4 lhs, DN_M4 rhs) +DN_API float DN_PCG32_NextF32(DN_PCG32 *rng) { - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs.columns[col][it]; - return result; + uint32_t x = DN_PCG32_Next(rng); + return (float)(int32_t)(x >> 8) * 0x1.0p-24f; } -DN_API DN_M4 DN_M4_AddF(DN_M4 lhs, DN_F32 rhs) +DN_API double DN_PCG32_NextF64(DN_PCG32 *rng) { - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs; - return result; + uint64_t x = DN_PCG32_Next64(rng); + return (double)(int64_t)(x >> 11) * 0x1.0p-53; } -DN_API DN_M4 DN_M4_SubF(DN_M4 lhs, DN_F32 rhs) +DN_API void DN_PCG32_Advance(DN_PCG32 *rng, uint64_t delta) { - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs; - return result; -} + uint64_t cur_mult = DN_PCG_DEFAULT_MULTIPLIER_64; + uint64_t cur_plus = DN_PCG_DEFAULT_INCREMENT_64; -DN_API DN_M4 DN_M4_MulF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] * rhs; - return result; -} + uint64_t acc_mult = 1; + uint64_t acc_plus = 0; -DN_API DN_M4 DN_M4_DivF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs; - return result; -} - - #if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString(DN_M4 mat) -{ - DN_FStr8<256> result = {}; - for (int row = 0; row < 4; row++) { - for (int it = 0; it < 4; it++) { - if (it == 0) - DN_FStr8_Add(&result, DN_STR8("|")); - DN_FStr8_AddF(&result, "%.5f", mat.columns[it][row]); - if (it != 3) - DN_FStr8_Add(&result, DN_STR8(", ")); - else - DN_FStr8_Add(&result, DN_STR8("|\n")); + while (delta != 0) { + if (delta & 1) { + acc_mult *= cur_mult; + acc_plus = acc_plus * cur_mult + cur_plus; } + cur_plus = (cur_mult + 1) * cur_plus; + cur_mult *= cur_mult; + delta >>= 1; } - return result; + rng->state = acc_mult * rng->state + acc_plus; } - #endif -#endif // !defined(DN_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) +#if !defined(DN_NO_JSON_BUILDER) +// NOTE: DN_JSONBuilder //////////////////////////////////////////////////////////////////////////// +DN_API DN_JSONBuilder DN_JSONBuilder_Init(DN_Arena *arena, int spaces_per_indent) { - bool result = DN_Memcmp(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ArrayCountU(lhs.e)) == 0; + DN_JSONBuilder result = {}; + result.spaces_per_indent = spaces_per_indent; + result.string_builder.arena = arena; return result; } -DN_API bool operator!=(DN_M2x3 const &lhs, DN_M2x3 const &rhs) +DN_API DN_Str8 DN_JSONBuilder_Build(DN_JSONBuilder const *builder, DN_Arena *arena) { - bool result = !(lhs == rhs); + DN_Str8 result = DN_Str8Builder_Build(&builder->string_builder, arena); return result; } -DN_API DN_M2x3 DN_M2x3_Identity() +DN_API void DN_JSONBuilder_KeyValue(DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value) { - DN_M2x3 result = { - { - 1, - 0, - 0, - 0, - 1, - 0, - } - }; - return result; -} + if (key.size == 0 && value.size == 0) + return; -DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset) -{ - DN_M2x3 result = { - { - 1, - 0, - offset.x, - 0, - 1, - offset.y, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) -{ - DN_M2x3 result = { - { - scale.x, - 0, - 0, - 0, - scale.y, - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Rotate(DN_F32 radians) -{ - DN_M2x3 result = { - { - DN_CosF32(radians), - DN_SinF32(radians), - 0, - -DN_SinF32(radians), - DN_CosF32(radians), - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Mul(DN_M2x3 m1, DN_M2x3 m2) -{ - // NOTE: Ordinarily you can't multiply M2x3 with M2x3 because column count - // (3) != row count (2). We pretend we have two 3x3 matrices with the last - // row set to [0 0 1] and perform a 3x3 matrix multiply. - // - // | (0)a (1)b (2)c | | (0)g (1)h (2)i | - // | (3)d (4)e (5)f | x | (3)j (4)k (5)l | - // | (6)0 (7)0 (8)1 | | (6)0 (7)0 (8)1 | - - DN_M2x3 result = { - { - m1.e[0] * m2.e[0] + m1.e[1] * m2.e[3], // a*g + b*j + c*0[omitted], - m1.e[0] * m2.e[1] + m1.e[1] * m2.e[4], // a*h + b*k + c*0[omitted], - m1.e[0] * m2.e[2] + m1.e[1] * m2.e[5] + m1.e[2], // a*i + b*l + c*1, - - m1.e[3] * m2.e[0] + m1.e[4] * m2.e[3], // d*g + e*j + f*0[omitted], - m1.e[3] * m2.e[1] + m1.e[4] * m2.e[4], // d*h + e*k + f*0[omitted], - m1.e[3] * m2.e[2] + m1.e[4] * m2.e[5] + m1.e[5], // d*i + e*l + f*1, - } - }; - - return result; -} - -DN_API DN_V2F32 DN_M2x3_Mul2F32(DN_M2x3 m1, DN_F32 x, DN_F32 y) -{ - // NOTE: Ordinarily you can't multiply M2x3 with V2 because column count (3) - // != row count (2). We pretend we have a V3 with `z` set to `1`. - // - // | (0)a (1)b (2)c | | x | - // | (3)d (4)e (5)f | x | y | - // | 1 | - - DN_V2F32 result = { - { - m1.e[0] * x + m1.e[1] * y + m1.e[2], // a*x + b*y + c*1 - m1.e[3] * x + m1.e[4] * y + m1.e[5], // d*x + e*y + f*1 - } - }; - return result; -} - -DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) -{ - DN_V2F32 result = DN_M2x3_Mul2F32(m1, v2.x, v2.y); - return result; -} - -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(const DN_Rect &lhs, const DN_Rect &rhs) -{ - bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); - return result; -} - -DN_API DN_V2F32 DN_Rect_Center(DN_Rect rect) -{ - DN_V2F32 result = rect.pos + (rect.size * .5f); - return result; -} - -DN_API bool DN_Rect_ContainsPoint(DN_Rect rect, DN_V2F32 p) -{ - DN_V2F32 min = rect.pos; - DN_V2F32 max = rect.pos + rect.size; - bool result = (p.x >= min.x && p.x <= max.x && p.y >= min.y && p.y <= max.y); - return result; -} - -DN_API bool DN_Rect_ContainsRect(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (b_min >= a_min && b_max <= a_max); - return result; -} - -DN_API DN_Rect DN_Rect_Expand(DN_Rect a, DN_F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API DN_Rect DN_Rect_ExpandV2(DN_Rect a, DN_V2F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API bool DN_Rect_Intersects(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (a_min.x <= b_max.x && a_max.x >= b_min.x) && - (a_min.y <= b_max.y && a_max.y >= b_min.y); - return result; -} - -DN_API DN_Rect DN_Rect_Intersection(DN_Rect a, DN_Rect b) -{ - DN_Rect result = DN_Rect_Init2V2(a.pos, DN_V2F32_Init1N(0)); - if (DN_Rect_Intersects(a, b)) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min = {}; - DN_V2F32 max = {}; - min.x = DN_Max(a_min.x, b_min.x); - min.y = DN_Max(a_min.y, b_min.y); - max.x = DN_Min(a_max.x, b_max.x); - max.y = DN_Min(a_max.y, b_max.y); - result = DN_Rect_Init2V2(min, max - min); + DN_JSONBuilderItem item = DN_JSONBuilderItem_KeyValue; + if (value.size >= 1) { + if (value.data[0] == '{' || value.data[0] == '[') + item = DN_JSONBuilderItem_OpenContainer; + else if (value.data[0] == '}' || value.data[0] == ']') + item = DN_JSONBuilderItem_CloseContainer; } + + bool adding_to_container_with_items = + item != DN_JSONBuilderItem_CloseContainer && (builder->last_item == DN_JSONBuilderItem_KeyValue || + builder->last_item == DN_JSONBuilderItem_CloseContainer); + + uint8_t prefix_size = 0; + char prefix[2] = {0}; + if (adding_to_container_with_items) + prefix[prefix_size++] = ','; + + if (builder->last_item != DN_JSONBuilderItem_Empty) + prefix[prefix_size++] = '\n'; + + if (item == DN_JSONBuilderItem_CloseContainer) + builder->indent_level--; + + int spaces_per_indent = builder->spaces_per_indent ? builder->spaces_per_indent : 2; + int spaces = builder->indent_level * spaces_per_indent; + + if (key.size) + DN_Str8Builder_AppendF(&builder->string_builder, + "%.*s%*c\"%.*s\": %.*s", + prefix_size, + prefix, + spaces, + ' ', + DN_STR_FMT(key), + DN_STR_FMT(value)); + else if (spaces == 0) + DN_Str8Builder_AppendF(&builder->string_builder, "%.*s%.*s", prefix_size, prefix, DN_STR_FMT(value)); + else + DN_Str8Builder_AppendF(&builder->string_builder, "%.*s%*c%.*s", prefix_size, prefix, spaces, ' ', DN_STR_FMT(value)); + + if (item == DN_JSONBuilderItem_OpenContainer) + builder->indent_level++; + + builder->last_item = item; +} + +DN_API void DN_JSONBuilder_KeyValueFV(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, va_list args) +{ + DN_OSTLSTMem tmem = DN_OS_TLSTMem(builder->string_builder.arena); + DN_Str8 value = DN_Str8_InitFV(tmem.arena, value_fmt, args); + DN_JSONBuilder_KeyValue(builder, key, value); +} + +DN_API void DN_JSONBuilder_KeyValueF(DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...) +{ + va_list args; + va_start(args, value_fmt); + DN_JSONBuilder_KeyValueFV(builder, key, value_fmt, args); + va_end(args); +} + +DN_API void DN_JSONBuilder_ObjectBeginNamed(DN_JSONBuilder *builder, DN_Str8 name) +{ + DN_JSONBuilder_KeyValue(builder, name, DN_STR8("{")); +} + +DN_API void DN_JSONBuilder_ObjectEnd(DN_JSONBuilder *builder) +{ + DN_JSONBuilder_KeyValue(builder, DN_STR8(""), DN_STR8("}")); +} + +DN_API void DN_JSONBuilder_ArrayBeginNamed(DN_JSONBuilder *builder, DN_Str8 name) +{ + DN_JSONBuilder_KeyValue(builder, name, DN_STR8("[")); +} + +DN_API void DN_JSONBuilder_ArrayEnd(DN_JSONBuilder *builder) +{ + DN_JSONBuilder_KeyValue(builder, DN_STR8(""), DN_STR8("]")); +} + +DN_API void DN_JSONBuilder_Str8Named(DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value) +{ + DN_JSONBuilder_KeyValueF(builder, key, "\"%.*s\"", value.size, value.data); +} + +DN_API void DN_JSONBuilder_LiteralNamed(DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value) +{ + DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value.size, value.data); +} + +DN_API void DN_JSONBuilder_U64Named(DN_JSONBuilder *builder, DN_Str8 key, uint64_t value) +{ + DN_JSONBuilder_KeyValueF(builder, key, "%I64u", value); +} + +DN_API void DN_JSONBuilder_I64Named(DN_JSONBuilder *builder, DN_Str8 key, int64_t value) +{ + DN_JSONBuilder_KeyValueF(builder, key, "%I64d", value); +} + +DN_API void DN_JSONBuilder_F64Named(DN_JSONBuilder *builder, DN_Str8 key, double value, int decimal_places) +{ + if (!builder) + return; + + if (decimal_places >= 16) + decimal_places = 16; + + // NOTE: Generate the format string for the float, depending on how many + // decimals places it wants. + char float_fmt[16]; + if (decimal_places > 0) { + // NOTE: Emit the format string "%.f" i.e. %.1f + DN_SNPrintF(float_fmt, sizeof(float_fmt), "%%.%df", decimal_places); + } else { + // NOTE: Emit the format string "%f" + DN_SNPrintF(float_fmt, sizeof(float_fmt), "%%f"); + } + DN_JSONBuilder_KeyValueF(builder, key, float_fmt, value); +} + +DN_API void DN_JSONBuilder_BoolNamed(DN_JSONBuilder *builder, DN_Str8 key, bool value) +{ + DN_Str8 value_string = value ? DN_STR8("true") : DN_STR8("false"); + DN_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data); +} +#endif // !defined(DN_NO_JSON_BUILDER) + +// NOTE: DN_JobQueue /////////////////////////////////////////////////////////////////////////////// +DN_API DN_JobQueueSPMC DN_OS_JobQueueSPMCInit() +{ + DN_JobQueueSPMC result = {}; + result.thread_wait_for_job_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/); + result.wait_for_completion_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/); + result.complete_queue_write_semaphore = DN_OS_SemaphoreInit(DN_ArrayCountU(result.complete_queue)); + result.mutex = DN_OS_MutexInit(); return result; } -DN_API DN_Rect DN_Rect_Union(DN_Rect a, DN_Rect b) +DN_API bool DN_OS_JobQueueSPMCCanAdd(DN_JobQueueSPMC const *queue, uint32_t count) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min, max; - min.x = DN_Min(a_min.x, b_min.x); - min.y = DN_Min(a_min.y, b_min.y); - max.x = DN_Max(a_max.x, b_max.x); - max.y = DN_Max(a_max.y, b_max.y); - DN_Rect result = DN_Rect_Init2V2(min, max - min); + uint32_t read_index = queue->read_index; + uint32_t write_index = queue->write_index; + uint32_t size = write_index - read_index; + bool result = (size + count) <= DN_ArrayCountU(queue->jobs); return result; } -DN_API DN_RectMinMax DN_Rect_MinMax(DN_Rect a) +DN_API bool DN_OS_JobQueueSPMCAddArray(DN_JobQueueSPMC *queue, DN_Job *jobs, uint32_t count) { - DN_RectMinMax result = {}; - result.min = a.pos; - result.max = a.pos + a.size; + if (!queue) + return false; + + uint32_t const pot_mask = DN_ArrayCountU(queue->jobs) - 1; + uint32_t read_index = queue->read_index; + uint32_t write_index = queue->write_index; + uint32_t size = write_index - read_index; + + if ((size + count) > DN_ArrayCountU(queue->jobs)) + return false; + + for (size_t offset = 0; offset < count; offset++) { + uint32_t wrapped_write_index = (write_index + offset) & pot_mask; + queue->jobs[wrapped_write_index] = jobs[offset]; + } + + DN_OS_MutexLock(&queue->mutex); + queue->write_index += count; + DN_OS_SemaphoreIncrement(&queue->thread_wait_for_job_semaphore, count); + DN_OS_MutexUnlock(&queue->mutex); + return true; +} + +DN_API bool DN_OS_JobQueueSPMCAdd(DN_JobQueueSPMC *queue, DN_Job job) +{ + bool result = DN_OS_JobQueueSPMCAddArray(queue, &job, 1); return result; } -DN_API DN_F32 DN_Rect_Area(DN_Rect a) +DN_API int32_t DN_OS_JobQueueSPMCThread(DN_OSThread *thread) { - DN_F32 result = a.size.w * a.size.h; - return result; -} + DN_JobQueueSPMC *queue = DN_CAST(DN_JobQueueSPMC *) thread->user_context; + uint32_t const pot_mask = DN_ArrayCountU(queue->jobs) - 1; + static_assert(DN_ArrayCountU(queue->jobs) == DN_ArrayCountU(queue->complete_queue), "PoT mask is used to mask access to both arrays"); -DN_API DN_Rect DN_Rect_CutLeftClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_max_x = min_x + amount; - if (clip) - result_max_x = DN_Min(result_max_x, max_x); - DN_Rect result = DN_Rect_Init4N(min_x, rect->pos.y, result_max_x - min_x, rect->size.h); - rect->pos.x = result_max_x; - rect->size.w = max_x - result_max_x; - return result; -} + for (;;) { + DN_OS_SemaphoreWait(&queue->thread_wait_for_job_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); + if (queue->quit) + break; -DN_API DN_Rect DN_Rect_CutRightClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_min_x = max_x - amount; - if (clip) - result_min_x = DN_Max(result_min_x, 0); - DN_Rect result = DN_Rect_Init4N(result_min_x, rect->pos.y, max_x - result_min_x, rect->size.h); - rect->size.w = result_min_x - min_x; - return result; -} + DN_Assert(queue->read_index != queue->write_index); -DN_API DN_Rect DN_Rect_CutTopClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_max_y = min_y + amount; - if (clip) - result_max_y = DN_Min(result_max_y, max_y); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, min_y, rect->size.w, result_max_y - min_y); - rect->pos.y = result_max_y; - rect->size.h = max_y - result_max_y; - return result; -} + DN_OS_MutexLock(&queue->mutex); + uint32_t wrapped_read_index = queue->read_index & pot_mask; + DN_Job job = queue->jobs[wrapped_read_index]; + queue->read_index += 1; + DN_OS_MutexUnlock(&queue->mutex); -DN_API DN_Rect DN_Rect_CutBottomClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_min_y = max_y - amount; - if (clip) - result_min_y = DN_Max(result_min_y, 0); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, result_min_y, rect->size.w, max_y - result_min_y); - rect->size.h = result_min_y - min_y; - return result; -} + job.elapsed_tsc -= DN_CPU_TSC(); + job.func(thread, job.user_context); + job.elapsed_tsc += DN_CPU_TSC(); -DN_API DN_Rect DN_RectCut_Cut(DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip) -{ - DN_Rect result = {}; - if (rect_cut.rect) { - switch (rect_cut.side) { - case DN_RectCutSide_Left: result = DN_Rect_CutLeftClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Right: result = DN_Rect_CutRightClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Top: result = DN_Rect_CutTopClip(rect_cut.rect, size.h, clip); break; - case DN_RectCutSide_Bottom: result = DN_Rect_CutBottomClip(rect_cut.rect, size.h, clip); break; + if (job.add_to_completion_queue) { + DN_OS_SemaphoreWait(&queue->complete_queue_write_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); + DN_OS_MutexLock(&queue->mutex); + queue->complete_queue[(queue->complete_write_index++ & pot_mask)] = job; + DN_OS_MutexUnlock(&queue->mutex); + DN_OS_SemaphoreIncrement(&queue->complete_queue_write_semaphore, 1); } - } - return result; -} -DN_API DN_V2F32 DN_Rect_InterpolatedPoint(DN_Rect rect, DN_V2F32 t01) -{ - DN_V2F32 result = DN_V2F32_Init2N(rect.pos.w + (rect.size.w * t01.x), - rect.pos.h + (rect.size.h * t01.y)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 1)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 1)); - return result; -} -#endif // !defined(DN_NO_RECT) - -// NOTE: Raycast /////////////////////////////////////////////////////////////////////////////////// - -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) -{ - // NOTE: Parametric equation of a line - // - // p = o + (t*d) - // - // - o is the starting 2d point - // - d is the direction of the line - // - t is a scalar that scales along the direction of the point - // - // To determine if a ray intersections a ray, we want to solve - // - // (o_a + (t_a * d_a)) = (o_b + (t_b * d_b)) - // - // Where '_a' and '_b' represent the 1st and 2nd point's origin, direction - // and 't' components respectively. This is 2 equations with 2 unknowns - // (`t_a` and `t_b`) which we can solve for by expressing the equation in - // terms of `t_a` and `t_b`. - // - // Working that math out produces the formula below for 't'. - - DN_RaycastLineIntersectV2Result result = {}; - DN_F32 denominator = ((dir_b.y * dir_a.x) - (dir_b.x * dir_a.y)); - if (denominator != 0.0f) { - result.t_a = (((origin_a.y - origin_b.y) * dir_b.x) + ((origin_b.x - origin_a.x) * dir_b.y)) / denominator; - result.t_b = (((origin_a.y - origin_b.y) * dir_a.x) + ((origin_b.x - origin_a.x) * dir_a.y)) / denominator; - result.hit = true; - } - return result; -} - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) -{ - DN_V2F32 result = {}; - result.x = a.x + ((b.x - a.x) * t); - result.y = a.y + ((b.y - a.y) * t); - return result; -} - -DN_API DN_F32 DN_Lerp_F32(DN_F32 a, DN_F32 t, DN_F32 b) -{ - DN_F32 result = a + ((b - a) * t); - return result; -} -#define DN_MATH_CPP - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_V2I32 -DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator!=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2I32 lhs, DN_V2I32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2I32 operator-(DN_V2I32 lhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2I32 operator+(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator*(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_V2I32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, DN_F32 rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 operator/(DN_V2I32 lhs, int32_t rhs) -{ - DN_V2I32 result = DN_V2I32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator*=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator/=(DN_V2I32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2I32 &operator-=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2I32 &operator+=(DN_V2I32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2I32 DN_V2I32_Min(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Max(DN_V2I32 a, DN_V2I32 b) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) -{ - DN_V2I32 result = DN_V2I32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -// NOTE: DN_V2U16 -DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2U16 lhs, DN_V2U16 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -DN_API DN_V2U16 operator-(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2U16 operator+(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator*(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_V2U16 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, DN_F32 rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 operator/(DN_V2U16 lhs, int32_t rhs) -{ - DN_V2U16 result = DN_V2U16_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator*=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator/=(DN_V2U16 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2U16 &operator-=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -// NOTE: DN_V2 -DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); - return result; -} - -DN_API bool operator>=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y); - return result; -} - -DN_API bool operator<=(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y); - return result; -} - -DN_API bool operator<(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y); - return result; -} - -DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y); - return result; -} - -// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator-(DN_V2F32 lhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(-lhs.x, -lhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs.x, lhs.y - rhs.y); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x - rhs, lhs.y - rhs); - return result; -} - -// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs.x, lhs.y + rhs.y); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x + rhs, lhs.y + rhs); - return result; -} - -// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs.x, lhs.y * rhs.y); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x * rhs, lhs.y * rhs); - return result; -} - -// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2I32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs.x, lhs.y / rhs.y); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_F32 rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) -{ - DN_V2F32 result = DN_V2F32_Init2N(lhs.x / rhs, lhs.y / rhs); - return result; -} - -// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2I32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, int32_t rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_V2F32 DN_V2F32_Min(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Min(a.x, b.x), DN_Min(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Max(DN_V2F32 a, DN_V2F32 b) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Max(a.x, b.x), DN_Max(a.y, b.y)); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Abs(DN_V2F32 a) -{ - DN_V2F32 result = DN_V2F32_Init2N(DN_Abs(a.x), DN_Abs(a.y)); - return result; -} - -DN_API DN_F32 DN_V2F32_Dot(DN_V2F32 a, DN_V2F32 b) -{ - // NOTE: Scalar projection of B onto A ///////////////////////////////////////////////////////// - // - // Scalar projection calculates the signed distance between `b` and `a` - // where `a` is a unit vector then, the dot product calculates the projection - // of `b` onto the infinite line that the direction of `a` represents. This - // calculation is the signed distance. - // - // signed_distance = dot_product(a, b) = (a.x * b.x) + (a.y * b.y) - // - // Y - // ^ b - // | /| - // | / | - // | / | - // | / | Projection - // | / | - // |/ V - // +--->--------> X - // . a . - // . . - // |------| <- Calculated signed distance - // - // The signed-ness of the result indicates the relationship: - // - // Distance <0 means `b` is behind `a` - // Distance >0 means `b` is in-front of `a` - // Distance ==0 means `b` is perpendicular to `a` - // - // If `a` is not normalized then the signed-ness of the result still holds - // however result no longer represents the actual distance between the - // 2 objects. One of the vectors must be normalised (e.g. turned into a unit - // vector). - // - // NOTE: DN_V projection ///////////////////////////////////////////////////////////////////// - // - // DN_V projection calculates the exact X,Y coordinates of where `b` meets - // `a` when it was projected. This is calculated by multipying the - // 'scalar projection' result by the unit vector of `a` - // - // vector_projection = a * signed_distance = a * dot_product(a, b) - - DN_F32 result = (a.x * b.x) + (a.y * b.y); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - // NOTE: Pythagoras's theorem (a^2 + b^2 = c^2) without the square root - DN_F32 a = rhs.x - lhs.x; - DN_F32 b = rhs.y - lhs.y; - DN_F32 c_squared = DN_Squared(a) + DN_Squared(b); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length_V2x2(DN_V2F32 lhs, DN_V2F32 rhs) -{ - DN_F32 result_squared = DN_V2F32_LengthSq_V2x2(lhs, rhs); - DN_F32 result = DN_SqrtF32(result_squared); - return result; -} - -DN_API DN_F32 DN_V2F32_LengthSq(DN_V2F32 lhs) -{ - // NOTE: Pythagoras's theorem without the square root - DN_F32 c_squared = DN_Squared(lhs.x) + DN_Squared(lhs.y); - DN_F32 result = c_squared; - return result; -} - -DN_API DN_F32 DN_V2F32_Length(DN_V2F32 lhs) -{ - DN_F32 c_squared = DN_V2F32_LengthSq(lhs); - DN_F32 result = DN_SqrtF32(c_squared); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Normalise(DN_V2F32 a) -{ - DN_F32 length = DN_V2F32_Length(a); - DN_V2F32 result = a / length; - return result; -} - -DN_API DN_V2F32 DN_V2F32_Perpendicular(DN_V2F32 a) -{ - // NOTE: Matrix form of a 2D vector can be defined as - // - // x' = x cos(t) - y sin(t) - // y' = x sin(t) + y cos(t) - // - // Calculate a line perpendicular to a vector means rotating the vector by - // 90 degrees - // - // x' = x cos(90) - y sin(90) - // y' = x sin(90) + y cos(90) - // - // Where `cos(90) = 0` and `sin(90) = 1` then, - // - // x' = -y - // y' = +x - - DN_V2F32 result = DN_V2F32_Init2N(-a.y, a.x); - return result; -} - -DN_API DN_V2F32 DN_V2F32_Reflect(DN_V2F32 in, DN_V2F32 surface) -{ - DN_V2F32 normal = DN_V2F32_Perpendicular(surface); - DN_V2F32 normal_norm = DN_V2F32_Normalise(normal); - DN_F32 signed_dist = DN_V2F32_Dot(in, normal_norm); - DN_V2F32 result = DN_V2F32_Init2N(in.x, in.y + (-signed_dist * 2.f)); - return result; -} - -DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) -{ - DN_F32 result = a.w * a.h; - return result; -} -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator==(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z); - return result; -} - -DN_API bool operator>=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z); - return result; -} - -DN_API bool operator<=(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z); - return result; -} - -DN_API bool operator<(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z); - return result; -} - -DN_API bool operator>(DN_V3F32 lhs, DN_V3F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); - return result; -} - -DN_API DN_V3F32 operator-(DN_V3F32 lhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(-lhs.x, -lhs.y, -lhs.z); - return result; -} - -DN_API DN_V3F32 operator+(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator*(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_V3F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, DN_F32 rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 operator/(DN_V3F32 lhs, int32_t rhs) -{ - DN_V3F32 result = DN_V3F32_Init3F32(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs); - return result; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator*=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, DN_F32 rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator/=(DN_V3F32 &lhs, int32_t rhs) -{ - lhs = lhs / rhs; - return lhs; -} - -DN_API DN_V3F32 &operator-=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V3F32 &operator+=(DN_V3F32 &lhs, DN_V3F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V3_LengthSq(DN_V3F32 a) -{ - DN_F32 result = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - return result; -} - -DN_API DN_F32 DN_V3_Length(DN_V3F32 a) -{ - DN_F32 length_sq = DN_Squared(a.x) + DN_Squared(a.y) + DN_Squared(a.z); - DN_F32 result = DN_SqrtF32(length_sq); - return result; -} - -DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) -{ - DN_F32 length = DN_V3_Length(a); - DN_V3F32 result = a / length; - return result; -} -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.w == rhs.w); - return result; -} - -DN_API bool operator!=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = !(lhs == rhs); - return result; -} - -DN_API bool operator>=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z) && (lhs.w >= rhs.w); - return result; -} - -DN_API bool operator<=(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z) && (lhs.w <= rhs.w); - return result; -} - -DN_API bool operator<(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z) && (lhs.w < rhs.w); - return result; -} - -DN_API bool operator>(DN_V4F32 lhs, DN_V4F32 rhs) -{ - bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z) && (lhs.w > rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); - return result; -} - -DN_API DN_V4F32 operator-(DN_V4F32 lhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(-lhs.x, -lhs.y, -lhs.z, -lhs.w); - return result; -} - -DN_API DN_V4F32 operator+(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_V4F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator*(DN_V4F32 lhs, int32_t rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); - return result; -} - -DN_API DN_V4F32 operator/(DN_V4F32 lhs, DN_F32 rhs) -{ - DN_V4F32 result = DN_V4F32_Init4N(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); - return result; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, DN_F32 rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator*=(DN_V4F32 &lhs, int32_t rhs) -{ - lhs = lhs * rhs; - return lhs; -} - -DN_API DN_V4F32 &operator-=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs - rhs; - return lhs; -} - -DN_API DN_V4F32 &operator+=(DN_V4F32 &lhs, DN_V4F32 rhs) -{ - lhs = lhs + rhs; - return lhs; -} - -DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) -{ - DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); - return result; -} -#endif // !defined(DN_NO_V4) - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_M4 DN_M4_Identity() -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_ScaleF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {x, 0, 0, 0}, - {0, y, 0, 0}, - {0, 0, z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Scale(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {xyz.x, 0, 0, 0}, - {0, xyz.y, 0, 0}, - {0, 0, xyz.z, 0}, - {0, 0, 0, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_TranslateF(DN_F32 x, DN_F32 y, DN_F32 z) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {x, y, z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Translate(DN_V3F32 xyz) -{ - DN_M4 result = - { - { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {xyz.x, xyz.y, xyz.z, 1}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Transpose(DN_M4 mat) -{ - DN_M4 result = {}; - for (int col = 0; col < 4; col++) - for (int row = 0; row < 4; row++) - result.columns[col][row] = mat.columns[row][col]; - return result; -} - -DN_API DN_M4 DN_M4_Rotate(DN_V3F32 axis01, DN_F32 radians) -{ - DN_AssertF(DN_Abs(DN_V3_Length(axis01) - 1.f) <= 0.01f, - "Rotation axis must be normalised, length = %f", - DN_V3_Length(axis01)); - - DN_F32 sin = DN_SinF32(radians); - DN_F32 cos = DN_CosF32(radians); - DN_F32 one_minus_cos = 1.f - cos; - - DN_F32 x = axis01.x; - DN_F32 y = axis01.y; - DN_F32 z = axis01.z; - DN_F32 x2 = DN_Squared(x); - DN_F32 y2 = DN_Squared(y); - DN_F32 z2 = DN_Squared(z); - - DN_M4 result = - { - { - {cos + x2 * one_minus_cos, y * x * one_minus_cos + z * sin, z * x * one_minus_cos - y * sin, 0}, // Col 1 - {x * y * one_minus_cos - z * sin, cos + y2 * one_minus_cos, z * y * one_minus_cos + x * sin, 0}, // Col 2 - {x * z * one_minus_cos + y * sin, y * z * one_minus_cos - x * sin, cos + z2 * one_minus_cos, 0}, // Col 3 - {0, 0, 0, 1}, // Col 4 - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Orthographic(DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far) -{ - // NOTE: Here is the matrix in column major for readability. Below it's - // transposed due to how you have to declare column major matrices in C/C++. - // - // m = [2/r-l, 0, 0, -1*(r+l)/(r-l)] - // [0, 2/t-b, 0, 1*(t+b)/(t-b)] - // [0, 0, -2/f-n, -1*(f+n)/(f-n)] - // [0, 0, 0, 1 ] - - DN_M4 result = - { - { - {2.f / (right - left), 0.f, 0.f, 0.f}, - {0.f, 2.f / (top - bottom), 0.f, 0.f}, - {0.f, 0.f, -2.f / (z_far - z_near), 0.f}, - {(-1.f * (right + left)) / (right - left), (-1.f * (top + bottom)) / (top - bottom), (-1.f * (z_far + z_near)) / (z_far - z_near), 1.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Perspective(DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far) -{ - DN_F32 tan_fov = DN_TanF32(fov / 2.f); - DN_M4 result = - { - { - {1.f / (aspect * tan_fov), 0.f, 0.f, 0.f}, - {0, 1.f / tan_fov, 0.f, 0.f}, - {0.f, 0.f, (z_near + z_far) / (z_near - z_far), -1.f}, - {0.f, 0.f, (2.f * z_near * z_far) / (z_near - z_far), 0.f}, - } - }; - - return result; -} - -DN_API DN_M4 DN_M4_Add(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Sub(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_Mul(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) { - for (int row = 0; row < 4; row++) { - DN_F32 sum = 0; - for (int f32_it = 0; f32_it < 4; f32_it++) - sum += lhs.columns[f32_it][row] * rhs.columns[col][f32_it]; - - result.columns[col][row] = sum; - } - } - return result; -} - -DN_API DN_M4 DN_M4_Div(DN_M4 lhs, DN_M4 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs.columns[col][it]; - return result; -} - -DN_API DN_M4 DN_M4_AddF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] + rhs; - return result; -} - -DN_API DN_M4 DN_M4_SubF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] - rhs; - return result; -} - -DN_API DN_M4 DN_M4_MulF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] * rhs; - return result; -} - -DN_API DN_M4 DN_M4_DivF(DN_M4 lhs, DN_F32 rhs) -{ - DN_M4 result; - for (int col = 0; col < 4; col++) - for (int it = 0; it < 4; it++) - result.columns[col][it] = lhs.columns[col][it] / rhs; - return result; -} - - #if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString(DN_M4 mat) -{ - DN_FStr8<256> result = {}; - for (int row = 0; row < 4; row++) { - for (int it = 0; it < 4; it++) { - if (it == 0) - DN_FStr8_Add(&result, DN_STR8("|")); - DN_FStr8_AddF(&result, "%.5f", mat.columns[it][row]); - if (it != 3) - DN_FStr8_Add(&result, DN_STR8(", ")); - else - DN_FStr8_Add(&result, DN_STR8("|\n")); + // NOTE: Update finish counter + DN_OS_MutexLock(&queue->mutex); + queue->finish_index += 1; + + // NOTE: If all jobs are finished and we have another thread who is + // blocked via `WaitForCompletion` for this job queue, we will go + // release the semaphore to wake them all up. + bool all_jobs_finished = queue->finish_index == queue->write_index; + if (all_jobs_finished && queue->threads_waiting_for_completion) { + DN_OS_SemaphoreIncrement(&queue->wait_for_completion_semaphore, + queue->threads_waiting_for_completion); + queue->threads_waiting_for_completion = 0; } + DN_OS_MutexUnlock(&queue->mutex); } - return result; -} - #endif -#endif // !defined(DN_M4) - -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) -{ - bool result = DN_Memcmp(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ArrayCountU(lhs.e)) == 0; - return result; + return queue->quit_exit_code; } -DN_API bool operator!=(DN_M2x3 const &lhs, DN_M2x3 const &rhs) +DN_API void DN_OS_JobQueueSPMCWaitForCompletion(DN_JobQueueSPMC *queue) { - bool result = !(lhs == rhs); - return result; -} - -DN_API DN_M2x3 DN_M2x3_Identity() -{ - DN_M2x3 result = { - { - 1, - 0, - 0, - 0, - 1, - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Translate(DN_V2F32 offset) -{ - DN_M2x3 result = { - { - 1, - 0, - offset.x, - 0, - 1, - offset.y, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Scale(DN_V2F32 scale) -{ - DN_M2x3 result = { - { - scale.x, - 0, - 0, - 0, - scale.y, - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Rotate(DN_F32 radians) -{ - DN_M2x3 result = { - { - DN_CosF32(radians), - DN_SinF32(radians), - 0, - -DN_SinF32(radians), - DN_CosF32(radians), - 0, - } - }; - return result; -} - -DN_API DN_M2x3 DN_M2x3_Mul(DN_M2x3 m1, DN_M2x3 m2) -{ - // NOTE: Ordinarily you can't multiply M2x3 with M2x3 because column count - // (3) != row count (2). We pretend we have two 3x3 matrices with the last - // row set to [0 0 1] and perform a 3x3 matrix multiply. - // - // | (0)a (1)b (2)c | | (0)g (1)h (2)i | - // | (3)d (4)e (5)f | x | (3)j (4)k (5)l | - // | (6)0 (7)0 (8)1 | | (6)0 (7)0 (8)1 | - - DN_M2x3 result = { - { - m1.e[0] * m2.e[0] + m1.e[1] * m2.e[3], // a*g + b*j + c*0[omitted], - m1.e[0] * m2.e[1] + m1.e[1] * m2.e[4], // a*h + b*k + c*0[omitted], - m1.e[0] * m2.e[2] + m1.e[1] * m2.e[5] + m1.e[2], // a*i + b*l + c*1, - - m1.e[3] * m2.e[0] + m1.e[4] * m2.e[3], // d*g + e*j + f*0[omitted], - m1.e[3] * m2.e[1] + m1.e[4] * m2.e[4], // d*h + e*k + f*0[omitted], - m1.e[3] * m2.e[2] + m1.e[4] * m2.e[5] + m1.e[5], // d*i + e*l + f*1, - } - }; - - return result; -} - -DN_API DN_V2F32 DN_M2x3_Mul2F32(DN_M2x3 m1, DN_F32 x, DN_F32 y) -{ - // NOTE: Ordinarily you can't multiply M2x3 with V2 because column count (3) - // != row count (2). We pretend we have a V3 with `z` set to `1`. - // - // | (0)a (1)b (2)c | | x | - // | (3)d (4)e (5)f | x | y | - // | 1 | - - DN_V2F32 result = { - { - m1.e[0] * x + m1.e[1] * y + m1.e[2], // a*x + b*y + c*1 - m1.e[3] * x + m1.e[4] * y + m1.e[5], // d*x + e*y + f*1 - } - }; - return result; -} - -DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) -{ - DN_V2F32 result = DN_M2x3_Mul2F32(m1, v2.x, v2.y); - return result; -} - -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator==(const DN_Rect &lhs, const DN_Rect &rhs) -{ - bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); - return result; -} - -DN_API DN_V2F32 DN_Rect_Center(DN_Rect rect) -{ - DN_V2F32 result = rect.pos + (rect.size * .5f); - return result; -} - -DN_API bool DN_Rect_ContainsPoint(DN_Rect rect, DN_V2F32 p) -{ - DN_V2F32 min = rect.pos; - DN_V2F32 max = rect.pos + rect.size; - bool result = (p.x >= min.x && p.x <= max.x && p.y >= min.y && p.y <= max.y); - return result; -} - -DN_API bool DN_Rect_ContainsRect(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (b_min >= a_min && b_max <= a_max); - return result; -} - -DN_API DN_Rect DN_Rect_Expand(DN_Rect a, DN_F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API DN_Rect DN_Rect_ExpandV2(DN_Rect a, DN_V2F32 amount) -{ - DN_Rect result = a; - result.pos -= amount; - result.size += (amount * 2.f); - return result; -} - -DN_API bool DN_Rect_Intersects(DN_Rect a, DN_Rect b) -{ - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - bool result = (a_min.x <= b_max.x && a_max.x >= b_min.x) && - (a_min.y <= b_max.y && a_max.y >= b_min.y); - return result; -} - -DN_API DN_Rect DN_Rect_Intersection(DN_Rect a, DN_Rect b) -{ - DN_Rect result = DN_Rect_Init2V2(a.pos, DN_V2F32_Init1N(0)); - if (DN_Rect_Intersects(a, b)) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; - - DN_V2F32 min = {}; - DN_V2F32 max = {}; - min.x = DN_Max(a_min.x, b_min.x); - min.y = DN_Max(a_min.y, b_min.y); - max.x = DN_Min(a_max.x, b_max.x); - max.y = DN_Min(a_max.y, b_max.y); - result = DN_Rect_Init2V2(min, max - min); + DN_OS_MutexLock(&queue->mutex); + if (queue->finish_index == queue->write_index) { + DN_OS_MutexUnlock(&queue->mutex); + return; } - return result; + queue->threads_waiting_for_completion++; + DN_OS_MutexUnlock(&queue->mutex); + + DN_OS_SemaphoreWait(&queue->wait_for_completion_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); } -DN_API DN_Rect DN_Rect_Union(DN_Rect a, DN_Rect b) +DN_API DN_USize DN_OS_JobQueueSPMCGetFinishedJobs(DN_JobQueueSPMC *queue, DN_Job *jobs, DN_USize jobs_size) { - DN_V2F32 a_min = a.pos; - DN_V2F32 a_max = a.pos + a.size; - DN_V2F32 b_min = b.pos; - DN_V2F32 b_max = b.pos + b.size; + DN_USize result = 0; + if (!queue || !jobs || jobs_size <= 0) + return result; - DN_V2F32 min, max; - min.x = DN_Min(a_min.x, b_min.x); - min.y = DN_Min(a_min.y, b_min.y); - max.x = DN_Max(a_max.x, b_max.x); - max.y = DN_Max(a_max.y, b_max.y); - DN_Rect result = DN_Rect_Init2V2(min, max - min); - return result; -} + uint32_t const pot_mask = DN_ArrayCountU(queue->jobs) - 1; + DN_OS_MutexLock(&queue->mutex); + while (queue->complete_read_index < queue->complete_write_index && result < jobs_size) + jobs[result++] = queue->complete_queue[(queue->complete_read_index++ & pot_mask)]; + DN_OS_MutexUnlock(&queue->mutex); -DN_API DN_RectMinMax DN_Rect_MinMax(DN_Rect a) -{ - DN_RectMinMax result = {}; - result.min = a.pos; - result.max = a.pos + a.size; - return result; -} - -DN_API DN_F32 DN_Rect_Area(DN_Rect a) -{ - DN_F32 result = a.size.w * a.size.h; - return result; -} - -DN_API DN_Rect DN_Rect_CutLeftClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_max_x = min_x + amount; - if (clip) - result_max_x = DN_Min(result_max_x, max_x); - DN_Rect result = DN_Rect_Init4N(min_x, rect->pos.y, result_max_x - min_x, rect->size.h); - rect->pos.x = result_max_x; - rect->size.w = max_x - result_max_x; - return result; -} - -DN_API DN_Rect DN_Rect_CutRightClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_x = rect->pos.x; - DN_F32 max_x = rect->pos.x + rect->size.w; - DN_F32 result_min_x = max_x - amount; - if (clip) - result_min_x = DN_Max(result_min_x, 0); - DN_Rect result = DN_Rect_Init4N(result_min_x, rect->pos.y, max_x - result_min_x, rect->size.h); - rect->size.w = result_min_x - min_x; - return result; -} - -DN_API DN_Rect DN_Rect_CutTopClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_max_y = min_y + amount; - if (clip) - result_max_y = DN_Min(result_max_y, max_y); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, min_y, rect->size.w, result_max_y - min_y); - rect->pos.y = result_max_y; - rect->size.h = max_y - result_max_y; - return result; -} - -DN_API DN_Rect DN_Rect_CutBottomClip(DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip) -{ - DN_F32 min_y = rect->pos.y; - DN_F32 max_y = rect->pos.y + rect->size.h; - DN_F32 result_min_y = max_y - amount; - if (clip) - result_min_y = DN_Max(result_min_y, 0); - DN_Rect result = DN_Rect_Init4N(rect->pos.x, result_min_y, rect->size.w, max_y - result_min_y); - rect->size.h = result_min_y - min_y; - return result; -} - -DN_API DN_Rect DN_RectCut_Cut(DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip) -{ - DN_Rect result = {}; - if (rect_cut.rect) { - switch (rect_cut.side) { - case DN_RectCutSide_Left: result = DN_Rect_CutLeftClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Right: result = DN_Rect_CutRightClip(rect_cut.rect, size.w, clip); break; - case DN_RectCutSide_Top: result = DN_Rect_CutTopClip(rect_cut.rect, size.h, clip); break; - case DN_RectCutSide_Bottom: result = DN_Rect_CutBottomClip(rect_cut.rect, size.h, clip); break; - } - } - return result; -} - -DN_API DN_V2F32 DN_Rect_InterpolatedPoint(DN_Rect rect, DN_V2F32 t01) -{ - DN_V2F32 result = DN_V2F32_Init2N(rect.pos.w + (rect.size.w * t01.x), - rect.pos.h + (rect.size.h * t01.y)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_TopRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 0)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomLeft(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(0, 1)); - return result; -} - -DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) -{ - DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_Init2N(1, 1)); - return result; -} -#endif // !defined(DN_NO_RECT) - -// NOTE: Raycast /////////////////////////////////////////////////////////////////////////////////// - -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) -{ - // NOTE: Parametric equation of a line - // - // p = o + (t*d) - // - // - o is the starting 2d point - // - d is the direction of the line - // - t is a scalar that scales along the direction of the point - // - // To determine if a ray intersections a ray, we want to solve - // - // (o_a + (t_a * d_a)) = (o_b + (t_b * d_b)) - // - // Where '_a' and '_b' represent the 1st and 2nd point's origin, direction - // and 't' components respectively. This is 2 equations with 2 unknowns - // (`t_a` and `t_b`) which we can solve for by expressing the equation in - // terms of `t_a` and `t_b`. - // - // Working that math out produces the formula below for 't'. - - DN_RaycastLineIntersectV2Result result = {}; - DN_F32 denominator = ((dir_b.y * dir_a.x) - (dir_b.x * dir_a.y)); - if (denominator != 0.0f) { - result.t_a = (((origin_a.y - origin_b.y) * dir_b.x) + ((origin_b.x - origin_a.x) * dir_b.y)) / denominator; - result.t_b = (((origin_a.y - origin_b.y) * dir_a.x) + ((origin_b.x - origin_a.x) * dir_a.y)) / denominator; - result.hit = true; - } - return result; -} - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) -{ - DN_V2F32 result = {}; - result.x = a.x + ((b.x - a.x) * t); - result.y = a.y + ((b.y - a.y) * t); - return result; -} - -DN_API DN_F32 DN_Lerp_F32(DN_F32 a, DN_F32 t, DN_F32 b) -{ - DN_F32 result = a + ((b - a) * t); return result; } \ No newline at end of file diff --git a/Single_Header/dn_single_header.h b/Single_Header/dn_single_header.h index 790bc44..349810c 100644 --- a/Single_Header/dn_single_header.h +++ b/Single_Header/dn_single_header.h @@ -1,4 +1,4 @@ -// Generated by the DN single header generator 2025-06-27 16:54:49 +// Generated by the DN single header generator 2025-06-28 20:52:01 #if !defined(DN_BASE_INC_H) #define DN_BASE_INC_H @@ -3957,6 +3957,7 @@ template struct DN_List #define DN_LArray_PrependArray(c_array, size, max, items, count) (decltype(&(c_array)[0])) DN_CArray2_AddArray (c_array, size, max, sizeof((c_array)[0]), items, count, DN_ArrayAdd_Prepend) #define DN_LArray_Prepend(c_array, size, max, item) (decltype(&(c_array)[0])) DN_CArray2_AddArray (c_array, size, max, sizeof((c_array)[0]), &item, 1, DN_ArrayAdd_Prepend) #define DN_LArray_EraseRange(c_array, size, begin_index, count, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), begin_index, count, erase) +#define DN_LArray_Erase(c_array, size, index, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), index, 1, erase) #define DN_IArray_Front(array) (array)->data #define DN_IArray_GrowIfNeededFromPool(array, pool) DN_CArray2_GrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool) @@ -3971,6 +3972,7 @@ template struct DN_List #define DN_IArray_PrependArray(array, items, count) (decltype(&((array)->data)[0])) DN_CArray2_AddArray ((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Prepend) #define DN_IArray_Prepend(array, item) (decltype(&((array)->data)[0])) DN_CArray2_AddArray ((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend) #define DN_IArray_EraseRange(array, size, begin_index, count, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), begin_index, count, erase) +#define DN_IArray_Erase(array, size, index, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), index, 1, erase) DN_API DN_ArrayEraseResult DN_CArray2_EraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); DN_API void *DN_CArray2_MakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZeroMem zero_mem); @@ -7006,2319 +7008,503 @@ DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); #endif // !defined(DN_MATH_H) +#if !defined(DN_ASYNC_H) +#define DN_ASYNC_H + +// DN: Single header generator commented out this header => #include "../dn_base_inc.h" +// DN: Single header generator commented out this header => #include "../dn_os_inc.h" + +enum DN_ASYNCPriority +{ + DN_ASYNCPriority_Low, + DN_ASYNCPriority_High, + DN_ASYNCPriority_Count, +}; + +struct DN_ASYNCCore +{ + DN_OSMutex ring_mutex; + DN_OSConditionVariable ring_write_cv; + DN_OSSemaphore worker_sem; + DN_Ring ring; + DN_OSThread *threads; + DN_U32 thread_count; + DN_U32 busy_threads; + DN_U32 join_threads; +}; + +typedef void(DN_ASYNCWorkFunc)(void *input); + +struct DN_ASYNCWork +{ + DN_ASYNCWorkFunc *func; + void *input; + void *output; +}; + +struct DN_ASYNCJob +{ + DN_ASYNCWork work; + DN_OSSemaphore completion_sem; +}; + +struct DN_ASYNCTask +{ + DN_ASYNCWork work; +}; + +DN_API void DN_ASYNC_Init (DN_ASYNCCore *async, char *base, DN_USize base_size, DN_OSThread *threads, DN_U32 threads_size); +DN_API void DN_ASYNC_Deinit (DN_ASYNCCore *async); +DN_API bool DN_ASYNC_QueueWork(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms); +DN_API DN_OSSemaphore DN_ASYNC_QueueTask(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms); +DN_API void DN_ASYNC_WaitTask (DN_OSSemaphore *sem, DN_U32 timeout_ms); + +#endif // DN_ASYNC_H +#if !defined(DN_BIN_PACK_H) +#define DN_BIN_PACK_H + +#if !defined(DN_BASE_INC_H) + #error dn_base_inc.h must be included before this +#endif + +enum DN_BinPackMode +{ + DN_BinPackMode_Serialise, + DN_BinPackMode_Deserialise, +}; + +struct DN_BinPack +{ + DN_Str8Builder writer; + DN_Str8 read; + DN_USize read_index; +}; + +DN_API void DN_BinPack_U64 (DN_BinPack *pack, DN_BinPackMode mode, DN_U64 *item); +DN_API void DN_BinPack_U32 (DN_BinPack *pack, DN_BinPackMode mode, DN_U32 *item); +DN_API void DN_BinPack_U16 (DN_BinPack *pack, DN_BinPackMode mode, DN_U16 *item); +DN_API void DN_BinPack_U8 (DN_BinPack *pack, DN_BinPackMode mode, DN_U8 *item); +DN_API void DN_BinPack_I64 (DN_BinPack *pack, DN_BinPackMode mode, DN_I64 *item); +DN_API void DN_BinPack_I32 (DN_BinPack *pack, DN_BinPackMode mode, DN_I32 *item); +DN_API void DN_BinPack_I16 (DN_BinPack *pack, DN_BinPackMode mode, DN_I16 *item); +DN_API void DN_BinPack_I8 (DN_BinPack *pack, DN_BinPackMode mode, DN_I8 *item); +DN_API void DN_BinPack_F64 (DN_BinPack *pack, DN_BinPackMode mode, DN_F64 *item); +DN_API void DN_BinPack_F32 (DN_BinPack *pack, DN_BinPackMode mode, DN_F32 *item); +#if defined(DN_MATH_H) +DN_API void DN_BinPack_V2 (DN_BinPack *pack, DN_BinPackMode mode, DN_V2F32 *item); +DN_API void DN_BinPack_V4 (DN_BinPack *pack, DN_BinPackMode mode, DN_V4F32 *item); +#endif +DN_API void DN_BinPack_Bool (DN_BinPack *pack, DN_BinPackMode mode, bool *item); +DN_API void DN_BinPack_Str8 (DN_BinPack *pack, DN_Arena *arena, DN_BinPackMode mode, DN_Str8 *string); +DN_API void DN_BinPack_Str8Pool(DN_BinPack *pack, DN_Pool *pool, DN_BinPackMode mode, DN_Str8 *string); +template DN_API void DN_BinPack_FStr8 (DN_BinPack *pack, DN_BinPackMode mode, DN_FStr8 *string); +DN_API void DN_BinPack_Bytes (DN_BinPack *pack, DN_Arena *arena, DN_BinPackMode mode, void **ptr, DN_USize *size); +DN_API void DN_BinPack_CArray (DN_BinPack *pack, DN_BinPackMode mode, void *ptr, DN_USize size); +DN_API DN_Str8 DN_BinPack_Build (DN_BinPack const *pack, DN_Arena *arena); + +#endif // !defined(DN_BIN_PACK_H) +#if !defined(DN_CSV_H) +#define DN_CSV_H + +enum DN_CSVSerialise +{ + DN_CSVSerialise_Read, + DN_CSVSerialise_Write, +}; + +struct DN_CSVTokeniser +{ + bool bad; + DN_Str8 string; + char delimiter; + char const *it; + bool end_of_line; +}; + +struct DN_CSVPack +{ + DN_Str8Builder write_builder; + DN_USize write_column; + DN_CSVTokeniser read_tokeniser; +}; + +#endif // !defined(DN_CSV_H) +#if !defined(DN_HASH_H) +#define DN_HASH_H + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// $$\ $$\ $$$$$$\ $$$$$$\ $$\ $$\ +// $$ | $$ |$$ __$$\ $$ __$$\ $$ | $$ | +// $$ | $$ |$$ / $$ |$$ / \__|$$ | $$ | +// $$$$$$$$ |$$$$$$$$ |\$$$$$$\ $$$$$$$$ | +// $$ __$$ |$$ __$$ | \____$$\ $$ __$$ | +// $$ | $$ |$$ | $$ |$$\ $$ |$$ | $$ | +// $$ | $$ |$$ | $$ |\$$$$$$ |$$ | $$ | +// \__| \__|\__| \__| \______/ \__| \__| +// +// dn_hash.h -- Hashing functions +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + +// NOTE: DN_FNV1A ////////////////////////////////////////////////////////////////////////////////// +#if !defined(DN_FNV1A32_SEED) + #define DN_FNV1A32_SEED 2166136261U +#endif + +#if !defined(DN_FNV1A64_SEED) + #define DN_FNV1A64_SEED 14695981039346656037ULL +#endif + +// NOTE: DN_MurmurHash3 //////////////////////////////////////////////////////////////////////////// +struct DN_MurmurHash3 { uint64_t e[2]; }; + +// NOTE: DN_FNV1A ////////////////////////////////////////////////////////////////////////////////// +DN_API uint32_t DN_FNV1A32_Hash (void const *bytes, DN_USize size); +DN_API uint64_t DN_FNV1A64_Hash (void const *bytes, DN_USize size); +DN_API uint32_t DN_FNV1A32_Iterate (void const *bytes, DN_USize size, uint32_t hash); +DN_API uint64_t DN_FNV1A64_Iterate (void const *bytes, DN_USize size, uint64_t hash); + +// NOTE: DN_MurmurHash3 //////////////////////////////////////////////////////////////////////////// +DN_API uint32_t DN_MurmurHash3_x86U32 (void const *key, int len, uint32_t seed); +DN_API DN_MurmurHash3 DN_MurmurHash3_x64U128 (void const *key, int len, uint32_t seed); +#define DN_MurmurHash3_x64U128AsU64(key, len, seed) (DN_MurmurHash3_x64U128(key, len, seed).e[0]) +#define DN_MurmurHash3_x64U128AsU32(key, len, seed) (DN_CAST(uint32_t)DN_MurmurHash3_x64U128(key, len, seed).e[0]) + +#endif // !defined(DN_HASH_H) +#if !defined(DN_HELPERS_H) +#define DN_HELPERS_H + +#if !defined(DN_BASE_H) + #error dn_base_inc.h must be included before this +#endif + #if !defined(DN_MATH_H) -#define DN_MATH_H - -DN_MSVC_WARNING_PUSH -DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V2I32 -{ - struct { int32_t x, y; }; - struct { int32_t w, h; }; - int32_t data[2]; -}; - -union DN_V2U16 -{ - struct { uint16_t x, y; }; - struct { uint16_t w, h; }; - uint16_t data[2]; -}; - -union DN_V2F32 -{ - struct { DN_F32 x, y; }; - struct { DN_F32 w, h; }; - DN_F32 data[2]; -}; -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V3F32 -{ - struct { DN_F32 x, y, z; }; - struct { DN_F32 r, g, b; }; - DN_F32 data[3]; -}; - -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V4F32 -{ - struct { DN_F32 x, y, z, w; }; - struct { DN_F32 r, g, b, a; }; - #if !defined(DN_NO_V3) - DN_V3F32 rgb; - DN_V3F32 xyz; - #endif - DN_F32 data[4]; -}; -#endif // !defined(DN_NO_V4) -DN_MSVC_WARNING_POP - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -struct DN_M4 -{ - DN_F32 columns[4][4]; // Column major matrix -}; -#endif // !defined(DN_M4) - -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -union DN_M2x3 -{ - DN_F32 e[6]; - DN_F32 row[2][3]; -}; - -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_RECT) -#if defined(DN_NO_V2) - #error "Rectangles requires V2, DN_NO_V2 must not be defined" + #error dn_math.h must be included before this #endif -struct DN_Rect + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// $$\ $$\ $$$$$$$$\ $$\ $$$$$$$\ $$$$$$$$\ $$$$$$$\ $$$$$$\ +// $$ | $$ |$$ _____|$$ | $$ __$$\ $$ _____|$$ __$$\ $$ __$$\ +// $$ | $$ |$$ | $$ | $$ | $$ |$$ | $$ | $$ |$$ / \__| +// $$$$$$$$ |$$$$$\ $$ | $$$$$$$ |$$$$$\ $$$$$$$ |\$$$$$$\ +// $$ __$$ |$$ __| $$ | $$ ____/ $$ __| $$ __$$< \____$$\ +// $$ | $$ |$$ | $$ | $$ | $$ | $$ | $$ |$$\ $$ | +// $$ | $$ |$$$$$$$$\ $$$$$$$$\ $$ | $$$$$$$$\ $$ | $$ |\$$$$$$ | +// \__| \__|\________|\________|\__| \________|\__| \__| \______/ +// +// dn_helpers.h -- Helper functions/data structures +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + +// NOTE: DN_PCG32 ////////////////////////////////////////////////////////////////////////////////// +struct DN_PCG32 { uint64_t state; }; + +#if !defined(DN_NO_JSON_BUILDER) +// NOTE: DN_JSONBuilder //////////////////////////////////////////////////////////////////////////// +enum DN_JSONBuilderItem { - DN_V2F32 pos, size; + DN_JSONBuilderItem_Empty, + DN_JSONBuilderItem_OpenContainer, + DN_JSONBuilderItem_CloseContainer, + DN_JSONBuilderItem_KeyValue, }; -struct DN_RectMinMax +struct DN_JSONBuilder { - DN_V2F32 min, max; + bool use_stdout; // When set, ignore the string builder and dump immediately to stdout + DN_Str8Builder string_builder; // (Internal) + int indent_level; // (Internal) + int spaces_per_indent; // The number of spaces per indent level + DN_JSONBuilderItem last_item; +}; +#endif // !defined(DN_NO_JSON_BUIDLER) + +// NOTE: DN_BinarySearch /////////////////////////////////////////////////////////////////////////// +template +using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs); + +template +bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs); + +enum DN_BinarySearchType +{ + // Index of the match. If no match is found, found is set to false and the + // index is set to the index where the match should be inserted/exist, if + // it were in the array + DN_BinarySearchType_Match, + + // Index of the first element in the array that is `element >= find`. If no such + // item is found or the array is empty, then, the index is set to the array + // size and found is set to `false`. + // + // For example: + // int array[] = {0, 1, 2, 3, 4, 5}; + // DN_BinarySearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BinarySearchType_LowerBound); + // printf("%zu\n", result.index); // Prints index '4' + + DN_BinarySearchType_LowerBound, + + // Index of the first element in the array that is `element > find`. If no such + // item is found or the array is empty, then, the index is set to the array + // size and found is set to `false`. + // + // For example: + // int array[] = {0, 1, 2, 3, 4, 5}; + // DN_BinarySearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BinarySearchType_UpperBound); + // printf("%zu\n", result.index); // Prints index '5' + + DN_BinarySearchType_UpperBound, }; -enum DN_RectCutClip +struct DN_BinarySearchResult { - DN_RectCutClip_No, - DN_RectCutClip_Yes, + bool found; + DN_USize index; }; -enum DN_RectCutSide +template +using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context); + +// NOTE: Misc ////////////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_JobQueue /////////////////////////////////////////////////////////////////////////////// +typedef void(DN_JobQueueFunc)(DN_OSThread *thread, void *user_context); +struct DN_Job { - DN_RectCutSide_Left, - DN_RectCutSide_Right, - DN_RectCutSide_Top, - DN_RectCutSide_Bottom, + DN_JobQueueFunc *func; // The function to invoke for the job + void *user_context; // Pointer user can set to use in their `job_func` + uint64_t elapsed_tsc; + uint16_t user_tag; // Arbitrary value the user can set to identiy the type of `user_context` this job has + bool add_to_completion_queue; // When true, on job completion, job must be dequeued from the completion queue via `GetFinishedJobs` }; -struct DN_RectCut -{ - DN_Rect* rect; - DN_RectCutSide side; -}; -#endif // !defined(DN_NO_RECT) - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: API -struct DN_RaycastLineIntersectV2Result -{ - bool hit; // True if there was an intersection, false if the lines are parallel - DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` - DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` -}; - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} -#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} -#define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} -#define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} -#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} - -DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs); -DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs); - -DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); - -#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_Init1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} - -DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); - -#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} -#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} -#define DN_V2F32_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} -#define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} -#define DN_V2F32_InitV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} - -DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs); - -DN_API DN_V2F32 operator- (DN_V2F32 lhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 DN_V2F32_Min (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Max (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Abs (DN_V2F32 a); -DN_API DN_F32 DN_V2F32_Dot (DN_V2F32 a, DN_V2F32 b); -DN_API DN_F32 DN_V2F32_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_LengthSq (DN_V2F32 lhs); -DN_API DN_F32 DN_V2F32_Length (DN_V2F32 lhs); -DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); -DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} -#define DN_V3F32_InitV2F32_1F32(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} - -DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs); -DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); -DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); -DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} -#define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} -DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs); -DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs); -DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs); -DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b); -DN_API DN_M4 DN_M4_Identity (); -DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_Transpose (DN_M4 mat); -DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians); -DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); -#if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat); +#if !defined(DN_JOB_QUEUE_SPMC_SIZE) + #define DN_JOB_QUEUE_SPMC_SIZE 128 #endif -#endif // !defined(DN_NO_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API DN_M2x3 DN_M2x3_Identity (); -DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); -DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); -DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); -DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); -DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); -DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#define DN_Rect_Init2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} -#define DN_Rect_Init4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} -DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); -DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); -DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p); -DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount); -DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount); -DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b); -DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a); -DN_API DN_F32 DN_Rect_Area (DN_Rect a); -DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01); -DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect); - -DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); - -#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes) - -#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) - -DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); -#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} -#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} -#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} -#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} -#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); -DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); -DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); - -#endif // !defined(DN_MATH_H) -#if !defined(DN_MATH_H) -#define DN_MATH_H - -DN_MSVC_WARNING_PUSH -DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V2I32 -{ - struct { int32_t x, y; }; - struct { int32_t w, h; }; - int32_t data[2]; -}; - -union DN_V2U16 -{ - struct { uint16_t x, y; }; - struct { uint16_t w, h; }; - uint16_t data[2]; -}; - -union DN_V2F32 -{ - struct { DN_F32 x, y; }; - struct { DN_F32 w, h; }; - DN_F32 data[2]; -}; -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V3F32 -{ - struct { DN_F32 x, y, z; }; - struct { DN_F32 r, g, b; }; - DN_F32 data[3]; -}; - -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V4F32 -{ - struct { DN_F32 x, y, z, w; }; - struct { DN_F32 r, g, b, a; }; - #if !defined(DN_NO_V3) - DN_V3F32 rgb; - DN_V3F32 xyz; - #endif - DN_F32 data[4]; -}; -#endif // !defined(DN_NO_V4) -DN_MSVC_WARNING_POP - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -struct DN_M4 -{ - DN_F32 columns[4][4]; // Column major matrix -}; -#endif // !defined(DN_M4) - -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -union DN_M2x3 -{ - DN_F32 e[6]; - DN_F32 row[2][3]; -}; - -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_RECT) -#if defined(DN_NO_V2) - #error "Rectangles requires V2, DN_NO_V2 must not be defined" -#endif -struct DN_Rect -{ - DN_V2F32 pos, size; -}; - -struct DN_RectMinMax -{ - DN_V2F32 min, max; -}; - -enum DN_RectCutClip -{ - DN_RectCutClip_No, - DN_RectCutClip_Yes, -}; - -enum DN_RectCutSide -{ - DN_RectCutSide_Left, - DN_RectCutSide_Right, - DN_RectCutSide_Top, - DN_RectCutSide_Bottom, -}; - -struct DN_RectCut -{ - DN_Rect* rect; - DN_RectCutSide side; -}; -#endif // !defined(DN_NO_RECT) - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: API -struct DN_RaycastLineIntersectV2Result -{ - bool hit; // True if there was an intersection, false if the lines are parallel - DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` - DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` -}; - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} -#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} -#define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} -#define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} -#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} - -DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs); -DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs); - -DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); - -#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_Init1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} - -DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); - -#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} -#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} -#define DN_V2F32_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} -#define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} -#define DN_V2F32_InitV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} - -DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs); - -DN_API DN_V2F32 operator- (DN_V2F32 lhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 DN_V2F32_Min (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Max (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Abs (DN_V2F32 a); -DN_API DN_F32 DN_V2F32_Dot (DN_V2F32 a, DN_V2F32 b); -DN_API DN_F32 DN_V2F32_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_LengthSq (DN_V2F32 lhs); -DN_API DN_F32 DN_V2F32_Length (DN_V2F32 lhs); -DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); -DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} -#define DN_V3F32_InitV2F32_1F32(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} - -DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs); -DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); -DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); -DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} -#define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} -DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs); -DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs); -DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs); -DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b); -DN_API DN_M4 DN_M4_Identity (); -DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_Transpose (DN_M4 mat); -DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians); -DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); -#if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat); -#endif -#endif // !defined(DN_NO_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API DN_M2x3 DN_M2x3_Identity (); -DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); -DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); -DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); -DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); -DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); -DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#define DN_Rect_Init2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} -#define DN_Rect_Init4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} - -DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); -DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); -DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p); -DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount); -DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount); -DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b); -DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a); -DN_API DN_F32 DN_Rect_Area (DN_Rect a); -DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01); -DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect); - -DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); - -#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes) - -#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) - -DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); -#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} -#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} -#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} -#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} -#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); -DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); -DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); - -#endif // !defined(DN_MATH_H) -#if !defined(DN_MATH_H) -#define DN_MATH_H - -DN_MSVC_WARNING_PUSH -DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V2I32 -{ - struct { int32_t x, y; }; - struct { int32_t w, h; }; - int32_t data[2]; -}; - -union DN_V2U16 -{ - struct { uint16_t x, y; }; - struct { uint16_t w, h; }; - uint16_t data[2]; -}; - -union DN_V2F32 -{ - struct { DN_F32 x, y; }; - struct { DN_F32 w, h; }; - DN_F32 data[2]; -}; -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V3F32 -{ - struct { DN_F32 x, y, z; }; - struct { DN_F32 r, g, b; }; - DN_F32 data[3]; -}; - -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V4F32 -{ - struct { DN_F32 x, y, z, w; }; - struct { DN_F32 r, g, b, a; }; - #if !defined(DN_NO_V3) - DN_V3F32 rgb; - DN_V3F32 xyz; - #endif - DN_F32 data[4]; -}; -#endif // !defined(DN_NO_V4) -DN_MSVC_WARNING_POP - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -struct DN_M4 -{ - DN_F32 columns[4][4]; // Column major matrix -}; -#endif // !defined(DN_M4) - -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -union DN_M2x3 -{ - DN_F32 e[6]; - DN_F32 row[2][3]; -}; - -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_RECT) -#if defined(DN_NO_V2) - #error "Rectangles requires V2, DN_NO_V2 must not be defined" -#endif -struct DN_Rect -{ - DN_V2F32 pos, size; -}; - -struct DN_RectMinMax -{ - DN_V2F32 min, max; -}; - -enum DN_RectCutClip -{ - DN_RectCutClip_No, - DN_RectCutClip_Yes, -}; - -enum DN_RectCutSide -{ - DN_RectCutSide_Left, - DN_RectCutSide_Right, - DN_RectCutSide_Top, - DN_RectCutSide_Bottom, -}; - -struct DN_RectCut -{ - DN_Rect* rect; - DN_RectCutSide side; -}; -#endif // !defined(DN_NO_RECT) - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: API -struct DN_RaycastLineIntersectV2Result -{ - bool hit; // True if there was an intersection, false if the lines are parallel - DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` - DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` -}; - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} -#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} -#define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} -#define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} -#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} - -DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs); -DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs); - -DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); - -#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_Init1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} - -DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); - -#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} -#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} -#define DN_V2F32_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} -#define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} -#define DN_V2F32_InitV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} - -DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs); - -DN_API DN_V2F32 operator- (DN_V2F32 lhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 DN_V2F32_Min (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Max (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Abs (DN_V2F32 a); -DN_API DN_F32 DN_V2F32_Dot (DN_V2F32 a, DN_V2F32 b); -DN_API DN_F32 DN_V2F32_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_LengthSq (DN_V2F32 lhs); -DN_API DN_F32 DN_V2F32_Length (DN_V2F32 lhs); -DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); -DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} -#define DN_V3F32_InitV2F32_1F32(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} - -DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs); -DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); -DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); -DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} -#define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} -DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs); -DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs); -DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs); -DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b); -DN_API DN_M4 DN_M4_Identity (); -DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_Transpose (DN_M4 mat); -DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians); -DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); -#if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat); -#endif -#endif // !defined(DN_NO_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API DN_M2x3 DN_M2x3_Identity (); -DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); -DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); -DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); -DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); -DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); -DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#define DN_Rect_Init2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} -#define DN_Rect_Init4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} - -DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); -DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); -DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p); -DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount); -DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount); -DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b); -DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a); -DN_API DN_F32 DN_Rect_Area (DN_Rect a); -DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01); -DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect); - -DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); - -#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes) - -#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) - -DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); -#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} -#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} -#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} -#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} -#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); -DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); -DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); - -#endif // !defined(DN_MATH_H) -#if !defined(DN_MATH_H) -#define DN_MATH_H - -DN_MSVC_WARNING_PUSH -DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V2I32 -{ - struct { int32_t x, y; }; - struct { int32_t w, h; }; - int32_t data[2]; -}; - -union DN_V2U16 -{ - struct { uint16_t x, y; }; - struct { uint16_t w, h; }; - uint16_t data[2]; -}; - -union DN_V2F32 -{ - struct { DN_F32 x, y; }; - struct { DN_F32 w, h; }; - DN_F32 data[2]; -}; -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V3F32 -{ - struct { DN_F32 x, y, z; }; - struct { DN_F32 r, g, b; }; - DN_F32 data[3]; -}; - -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V4F32 -{ - struct { DN_F32 x, y, z, w; }; - struct { DN_F32 r, g, b, a; }; - #if !defined(DN_NO_V3) - DN_V3F32 rgb; - DN_V3F32 xyz; - #endif - DN_F32 data[4]; -}; -#endif // !defined(DN_NO_V4) -DN_MSVC_WARNING_POP - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -struct DN_M4 -{ - DN_F32 columns[4][4]; // Column major matrix -}; -#endif // !defined(DN_M4) - -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -union DN_M2x3 -{ - DN_F32 e[6]; - DN_F32 row[2][3]; -}; - -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_RECT) -#if defined(DN_NO_V2) - #error "Rectangles requires V2, DN_NO_V2 must not be defined" -#endif -struct DN_Rect -{ - DN_V2F32 pos, size; -}; - -struct DN_RectMinMax -{ - DN_V2F32 min, max; -}; - -enum DN_RectCutClip -{ - DN_RectCutClip_No, - DN_RectCutClip_Yes, -}; - -enum DN_RectCutSide -{ - DN_RectCutSide_Left, - DN_RectCutSide_Right, - DN_RectCutSide_Top, - DN_RectCutSide_Bottom, -}; - -struct DN_RectCut -{ - DN_Rect* rect; - DN_RectCutSide side; -}; -#endif // !defined(DN_NO_RECT) - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: API -struct DN_RaycastLineIntersectV2Result -{ - bool hit; // True if there was an intersection, false if the lines are parallel - DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` - DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` -}; - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} -#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} -#define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} -#define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} -#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} - -DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs); -DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs); - -DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); - -#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_Init1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} - -DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); - -#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} -#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} -#define DN_V2F32_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} -#define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} -#define DN_V2F32_InitV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} - -DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs); - -DN_API DN_V2F32 operator- (DN_V2F32 lhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 DN_V2F32_Min (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Max (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Abs (DN_V2F32 a); -DN_API DN_F32 DN_V2F32_Dot (DN_V2F32 a, DN_V2F32 b); -DN_API DN_F32 DN_V2F32_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_LengthSq (DN_V2F32 lhs); -DN_API DN_F32 DN_V2F32_Length (DN_V2F32 lhs); -DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); -DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} -#define DN_V3F32_InitV2F32_1F32(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} - -DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs); -DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); -DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); -DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} -#define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} -DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs); -DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs); -DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs); -DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b); -DN_API DN_M4 DN_M4_Identity (); -DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_Transpose (DN_M4 mat); -DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians); -DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); -#if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat); -#endif -#endif // !defined(DN_NO_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API DN_M2x3 DN_M2x3_Identity (); -DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); -DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); -DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); -DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); -DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); -DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#define DN_Rect_Init2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} -#define DN_Rect_Init4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} - -DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); -DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); -DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p); -DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount); -DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount); -DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b); -DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a); -DN_API DN_F32 DN_Rect_Area (DN_Rect a); -DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01); -DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect); - -DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); - -#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes) - -#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) - -DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); -#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} -#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} -#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} -#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} -#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); -DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); -DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); - -#endif // !defined(DN_MATH_H) -#if !defined(DN_MATH_H) -#define DN_MATH_H - -DN_MSVC_WARNING_PUSH -DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V2I32 -{ - struct { int32_t x, y; }; - struct { int32_t w, h; }; - int32_t data[2]; -}; - -union DN_V2U16 -{ - struct { uint16_t x, y; }; - struct { uint16_t w, h; }; - uint16_t data[2]; -}; - -union DN_V2F32 -{ - struct { DN_F32 x, y; }; - struct { DN_F32 w, h; }; - DN_F32 data[2]; -}; -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V3F32 -{ - struct { DN_F32 x, y, z; }; - struct { DN_F32 r, g, b; }; - DN_F32 data[3]; -}; - -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V4F32 -{ - struct { DN_F32 x, y, z, w; }; - struct { DN_F32 r, g, b, a; }; - #if !defined(DN_NO_V3) - DN_V3F32 rgb; - DN_V3F32 xyz; - #endif - DN_F32 data[4]; -}; -#endif // !defined(DN_NO_V4) -DN_MSVC_WARNING_POP - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -struct DN_M4 -{ - DN_F32 columns[4][4]; // Column major matrix -}; -#endif // !defined(DN_M4) - -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -union DN_M2x3 -{ - DN_F32 e[6]; - DN_F32 row[2][3]; -}; - -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_RECT) -#if defined(DN_NO_V2) - #error "Rectangles requires V2, DN_NO_V2 must not be defined" -#endif -struct DN_Rect -{ - DN_V2F32 pos, size; -}; - -struct DN_RectMinMax -{ - DN_V2F32 min, max; -}; - -enum DN_RectCutClip -{ - DN_RectCutClip_No, - DN_RectCutClip_Yes, -}; - -enum DN_RectCutSide -{ - DN_RectCutSide_Left, - DN_RectCutSide_Right, - DN_RectCutSide_Top, - DN_RectCutSide_Bottom, -}; - -struct DN_RectCut -{ - DN_Rect* rect; - DN_RectCutSide side; -}; -#endif // !defined(DN_NO_RECT) - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: API -struct DN_RaycastLineIntersectV2Result -{ - bool hit; // True if there was an intersection, false if the lines are parallel - DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` - DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` -}; - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} -#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} -#define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} -#define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} -#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} - -DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs); -DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs); - -DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); - -#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_Init1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} - -DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); - -#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} -#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} -#define DN_V2F32_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} -#define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} -#define DN_V2F32_InitV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} - -DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs); - -DN_API DN_V2F32 operator- (DN_V2F32 lhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 DN_V2F32_Min (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Max (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Abs (DN_V2F32 a); -DN_API DN_F32 DN_V2F32_Dot (DN_V2F32 a, DN_V2F32 b); -DN_API DN_F32 DN_V2F32_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_LengthSq (DN_V2F32 lhs); -DN_API DN_F32 DN_V2F32_Length (DN_V2F32 lhs); -DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); -DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} -#define DN_V3F32_InitV2F32_1F32(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} - -DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs); -DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); -DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); -DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} -#define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} -DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs); -DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs); -DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs); -DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b); -DN_API DN_M4 DN_M4_Identity (); -DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_Transpose (DN_M4 mat); -DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians); -DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); -#if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat); -#endif -#endif // !defined(DN_NO_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API DN_M2x3 DN_M2x3_Identity (); -DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); -DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); -DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); -DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); -DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); -DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#define DN_Rect_Init2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} -#define DN_Rect_Init4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} - -DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); -DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); -DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p); -DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount); -DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount); -DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b); -DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a); -DN_API DN_F32 DN_Rect_Area (DN_Rect a); -DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01); -DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect); - -DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); - -#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes) - -#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) - -DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); -#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} -#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} -#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} -#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} -#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); -DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); -DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); - -#endif // !defined(DN_MATH_H) -#if !defined(DN_MATH_H) -#define DN_MATH_H - -DN_MSVC_WARNING_PUSH -DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V2I32 -{ - struct { int32_t x, y; }; - struct { int32_t w, h; }; - int32_t data[2]; -}; - -union DN_V2U16 -{ - struct { uint16_t x, y; }; - struct { uint16_t w, h; }; - uint16_t data[2]; -}; - -union DN_V2F32 -{ - struct { DN_F32 x, y; }; - struct { DN_F32 w, h; }; - DN_F32 data[2]; -}; -#endif // !defined(DN_NO_V2) - -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V3F32 -{ - struct { DN_F32 x, y, z; }; - struct { DN_F32 r, g, b; }; - DN_F32 data[3]; -}; - -#endif // !defined(DN_NO_V3) - -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -union DN_V4F32 -{ - struct { DN_F32 x, y, z, w; }; - struct { DN_F32 r, g, b, a; }; - #if !defined(DN_NO_V3) - DN_V3F32 rgb; - DN_V3F32 xyz; - #endif - DN_F32 data[4]; -}; -#endif // !defined(DN_NO_V4) -DN_MSVC_WARNING_POP - -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -struct DN_M4 -{ - DN_F32 columns[4][4]; // Column major matrix -}; -#endif // !defined(DN_M4) - -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -union DN_M2x3 -{ - DN_F32 e[6]; - DN_F32 row[2][3]; -}; - -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_RECT) -#if defined(DN_NO_V2) - #error "Rectangles requires V2, DN_NO_V2 must not be defined" -#endif -struct DN_Rect -{ - DN_V2F32 pos, size; -}; - -struct DN_RectMinMax -{ - DN_V2F32 min, max; -}; - -enum DN_RectCutClip -{ - DN_RectCutClip_No, - DN_RectCutClip_Yes, -}; - -enum DN_RectCutSide -{ - DN_RectCutSide_Left, - DN_RectCutSide_Right, - DN_RectCutSide_Top, - DN_RectCutSide_Bottom, -}; - -struct DN_RectCut -{ - DN_Rect* rect; - DN_RectCutSide side; -}; -#endif // !defined(DN_NO_RECT) - -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: API -struct DN_RaycastLineIntersectV2Result -{ - bool hit; // True if there was an intersection, false if the lines are parallel - DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` - DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` -}; - -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} -#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} -#define DN_V2I32_Init1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} -#define DN_V2I32_Init2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} -#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} - -DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator- (DN_V2I32 lhs); -DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs); -DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs); -DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs); -DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs); -DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs); - -DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); -DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); - -#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_Init1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_Init2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} - -DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs); -DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs); -DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs); -DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); -DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); - -#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} -#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} -#define DN_V2F32_Init1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} -#define DN_V2F32_Init2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} -#define DN_V2F32_InitV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} - -DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs); - -DN_API DN_V2F32 operator- (DN_V2F32 lhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs); -DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs); - -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs); -DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs); - -DN_API DN_V2F32 DN_V2F32_Min (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Max (DN_V2F32 a, DN_V2F32 b); -DN_API DN_V2F32 DN_V2F32_Abs (DN_V2F32 a); -DN_API DN_F32 DN_V2F32_Dot (DN_V2F32 a, DN_V2F32 b); -DN_API DN_F32 DN_V2F32_LengthSq_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_Length_V2x2 (DN_V2F32 lhs, DN_V2F32 rhs); -DN_API DN_F32 DN_V2F32_LengthSq (DN_V2F32 lhs); -DN_API DN_F32 DN_V2F32_Length (DN_V2F32 lhs); -DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); -DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); -DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V3F32_Init1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V3F32_Init3F32(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} -#define DN_V3F32_InitV2F32_1F32(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} - -DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator- (DN_V3F32 lhs); -DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs); -DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs); -DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs); -DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs); -DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); -DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); -DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V4F32_Init1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V4F32_Init4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} -#define DN_V4F32_InitV3_1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} -DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator- (DN_V4F32 lhs); -DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs); -DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs); -DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs); -DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); -DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b); -DN_API DN_M4 DN_M4_Identity (); -DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z); -DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz); -DN_API DN_M4 DN_M4_Transpose (DN_M4 mat); -DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians); -DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far); -DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs); -DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); -DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); -#if !defined(DN_NO_FSTR8) -DN_API DN_FStr8<256> DN_M4_ColumnMajorString (DN_M4 mat); -#endif -#endif // !defined(DN_NO_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// -DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); -DN_API DN_M2x3 DN_M2x3_Identity (); -DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); -DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); -DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); -DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); -DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); -DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#define DN_Rect_Init2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} -#define DN_Rect_Init4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} - -DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); -DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); -DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p); -DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount); -DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount); -DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b); -DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b); -DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a); -DN_API DN_F32 DN_Rect_Area (DN_Rect a); -DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01); -DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect); -DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect); - -DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); -DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); - -#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes) -#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes) - -#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No) -#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) - -DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); -#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} -#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} -#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} -#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} -#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); -DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); -DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); - -#endif // !defined(DN_MATH_H) \ No newline at end of file +struct DN_JobQueueSPMC +{ + DN_OSMutex mutex; + DN_OSSemaphore thread_wait_for_job_semaphore; + DN_OSSemaphore wait_for_completion_semaphore; + DN_U32 threads_waiting_for_completion; + + DN_Job jobs[DN_JOB_QUEUE_SPMC_SIZE]; + DN_B32 quit; + DN_U32 quit_exit_code; + DN_U32 volatile read_index; + DN_U32 volatile finish_index; + DN_U32 volatile write_index; + + DN_OSSemaphore complete_queue_write_semaphore; + DN_Job complete_queue[DN_JOB_QUEUE_SPMC_SIZE]; + DN_U32 volatile complete_read_index; + DN_U32 volatile complete_write_index; +}; + +// NOTE: DN_PCG32 ////////////////////////////////////////////////////////////////////////////////// +DN_API DN_PCG32 DN_PCG32_Init (uint64_t seed); +DN_API uint32_t DN_PCG32_Next (DN_PCG32 *rng); +DN_API uint64_t DN_PCG32_Next64 (DN_PCG32 *rng); +DN_API uint32_t DN_PCG32_Range (DN_PCG32 *rng, uint32_t low, uint32_t high); +DN_API DN_F32 DN_PCG32_NextF32 (DN_PCG32 *rng); +DN_API DN_F64 DN_PCG32_NextF64 (DN_PCG32 *rng); +DN_API void DN_PCG32_Advance (DN_PCG32 *rng, uint64_t delta); + +#if !defined(DN_NO_JSON_BUILDER) +// NOTE: DN_JSONBuilder //////////////////////////////////////////////////////////////////////////// +#define DN_JSONBuilder_Object(builder) \ + DN_DeferLoop(DN_JSONBuilder_ObjectBegin(builder), \ + DN_JSONBuilder_ObjectEnd(builder)) + +#define DN_JSONBuilder_ObjectNamed(builder, name) \ + DN_DeferLoop(DN_JSONBuilder_ObjectBeginNamed(builder, name), \ + DN_JSONBuilder_ObjectEnd(builder)) + +#define DN_JSONBuilder_Array(builder) \ + DN_DeferLoop(DN_JSONBuilder_ArrayBegin(builder), \ + DN_JSONBuilder_ArrayEnd(builder)) + +#define DN_JSONBuilder_ArrayNamed(builder, name) \ + DN_DeferLoop(DN_JSONBuilder_ArrayBeginNamed(builder, name), \ + DN_JSONBuilder_ArrayEnd(builder)) + +DN_API DN_JSONBuilder DN_JSONBuilder_Init (DN_Arena *arena, int spaces_per_indent); +DN_API DN_Str8 DN_JSONBuilder_Build (DN_JSONBuilder const *builder, DN_Arena *arena); +DN_API void DN_JSONBuilder_KeyValue (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value); +DN_API void DN_JSONBuilder_KeyValueF (DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...); +DN_API void DN_JSONBuilder_ObjectBeginNamed (DN_JSONBuilder *builder, DN_Str8 name); +DN_API void DN_JSONBuilder_ObjectEnd (DN_JSONBuilder *builder); +DN_API void DN_JSONBuilder_ArrayBeginNamed (DN_JSONBuilder *builder, DN_Str8 name); +DN_API void DN_JSONBuilder_ArrayEnd (DN_JSONBuilder *builder); +DN_API void DN_JSONBuilder_Str8Named (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value); +DN_API void DN_JSONBuilder_LiteralNamed (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value); +DN_API void DN_JSONBuilder_U64Named (DN_JSONBuilder *builder, DN_Str8 key, uint64_t value); +DN_API void DN_JSONBuilder_I64Named (DN_JSONBuilder *builder, DN_Str8 key, int64_t value); +DN_API void DN_JSONBuilder_F64Named (DN_JSONBuilder *builder, DN_Str8 key, double value, int decimal_places); +DN_API void DN_JSONBuilder_BoolNamed (DN_JSONBuilder *builder, DN_Str8 key, bool value); + +#define DN_JSONBuilder_ObjectBegin(builder) DN_JSONBuilder_ObjectBeginNamed(builder, DN_STR8("")) +#define DN_JSONBuilder_ArrayBegin(builder) DN_JSONBuilder_ArrayBeginNamed(builder, DN_STR8("")) +#define DN_JSONBuilder_Str8(builder, value) DN_JSONBuilder_Str8Named(builder, DN_STR8(""), value) +#define DN_JSONBuilder_Literal(builder, value) DN_JSONBuilder_LiteralNamed(builder, DN_STR8(""), value) +#define DN_JSONBuilder_U64(builder, value) DN_JSONBuilder_U64Named(builder, DN_STR8(""), value) +#define DN_JSONBuilder_I64(builder, value) DN_JSONBuilder_I64Named(builder, DN_STR8(""), value) +#define DN_JSONBuilder_F64(builder, value) DN_JSONBuilder_F64Named(builder, DN_STR8(""), value) +#define DN_JSONBuilder_Bool(builder, value) DN_JSONBuilder_BoolNamed(builder, DN_STR8(""), value) +#endif // !defined(DN_NO_JSON_BUILDER) + +// NOTE: DN_BinarySearch /////////////////////////////////////////////////////////////////////////// +template bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs); +template DN_BinarySearchResult DN_BinarySearch (T const *array, + DN_USize array_size, + T const &find, + DN_BinarySearchType type = DN_BinarySearchType_Match, + DN_BinarySearchLessThanProc less_than = DN_BinarySearch_DefaultLessThan); + +// NOTE: DN_QSort ////////////////////////////////////////////////////////////////////////////////// +template bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs); +template void DN_QSort (T *array, + DN_USize array_size, + void *user_context, + DN_QSortLessThanProc less_than = DN_QSort_DefaultLessThan); + +// NOTE: DN_JobQueue /////////////////////////////////////////////////////////////////////////////// +DN_API DN_JobQueueSPMC DN_OS_JobQueueSPMCInit (); +DN_API bool DN_OS_JobQueueSPMCCanAdd (DN_JobQueueSPMC const *queue, uint32_t count); +DN_API bool DN_OS_JobQueueSPMCAddArray (DN_JobQueueSPMC *queue, DN_Job *jobs, uint32_t count); +DN_API bool DN_OS_JobQueueSPMCAdd (DN_JobQueueSPMC *queue, DN_Job job); +DN_API void DN_OS_JobQueueSPMCWaitForCompletion (DN_JobQueueSPMC *queue); +DN_API int32_t DN_OS_JobQueueSPMCThread (DN_OSThread *thread); +DN_API DN_USize DN_OS_JobQueueSPMCGetFinishedJobs (DN_JobQueueSPMC *queue, DN_Job *jobs, DN_USize jobs_size); + +// NOTE: DN_BinarySearch /////////////////////////////////////////////////////////////////////////// +template +bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs) +{ + bool result = lhs < rhs; + return result; +} + +template +DN_BinarySearchResult DN_BinarySearch(T const *array, + DN_USize array_size, + T const &find, + DN_BinarySearchType type, + DN_BinarySearchLessThanProc less_than) +{ + DN_BinarySearchResult result = {}; + if (!array || array_size <= 0 || !less_than) + return result; + + T const *end = array + array_size; + T const *first = array; + T const *last = end; + while (first != last) { + DN_USize count = last - first; + T const *it = first + (count / 2); + + bool advance_first = false; + if (type == DN_BinarySearchType_UpperBound) + advance_first = !less_than(find, it[0]); + else + advance_first = less_than(it[0], find); + + if (advance_first) + first = it + 1; + else + last = it; + } + + switch (type) { + case DN_BinarySearchType_Match: { + result.found = first != end && !less_than(find, *first); + } break; + + case DN_BinarySearchType_LowerBound: /*FALLTHRU*/ + case DN_BinarySearchType_UpperBound: { + result.found = first != end; + } break; + } + + result.index = first - array; + return result; +} + +// NOTE: DN_QSort ////////////////////////////////////////////////////////////////////////////////// +template +bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context) +{ + (void)user_context; + bool result = lhs < rhs; + return result; +} + +template +void DN_QSort(T *array, DN_USize array_size, void *user_context, DN_QSortLessThanProc less_than) +{ + if (!array || array_size <= 1 || !less_than) + return; + + // NOTE: Insertion Sort, under 24->32 is an optimal amount ///////////////////////////////////// + const DN_USize QSORT_THRESHOLD = 24; + if (array_size < QSORT_THRESHOLD) { + for (DN_USize item_to_insert_index = 1; item_to_insert_index < array_size; item_to_insert_index++) { + for (DN_USize index = 0; index < item_to_insert_index; index++) { + if (!less_than(array[index], array[item_to_insert_index], user_context)) { + T item_to_insert = array[item_to_insert_index]; + for (DN_USize i = item_to_insert_index; i > index; i--) + array[i] = array[i - 1]; + + array[index] = item_to_insert; + break; + } + } + } + return; + } + + // NOTE: Quick sort, under 24->32 is an optimal amount ///////////////////////////////////////// + DN_USize last_index = array_size - 1; + DN_USize pivot_index = array_size / 2; + DN_USize partition_index = 0; + DN_USize start_index = 0; + + // Swap pivot with last index, so pivot is always at the end of the array. + // This makes logic much simpler. + DN_Swap(array[last_index], array[pivot_index]); + pivot_index = last_index; + + // 4^, 8, 7, 5, 2, 3, 6 + if (less_than(array[start_index], array[pivot_index], user_context)) + partition_index++; + start_index++; + + // 4, |8, 7, 5^, 2, 3, 6* + // 4, 5, |7, 8, 2^, 3, 6* + // 4, 5, 2, |8, 7, ^3, 6* + // 4, 5, 2, 3, |7, 8, ^6* + for (DN_USize index = start_index; index < last_index; index++) { + if (less_than(array[index], array[pivot_index], user_context)) { + DN_Swap(array[partition_index], array[index]); + partition_index++; + } + } + + // Move pivot to right of partition + // 4, 5, 2, 3, |6, 8, ^7* + DN_Swap(array[partition_index], array[pivot_index]); + DN_QSort(array, partition_index, user_context, less_than); + + // Skip the value at partion index since that is guaranteed to be sorted. + // 4, 5, 2, 3, (x), 8, 7 + DN_USize one_after_partition_index = partition_index + 1; + DN_QSort(array + one_after_partition_index, (array_size - one_after_partition_index), user_context, less_than); +} + +#endif // !defined(DN_HELPERS_H) \ No newline at end of file diff --git a/Source/.gitignore b/Source/.gitignore new file mode 100644 index 0000000..61e5de3 --- /dev/null +++ b/Source/.gitignore @@ -0,0 +1,6 @@ +tags +*.swp +*.swo +Build +.vs/ +*.db diff --git a/Source/Base/dn_base_containers.h b/Source/Base/dn_base_containers.h index 768e6b7..21fab9e 100644 --- a/Source/Base/dn_base_containers.h +++ b/Source/Base/dn_base_containers.h @@ -216,6 +216,7 @@ template struct DN_List #define DN_LArray_PrependArray(c_array, size, max, items, count) (decltype(&(c_array)[0])) DN_CArray2_AddArray (c_array, size, max, sizeof((c_array)[0]), items, count, DN_ArrayAdd_Prepend) #define DN_LArray_Prepend(c_array, size, max, item) (decltype(&(c_array)[0])) DN_CArray2_AddArray (c_array, size, max, sizeof((c_array)[0]), &item, 1, DN_ArrayAdd_Prepend) #define DN_LArray_EraseRange(c_array, size, begin_index, count, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), begin_index, count, erase) +#define DN_LArray_Erase(c_array, size, index, erase) DN_CArray2_EraseRange(c_array, size, sizeof((c_array)[0]), index, 1, erase) #define DN_IArray_Front(array) (array)->data #define DN_IArray_GrowIfNeededFromPool(array, pool) DN_CArray2_GrowIfNeededFromPool((void **)(&(array)->data), (array)->size, &(array)->max, sizeof((array)->data[0]), pool) @@ -230,6 +231,7 @@ template struct DN_List #define DN_IArray_PrependArray(array, items, count) (decltype(&((array)->data)[0])) DN_CArray2_AddArray ((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), items, count, DN_ArrayAdd_Prepend) #define DN_IArray_Prepend(array, item) (decltype(&((array)->data)[0])) DN_CArray2_AddArray ((array)->data, &(array)->size, (array)->max, sizeof(((array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend) #define DN_IArray_EraseRange(array, size, begin_index, count, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), begin_index, count, erase) +#define DN_IArray_Erase(array, size, index, erase) DN_CArray2_EraseRange((array)->data, &(array)->size, sizeof(((array)->data)[0]), index, 1, erase) DN_API DN_ArrayEraseResult DN_CArray2_EraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase); DN_API void *DN_CArray2_MakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZeroMem zero_mem); diff --git a/Source/_clang-format b/Source/_clang-format new file mode 100644 index 0000000..ea0f0f3 --- /dev/null +++ b/Source/_clang-format @@ -0,0 +1,458 @@ +Language: Cpp + +IndentWidth: 2 +TabWidth: 2 + +# Align parameters on the open bracket, e.g.: +# someLongFunction(argument1, +# argument2); +AlignAfterOpenBracket: Align + +# Align array column and left justify the columns e.g.: +# struct test demo[] = +# { +# {56, 23, "hello"}, +# {-1, 93463, "world"}, +# {7, 5, "!!" } +# }; +AlignArrayOfStructures: Left + +# Align assignments on consecutive lines. This will result in formattings like: +# +# int a = 1; +# int somelongname = 2; +# double c = 3; +# +# int d = 3; +# /* A comment. */ +# double e = 4; +AlignConsecutiveAssignments: Consecutive +AlignConsecutiveBitFields: Consecutive +AlignConsecutiveDeclarations: Consecutive +AlignConsecutiveMacros: Consecutive + +# Align escaped newlines as far left as possible. +# #define A \ +# int aaaa; \ +# int b; \ +# int dddddddddd; +AlignEscapedNewlines: Left + +# Horizontally align operands of binary and ternary expressions. +# Specifically, this aligns operands of a single expression that needs to be +# split over multiple lines, e.g.: +# +# int aaa = bbbbbbbbbbbbbbb + +# ccccccccccccccc; +AlignOperands: Align + +# true: false: +# int a; // My comment a vs. int a; // My comment a +# int b = 2; // comment b int b = 2; // comment about b +AlignTrailingComments: true + +# If the function declaration doesn’t fit on a line, allow putting all +# parameters of a function declaration onto the next line even if +# BinPackParameters is false. +# +# true: +# void myFunction( +# int a, int b, int c, int d, int e); +# +# false: +# void myFunction(int a, +# int b, +# int c, +# int d, +# int e); +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never # "while (true) { continue; }" can be put on a single line. + +# If true, short case labels will be contracted to a single line. +# +# true: false: +# switch (a) { vs. switch (a) { +# case 1: x = 1; break; case 1: +# case 2: return; x = 1; +# } break; +# case 2: +# return; +# } +AllowShortCaseLabelsOnASingleLine: true +AllowShortEnumsOnASingleLine: true # enum { A, B } myEnum; + +# Only merge functions defined inside a class. Implies “empty”. +# +# class Foo { +# void f() { foo(); } +# }; +# void f() { +# foo(); +# } +# void f() {} +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false + +# Only merge empty lambdas. +# +# auto lambda = [](int a) {} +# auto lambda2 = [](int a) { +# return a; +# }; +AllowShortLambdasOnASingleLine: Empty +AllowShortLoopsOnASingleLine: false + +# true: false: +# aaaa = vs. aaaa = "bbbb" +# "bbbb" "cccc"; +# "cccc"; +AlwaysBreakBeforeMultilineStrings: true + +# Force break after template declaration only when the following declaration +# spans multiple lines. +# +# template T foo() { +# } +# template +# T foo(int aaaaaaaaaaaaaaaaaaaaa, +# int bbbbbbbbbbbbbbbbbbbbb) { +# } +AlwaysBreakTemplateDeclarations: MultiLine + +# If false, a function call’s arguments will either be all on the same line or +# will have one line each. +# +# true: +# void f() { +# f(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaa, +# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); +# } +# +# false: +# void f() { +# f(aaaaaaaaaaaaaaaaaaaa, +# aaaaaaaaaaaaaaaaaaaa, +# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa); +# } +BinPackArguments: false +BinPackParameters: false # As BinPackArguments but for function definition parameters + +# Add space after the : only (space may be added before if needed for +# AlignConsecutiveBitFields). +# +# unsigned bf: 2; +BitFieldColonSpacing: After + +# LooooooooooongType loooooooooooooooooooooongVariable = +# someLooooooooooooooooongFunction(); +# +# bool value = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa == +# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && +# aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > +# ccccccccccccccccccccccccccccccccccccccccc; +BreakBeforeBinaryOperators: None + +# BS_Attach (in configuration: Attach) Always attach braces to surrounding context. +# BS_Mozilla (in configuration: Mozilla) Like Attach, but break before braces on enum, function, and record definitions. +BreakBeforeBraces: Mozilla + +# true: +# template +# concept ... +# +# false: +# template concept ... +BreakBeforeConceptDeclarations: false + +# true: +# veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription +# ? firstValue +# : SecondValueVeryVeryVeryVeryLong; +# +# false: +# veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription ? +# firstValue : +# SecondValueVeryVeryVeryVeryLong; +BreakBeforeTernaryOperators: true + +# Break constructor initializers before the colon and commas, and align the +# commas with the colon. +# +# Constructor() +# : initializer1() +# , initializer2() +BreakConstructorInitializers: BeforeComma + +# Break inheritance list only after the commas. +# +# class Foo : Base1, +# Base2 +# {}; +BreakInheritanceList: AfterComma + +# true: +# const char* x = "veryVeryVeryVeryVeryVe" +# "ryVeryVeryVeryVeryVery" +# "VeryLongString"; +BreakStringLiterals: true +ColumnLimit: 0 + +# false: +# namespace Foo { +# namespace Bar { +# } +# } +CompactNamespaces: false + +# true: false: +# vector x{1, 2, 3, 4}; vs. vector x{ 1, 2, 3, 4 }; +# vector x{{}, {}, {}, {}}; vector x{ {}, {}, {}, {} }; +# f(MyMap[{composite, key}]); f(MyMap[{ composite, key }]); +# new int[3]{1, 2, 3}; new int[3]{ 1, 2, 3 }; +Cpp11BracedListStyle: true + +# Analyze the formatted file for the most used line ending (\r\n or \n). UseCRLF +# is only used as a fallback if none can be derived. +DeriveLineEnding: true +DerivePointerAlignment: true # As per DeriveLineEnding except for pointers and references + +# Add empty line only when access modifier starts a new logical block. Logical +# block is a group of one or more member fields or functions. +# +# struct foo { +# private: +# int i; +# +# protected: +# int j; +# /* comment */ +# public: +# foo() {} +# +# private: +# protected: +# }; +EmptyLineBeforeAccessModifier: LogicalBlock + +# true: false: +# namespace a { vs. namespace a { +# foo(); foo(); +# bar(); bar(); +# } // namespace a } +FixNamespaceComments: true + +# false: true: +# class C { vs. class C { +# class D { class D { +# void bar(); void bar(); +# protected: protected: +# D(); D(); +# }; }; +# public: public: +# C(); C(); +# }; }; +# void foo() { void foo() { +# return 1; return 1; +# } } +IndentAccessModifiers: false + +# false: true: +# switch (fool) { vs. switch (fool) { +# case 1: { case 1: +# bar(); { +# } break; bar(); +# default: { } +# plop(); break; +# } default: +# } { +# plop(); +# } +# } +IndentCaseBlocks: false + +# false: true: +# switch (fool) { vs. switch (fool) { +# case 1: case 1: +# bar(); bar(); +# break; break; +# default: default: +# plop(); plop(); +# } } +IndentCaseLabels: true + +# extern "C" { +# void foo(); +# } +IndentExternBlock: NoIndent + +# Indents directives before the hash. +# +# #if FOO +# #if BAR +# #include +# #endif +# #endif +IndentPPDirectives: BeforeHash + +# true: false: +# if (foo) { vs. if (foo) { +# bar(); +# bar(); } +# } +KeepEmptyLinesAtTheStartOfBlocks: false + +# The maximum number of consecutive empty lines to keep. +# +# MaxEmptyLinesToKeep: 1 vs. MaxEmptyLinesToKeep: 0 +# int f() { int f() { +# int = 1; int i = 1; +# i = foo(); +# i = foo(); return i; +# } +# return i; +# } +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None + +# Put all constructor initializers on the current line if they fit. Otherwise, +# put each one on its own line. +# +# Constructor() : a(), b() +# +# Constructor() +# : aaaaaaaaaaaaaaaaaaaa(), +# bbbbbbbbbbbbbbbbbbbb(), +# ddddddddddddd() +PackConstructorInitializers: CurrentLine +PointerAlignment: Right + +# false: +# // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information +# /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information */ +# +# true: +# // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of +# // information +# /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of +# * information */ +ReflowComments: true + +# false: true: +# +# if (isa(D)) { vs. if (isa(D)) +# handleFunctionDecl(D); handleFunctionDecl(D); +# } else if (isa(D)) { else if (isa(D)) +# handleVarDecl(D); handleVarDecl(D); +# } +# +# if (isa(D)) { vs. if (isa(D)) { +# for (auto *A : D.attrs()) { for (auto *A : D.attrs()) +# if (shouldProcessAttr(A)) { if (shouldProcessAttr(A)) +# handleAttr(A); handleAttr(A); +# } } +# } +# } +# +# if (isa(D)) { vs. if (isa(D)) +# for (auto *A : D.attrs()) { for (auto *A : D.attrs()) +# handleAttr(A); handleAttr(A); +# } +# } +# +# if (auto *D = (T)(D)) { vs. if (auto *D = (T)(D)) { +# if (shouldProcess(D)) { if (shouldProcess(D)) +# handleVarDecl(D); handleVarDecl(D); +# } else { else +# markAsIgnored(D); markAsIgnored(D); +# } } +# } +# +# if (a) { vs. if (a) +# b(); b(); +# } else { else if (c) +# if (c) { d(); +# d(); else +# } else { e(); +# e(); +# } +# } +RemoveBracesLLVM: true + +# Never v.s. Always +# #include #include +# struct Foo { +# int a, b, c; struct Foo { +# }; int a, b, c; +# namespace Ns { }; +# class Bar { +# public: namespace Ns { +# struct Foobar { class Bar { +# int a; public: +# int b; struct Foobar { +# }; int a; +# private: int b; +# int t; }; +# int method1() { +# // ... private: +# } int t; +# enum List { +# ITEM1, int method1() { +# ITEM2 // ... +# }; } +# template +# int method2(T x) { enum List { +# // ... ITEM1, +# } ITEM2 +# int i, j, k; }; +# int method3(int par) { +# // ... template +# } int method2(T x) { +# }; // ... +# class C {}; } +# } +# int i, j, k; +# +# int method3(int par) { +# // ... +# } +# }; +# +# class C {}; +# } +SeparateDefinitionBlocks: Always + +# true: false: +# int a = 5; vs. int a= 5; +# a += 42; a+= 42; +SpaceBeforeAssignmentOperators: true + +# Put a space before opening parentheses only after control statement keywords +# (for/if/while...). +# +# void f() { +# if (true) { +# f(); +# } +# } +SpaceBeforeParens: ControlStatements +SpacesBeforeTrailingComments: 1 + +# static_cast(arg); +# std::function fct; +SpacesInAngles: Never + +Standard: Auto + +# Macros which are ignored in front of a statement, as if they were an +# attribute. So that they are not parsed as identifier, for example for Qts +# emit. +# unsigned char data = 'x'; +# emit signal(data); // This is parsed as variable declaration. +# +# vs. +# +# unsigned char data = 'x'; +# emit signal(data); // Now it's fine again. +StatementAttributeLikeMacros: [emit] +--- diff --git a/build.bat b/build.bat index 49242e1..79b2e1c 100644 --- a/build.bat +++ b/build.bat @@ -3,9 +3,10 @@ setlocal EnableDelayedExpansion set script_dir_backslash=%~dp0 set script_dir=%script_dir_backslash:~0,-1% +set build_dir=%script_dir%\Build -if not exist Build mkdir Build -pushd Build +if not exist %build_dir% mkdir %build_dir% +pushd %build_dir% REM Flags ====================================================================================== REM MT Static CRT REM EHa- Disable exception handling @@ -14,7 +15,6 @@ pushd Build REM Oi Use CPU Intrinsics REM Z7 Combine multi-debug files to one debug file set common_flags=-D DN_UNIT_TESTS_WITH_KECCAK %script_dir%\Source\Extra\dn_tests_main.cpp - set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo REM Optionally pass `-analyze` to `msvc_compile_flags` for more checks, but, @@ -33,9 +33,8 @@ pushd Build echo [BUILD] MSVC's cl detected, compiling ... set msvc_cmd=cl %msvc_compile_flags% %msvc_link_flags% powershell -Command "$time = Measure-Command { !msvc_cmd! | Out-Default }; Write-Host '[BUILD] msvc:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1 - - call cl %script_dir%\single_header_generator.cpp -nologo -link - call single_header_generator.exe %script_dir%\Source %script_dir%\Single_Header + call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -link + call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single_Header ) diff --git a/single_header_generator.cpp b/single_header_generator.cpp index e70183a..42524c7 100644 --- a/single_header_generator.cpp +++ b/single_header_generator.cpp @@ -1,4 +1,4 @@ -#define USE_SINGLE_HEADER 1 +#define USE_SINGLE_HEADER 0 #if USE_SINGLE_HEADER #include "Single_Header/dn_single_header.h" @@ -157,14 +157,13 @@ int main(int argc, char **argv) DN_STR8("Extra/dn_math"), DN_STR8("Extra/dn_async"), DN_STR8("Extra/dn_bin_pack"), - DN_STR8("Extra/dn_cgen"), DN_STR8("Extra/dn_csv"), DN_STR8("Extra/dn_hash"), DN_STR8("Extra/dn_helpers"), }; DN_Str8 suffix = type == FileType_Header ? DN_STR8("h") : DN_STR8("cpp"); for (DN_ForItCArray(extra_it, DN_Str8, extra_files)) { - DN_Str8 extra_path = DN_OS_PathFFromTLS("%S/%S.%S", dn_root_dir, extra_files, suffix); + DN_Str8 extra_path = DN_OS_PathFFromTLS("%S/%S.%S", dn_root_dir, *extra_it.data, suffix); AppendCppFileLineByLine(&builder, extra_path); }