Compare commits

..

2 Commits

Author SHA1 Message Date
5fdb1aa1a4 dqn: Update readme 2023-07-16 17:59:07 +10:00
c3902e3a29 dqn: Move vector math to impl, add new macros 2023-07-16 17:52:18 +10:00
11 changed files with 794 additions and 259 deletions

BIN
dqn.rdbg

Binary file not shown.

View File

@ -24,11 +24,30 @@
#define DQN_COMPILER_GCC #define DQN_COMPILER_GCC
#endif #endif
// Declare struct literals that work in both C and C++ because the syntax is
// different between languages.
#if 0
struct Foo { int a; }
struct Foo foo = DQN_LITERAL(Foo){32}; // Works on both C and C++
#endif
#if defined(__cplusplus)
#define DQN_LITERAL(T) T
#else
#define DQN_LITERAL(T) (T)
#endif
#if defined(__cplusplus)
#define DQN_THREAD_LOCAL thread_local
#else
#define DQN_THREAD_LOCAL _Thread_local
#endif
#if defined(_WIN32) #if defined(_WIN32)
#define DQN_OS_WIN32 #define DQN_OS_WIN32
#elif defined(__aarch64__) || defined(_M_ARM64) #elif defined(__aarch64__) || defined(_M_ARM64)
#define DQN_OS_ARM64 #define DQN_OS_ARM64
#else #elif defined(__linux__)
#define DQN_OS_UNIX #define DQN_OS_UNIX
#endif #endif
@ -121,7 +140,6 @@
// NOTE: Preprocessor Token Tricks ================================================================= // NOTE: Preprocessor Token Tricks =================================================================
#define DQN_TOKEN_COMBINE2(x, y) x ## y #define DQN_TOKEN_COMBINE2(x, y) x ## y
#define DQN_TOKEN_COMBINE(x, y) DQN_TOKEN_COMBINE2(x, y) #define DQN_TOKEN_COMBINE(x, y) DQN_TOKEN_COMBINE2(x, y)
#define DQN_UNIQUE_NAME(prefix) DQN_TOKEN_COMBINE(prefix, __LINE__)
#define DQN_SWAP(a, b) \ #define DQN_SWAP(a, b) \
do \ do \
@ -194,19 +212,17 @@
#define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered") #define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered")
// NOTE: Check macro =============================================================================== // NOTE: Check macro ===============================================================================
// Assert the expression given in debug, whilst in release- assertion is // Check the expression trapping in debug, whilst in release- trapping is
// removed and the expression is evaluated and returned. // removed and the expression is evaluated as if it were a normal 'if' branch.
//
// This function provides dual logic which allows handling of the condition
// gracefully in release mode, but asserting in debug mode. This is an internal
// function, prefer the @see DQN_CHECK macros.
//
// Returns true if the expression evaluated to true, false otherwise.
// //
// This allows handling of the condition gracefully when compiled out but traps
// to notify the developer in builds when it's compiled in.
#if 0 #if 0
bool flag = true; bool flag = true;
if (!DQN_CHECKF(flag, "Flag was false!")) { if (DQN_CHECKF(flag, "Flag was false!")) {
// This branch will execute! // This branch will execute!
} else {
// Prints "Flag was false!"
} }
#endif #endif
#define DQN_CHECK(expr) DQN_CHECKF(expr, "") #define DQN_CHECK(expr) DQN_CHECKF(expr, "")
@ -255,6 +271,7 @@ struct Dqn_DeferHelper
Dqn_Defer<Lambda> operator+(Lambda lambda) { return Dqn_Defer<Lambda>(lambda); }; Dqn_Defer<Lambda> operator+(Lambda lambda) { return Dqn_Defer<Lambda>(lambda); };
}; };
#define DQN_UNIQUE_NAME(prefix) DQN_TOKEN_COMBINE(prefix, __LINE__)
#define DQN_DEFER const auto DQN_UNIQUE_NAME(defer_lambda_) = Dqn_DeferHelper() + [&]() #define DQN_DEFER const auto DQN_UNIQUE_NAME(defer_lambda_) = Dqn_DeferHelper() + [&]()
#define DQN_DEFER_LOOP(begin, end) \ #define DQN_DEFER_LOOP(begin, end) \

View File

@ -1,36 +1,295 @@
#if !defined(DQN_NO_V2) #if !defined(DQN_NO_V2)
// NOTE: [$VEC2] Vector2 =========================================================================== // NOTE: [$VEC2] Vector2 ===========================================================================
DQN_API Dqn_V2I Dqn_V2ToV2I(Dqn_V2 a) DQN_API bool operator!=(Dqn_V2I lhs, Dqn_V2I rhs)
{ {
Dqn_V2I result = Dqn_V2I(DQN_CAST(int32_t)a.x, DQN_CAST(int32_t)a.y); bool result = !(lhs == rhs);
return result; return result;
} }
DQN_API Dqn_V2 Dqn_V2Min(Dqn_V2 a, Dqn_V2 b) DQN_API bool operator==(Dqn_V2I lhs, Dqn_V2I rhs)
{ {
Dqn_V2 result = Dqn_V2(DQN_MIN(a.x, b.x), DQN_MIN(a.y, b.y)); bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y);
return result; return result;
} }
DQN_API Dqn_V2 Dqn_V2Max(Dqn_V2 a, Dqn_V2 b) DQN_API bool operator>=(Dqn_V2I lhs, Dqn_V2I rhs)
{ {
Dqn_V2 result = Dqn_V2(DQN_MAX(a.x, b.x), DQN_MAX(a.y, b.y)); bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y);
return result; return result;
} }
DQN_API Dqn_V2 Dqn_V2Abs(Dqn_V2 a) DQN_API bool operator<=(Dqn_V2I lhs, Dqn_V2I rhs)
{ {
Dqn_V2 result = Dqn_V2(DQN_ABS(a.x), DQN_ABS(a.y)); bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y);
return result; return result;
} }
DQN_API Dqn_f32 Dqn_V2Dot(Dqn_V2 a, Dqn_V2 b) DQN_API bool operator<(Dqn_V2I lhs, Dqn_V2I rhs)
{
bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y);
return result;
}
DQN_API bool operator>(Dqn_V2I lhs, Dqn_V2I rhs)
{
bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y);
return result;
}
DQN_API Dqn_V2I operator-(Dqn_V2I lhs, Dqn_V2I rhs)
{
Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x - rhs.x, lhs.y - rhs.y);
return result;
}
DQN_API Dqn_V2I operator+(Dqn_V2I lhs, Dqn_V2I rhs)
{
Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x + rhs.x, lhs.y + rhs.y);
return result;
}
DQN_API Dqn_V2I operator*(Dqn_V2I lhs, Dqn_V2I rhs)
{
Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x * rhs.x, lhs.y * rhs.y);
return result;
}
DQN_API Dqn_V2I operator*(Dqn_V2I lhs, Dqn_f32 rhs)
{
Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x * rhs, lhs.y * rhs);
return result;
}
DQN_API Dqn_V2I operator*(Dqn_V2I lhs, int32_t rhs)
{
Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x * rhs, lhs.y * rhs);
return result;
}
DQN_API Dqn_V2I operator/(Dqn_V2I lhs, Dqn_V2I rhs)
{
Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x / rhs.x, lhs.y / rhs.y);
return result;
}
DQN_API Dqn_V2I operator/(Dqn_V2I lhs, Dqn_f32 rhs)
{
Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x / rhs, lhs.y / rhs);
return result;
}
DQN_API Dqn_V2I operator/(Dqn_V2I lhs, int32_t rhs)
{
Dqn_V2I result = Dqn_V2I_InitNx2(lhs.x / rhs, lhs.y / rhs);
return result;
}
DQN_API Dqn_V2I &operator*=(Dqn_V2I &lhs, Dqn_V2I rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V2I &operator*=(Dqn_V2I &lhs, Dqn_f32 rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V2I &operator*=(Dqn_V2I &lhs, int32_t rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V2I &operator/=(Dqn_V2I &lhs, Dqn_V2I rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V2I &operator/=(Dqn_V2I &lhs, Dqn_f32 rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V2I &operator/=(Dqn_V2I &lhs, int32_t rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V2I &operator-=(Dqn_V2I &lhs, Dqn_V2I rhs)
{
lhs = lhs - rhs;
return lhs;
}
DQN_API Dqn_V2I &operator+=(Dqn_V2I &lhs, Dqn_V2I rhs)
{
lhs = lhs + rhs;
return lhs;
}
// NOTE: Vector2
DQN_API bool operator!=(Dqn_V2 lhs, Dqn_V2 rhs)
{
bool result = !(lhs == rhs);
return result;
}
DQN_API bool operator==(Dqn_V2 lhs, Dqn_V2 rhs)
{
bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y);
return result;
}
DQN_API bool operator>=(Dqn_V2 lhs, Dqn_V2 rhs)
{
bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y);
return result;
}
DQN_API bool operator<=(Dqn_V2 lhs, Dqn_V2 rhs)
{
bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y);
return result;
}
DQN_API bool operator<(Dqn_V2 lhs, Dqn_V2 rhs)
{
bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y);
return result;
}
DQN_API bool operator>(Dqn_V2 lhs, Dqn_V2 rhs)
{
bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y);
return result;
}
DQN_API Dqn_V2 operator-(Dqn_V2 lhs, Dqn_V2 rhs)
{
Dqn_V2 result = Dqn_V2_InitNx2(lhs.x - rhs.x, lhs.y - rhs.y);
return result;
}
DQN_API Dqn_V2 operator+(Dqn_V2 lhs, Dqn_V2 rhs)
{
Dqn_V2 result = Dqn_V2_InitNx2(lhs.x + rhs.x, lhs.y + rhs.y);
return result;
}
DQN_API Dqn_V2 operator*(Dqn_V2 lhs, Dqn_V2 rhs)
{
Dqn_V2 result = Dqn_V2_InitNx2(lhs.x * rhs.x, lhs.y * rhs.y);
return result;
}
DQN_API Dqn_V2 operator*(Dqn_V2 lhs, Dqn_f32 rhs)
{
Dqn_V2 result = Dqn_V2_InitNx2(lhs.x * rhs, lhs.y * rhs);
return result;
}
DQN_API Dqn_V2 operator*(Dqn_V2 lhs, int32_t rhs)
{
Dqn_V2 result = Dqn_V2_InitNx2(lhs.x * rhs, lhs.y * rhs);
return result;
}
DQN_API Dqn_V2 operator/(Dqn_V2 lhs, Dqn_V2 rhs)
{
Dqn_V2 result = Dqn_V2_InitNx2(lhs.x / rhs.x, lhs.y / rhs.y);
return result;
}
DQN_API Dqn_V2 operator/(Dqn_V2 lhs, Dqn_f32 rhs)
{
Dqn_V2 result = Dqn_V2_InitNx2(lhs.x / rhs, lhs.y / rhs);
return result;
}
DQN_API Dqn_V2 operator/(Dqn_V2 lhs, int32_t rhs)
{
Dqn_V2 result = Dqn_V2_InitNx2(lhs.x / rhs, lhs.y / rhs);
return result;
}
DQN_API Dqn_V2 &operator*=(Dqn_V2 &lhs, Dqn_V2 rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V2 &operator*=(Dqn_V2 &lhs, Dqn_f32 rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V2 &operator*=(Dqn_V2 &lhs, int32_t rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V2 &operator/=(Dqn_V2 &lhs, Dqn_V2 rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V2 &operator/=(Dqn_V2 &lhs, Dqn_f32 rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V2 &operator/=(Dqn_V2 &lhs, int32_t rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V2 &operator-=(Dqn_V2 &lhs, Dqn_V2 rhs)
{
lhs = lhs - rhs;
return lhs;
}
DQN_API Dqn_V2 &operator+=(Dqn_V2 &lhs, Dqn_V2 rhs)
{
lhs = lhs + rhs;
return lhs;
}
DQN_API Dqn_V2 Dqn_V2_Min(Dqn_V2 a, Dqn_V2 b)
{
Dqn_V2 result = Dqn_V2_InitNx2(DQN_MIN(a.x, b.x), DQN_MIN(a.y, b.y));
return result;
}
DQN_API Dqn_V2 Dqn_V2_Max(Dqn_V2 a, Dqn_V2 b)
{
Dqn_V2 result = Dqn_V2_InitNx2(DQN_MAX(a.x, b.x), DQN_MAX(a.y, b.y));
return result;
}
DQN_API Dqn_V2 Dqn_V2_Abs(Dqn_V2 a)
{
Dqn_V2 result = Dqn_V2_InitNx2(DQN_ABS(a.x), DQN_ABS(a.y));
return result;
}
DQN_API Dqn_f32 Dqn_V2_Dot(Dqn_V2 a, Dqn_V2 b)
{ {
Dqn_f32 result = (a.x * b.x) + (a.y * b.y); Dqn_f32 result = (a.x * b.x) + (a.y * b.y);
return result; return result;
} }
DQN_API Dqn_f32 Dqn_V2LengthSq(Dqn_V2 a, Dqn_V2 b) DQN_API Dqn_f32 Dqn_V2_LengthSq(Dqn_V2 a, Dqn_V2 b)
{ {
Dqn_f32 x_side = b.x - a.x; Dqn_f32 x_side = b.x - a.x;
Dqn_f32 y_side = b.y - a.y; Dqn_f32 y_side = b.y - a.y;
@ -38,7 +297,7 @@ DQN_API Dqn_f32 Dqn_V2LengthSq(Dqn_V2 a, Dqn_V2 b)
return result; return result;
} }
DQN_API Dqn_V2 Dqn_V2Normalise(Dqn_V2 a) DQN_API Dqn_V2 Dqn_V2_Normalise(Dqn_V2 a)
{ {
Dqn_f32 length_sq = DQN_SQUARED(a.x) + DQN_SQUARED(a.y); Dqn_f32 length_sq = DQN_SQUARED(a.x) + DQN_SQUARED(a.y);
Dqn_f32 length = DQN_SQRTF(length_sq); Dqn_f32 length = DQN_SQRTF(length_sq);
@ -46,31 +305,163 @@ DQN_API Dqn_V2 Dqn_V2Normalise(Dqn_V2 a)
return result; return result;
} }
DQN_API Dqn_V2 Dqn_V2Perpendicular(Dqn_V2 a) DQN_API Dqn_V2 Dqn_V2_Perpendicular(Dqn_V2 a)
{ {
Dqn_V2 result = Dqn_V2(-a.y, a.x); Dqn_V2 result = Dqn_V2_InitNx2(-a.y, a.x);
return result; return result;
} }
#endif // !defined(DQN_NO_V2) #endif // !defined(DQN_NO_V2)
#if !defined(DQN_NO_V3) #if !defined(DQN_NO_V3)
// NOTE: [$VEC3] Vector3 =========================================================================== // NOTE: [$VEC3] Vector3 ===========================================================================
DQN_API Dqn_f32 Dqn_V3LengthSq(Dqn_V3 a) DQN_API bool operator!=(Dqn_V3 lhs, Dqn_V3 rhs)
{
bool result = !(lhs == rhs);
return result;
}
DQN_API bool operator==(Dqn_V3 lhs, Dqn_V3 rhs)
{
bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z);
return result;
}
DQN_API bool operator>=(Dqn_V3 lhs, Dqn_V3 rhs)
{
bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z);
return result;
}
DQN_API bool operator<=(Dqn_V3 lhs, Dqn_V3 rhs)
{
bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z);
return result;
}
DQN_API bool operator< (Dqn_V3 lhs, Dqn_V3 rhs)
{
bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z);
return result;
}
DQN_API bool operator>(Dqn_V3 lhs, Dqn_V3 rhs)
{
bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z);
return result;
}
DQN_API Dqn_V3 operator-(Dqn_V3 lhs, Dqn_V3 rhs)
{
Dqn_V3 result = Dqn_V3_InitNx3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z);
return result;
}
DQN_API Dqn_V3 operator+(Dqn_V3 lhs, Dqn_V3 rhs)
{
Dqn_V3 result = Dqn_V3_InitNx3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z);
return result;
}
DQN_API Dqn_V3 operator*(Dqn_V3 lhs, Dqn_V3 rhs)
{
Dqn_V3 result = Dqn_V3_InitNx3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z);
return result;
}
DQN_API Dqn_V3 operator*(Dqn_V3 lhs, Dqn_f32 rhs)
{
Dqn_V3 result = Dqn_V3_InitNx3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs);
return result;
}
DQN_API Dqn_V3 operator*(Dqn_V3 lhs, int32_t rhs)
{
Dqn_V3 result = Dqn_V3_InitNx3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs);
return result;
}
DQN_API Dqn_V3 operator/(Dqn_V3 lhs, Dqn_V3 rhs)
{
Dqn_V3 result = Dqn_V3_InitNx3(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z);
return result;
}
DQN_API Dqn_V3 operator/(Dqn_V3 lhs, Dqn_f32 rhs)
{
Dqn_V3 result = Dqn_V3_InitNx3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs);
return result;
}
DQN_API Dqn_V3 operator/(Dqn_V3 lhs, int32_t rhs)
{
Dqn_V3 result = Dqn_V3_InitNx3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs);
return result;
}
DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, Dqn_V3 rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, Dqn_f32 rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, int32_t rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, Dqn_V3 rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, Dqn_f32 rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, int32_t rhs)
{
lhs = lhs / rhs;
return lhs;
}
DQN_API Dqn_V3 &operator-=(Dqn_V3 &lhs, Dqn_V3 rhs)
{
lhs = lhs - rhs;
return lhs;
}
DQN_API Dqn_V3 &operator+=(Dqn_V3 &lhs, Dqn_V3 rhs)
{
lhs = lhs + rhs;
return lhs;
}
DQN_API Dqn_f32 Dqn_V3_LengthSq(Dqn_V3 a)
{ {
Dqn_f32 result = DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z); Dqn_f32 result = DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z);
return result; return result;
} }
DQN_API Dqn_f32 Dqn_V3Length(Dqn_V3 a) DQN_API Dqn_f32 Dqn_V3_Length(Dqn_V3 a)
{ {
Dqn_f32 length_sq = DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z); Dqn_f32 length_sq = DQN_SQUARED(a.x) + DQN_SQUARED(a.y) + DQN_SQUARED(a.z);
Dqn_f32 result = DQN_SQRTF(length_sq); Dqn_f32 result = DQN_SQRTF(length_sq);
return result; return result;
} }
DQN_API Dqn_V3 Dqn_V3Normalise(Dqn_V3 a) DQN_API Dqn_V3 Dqn_V3_Normalise(Dqn_V3 a)
{ {
Dqn_f32 length = Dqn_V3Length(a); Dqn_f32 length = Dqn_V3_Length(a);
Dqn_V3 result = a / length; Dqn_V3 result = a / length;
return result; return result;
} }
@ -78,6 +469,108 @@ DQN_API Dqn_V3 Dqn_V3Normalise(Dqn_V3 a)
#if !defined(DQN_NO_V4) #if !defined(DQN_NO_V4)
// NOTE: [$VEC4] Vector4 =========================================================================== // NOTE: [$VEC4] Vector4 ===========================================================================
DQN_API bool operator!=(Dqn_V4 lhs, Dqn_V4 rhs)
{
bool result = !(lhs == rhs);
return result;
}
DQN_API bool operator==(Dqn_V4 lhs, Dqn_V4 rhs)
{
bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.w == rhs.w);
return result;
}
DQN_API bool operator>=(Dqn_V4 lhs, Dqn_V4 rhs)
{
bool result = (lhs.x >= rhs.x) && (lhs.y >= rhs.y) && (lhs.z >= rhs.z) && (lhs.w >= rhs.w);
return result;
}
DQN_API bool operator<=(Dqn_V4 lhs, Dqn_V4 rhs)
{
bool result = (lhs.x <= rhs.x) && (lhs.y <= rhs.y) && (lhs.z <= rhs.z) && (lhs.w <= rhs.w);
return result;
}
DQN_API bool operator< (Dqn_V4 lhs, Dqn_V4 rhs)
{
bool result = (lhs.x < rhs.x) && (lhs.y < rhs.y) && (lhs.z < rhs.z) && (lhs.w < rhs.w);
return result;
}
DQN_API bool operator>(Dqn_V4 lhs, Dqn_V4 rhs)
{
bool result = (lhs.x > rhs.x) && (lhs.y > rhs.y) && (lhs.z > rhs.z) && (lhs.w > rhs.w);
return result;
}
DQN_API Dqn_V4 operator-(Dqn_V4 lhs, Dqn_V4 rhs)
{
Dqn_V4 result = Dqn_V4_InitNx4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w);
return result;
}
DQN_API Dqn_V4 operator+(Dqn_V4 lhs, Dqn_V4 rhs)
{
Dqn_V4 result = Dqn_V4_InitNx4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w);
return result;
}
DQN_API Dqn_V4 operator* (Dqn_V4 lhs, Dqn_V4 rhs)
{
Dqn_V4 result = Dqn_V4_InitNx4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w);
return result;
}
DQN_API Dqn_V4 operator*(Dqn_V4 lhs, Dqn_f32 rhs)
{
Dqn_V4 result = Dqn_V4_InitNx4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs);
return result;
}
DQN_API Dqn_V4 operator*(Dqn_V4 lhs, int32_t rhs)
{
Dqn_V4 result = Dqn_V4_InitNx4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs);
return result;
}
DQN_API Dqn_V4 operator/(Dqn_V4 lhs, Dqn_f32 rhs)
{
Dqn_V4 result = Dqn_V4_InitNx4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs);
return result;
}
DQN_API Dqn_V4 &operator*=(Dqn_V4 &lhs, Dqn_V4 rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V4 &operator*=(Dqn_V4 &lhs, Dqn_f32 rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V4 &operator*=(Dqn_V4 &lhs, int32_t rhs)
{
lhs = lhs * rhs;
return lhs;
}
DQN_API Dqn_V4 &operator-=(Dqn_V4 &lhs, Dqn_V4 rhs)
{
lhs = lhs - rhs;
return lhs;
}
DQN_API Dqn_V4 &operator+=(Dqn_V4 &lhs, Dqn_V4 rhs)
{
lhs = lhs + rhs;
return lhs;
}
DQN_API Dqn_f32 Dqn_V4Dot(Dqn_V4 a, Dqn_V4 b) DQN_API Dqn_f32 Dqn_V4Dot(Dqn_V4 a, Dqn_V4 b)
{ {
Dqn_f32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); Dqn_f32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w);
@ -163,9 +656,9 @@ DQN_API Dqn_M4 Dqn_M4_Transpose(Dqn_M4 mat)
DQN_API Dqn_M4 Dqn_M4_Rotate(Dqn_V3 axis01, Dqn_f32 radians) DQN_API Dqn_M4 Dqn_M4_Rotate(Dqn_V3 axis01, Dqn_f32 radians)
{ {
DQN_ASSERTF(DQN_ABS(Dqn_V3Length(axis01) - 1.f) <= 0.01f, DQN_ASSERTF(DQN_ABS(Dqn_V3_Length(axis01) - 1.f) <= 0.01f,
"Rotation axis must be normalised, length = %f", "Rotation axis must be normalised, length = %f",
Dqn_V3Length(axis01)); Dqn_V3_Length(axis01));
Dqn_f32 sin = DQN_SINF(radians); Dqn_f32 sin = DQN_SINF(radians);
Dqn_f32 cos = DQN_COSF(radians); Dqn_f32 cos = DQN_COSF(radians);
@ -338,98 +831,80 @@ DQN_API Dqn_FString8<256> Dqn_M4_ColumnMajorString(Dqn_M4 mat)
#if !defined(DQN_NO_RECT) #if !defined(DQN_NO_RECT)
// NOTE: [$RECT] Dqn_Rect ========================================================================== // NOTE: [$RECT] Dqn_Rect ==========================================================================
DQN_API Dqn_Rect Dqn_Rect_InitFromPosAndSize(Dqn_V2 pos, Dqn_V2 size) DQN_API bool operator==(const Dqn_Rect& lhs, const Dqn_Rect& rhs)
{ {
Dqn_Rect result = {}; bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size);
result.min = pos;
if (size.x < 0) result.min.x -= size.x;
if (size.y < 0) result.min.y -= size.y;
result.max = result.min + Dqn_V2Abs(size);
return result; return result;
} }
DQN_API Dqn_V2 Dqn_Rect_Center(Dqn_Rect rect) DQN_API Dqn_V2 Dqn_Rect_Center(Dqn_Rect rect)
{ {
Dqn_V2 size = rect.max - rect.min; Dqn_V2 result = rect.pos + (rect.size * .5f);
Dqn_V2 result = rect.min + (size * 0.5f);
return result; return result;
} }
DQN_API bool Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p) DQN_API bool Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p)
{ {
bool result = (p.x >= rect.min.x && p.x <= rect.max.x && p.y >= rect.min.y && p.y <= rect.max.y); Dqn_V2 min = rect.pos;
Dqn_V2 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; return result;
} }
DQN_API bool Dqn_Rect_ContainsRect(Dqn_Rect a, Dqn_Rect b) DQN_API bool Dqn_Rect_ContainsRect(Dqn_Rect a, Dqn_Rect b)
{ {
bool result = (b.min >= a.min && b.max <= a.max); Dqn_V2 a_min = a.pos;
return result; Dqn_V2 a_max = a.pos + a.size;
} Dqn_V2 b_min = b.pos;
Dqn_V2 b_max = b.pos + b.size;
DQN_API Dqn_V2 Dqn_Rect_Size(Dqn_Rect rect) bool result = (b_min >= a_min && b_max <= a_max);
{
Dqn_V2 result = rect.max - rect.min;
return result;
}
DQN_API Dqn_Rect Dqn_Rect_Move(Dqn_Rect src, Dqn_V2 move_amount)
{
Dqn_Rect result = src;
result.min += move_amount;
result.max += move_amount;
return result;
}
DQN_API Dqn_Rect Dqn_Rect_MoveTo(Dqn_Rect src, Dqn_V2 dest)
{
Dqn_V2 move_amount = dest - src.min;
Dqn_Rect result = src;
result.min += move_amount;
result.max += move_amount;
return result; return result;
} }
DQN_API bool Dqn_Rect_Intersects(Dqn_Rect a, Dqn_Rect b) DQN_API bool Dqn_Rect_Intersects(Dqn_Rect a, Dqn_Rect b)
{ {
bool result = (a.min.x <= b.max.x && a.max.x >= b.min.x) && Dqn_V2 a_min = a.pos;
(a.min.y <= b.max.y && a.max.y >= b.min.y); Dqn_V2 a_max = a.pos + a.size;
Dqn_V2 b_min = b.pos;
Dqn_V2 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; return result;
} }
DQN_API Dqn_Rect Dqn_Rect_Intersection(Dqn_Rect a, Dqn_Rect b) DQN_API Dqn_Rect Dqn_Rect_Intersection(Dqn_Rect a, Dqn_Rect b)
{ {
Dqn_Rect result = {}; Dqn_Rect result = {};
if (Dqn_Rect_Intersects(a, b)) if (Dqn_Rect_Intersects(a, b)) {
{ Dqn_V2 a_min = a.pos;
result.min.x = DQN_MAX(a.min.x, b.min.x); Dqn_V2 a_max = a.pos + a.size;
result.min.y = DQN_MAX(a.min.y, b.min.y); Dqn_V2 b_min = b.pos;
result.max.x = DQN_MIN(a.max.x, b.max.x); Dqn_V2 b_max = b.pos + b.size;
result.max.y = DQN_MIN(a.max.y, b.max.y);
}
Dqn_V2 min = {};
Dqn_V2 max = {};
min.x = DQN_MAX(a_min.x, b_min.x);
min.y = DQN_MAX(a_min.y, b_min.y);
max.x = DQN_MIN(a_max.x, b_max.x);
max.y = DQN_MIN(a_max.y, b_max.y);
result = Dqn_Rect_InitV2x2(min, max - min);
}
return result; return result;
} }
DQN_API Dqn_Rect Dqn_Rect_Union(Dqn_Rect a, Dqn_Rect b) DQN_API Dqn_Rect Dqn_Rect_Union(Dqn_Rect a, Dqn_Rect b)
{ {
Dqn_Rect result = {}; Dqn_V2 a_min = a.pos;
result.min.x = DQN_MIN(a.min.x, b.min.x); Dqn_V2 a_max = a.pos + a.size;
result.min.y = DQN_MIN(a.min.y, b.min.y); Dqn_V2 b_min = b.pos;
result.max.x = DQN_MAX(a.max.x, b.max.x); Dqn_V2 b_max = b.pos + b.size;
result.max.y = DQN_MAX(a.max.y, b.max.y);
return result;
}
DQN_API Dqn_Rect Dqn_Rect_FromRectI32(Dqn_RectI32 a) Dqn_V2 min, max;
{ min.x = DQN_MIN(a_min.x, b_min.x);
Dqn_Rect result = Dqn_Rect(a.min, a.max); min.y = DQN_MIN(a_min.y, b_min.y);
return result; max.x = DQN_MAX(a_max.x, b_max.x);
} max.y = DQN_MAX(a_max.y, b_max.y);
Dqn_Rect result = Dqn_Rect_InitV2x2(min, max - min);
DQN_API Dqn_V2I Dqn_RectI32_Size(Dqn_RectI32 rect)
{
Dqn_V2I result = rect.max - rect.min;
return result; return result;
} }
#endif // !defined(DQN_NO_RECT) #endif // !defined(DQN_NO_RECT)

View File

@ -8,124 +8,128 @@
// [$RECT] Dqn_Rect | DQN_NO_RECT | // [$RECT] Dqn_Rect | DQN_NO_RECT |
// [$MATH] Other | | // [$MATH] Other | |
// ================================================================================================= // =================================================================================================
#if defined(DQN_COMPILER_W32_MSVC)
#pragma warning(push)
#pragma warning(disable: 4201) // warning C4201: nonstandard extension used: nameless struct/union
#endif
#if !defined(DQN_NO_V2) #if !defined(DQN_NO_V2)
// NOTE: [$VEC2] Vector2 =========================================================================== // NOTE: [$VEC2] Vector2 ===========================================================================
struct Dqn_V2I union Dqn_V2I
{ {
int32_t x, y; struct { int32_t x, y; };
struct { int32_t w, h; };
Dqn_V2I() = default; int32_t data[2];
Dqn_V2I(Dqn_f32 x_, Dqn_f32 y_): x((int32_t)x_), y((int32_t)y_) {}
Dqn_V2I(int32_t x_, int32_t y_): x(x_), y(y_) {}
Dqn_V2I(int32_t xy): x(xy), y(xy) {}
bool operator!=(Dqn_V2I other) const { return !(*this == other); }
bool operator==(Dqn_V2I other) const { return (x == other.x) && (y == other.y); }
bool operator>=(Dqn_V2I other) const { return (x >= other.x) && (y >= other.y); }
bool operator<=(Dqn_V2I other) const { return (x <= other.x) && (y <= other.y); }
bool operator< (Dqn_V2I other) const { return (x < other.x) && (y < other.y); }
bool operator> (Dqn_V2I other) const { return (x > other.x) && (y > other.y); }
Dqn_V2I operator- (Dqn_V2I other) const { Dqn_V2I result(x - other.x, y - other.y); return result; }
Dqn_V2I operator+ (Dqn_V2I other) const { Dqn_V2I result(x + other.x, y + other.y); return result; }
Dqn_V2I operator* (Dqn_V2I other) const { Dqn_V2I result(x * other.x, y * other.y); return result; }
Dqn_V2I operator* (Dqn_f32 other) const { Dqn_V2I result(x * other, y * other); return result; }
Dqn_V2I operator* (int32_t other) const { Dqn_V2I result(x * other, y * other); return result; }
Dqn_V2I operator/ (Dqn_V2I other) const { Dqn_V2I result(x / other.x, y / other.y); return result; }
Dqn_V2I operator/ (Dqn_f32 other) const { Dqn_V2I result(x / other, y / other); return result; }
Dqn_V2I operator/ (int32_t other) const { Dqn_V2I result(x / other, y / other); return result; }
Dqn_V2I &operator*=(Dqn_V2I other) { *this = *this * other; return *this; }
Dqn_V2I &operator*=(Dqn_f32 other) { *this = *this * other; return *this; }
Dqn_V2I &operator*=(int32_t other) { *this = *this * other; return *this; }
Dqn_V2I &operator-=(Dqn_V2I other) { *this = *this - other; return *this; }
Dqn_V2I &operator+=(Dqn_V2I other) { *this = *this + other; return *this; }
}; };
struct Dqn_V2 #define Dqn_V2I_InitNx1(x) DQN_LITERAL(Dqn_V2I){(int32_t)(x), (int32_t)(x)}
#define Dqn_V2I_InitNx2(x, y) DQN_LITERAL(Dqn_V2I){(int32_t)(x), (int32_t)(y)}
DQN_API bool operator!=(Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API bool operator==(Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API bool operator>=(Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API bool operator<=(Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API bool operator< (Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API bool operator> (Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API Dqn_V2I operator- (Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API Dqn_V2I operator+ (Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, Dqn_f32 rhs);
DQN_API Dqn_V2I operator* (Dqn_V2I lhs, int32_t rhs);
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, Dqn_V2I rhs);
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, Dqn_f32 rhs);
DQN_API Dqn_V2I operator/ (Dqn_V2I lhs, int32_t rhs);
DQN_API Dqn_V2I &operator*=(Dqn_V2I& lhs, Dqn_V2I rhs);
DQN_API Dqn_V2I &operator*=(Dqn_V2I& lhs, Dqn_f32 rhs);
DQN_API Dqn_V2I &operator*=(Dqn_V2I& lhs, int32_t rhs);
DQN_API Dqn_V2I &operator/=(Dqn_V2I& lhs, Dqn_V2I rhs);
DQN_API Dqn_V2I &operator/=(Dqn_V2I& lhs, Dqn_f32 rhs);
DQN_API Dqn_V2I &operator/=(Dqn_V2I& lhs, int32_t rhs);
DQN_API Dqn_V2I &operator-=(Dqn_V2I& lhs, Dqn_V2I rhs);
DQN_API Dqn_V2I &operator+=(Dqn_V2I& lhs, Dqn_V2I rhs);
union Dqn_V2
{ {
Dqn_f32 x, y; struct { Dqn_f32 x, y; };
struct { Dqn_f32 w, h; };
Dqn_V2() = default; Dqn_f32 data[2];
Dqn_V2(Dqn_f32 a) : x(a), y(a) {}
Dqn_V2(int32_t a) : x((Dqn_f32)a), y((Dqn_f32)a) {}
Dqn_V2(Dqn_f32 x, Dqn_f32 y): x(x), y(y) {}
Dqn_V2(int32_t x, int32_t y): x((Dqn_f32)x), y((Dqn_f32)y) {}
Dqn_V2(Dqn_V2I a) : x((Dqn_f32)a.x),y((Dqn_f32)a.y){}
bool operator!=(Dqn_V2 other) const { return !(*this == other); }
bool operator==(Dqn_V2 other) const { return (x == other.x) && (y == other.y); }
bool operator>=(Dqn_V2 other) const { return (x >= other.x) && (y >= other.y); }
bool operator<=(Dqn_V2 other) const { return (x <= other.x) && (y <= other.y); }
bool operator< (Dqn_V2 other) const { return (x < other.x) && (y < other.y); }
bool operator> (Dqn_V2 other) const { return (x > other.x) && (y > other.y); }
Dqn_V2 operator- (Dqn_V2 other) const { Dqn_V2 result(x - other.x, y - other.y); return result; }
Dqn_V2 operator+ (Dqn_V2 other) const { Dqn_V2 result(x + other.x, y + other.y); return result; }
Dqn_V2 operator* (Dqn_V2 other) const { Dqn_V2 result(x * other.x, y * other.y); return result; }
Dqn_V2 operator* (Dqn_f32 other) const { Dqn_V2 result(x * other, y * other); return result; }
Dqn_V2 operator* (int32_t other) const { Dqn_V2 result(x * other, y * other); return result; }
Dqn_V2 operator/ (Dqn_V2 other) const { Dqn_V2 result(x / other.x, y / other.y); return result; }
Dqn_V2 operator/ (Dqn_f32 other) const { Dqn_V2 result(x / other, y / other); return result; }
Dqn_V2 operator/ (int32_t other) const { Dqn_V2 result(x / other, y / other); return result; }
Dqn_V2 &operator*=(Dqn_V2 other) { *this = *this * other; return *this; }
Dqn_V2 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; }
Dqn_V2 &operator*=(int32_t other) { *this = *this * other; return *this; }
Dqn_V2 &operator/=(Dqn_V2 other) { *this = *this / other; return *this; }
Dqn_V2 &operator/=(Dqn_f32 other) { *this = *this / other; return *this; }
Dqn_V2 &operator/=(int32_t other) { *this = *this / other; return *this; }
Dqn_V2 &operator-=(Dqn_V2 other) { *this = *this - other; return *this; }
Dqn_V2 &operator+=(Dqn_V2 other) { *this = *this + other; return *this; }
}; };
DQN_API Dqn_V2I Dqn_V2ToV2I(Dqn_V2 a); #define Dqn_V2_InitNx1(x) DQN_LITERAL(Dqn_V2){(Dqn_f32)(x), (Dqn_f32)(x)}
DQN_API Dqn_V2 Dqn_V2Min(Dqn_V2 a, Dqn_V2 b); #define Dqn_V2_InitNx2(x, y) DQN_LITERAL(Dqn_V2){(Dqn_f32)(x), (Dqn_f32)(y)}
DQN_API Dqn_V2 Dqn_V2Max(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2Abs(Dqn_V2 a); DQN_API bool operator!=(Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_f32 Dqn_V2Dot(Dqn_V2 a, Dqn_V2 b); DQN_API bool operator==(Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_f32 Dqn_V2LengthSq(Dqn_V2 a, Dqn_V2 b); DQN_API bool operator>=(Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 Dqn_V2Normalise(Dqn_V2 a); DQN_API bool operator<=(Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 Dqn_V2Perpendicular(Dqn_V2 a); DQN_API bool operator< (Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API bool operator> (Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 operator- (Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 operator+ (Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, Dqn_f32 rhs);
DQN_API Dqn_V2 operator* (Dqn_V2 lhs, int32_t rhs);
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, Dqn_f32 rhs);
DQN_API Dqn_V2 operator/ (Dqn_V2 lhs, int32_t rhs);
DQN_API Dqn_V2 &operator*=(Dqn_V2& lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 &operator*=(Dqn_V2& lhs, Dqn_f32 rhs);
DQN_API Dqn_V2 &operator*=(Dqn_V2& lhs, int32_t rhs);
DQN_API Dqn_V2 &operator/=(Dqn_V2& lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 &operator/=(Dqn_V2& lhs, Dqn_f32 rhs);
DQN_API Dqn_V2 &operator/=(Dqn_V2& lhs, int32_t rhs);
DQN_API Dqn_V2 &operator-=(Dqn_V2& lhs, Dqn_V2 rhs);
DQN_API Dqn_V2 &operator+=(Dqn_V2& lhs, Dqn_V2 rhs);
DQN_API Dqn_V2I Dqn_V2_ToV2I(Dqn_V2 a);
DQN_API Dqn_V2 Dqn_V2_Min(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2_Max(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2_Abs(Dqn_V2 a);
DQN_API Dqn_f32 Dqn_V2_Dot(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_f32 Dqn_V2_LengthSq(Dqn_V2 a, Dqn_V2 b);
DQN_API Dqn_V2 Dqn_V2_Normalise(Dqn_V2 a);
DQN_API Dqn_V2 Dqn_V2_Perpendicular(Dqn_V2 a);
#endif // !defined(DQN_NO_V2) #endif // !defined(DQN_NO_V2)
#if !defined(DQN_NO_V3) #if !defined(DQN_NO_V3)
// NOTE: [$VEC3] Vector3 =========================================================================== // NOTE: [$VEC3] Vector3 ===========================================================================
struct Dqn_V3 union Dqn_V3
{ {
Dqn_f32 x, y, z; struct { Dqn_f32 x, y, z; };
struct { Dqn_f32 r, g, b; };
Dqn_V3() = default; Dqn_f32 data[3];
Dqn_V3(Dqn_f32 a) : x(a), y(a), z(a) {}
Dqn_V3(int32_t a) : x(DQN_CAST(Dqn_f32)a), y(DQN_CAST(Dqn_f32)a), z(DQN_CAST(Dqn_f32)a) {}
Dqn_V3(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z): x(x), y(y), z(z) {}
Dqn_V3(int32_t x, int32_t y, Dqn_f32 z): x(DQN_CAST(Dqn_f32)x), y(DQN_CAST(Dqn_f32)y), z(DQN_CAST(Dqn_f32)z) {}
Dqn_V3(Dqn_V2 xy, Dqn_f32 z) : x(xy.x), y(xy.y), z(z) {}
bool operator!= (Dqn_V3 other) const { return !(*this == other); }
bool operator== (Dqn_V3 other) const { return (x == other.x) && (y == other.y) && (z == other.z); }
bool operator>= (Dqn_V3 other) const { return (x >= other.x) && (y >= other.y) && (z >= other.z); }
bool operator<= (Dqn_V3 other) const { return (x <= other.x) && (y <= other.y) && (z <= other.z); }
bool operator< (Dqn_V3 other) const { return (x < other.x) && (y < other.y) && (z < other.z); }
bool operator> (Dqn_V3 other) const { return (x > other.x) && (y > other.y) && (z > other.z); }
Dqn_V3 operator- (Dqn_V3 other) const { Dqn_V3 result(x - other.x, y - other.y, z - other.z); return result; }
Dqn_V3 operator+ (Dqn_V3 other) const { Dqn_V3 result(x + other.x, y + other.y, z + other.z); return result; }
Dqn_V3 operator* (Dqn_V3 other) const { Dqn_V3 result(x * other.x, y * other.y, z * other.z); return result; }
Dqn_V3 operator* (Dqn_f32 other) const { Dqn_V3 result(x * other, y * other, z * other); return result; }
Dqn_V3 operator* (int32_t other) const { Dqn_V3 result(x * other, y * other, z * other); return result; }
Dqn_V3 operator/ (Dqn_V3 other) const { Dqn_V3 result(x / other.x, y / other.y, z / other.z); return result; }
Dqn_V3 operator/ (Dqn_f32 other) const { Dqn_V3 result(x / other, y / other, z / other); return result; }
Dqn_V3 operator/ (int32_t other) const { Dqn_V3 result(x / other, y / other, z / other); return result; }
Dqn_V3 &operator*=(Dqn_V3 other) { *this = *this * other; return *this; }
Dqn_V3 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; }
Dqn_V3 &operator*=(int32_t other) { *this = *this * other; return *this; }
Dqn_V3 &operator/=(Dqn_V3 other) { *this = *this / other; return *this; }
Dqn_V3 &operator/=(Dqn_f32 other) { *this = *this / other; return *this; }
Dqn_V3 &operator/=(int32_t other) { *this = *this / other; return *this; }
Dqn_V3 &operator-=(Dqn_V3 other) { *this = *this - other; return *this; }
Dqn_V3 &operator+=(Dqn_V3 other) { *this = *this + other; return *this; }
}; };
DQN_API Dqn_f32 Dqn_V3LengthSq(Dqn_V3 a); #define Dqn_V3_InitNx1(x) DQN_LITERAL(Dqn_V3){(Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x)}
DQN_API Dqn_f32 Dqn_V3Length(Dqn_V3 a); #define Dqn_V3_InitNx3(x, y, z) DQN_LITERAL(Dqn_V3){(Dqn_f32)(x), (Dqn_f32)(y), (Dqn_f32)(z)}
DQN_API Dqn_V3 Dqn_V3Normalise(Dqn_V3 a); #define Dqn_V3_InitV2x1_Nx1(xy, z) DQN_LITERAL(Dqn_V3){(Dqn_f32)(xy.x), (Dqn_f32)(xy.y), (Dqn_f32)(z)}
DQN_API bool operator!=(Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API bool operator==(Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API bool operator>=(Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API bool operator<=(Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API bool operator< (Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API bool operator> (Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API Dqn_V3 operator- (Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API Dqn_V3 operator+ (Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, Dqn_f32 rhs);
DQN_API Dqn_V3 operator* (Dqn_V3 lhs, int32_t rhs);
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, Dqn_V3 rhs);
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, Dqn_f32 rhs);
DQN_API Dqn_V3 operator/ (Dqn_V3 lhs, int32_t rhs);
DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, Dqn_V3 rhs);
DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, Dqn_f32 rhs);
DQN_API Dqn_V3 &operator*=(Dqn_V3 &lhs, int32_t rhs);
DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, Dqn_V3 rhs);
DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, Dqn_f32 rhs);
DQN_API Dqn_V3 &operator/=(Dqn_V3 &lhs, int32_t rhs);
DQN_API Dqn_V3 &operator-=(Dqn_V3 &lhs, Dqn_V3 rhs);
DQN_API Dqn_V3 &operator+=(Dqn_V3 &lhs, Dqn_V3 rhs);
DQN_API Dqn_f32 Dqn_V3_LengthSq(Dqn_V3 a);
DQN_API Dqn_f32 Dqn_V3_Length(Dqn_V3 a);
DQN_API Dqn_V3 Dqn_V3_Normalise(Dqn_V3 a);
#endif // !defined(DQN_NO_V3) #endif // !defined(DQN_NO_V3)
#if !defined(DQN_NO_V4) #if !defined(DQN_NO_V4)
@ -135,39 +139,42 @@ DQN_API Dqn_V3 Dqn_V3Normalise(Dqn_V3 a);
#error "Dqn_Rect requires Dqn_V3 hence DQN_NO_V3 must *not* be defined" #error "Dqn_Rect requires Dqn_V3 hence DQN_NO_V3 must *not* be defined"
#endif #endif
#if defined(DQN_COMPILER_W32_MSVC)
#pragma warning(push)
#pragma warning(disable: 4201) // warning C4201: nonstandard extension used: nameless struct/union
#endif
union Dqn_V4 union Dqn_V4
{ {
struct { Dqn_f32 x, y, z, w; }; struct { Dqn_f32 x, y, z, w; };
struct { Dqn_f32 r, g, b, a; }; struct { Dqn_f32 r, g, b, a; };
struct { Dqn_V2 min; Dqn_V2 max; } v2;
Dqn_V3 rgb; Dqn_V3 rgb;
Dqn_f32 e[4]; Dqn_f32 data[4];
Dqn_V4() = default;
Dqn_V4(Dqn_f32 xyzw) : x(xyzw), y(xyzw), z(xyzw), w(xyzw) {}
Dqn_V4(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z, Dqn_f32 w): x(x), y(y), z(z), w(w) {}
Dqn_V4(int32_t x, int32_t y, int32_t z, int32_t w): x(DQN_CAST(Dqn_f32)x), y(DQN_CAST(Dqn_f32)y), z(DQN_CAST(Dqn_f32)z), w(DQN_CAST(Dqn_f32)w) {}
Dqn_V4(Dqn_V3 xyz, Dqn_f32 w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
Dqn_V4(Dqn_V2 v2) : x(v2.x), y(v2.y), z(v2.x), w(v2.y) {}
bool operator!=(Dqn_V4 other) const { return !(*this == other); }
bool operator==(Dqn_V4 other) const { return (x == other.x) && (y == other.y) && (z == other.z) && (w == other.w); }
bool operator>=(Dqn_V4 other) const { return (x >= other.x) && (y >= other.y) && (z >= other.z) && (w >= other.w); }
bool operator<=(Dqn_V4 other) const { return (x <= other.x) && (y <= other.y) && (z <= other.z) && (w <= other.w); }
bool operator< (Dqn_V4 other) const { return (x < other.x) && (y < other.y) && (z < other.z) && (w < other.w); }
bool operator> (Dqn_V4 other) const { return (x > other.x) && (y > other.y) && (z > other.z) && (w > other.w); }
Dqn_V4 operator- (Dqn_V4 other) const { Dqn_V4 result(x - other.x, y - other.y, z - other.z, w - other.w); return result; }
Dqn_V4 operator+ (Dqn_V4 other) const { Dqn_V4 result(x + other.x, y + other.y, z + other.z, w + other.w); return result; }
Dqn_V4 operator* (Dqn_V4 other) const { Dqn_V4 result(x * other.x, y * other.y, z * other.z, w * other.w); return result; }
Dqn_V4 operator* (Dqn_f32 other) const { Dqn_V4 result(x * other, y * other, z * other, w * other); return result; }
Dqn_V4 operator* (int32_t other) const { Dqn_V4 result(x * other, y * other, z * other, w * other); return result; }
Dqn_V4 operator/ (Dqn_f32 other) const { Dqn_V4 result(x / other, y / other, z / other, w / other); return result; }
Dqn_V4 &operator*=(Dqn_V4 other) { *this = *this * other; return *this; }
Dqn_V4 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; }
Dqn_V4 &operator*=(int32_t other) { *this = *this * other; return *this; }
Dqn_V4 &operator-=(Dqn_V4 other) { *this = *this - other; return *this; }
Dqn_V4 &operator+=(Dqn_V4 other) { *this = *this + other; return *this; }
}; };
#define Dqn_V4_InitNx1(x) DQN_LITERAL(Dqn_V4){(Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x), (Dqn_f32)(x)}
#define Dqn_V4_InitNx4(x, y, z, w) DQN_LITERAL(Dqn_V4){(Dqn_f32)(x), (Dqn_f32)(y), (Dqn_f32)(z), (Dqn_f32)(w)}
bool operator!=(Dqn_V4 lhs, Dqn_V4 rhs);
bool operator==(Dqn_V4 lhs, Dqn_V4 rhs);
bool operator>=(Dqn_V4 lhs, Dqn_V4 rhs);
bool operator<=(Dqn_V4 lhs, Dqn_V4 rhs);
bool operator< (Dqn_V4 lhs, Dqn_V4 rhs);
bool operator> (Dqn_V4 lhs, Dqn_V4 rhs);
Dqn_V4 operator- (Dqn_V4 lhs, Dqn_V4 rhs);
Dqn_V4 operator+ (Dqn_V4 lhs, Dqn_V4 rhs);
Dqn_V4 operator* (Dqn_V4 lhs, Dqn_V4 rhs);
Dqn_V4 operator* (Dqn_V4 lhs, Dqn_f32 rhs);
Dqn_V4 operator* (Dqn_V4 lhs, int32_t rhs);
Dqn_V4 operator/ (Dqn_V4 lhs, Dqn_f32 rhs);
Dqn_V4 &operator*=(Dqn_V4 &lhs, Dqn_V4 rhs);
Dqn_V4 &operator*=(Dqn_V4 &lhs, Dqn_f32 rhs);
Dqn_V4 &operator*=(Dqn_V4 &lhs, int32_t rhs);
Dqn_V4 &operator-=(Dqn_V4 &lhs, Dqn_V4 rhs);
Dqn_V4 &operator+=(Dqn_V4 &lhs, Dqn_V4 rhs);
#if defined(DQN_COMPILER_W32_MSVC)
#pragma warning(pop)
#endif
#endif // !defined(DQN_NO_V4) #endif // !defined(DQN_NO_V4)
#if !defined(DQN_NO_M4) #if !defined(DQN_NO_M4)
@ -211,36 +218,28 @@ DQN_API Dqn_FString8<256> Dqn_M4_ColumnMajorString(Dqn_M4 mat);
struct Dqn_Rect struct Dqn_Rect
{ {
Dqn_V2 min, max; Dqn_V2 pos, size;
Dqn_Rect() = default;
Dqn_Rect(Dqn_V2 min, Dqn_V2 max) : min(min), max(max) {}
Dqn_Rect(Dqn_V2I min, Dqn_V2I max) : min(min), max(max) {}
Dqn_Rect(Dqn_f32 x, Dqn_f32 y, Dqn_f32 max_x, Dqn_f32 max_y) : min(x, y), max(max_x, max_y) {}
bool operator==(Dqn_Rect other) const { return (min == other.min) && (max == other.max); }
}; };
struct Dqn_RectI32 #if defined(__cplusplus)
{ #define Dqn_Rect_InitV2x2(pos, size) Dqn_Rect{pos, size}
Dqn_V2I min, max; #else
Dqn_RectI32() = default; #define Dqn_Rect_InitV2x2(pos, size) (Dqn_Rect){pos, size}
Dqn_RectI32(Dqn_V2I min, Dqn_V2I max) : min(min), max(max) {} #endif
};
DQN_API Dqn_Rect Dqn_Rect_InitFromPosAndSize(Dqn_V2 pos, Dqn_V2 size); DQN_API bool operator== (const Dqn_Rect& lhs, const Dqn_Rect& rhs);
DQN_API Dqn_V2 Dqn_Rect_Center (Dqn_Rect rect); DQN_API Dqn_V2 Dqn_Rect_Center (Dqn_Rect rect);
DQN_API bool Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p); DQN_API bool Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p);
DQN_API bool Dqn_Rect_ContainsRect (Dqn_Rect a, Dqn_Rect b); DQN_API bool Dqn_Rect_ContainsRect (Dqn_Rect a, Dqn_Rect b);
DQN_API Dqn_V2 Dqn_Rect_Size(Dqn_Rect rect);
DQN_API Dqn_Rect Dqn_Rect_Move(Dqn_Rect src, Dqn_V2 move_amount);
DQN_API Dqn_Rect Dqn_Rect_MoveTo(Dqn_Rect src, Dqn_V2 dest);
DQN_API bool Dqn_Rect_Intersects (Dqn_Rect a, Dqn_Rect b); DQN_API bool Dqn_Rect_Intersects (Dqn_Rect a, Dqn_Rect b);
DQN_API Dqn_Rect Dqn_Rect_Intersection (Dqn_Rect a, Dqn_Rect b); DQN_API Dqn_Rect Dqn_Rect_Intersection (Dqn_Rect a, Dqn_Rect b);
DQN_API Dqn_Rect Dqn_Rect_Union (Dqn_Rect a, Dqn_Rect b); DQN_API Dqn_Rect Dqn_Rect_Union (Dqn_Rect a, Dqn_Rect b);
DQN_API Dqn_Rect Dqn_Rect_FromRectI32(Dqn_RectI32 a);
DQN_API Dqn_V2I Dqn_RectI32_Size(Dqn_RectI32 rect);
#endif // !defined(DQN_NO_RECT) #endif // !defined(DQN_NO_RECT)
// NOTE: [$MATH] Other ============================================================================= // NOTE: [$MATH] Other =============================================================================
DQN_API Dqn_V2 Dqn_Lerp_V2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b); DQN_API Dqn_V2 Dqn_Lerp_V2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b);
DQN_API Dqn_f32 Dqn_Lerp_F32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b); DQN_API Dqn_f32 Dqn_Lerp_F32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b);
#if defined(DQN_COMPILER_W32_MSVC)
#pragma warning(pop)
#endif

View File

@ -289,6 +289,24 @@ DQN_API void Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_FUNCTION Dqn_ArenaBlock *block
Dqn_VMem_Release(block, block_metadata_size + block->size); Dqn_VMem_Release(block, block_metadata_size + block->size);
Dqn_Library_LeakTraceMarkFree(DQN_LEAK_TRACE_ARG block); Dqn_Library_LeakTraceMarkFree(DQN_LEAK_TRACE_ARG block);
} else { } else {
if (block->arena->use_after_free_guard) {
DQN_ASSERTF(
block->flags & Dqn_ArenaBlockFlags_UseAfterFreeGuard,
"Arena has set use-after-free guard but the memory it uses was not initialised "
"with use-after-free semantics. You might have set the arena use-after-free "
"flag after it has already done an allocation which is not valid. Make sure "
"you set the flag first before the arena is used.");
} else {
DQN_ASSERTF(
(block->flags & Dqn_ArenaBlockFlags_UseAfterFreeGuard) == 0,
"The arena's memory block has the use-after-free guard set but the arena does "
"not have the use-after-free flag set. This is not valid, a block that has "
"use-after-free semantics was allocated from an arena with the equivalent flag set "
"and for the lifetime of the block the owning arena must also have the same flag "
"set for correct behaviour. Make sure you do not unset the flag on the arena "
"whilst it still has memory blocks that it owns.");
}
block->used = reset_info.used_value; block->used = reset_info.used_value;
// NOTE: Guard all the committed pages again // NOTE: Guard all the committed pages again
if (block->arena->use_after_free_guard) if (block->arena->use_after_free_guard)
@ -473,6 +491,9 @@ DQN_API Dqn_ArenaBlock *Dqn_Arena_Grow_(DQN_LEAK_TRACE_FUNCTION Dqn_Arena *arena
result->flags = flags; result->flags = flags;
result->arena = arena; result->arena = arena;
if (arena->use_after_free_guard)
result->flags |= Dqn_ArenaBlockFlags_UseAfterFreeGuard;
// NOTE: Reset the block (this will guard the memory pages if required, otherwise no-op). // NOTE: Reset the block (this will guard the memory pages if required, otherwise no-op).
Dqn_ArenaBlockResetInfo_ reset_info = {}; Dqn_ArenaBlockResetInfo_ reset_info = {};
Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_ARG result, Dqn_ZeroMem_No, reset_info); Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_ARG result, Dqn_ZeroMem_No, reset_info);

View File

@ -189,7 +189,8 @@ DQN_API int Dqn_VMem_Protect (void *ptr, Dqn_usize size, uint32_t page_flags);
enum Dqn_ArenaBlockFlags enum Dqn_ArenaBlockFlags
{ {
Dqn_ArenaBlockFlags_Private = 1 << 0, ///< Private blocks can only allocate its memory when used in the 'FromBlock' API variants Dqn_ArenaBlockFlags_Private = 1 << 0, // Private blocks can only allocate its memory when used in the 'FromBlock' API variants
Dqn_ArenaBlockFlags_UseAfterFreeGuard = 1 << 1, // Block was allocated with use-after-free guard semantics
}; };
struct Dqn_ArenaStat struct Dqn_ArenaStat

View File

@ -538,7 +538,7 @@ DQN_API uint32_t Dqn_Thread_GetID()
DQN_API Dqn_ThreadContext *Dqn_Thread_GetContext_(DQN_LEAK_TRACE_FUNCTION_NO_COMMA) DQN_API Dqn_ThreadContext *Dqn_Thread_GetContext_(DQN_LEAK_TRACE_FUNCTION_NO_COMMA)
{ {
thread_local Dqn_ThreadContext result = {}; DQN_THREAD_LOCAL Dqn_ThreadContext result = {};
if (!result.init) { if (!result.init) {
result.init = true; result.init = true;
DQN_ASSERTF(dqn_library.lib_init, "Library must be initialised by calling Dqn_Library_Init(nullptr)"); DQN_ASSERTF(dqn_library.lib_init, "Library must be initialised by calling Dqn_Library_Init(nullptr)");

View File

@ -3,9 +3,9 @@
#pragma comment(lib, "bcrypt") #pragma comment(lib, "bcrypt")
#pragma comment(lib, "wininet") #pragma comment(lib, "wininet")
#if defined(DQN_NO_WIN32_MINIMAL_HEADER) || defined(_INC_WINDOWS) #if defined(DQN_NO_WIN32_MIN_HEADER)
#include <bcrypt.h> // Dqn_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc #include <bcrypt.h> // Dqn_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc
#include <shellscalingapi.h> // Dqn_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc #include <shellapi.h> // Dqn_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc
#if !defined(DQN_NO_WINNET) #if !defined(DQN_NO_WINNET)
#include <wininet.h> // Dqn_Win_Net -> InternetConnect ... etc #include <wininet.h> // Dqn_Win_Net -> InternetConnect ... etc
#endif // DQN_NO_WINNET #endif // DQN_NO_WINNET

View File

@ -199,7 +199,12 @@ DQN_API uint64_t Dqn_Date_EpochTime ();
// NOTE: [$W32H] Win32 Min Header ================================================================== // NOTE: [$W32H] Win32 Min Header ==================================================================
#if defined(DQN_OS_WIN32) #if defined(DQN_OS_WIN32)
#if !defined(DQN_NO_WIN32_MIN_HEADER) && !defined(_INC_WINDOWS) #if !defined(DQN_NO_WIN32_MIN_HEADER) && !defined(_INC_WINDOWS)
#if defined(DQN_COMPILER_W32_MSVC)
#pragma warning(push)
#pragma warning(disable: 4201) // warning C4201: nonstandard extension used: nameless struct/union
#endif
// Taken from Windows.h // Taken from Windows.h
// typedef unsigned long DWORD; // typedef unsigned long DWORD;
// typedef unsigned short WORD; // typedef unsigned short WORD;
@ -220,6 +225,9 @@ DQN_API uint64_t Dqn_Date_EpochTime ();
} u; } u;
uint64_t QuadPart; uint64_t QuadPart;
} LARGE_INTEGER; } LARGE_INTEGER;
#if defined(DQN_COMPILER_W32_MSVC)
#pragma warning(pop)
#endif
#endif // !defined(DQN_NO_WIN32_MIN_HEADER) && !defined(_INC_WINDOWS) #endif // !defined(DQN_NO_WIN32_MIN_HEADER) && !defined(_INC_WINDOWS)
// NOTE: [$WIND] Dqn_Win =========================================================================== // NOTE: [$WIND] Dqn_Win ===========================================================================

View File

@ -33,10 +33,10 @@ DQN_API void Dqn_Print_Std(Dqn_PrintStd std_handle, Dqn_String8 string)
#if defined(DQN_OS_WIN32) #if defined(DQN_OS_WIN32)
// NOTE: Get the output handles from kernel // NOTE: Get the output handles from kernel
// ========================================================================= // =========================================================================
thread_local void *std_out_print_handle = nullptr; DQN_THREAD_LOCAL void *std_out_print_handle = nullptr;
thread_local void *std_err_print_handle = nullptr; DQN_THREAD_LOCAL void *std_err_print_handle = nullptr;
thread_local bool std_out_print_to_console = false; DQN_THREAD_LOCAL bool std_out_print_to_console = false;
thread_local bool std_err_print_to_console = false; DQN_THREAD_LOCAL bool std_err_print_to_console = false;
if (!std_out_print_handle) { if (!std_out_print_handle) {
unsigned long mode = 0; (void)mode; unsigned long mode = 0; (void)mode;
@ -171,7 +171,7 @@ DQN_API void Dqn_Print_StdLnFVStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle styl
DQN_API Dqn_String8 Dqn_Print_ESCColourString(Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b) DQN_API Dqn_String8 Dqn_Print_ESCColourString(Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b)
{ {
thread_local char buffer[32]; DQN_THREAD_LOCAL char buffer[32];
buffer[0] = 0; buffer[0] = 0;
Dqn_String8 result = {}; Dqn_String8 result = {};
result.size = STB_SPRINTF_DECORATE(snprintf)(buffer, result.size = STB_SPRINTF_DECORATE(snprintf)(buffer,

View File

@ -9,20 +9,34 @@ amalgamates all the files into one translation unit.
## Build ## Build
To build with this library, copy all the `*.[h|cpp]` files at the root of the To build with this library, copy all the `*.[h|cpp]` files at the root of the
repository and in one header file, repository to your desired location, accessible by your project and in one
header file include the header.
```cpp ```cpp
#include "dqn.h" #include "dqn.h"
``` ```
Which includes all other files and their declaration into your header. In one `dqn.h` includes all other files and their declaration into your header. In
`.cpp` file defined the implementation macro to enable the implementation of the *one* `.cpp` file define the macro to enable the implementation of the header in
header in that translation unit, the translation unit.
```cpp ```cpp
#define DQN_IMPLEMENTATION #define DQN_IMPLEMENTATION
#include "dqn.h" #include "dqn.h"
``` ```
Ensure that the folder containing the files is part of the include search path Finally ensure that the compiler has in its search paths for the include
for the compiler for the amalgamated `dqn.h` to successfully locate the files. directory where headers are located, e.g. `-I <path/to/dqn/headers>`.
## Customisation
The headers provide macros to compile out sections that are not needed. This can
be useful to speed up compile times if you want a particular part of the
library. Each header contains a table-of-contents that denotes the macro to
define to disable that section that should be defined before the header include.
```cpp
#define DQN_NO_VARRAY // Disable virtual array container
#define DQN_NO_JSON_BUILDER // Disable the JSON string builder
#include "dqn.h"
```