From 30e219e7c31d075dd30a7416acaaf0889cfa80f6 Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Sun, 9 Apr 2017 16:53:24 +1000 Subject: [PATCH] Add extra v2, v3 operations (cross, length etc) --- dqnt.h | 89 ++++++++++++++++++++++++++++++++++++++++++++-- dqnt_unit_test.cpp | 38 +++++++++++++++++--- 2 files changed, 120 insertions(+), 7 deletions(-) diff --git a/dqnt.h b/dqnt.h index 5aa2abb..8959819 100644 --- a/dqnt.h +++ b/dqnt.h @@ -47,12 +47,12 @@ typedef float f32; #define DQNT_MAX(a, b) ((a) < (b) ? (b) : (a)) #define DQNT_MIN(a, b) ((a) < (b) ? (a) : (b)) #define DQNT_SQUARED(x) ((x) * (x)) -#define DQNT_SQRT(x) (sqrtf(x)) //////////////////////////////////////////////////////////////////////////////// // Math //////////////////////////////////////////////////////////////////////////////// -DQNT_FILE_SCOPE f32 dqnt_lerp(f32 a, f32 t, f32 b); +DQNT_FILE_SCOPE f32 dqnt_math_lerp(f32 a, f32 t, f32 b); +DQNT_FILE_SCOPE f32 dqnt_math_sqrtf(f32 a); //////////////////////////////////////////////////////////////////////////////// // Vec2 @@ -75,6 +75,12 @@ DQNT_FILE_SCOPE DqntV2 dqnt_v2_hadamard(DqntV2 a, DqntV2 b); DQNT_FILE_SCOPE f32 dqnt_v2_dot (DqntV2 a, DqntV2 b); DQNT_FILE_SCOPE bool dqnt_v2_equals (DqntV2 a, DqntV2 b); +DQNT_FILE_SCOPE f32 dqnt_v2_length_squared(DqntV2 a, DqntV2 b); +DQNT_FILE_SCOPE f32 dqnt_v2_length (DqntV2 a, DqntV2 b); +DQNT_FILE_SCOPE DqntV2 dqnt_v2_normalise (DqntV2 a); +DQNT_FILE_SCOPE bool dqnt_v2_overlaps (DqntV2 a, DqntV2 b); +DQNT_FILE_SCOPE DqntV2 dqnt_v2_perpendicular (DqntV2 a); + // Resize the dimension to fit the aspect ratio provided. Downscale only. DQNT_FILE_SCOPE DqntV2 dqnt_v2_constrain_to_ratio(DqntV2 dim, DqntV2 ratio); @@ -99,6 +105,8 @@ DQNT_FILE_SCOPE DqntV3 dqnt_v3_hadamard(DqntV3 a, DqntV3 b); DQNT_FILE_SCOPE f32 dqnt_v3_dot (DqntV3 a, DqntV3 b); DQNT_FILE_SCOPE bool dqnt_v3_equals (DqntV3 a, DqntV3 b); +DQNT_FILE_SCOPE DqntV3 dqnt_v3_cross(DqntV3 a, DqntV3 b); + //////////////////////////////////////////////////////////////////////////////// // Vec4 //////////////////////////////////////////////////////////////////////////////// @@ -222,7 +230,7 @@ DQNT_FILE_SCOPE i32 dqnt_rnd_pcg_range(DqntRandPCGState *pcg, i32 min, i32 max) //////////////////////////////////////////////////////////////////////////////// // Math //////////////////////////////////////////////////////////////////////////////// -DQNT_FILE_SCOPE f32 dqnt_lerp(f32 a, f32 t, f32 b) +DQNT_FILE_SCOPE f32 dqnt_math_lerp(f32 a, f32 t, f32 b) { /* Linear blend between two values. We having a starting point "a", and @@ -240,6 +248,12 @@ DQNT_FILE_SCOPE f32 dqnt_lerp(f32 a, f32 t, f32 b) return result; } +DQNT_FILE_SCOPE f32 dqnt_math_sqrtf(f32 a) +{ + f32 result = sqrtf(a); + return result; +} + //////////////////////////////////////////////////////////////////////////////// // Vec2 //////////////////////////////////////////////////////////////////////////////// @@ -318,6 +332,59 @@ DQNT_FILE_SCOPE inline bool dqnt_v2_equals(DqntV2 a, DqntV2 b) return result; } +DQNT_FILE_SCOPE inline f32 dqnt_v2_length_squared(DqntV2 a, DqntV2 b) +{ + f32 x = b.x - a.x; + f32 y = b.y - a.y; + f32 result = (DQNT_SQUARED(x) + DQNT_SQUARED(y)); + return result; +} + +DQNT_FILE_SCOPE inline f32 dqnt_v2_length(DqntV2 a, DqntV2 b) +{ + f32 lengthSq = dqnt_v2_length_squared(a, b); + f32 result = dqnt_math_sqrtf(lengthSq); + return result; +} + +DQNT_FILE_SCOPE inline DqntV2 dqnt_v2_normalise(DqntV2 a) +{ + f32 magnitude = dqnt_v2_length(dqnt_v2(0, 0), a); + DqntV2 result = dqnt_v2(a.x, a.y); + result = dqnt_v2_scale(a, 1 / magnitude); + return result; +} + +DQNT_FILE_SCOPE inline bool dqnt_v2_overlaps(DqntV2 a, DqntV2 b) +{ + bool result = false; + + f32 lenOfA = a.max - a.min; + f32 lenOfB = b.max - b.min; + + if (lenOfA > lenOfB) + { + DqntV2 tmp = a; + a = b; + b = tmp; + } + + if ((a.min >= b.min && a.min <= b.max) || + (a.max >= b.min && a.max <= b.max)) + { + result = true; + } + + return result; +} + +DQNT_FILE_SCOPE inline DqntV2 dqnt_v2_perpendicular(DqntV2 a) +{ + DqntV2 result = {a.y, -a.x}; + return result; +} + + DQNT_FILE_SCOPE DqntV2 dqnt_v2_constrain_to_ratio(DqntV2 dim, DqntV2 ratio) { DqntV2 result = {}; @@ -410,6 +477,22 @@ DQNT_FILE_SCOPE inline bool dqnt_v3_equals(DqntV3 a, DqntV3 b) return result; } +DQNT_FILE_SCOPE inline DqntV3 dqnt_v3_cross(DqntV3 a, DqntV3 b) +{ + /* + CROSS PRODUCT + Generate a perpendicular vector to the 2 vectors + |a| |d| |bf - ce| + |b| x |e| = |cd - af| + |c| |f| |ae - be| + */ + DqntV3 result = {}; + result.e[0] = (a.e[1] * b.e[2]) - (a.e[2] * b.e[1]); + result.e[1] = (a.e[2] * b.e[0]) - (a.e[0] * b.e[2]); + result.e[2] = (a.e[0] * b.e[1]) - (a.e[1] * b.e[0]); + return result; +} + //////////////////////////////////////////////////////////////////////////////// // Vec4 //////////////////////////////////////////////////////////////////////////////// diff --git a/dqnt_unit_test.cpp b/dqnt_unit_test.cpp index 796a0ce..2e815f7 100644 --- a/dqnt_unit_test.cpp +++ b/dqnt_unit_test.cpp @@ -1,5 +1,4 @@ #define DQNT_IMPLEMENTATION -#define DQNT_MAKE_STATIC #include "dqnt.h" #include "stdio.h" @@ -300,19 +299,24 @@ void dqnt_math_test() f32 start = 10; f32 t = 0.5f; f32 end = 20; - DQNT_ASSERT(dqnt_lerp(start, t, end) == 15); + DQNT_ASSERT(dqnt_math_lerp(start, t, end) == 15); } { f32 start = 10; f32 t = 2.0f; f32 end = 20; - DQNT_ASSERT(dqnt_lerp(start, t, end) == 30); + DQNT_ASSERT(dqnt_math_lerp(start, t, end) == 30); } printf("dqnt_math_test(): lerp: Completed successfully\n"); } + { // sqrtf + DQNT_ASSERT(dqnt_math_sqrtf(4.0f) == 2.0f); + printf("dqnt_math_test(): sqrtf: Completed successfully\n"); + } + printf("dqnt_math_test(): Completed successfully\n"); } @@ -358,6 +362,29 @@ void dqnt_vec_test() DQNT_ASSERT(dotResult == 55); } + // V2 Properties + { + DqntV2 a = dqnt_v2(0, 0); + DqntV2 b = dqnt_v2(3, 4); + + f32 lengthSq = dqnt_v2_length_squared(a, b); + DQNT_ASSERT(lengthSq == 25); + + f32 length = dqnt_v2_length(a, b); + DQNT_ASSERT(length == 5); + + DqntV2 normalised = dqnt_v2_normalise(b); + DQNT_ASSERT(normalised.x == (b.x / 5.0f)); + DQNT_ASSERT(normalised.y == (b.y / 5.0f)); + + DqntV2 c = dqnt_v2(3.5f, 8.0f); + DQNT_ASSERT(dqnt_v2_overlaps(b, c) == true); + DQNT_ASSERT(dqnt_v2_overlaps(b, a) == false); + + DqntV2 d = dqnt_v2_perpendicular(c); + DQNT_ASSERT(dqnt_v2_dot(c, d) == 0); + } + { // constrain_to_ratio DqntV2 ratio = dqnt_v2(16, 9); DqntV2 dim = dqnt_v2(2000, 1080); @@ -406,6 +433,9 @@ void dqnt_vec_test() f32 dotResult = dqnt_v3_dot(dqnt_v3(5, 10, 2), dqnt_v3(3, 4, 6)); DQNT_ASSERT(dotResult == 67); + + DqntV3 cross = dqnt_v3_cross(vecA, vecB); + DQNT_ASSERT(dqnt_v3_equals(cross, dqnt_v3(15, 0, -5)) == true); } printf("dqnt_vec_test(): vec3: Completed successfully\n"); @@ -465,7 +495,7 @@ int main(void) dqnt_vec_test(); dqnt_other_test(); - printf("\nPress Any Key to Exit\n"); + printf("\nPress 'Enter' Key to Exit\n"); getchar(); return 0;