From 4c2c94beeaf20376867334f4b875619f3d0a1ca1 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sun, 29 Oct 2023 11:23:17 +0200 Subject: [PATCH] gl3,gl4: Reuse HandmadeMath and DG_dynarr --- CMakeLists.txt | 4 +- .../refresh/{gl3/header => files}/DG_dynarr.h | 0 .../{gl3/header => files}/HandmadeMath.h | 0 src/client/refresh/gl3/gl3_main.c | 4 +- src/client/refresh/gl3/gl3_mesh.c | 2 +- src/client/refresh/gl3/header/local.h | 2 +- src/client/refresh/gl4/gl4_main.c | 4 +- src/client/refresh/gl4/gl4_mesh.c | 2 +- src/client/refresh/gl4/header/DG_dynarr.h | 960 ------- src/client/refresh/gl4/header/HandmadeMath.h | 2453 ----------------- src/client/refresh/gl4/header/local.h | 2 +- 11 files changed, 10 insertions(+), 3423 deletions(-) rename src/client/refresh/{gl3/header => files}/DG_dynarr.h (100%) rename src/client/refresh/{gl3/header => files}/HandmadeMath.h (100%) delete mode 100644 src/client/refresh/gl4/header/DG_dynarr.h delete mode 100644 src/client/refresh/gl4/header/HandmadeMath.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fd8bcace..6208cce4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -625,8 +625,8 @@ set(GL3-Header ${REF_SRC_DIR}/constants/anormtab.h ${REF_SRC_DIR}/constants/warpsin.h ${REF_SRC_DIR}/files/stb_image.h - ${REF_SRC_DIR}/gl3/header/DG_dynarr.h - ${REF_SRC_DIR}/gl3/header/HandmadeMath.h + ${REF_SRC_DIR}/files/DG_dynarr.h + ${REF_SRC_DIR}/files/HandmadeMath.h ${REF_SRC_DIR}/gl3/header/local.h ${REF_SRC_DIR}/gl3/header/model.h ${COMMON_SRC_DIR}/header/shared.h diff --git a/src/client/refresh/gl3/header/DG_dynarr.h b/src/client/refresh/files/DG_dynarr.h similarity index 100% rename from src/client/refresh/gl3/header/DG_dynarr.h rename to src/client/refresh/files/DG_dynarr.h diff --git a/src/client/refresh/gl3/header/HandmadeMath.h b/src/client/refresh/files/HandmadeMath.h similarity index 100% rename from src/client/refresh/gl3/header/HandmadeMath.h rename to src/client/refresh/files/HandmadeMath.h diff --git a/src/client/refresh/gl3/gl3_main.c b/src/client/refresh/gl3/gl3_main.c index 3ce8f59a..04394e55 100644 --- a/src/client/refresh/gl3/gl3_main.c +++ b/src/client/refresh/gl3/gl3_main.c @@ -30,10 +30,10 @@ #include "header/local.h" #define HANDMADE_MATH_IMPLEMENTATION -#include "header/HandmadeMath.h" +#include "../files/HandmadeMath.h" #define DG_DYNARR_IMPLEMENTATION -#include "header/DG_dynarr.h" +#include "../files/DG_dynarr.h" #ifdef YQ2_GL3_GLES3 #define REF_VERSION "Yamagi Quake II OpenGL ES3 Refresher" diff --git a/src/client/refresh/gl3/gl3_mesh.c b/src/client/refresh/gl3/gl3_mesh.c index b33d72d4..95cd0344 100644 --- a/src/client/refresh/gl3/gl3_mesh.c +++ b/src/client/refresh/gl3/gl3_mesh.c @@ -27,7 +27,7 @@ #include "header/local.h" -#include "header/DG_dynarr.h" +#include "../files/DG_dynarr.h" #define NUMVERTEXNORMALS 162 #define SHADEDOT_QUANT 16 diff --git a/src/client/refresh/gl3/header/local.h b/src/client/refresh/gl3/header/local.h index 053a9f1d..62b401b2 100644 --- a/src/client/refresh/gl3/header/local.h +++ b/src/client/refresh/gl3/header/local.h @@ -56,7 +56,7 @@ #include "../../ref_shared.h" -#include "HandmadeMath.h" +#include "../../files/HandmadeMath.h" #if 0 // only use this for development .. #define STUB_ONCE(msg) do { \ diff --git a/src/client/refresh/gl4/gl4_main.c b/src/client/refresh/gl4/gl4_main.c index a20fd8f2..7e4ea54b 100644 --- a/src/client/refresh/gl4/gl4_main.c +++ b/src/client/refresh/gl4/gl4_main.c @@ -30,10 +30,10 @@ #include "header/local.h" #define HANDMADE_MATH_IMPLEMENTATION -#include "header/HandmadeMath.h" +#include "../files/HandmadeMath.h" #define DG_DYNARR_IMPLEMENTATION -#include "header/DG_dynarr.h" +#include "../files/DG_dynarr.h" #ifdef YQ2_GL3_GLES3 #define REF_VERSION "Yamagi Quake II OpenGL ES3 Refresher" diff --git a/src/client/refresh/gl4/gl4_mesh.c b/src/client/refresh/gl4/gl4_mesh.c index c3f3c30c..2187886b 100644 --- a/src/client/refresh/gl4/gl4_mesh.c +++ b/src/client/refresh/gl4/gl4_mesh.c @@ -27,7 +27,7 @@ #include "header/local.h" -#include "header/DG_dynarr.h" +#include "../files/DG_dynarr.h" #define NUMVERTEXNORMALS 162 #define SHADEDOT_QUANT 16 diff --git a/src/client/refresh/gl4/header/DG_dynarr.h b/src/client/refresh/gl4/header/DG_dynarr.h deleted file mode 100644 index d6189a31..00000000 --- a/src/client/refresh/gl4/header/DG_dynarr.h +++ /dev/null @@ -1,960 +0,0 @@ -/* - * A header-only typesafe dynamic array implementation for plain C, - * kinda like C++ std::vector. This code is compatible with C++, but should - * only be used with POD (plain old data) types, as it uses memcpy() etc - * instead of copy/move construction/assignment. - * It requires a new type (created with the DA_TYPEDEF(ELEMENT_TYPE, ARRAY_TYPE_NAME) - * macro) for each kind of element you want to put in a dynamic array; however - * the "functions" to manipulate the array are actually macros and the same - * for all element types. - * The array elements are accessed via dynArr.p[i] or da_get(dynArr, i) - * - the latter checks whether i is a valid index and asserts if not. - * - * One thing to keep in mind is that, because of using macros, the arguments to - * the "functions" are usually evaluated more than once, so you should avoid - * putting things with side effect (like function-calls with side effects or i++) - * into them. Notable exceptions are the value arguments (v) of da_push() - * and da_insert(), so it's still ok to do da_push(arr, fun_with_sideffects()); - * or da_insert(a, 3, x++); - * - * The function-like da_* macros are short aliases of dg_dynarr_* macros. - * If the short names clash with anything in your code or other headers - * you are using, you can, before #including this header, do - * #define DG_DYNARR_NO_SHORTNAMES - * and use the long dg_dynarr_* forms of the macros instead. - * - * Using this library in your project: - * Put this file somewhere in your project. - * In *one* of your .c/.cpp files, do - * #define DG_DYNARR_IMPLEMENTATION - * #include "DG_dynarr.h" - * to create the implementation of this library in that file. - * You can just #include "DG_dynarr.h" (without the #define) in other source - * files to use it there. - * - * See below this comment block for a usage example. - * - * You can #define your own allocators, assertion and the amount of runtime - * checking of indexes, see CONFIGURATION section in the code for more information. - * - * - * This is heavily inspired by Sean Barrett's stretchy_buffer.h - * ( see: https://github.com/nothings/stb/blob/master/stretchy_buffer.h ) - * However I wanted to have a struct that holds the array pointer and the length - * and capacity, so that struct always remains at the same address while the - * array memory might be reallocated. - * I can live with arr.p[i] instead of arr[i], but I like how he managed to use - * macros to create an API that doesn't force the user to specify the stored - * type over and over again, so I stole some of his tricks :-) - * - * This has been tested with GCC 4.8 and clang 3.8 (-std=gnu89, -std=c99 and as C++; - * -std=c89 works if you convert the C++-style comments to C comments) and - * Microsoft Visual Studio 6 and 2010 (32bit) and 2013 (32bit and 64bit). - * I guess it works with all (recentish) C++ compilers and C compilers supporting - * C99 or even C89 + C++ comments (otherwise converting the comments should help). - * - * (C) 2016 Daniel Gibson - * - * LICENSE - * This software is dual-licensed to the public domain and under the following - * license: you are granted a perpetual, irrevocable license to copy, modify, - * publish, and distribute this file as you see fit. - * No warranty implied; use at your own risk. - */ -#if 0 // Usage Example: - #define DG_DYNARR_IMPLEMENTATION // this define is only needed in *one* .c/.cpp file! - #include "DG_dynarr.h" - - DA_TYPEDEF(int, MyIntArrType); // creates MyIntArrType - a dynamic array for ints - - void printIntArr(MyIntArrType* arr, const char* name) - { - // note that arr is a pointer here, so use *arr in the da_*() functions. - printf("%s = {", name); - if(da_count(*arr) > 0) - printf(" %d", arr->p[0]); - for(int i=1; ip[i]); - printf(" }\n"); - } - - void myFunction() - { - MyIntArrType a1 = {0}; // make sure to zero out the struct - // instead of = {0}; you could also call da_init(a1); - - da_push(a1, 42); - assert(da_count(a1) == 1 && a1.p[0] == 42); - - int* addedElements = da_addn_uninit(a1, 3); - assert(da_count(a1) == 4); - for(size_t i=0; i<3; ++i) - addedElements[i] = i+5; - - printIntArr(&a1, "a1"); // "a1 = { 42, 5, 6, 7 }" - - MyIntArrType a2; - da_init(a2); - - da_addn(a2, a1.p, da_count(a1)); // copy all elements from a1 to a2 - assert(da_count(a2) == 4); - - da_insert(a2, 1, 11); - printIntArr(&a2, "a2"); // "a2 = { 42, 11, 5, 6, 7 }" - - da_delete(a2, 2); - printIntArr(&a2, "a2"); // "a2 = { 42, 11, 6, 7 }" - - da_deletefast(a2, 0); - printIntArr(&a2, "a2"); // "a2 = { 7, 11, 6 }" - - da_push(a1, 3); - printIntArr(&a1, "a1"); // "a1 = { 42, 5, 6, 7, 3 }" - - int x=da_pop(a1); - printf("x = %d\n", x); // "x = 3" - printIntArr(&a1, "a1"); // "a1 = { 42, 5, 6, 7 }" - - da_free(a1); // make sure not to leak memory! - da_free(a2); - } -#endif // 0 (usage example) - -#ifndef DG__DYNARR_H -#define DG__DYNARR_H - -// ######### CONFIGURATION ######### - -// following: some #defines that you can tweak to your liking - -// you can reduce some overhead by defining DG_DYNARR_INDEX_CHECK_LEVEL to 2, 1 or 0 -#ifndef DG_DYNARR_INDEX_CHECK_LEVEL - - // 0: (almost) no index checking - // 1: macros "returning" something return a.p[0] or NULL if the index was invalid - // 2: assertions in all macros taking indexes that make sure they're valid - // 3: 1 and 2 - #define DG_DYNARR_INDEX_CHECK_LEVEL 3 - -#endif // DG_DYNARR_INDEX_CHECK_LEVEL - -// you can #define your own DG_DYNARR_ASSERT(condition, msgstring) -// that will be used for all assertions in this code. -#ifndef DG_DYNARR_ASSERT - #include - #define DG_DYNARR_ASSERT(cond, msg) assert((cond) && msg) -#endif - -// you can #define DG_DYNARR_OUT_OF_MEMORY to some code that will be executed -// if allocating memory fails -// it's needed only before the #define DG_DYNARR_IMPLEMENTATION #include of -// this header, so the following is here only for reference and commented out -/* - #ifndef DG_DYNARR_OUT_OF_MEMORY - #define DG_DYNARR_OUT_OF_MEMORY DG_DYNARR_ASSERT(0, "Out of Memory!"); - #endif -*/ - -// By default, C's malloc(), realloc() and free() is used to allocate/free heap memory -// (see beginning of "#ifdef DG_DYNARR_IMPLEMENTATION" block below). -// You can #define DG_DYNARR_MALLOC, DG_DYNARR_REALLOC and DG_DYNARR_FREE yourself -// to provide alternative implementations like Win32 Heap(Re)Alloc/HeapFree -// it's needed only before the #define DG_DYNARR_IMPLEMENTATION #include of -// this header, so the following is here only for reference and commented out -/* - #define DG_DYNARR_MALLOC(elemSize, numElems) malloc(elemSize*numElems) - - // oldNumElems is not used for C's realloc, but maybe you need it for - // your allocator to copy the old elements over - #define DG_DYNARR_REALLOC(ptr, elemSize, oldNumElems, newCapacity) \ - realloc(ptr, elemSize*newCapacity); - - #define DG_DYNARR_FREE(ptr) free(ptr) -*/ - -// if you want to prepend something to the non inline (DG_DYNARR_INLINE) functions, -// like "__declspec(dllexport)" or whatever, #define DG_DYNARR_DEF -#ifndef DG_DYNARR_DEF - // by defaults it's empty. - #define DG_DYNARR_DEF -#endif - -// some functions are inline, in case your compiler doesn't like "static inline" -// but wants "__inline__" or something instead, #define DG_DYNARR_INLINE accordingly. -#ifndef DG_DYNARR_INLINE - // for pre-C99 compilers you might have to use something compiler-specific (or maybe only "static") - #ifdef _MSC_VER - #define DG_DYNARR_INLINE static __inline - #else - #define DG_DYNARR_INLINE static inline - #endif -#endif - - - -// ############### Short da_* aliases for the long names ############### - -#ifndef DG_DYNARR_NO_SHORTNAMES - -// this macro is used to create an array type (struct) for elements of TYPE -// use like DA_TYPEDEF(int, MyIntArrType); MyIntArrType ia = {0}; da_push(ia, 42); ... -#define DA_TYPEDEF(TYPE, NewArrayTypeName) \ - DG_DYNARR_TYPEDEF(TYPE, NewArrayTypeName) - -// makes sure the array is initialized and can be used. -// either do YourArray arr = {0}; or YourArray arr; da_init(arr); -#define da_init(a) \ - dg_dynarr_init(a) - -/* - * This allows you to provide an external buffer that'll be used as long as it's big enough - * once you add more elements than buf can hold, fresh memory will be allocated on the heap - * Use like: - * DA_TYPEDEF(double, MyDoubleArrType); - * MyDoubleArrType arr; - * double buf[8]; - * dg_dynarr_init_external(arr, buf, 8); - * dg_dynarr_push(arr, 1.23); - * ... - */ -#define da_init_external(a, buf, buf_cap) \ - dg_dynarr_init_external(a, buf, buf_cap) - -// use this to free the memory allocated by dg_dynarr once you don't need the array anymore -// Note: it is safe to add new elements to the array after da_free() -// it will allocate new memory, just like it would directly after da_init() -#define da_free(a) \ - dg_dynarr_free(a) - - -// add an element to the array (appended at the end) -#define da_push(a, v) \ - dg_dynarr_push(a, v) - -// add an element to the array (appended at the end) -// does the same as push, just for consistency with addn (like insert and insertn) -#define da_add(a, v) \ - dg_dynarr_add(a, v) - -// append n elements to a and initialize them from array vals, doesn't return anything -// ! vals (and all other args) are evaluated multiple times ! -#define da_addn(a, vals, n) \ - dg_dynarr_addn(a, vals, n) - -// add n elements to the end of the array and zeroes them with memset() -// returns pointer to first added element, NULL if out of memory (array is empty then) -#define da_addn_zeroed(a, n) \ - dg_dynarr_addn_zeroed(a, n) - -// add n elements to the end of the array, will remain uninitialized -// returns pointer to first added element, NULL if out of memory (array is empty then) -#define da_addn_uninit(a, n) \ - dg_dynarr_addn_uninit(a, n) - - -// insert a single value v at index idx -#define da_insert(a, idx, v) \ - dg_dynarr_insert(a, idx, v) - -// insert n elements into a at idx, initialize them from array vals -// doesn't return anything -// ! vals (and all other args) is evaluated multiple times ! -#define da_insertn(a, idx, vals, n) \ - dg_dynarr_insertn(a, idx, vals, n) - -// insert n elements into a at idx and zeroe them with memset() -// returns pointer to first inserted element or NULL if out of memory -#define da_insertn_zeroed(a, idx, n) \ - dg_dynarr_insertn_zeroed(a, idx, n) - -// insert n uninitialized elements into a at idx; -// returns pointer to first inserted element or NULL if out of memory -#define da_insertn_uninit(a, idx, n) \ - dg_dynarr_insertn_uninit(a, idx, n) - -// set a single value v at index idx - like "a.p[idx] = v;" but with checks (unless disabled) -#define da_set(a, idx, v) \ - dg_dynarr_set(a, idx, v) - -// overwrite n elements of a, starting at idx, with values from array vals -// doesn't return anything -// ! vals (and all other args) is evaluated multiple times ! -#define da_setn(a, idx, vals, n) \ - dg_dynarr_setn(a, idx, vals, n) - -// delete the element at idx, moving all following elements (=> keeps order) -#define da_delete(a, idx) \ - dg_dynarr_delete(a, idx) - -// delete n elements starting at idx, moving all following elements (=> keeps order) -#define da_deleten(a, idx, n) \ - dg_dynarr_deleten(a, idx, n) - -// delete the element at idx, move the last element there (=> doesn't keep order) -#define da_deletefast(a, idx) \ - dg_dynarr_deletefast(a, idx) - -// delete n elements starting at idx, move the last n elements there (=> doesn't keep order) -#define da_deletenfast(a, idx, n) \ - dg_dynarr_deletenfast(a, idx, n) - -// removes all elements from the array, but does not free the buffer -// (if you want to free the buffer too, just use da_free()) -#define da_clear(a) \ - dg_dynarr_clear(a) - -// sets the logical number of elements in the array -// if cnt > dg_dynarr_count(a), the logical count will be increased accordingly -// and the new elements will be uninitialized -#define da_setcount(a, cnt) \ - dg_dynarr_setcount(a, cnt) - -// make sure the array can store cap elements without reallocating -// logical count remains unchanged -#define da_reserve(a, cap) \ - dg_dynarr_reserve(a, cap) - -// this makes sure a only uses as much memory as for its elements -// => maybe useful if a used to contain a huge amount of elements, -// but you deleted most of them and want to free some memory -// Note however that this implies an allocation and copying the remaining -// elements, so only do this if it frees enough memory to be worthwhile! -#define da_shrink_to_fit(a) \ - dg_dynarr_shrink_to_fit(a) - - -// removes and returns the last element of the array -#define da_pop(a) \ - dg_dynarr_pop(a) - -// returns the last element of the array -#define da_last(a) \ - dg_dynarr_last(a) - -// returns the pointer *to* the last element of the array -// (in contrast to dg_dynarr_end() which returns a pointer *after* the last element) -// returns NULL if array is empty -#define da_lastptr(a) \ - dg_dynarr_lastptr(a) - -// get element at index idx (like a.p[idx]), but with checks -// (unless you disabled them with #define DG_DYNARR_INDEX_CHECK_LEVEL 0) -#define da_get(a, idx) \ - dg_dynarr_get(a,idx) - -// get pointer to element at index idx (like &a.p[idx]), but with checks -// and it returns NULL if idx is invalid -#define da_getptr(a, idx) \ - dg_dynarr_getptr(a, idx) - -// returns a pointer to the first element of the array -// (together with dg_dynarr_end() you can do C++-style iterating) -#define da_begin(a) \ - dg_dynarr_begin(a) - -// returns a pointer to the past-the-end element of the array -// Allows C++-style iterating, in case you're into that kind of thing: -// for(T *it=da_begin(a), *end=da_end(a); it!=end; ++it) foo(*it); -// (see da_lastptr() to get a pointer *to* the last element) -#define da_end(a) \ - dg_dynarr_end(a) - - -// returns (logical) number of elements currently in the array -#define da_count(a) \ - dg_dynarr_count(a) - -// get the current reserved capacity of the array -#define da_capacity(a) \ - dg_dynarr_capacity(a) - -// returns 1 if the array is empty, else 0 -#define da_empty(a) \ - dg_dynarr_empty(a) - -// returns 1 if the last (re)allocation when inserting failed (Out Of Memory) -// or if the array has never allocated any memory yet, else 0 -// deleting the contents when growing fails instead of keeping old may seem -// a bit uncool, but it's simple and OOM should rarely happen on modern systems -// anyway - after all you need to deplete both RAM and swap/pagefile.sys -#define da_oom(a) \ - dg_dynarr_oom(a) - - -// sort a using the given qsort()-comparator cmp -// (just a slim wrapper around qsort()) -#define da_sort(a, cmp) \ - dg_dynarr_sort(a, cmp) - -#endif // DG_DYNARR_NO_SHORTNAMES - - -// ######### Implementation of the actual macros (using the long names) ########## - -// use like DG_DYNARR_TYPEDEF(int, MyIntArrType); MyIntArrType ia = {0}; dg_dynarr_push(ia, 42); ... -#define DG_DYNARR_TYPEDEF(TYPE, NewArrayTypeName) \ - typedef struct { TYPE* p; dg__dynarr_md md; } NewArrayTypeName; - -// makes sure the array is initialized and can be used. -// either do YourArray arr = {0}; or YourArray arr; dg_dynarr_init(arr); -#define dg_dynarr_init(a) \ - dg__dynarr_init((void**)&(a).p, &(a).md, NULL, 0) - -// this allows you to provide an external buffer that'll be used as long as it's big enough -// once you add more elements than buf can hold, fresh memory will be allocated on the heap -#define dg_dynarr_init_external(a, buf, buf_cap) \ - dg__dynarr_init((void**)&(a).p, &(a).md, (buf), (buf_cap)) - -// use this to free the memory allocated by dg_dynarr -// Note: it is safe to add new elements to the array after dg_dynarr_free() -// it will allocate new memory, just like it would directly after dg_dynarr_init() -#define dg_dynarr_free(a) \ - dg__dynarr_free((void**)&(a).p, &(a).md) - - -// add an element to the array (appended at the end) -#define dg_dynarr_push(a, v) \ - (dg__dynarr_maybegrowadd(dg__dynarr_unp(a), 1) ? (((a).p[(a).md.cnt++] = (v)),0) : 0) - -// add an element to the array (appended at the end) -// does the same as push, just for consistency with addn (like insert and insertn) -#define dg_dynarr_add(a, v) \ - dg_dynarr_push((a), (v)) - -// append n elements to a and initialize them from array vals, doesn't return anything -// ! vals (and all other args) are evaluated multiple times ! -#define dg_dynarr_addn(a, vals, n) do { \ - DG_DYNARR_ASSERT((vals)!=NULL, "Don't pass NULL als vals to dg_dynarr_addn!"); \ - if((vals)!=NULL && dg__dynarr_add(dg__dynarr_unp(a), n, 0)) { \ - size_t i_=(a).md.cnt-(n), v_=0; \ - while(i_<(a).md.cnt) (a).p[i_++]=(vals)[v_++]; \ - } } DG__DYNARR_WHILE0 - -// add n elements to the end of the array and zeroe them with memset() -// returns pointer to first added element, NULL if out of memory (array is empty then) -#define dg_dynarr_addn_zeroed(a, n) \ - (dg__dynarr_add(dg__dynarr_unp(a), (n), 1) ? &(a).p[(a).md.cnt-(size_t)(n)] : NULL) - -// add n elements to the end of the array, which are uninitialized -// returns pointer to first added element, NULL if out of memory (array is empty then) -#define dg_dynarr_addn_uninit(a, n) \ - (dg__dynarr_add(dg__dynarr_unp(a), (n), 0) ? &(a).p[(a).md.cnt-(size_t)(n)] : NULL) - -// insert a single value v at index idx -#define dg_dynarr_insert(a, idx, v) \ - (dg__dynarr_checkidxle((a),(idx)), \ - dg__dynarr_insert(dg__dynarr_unp(a), (idx), 1, 0), \ - (a).p[dg__dynarr_idx((a).md, (idx))] = (v)) - -// insert n elements into a at idx, initialize them from array vals -// doesn't return anything -// ! vals (and all other args) is evaluated multiple times ! -#define dg_dynarr_insertn(a, idx, vals, n) do { \ - DG_DYNARR_ASSERT((vals)!=NULL, "Don't pass NULL as vals to dg_dynarr_insertn!"); \ - dg__dynarr_checkidxle((a),(idx)); \ - if((vals)!=NULL && dg__dynarr_insert(dg__dynarr_unp(a), (idx), (n), 0)){ \ - size_t i_=(idx), v_=0, e_=(idx)+(n); \ - while(i_ < e_) (a).p[i_++] = (vals)[v_++]; \ - }} DG__DYNARR_WHILE0 - -// insert n elements into a at idx and zeroe them with memset() -// returns pointer to first inserted element or NULL if out of memory -#define dg_dynarr_insertn_zeroed(a, idx, n) \ - (dg__dynarr_checkidxle((a),(idx)), \ - dg__dynarr_insert(dg__dynarr_unp(a), (idx), (n), 1) \ - ? &(a).p[dg__dynarr_idx((a).md, (idx))] : NULL) - -// insert n uninitialized elements into a at idx; -// returns pointer to first inserted element or NULL if out of memory -#define dg_dynarr_insertn_uninit(a, idx, n) \ - (dg__dynarr_checkidxle((a),(idx)), \ - dg__dynarr_insert(dg__dynarr_unp(a), idx, n, 0) \ - ? &(a).p[dg__dynarr_idx((a).md, (idx))] : NULL) - -// set a single value v at index idx - like "a.p[idx] = v;" but with checks (unless disabled) -#define dg_dynarr_set(a, idx, v) \ - (dg__dynarr_checkidx((a),(idx)), \ - (a).p[dg__dynarr_idx((a).md, (idx))] = (v)) - -// overwrite n elements of a, starting at idx, with values from array vals -// doesn't return anything -// ! vals (and all other args) is evaluated multiple times ! -#define dg_dynarr_setn(a, idx, vals, n) do { \ - DG_DYNARR_ASSERT((vals)!=NULL, "Don't pass NULL as vals to dg_dynarr_setn!"); \ - size_t idx_=(idx); size_t end_=idx_+(size_t)n; \ - dg__dynarr_checkidx((a),idx_); dg__dynarr_checkidx((a),end_-1); \ - if((vals)!=NULL && idx_ < (a).md.cnt && end_ <= (a).md.cnt) { \ - size_t v_=0; \ - while(idx_ < end_) (a).p[idx_++] = (vals)[v_++]; \ - }} DG__DYNARR_WHILE0 - - -// delete the element at idx, moving all following elements (=> keeps order) -#define dg_dynarr_delete(a, idx) \ - (dg__dynarr_checkidx((a),(idx)), dg__dynarr_delete(dg__dynarr_unp(a), (idx), 1)) - -// delete n elements starting at idx, moving all following elements (=> keeps order) -#define dg_dynarr_deleten(a, idx, n) \ - (dg__dynarr_checkidx((a),(idx)), dg__dynarr_delete(dg__dynarr_unp(a), (idx), (n))) - // TODO: check whether idx+n < count? - -// delete the element at idx, move the last element there (=> doesn't keep order) -#define dg_dynarr_deletefast(a, idx) \ - (dg__dynarr_checkidx((a),(idx)), dg__dynarr_deletefast(dg__dynarr_unp(a), (idx), 1)) - -// delete n elements starting at idx, move the last n elements there (=> doesn't keep order) -#define dg_dynarr_deletenfast(a, idx, n) \ - (dg__dynarr_checkidx((a),(idx)), dg__dynarr_deletefast(dg__dynarr_unp(a), idx, n)) - // TODO: check whether idx+n < count? - -// removes all elements from the array, but does not free the buffer -// (if you want to free the buffer too, just use dg_dynarr_free()) -#define dg_dynarr_clear(a) \ - ((a).md.cnt=0) - -// sets the logical number of elements in the array -// if cnt > dg_dynarr_count(a), the logical count will be increased accordingly -// and the new elements will be uninitialized -#define dg_dynarr_setcount(a, n) \ - (dg__dynarr_maybegrow(dg__dynarr_unp(a), (n)) ? ((a).md.cnt = (n)) : 0) - -// make sure the array can store cap elements without reallocating -// logical count remains unchanged -#define dg_dynarr_reserve(a, cap) \ - dg__dynarr_maybegrow(dg__dynarr_unp(a), (cap)) - -// this makes sure a only uses as much memory as for its elements -// => maybe useful if a used to contain a huge amount of elements, -// but you deleted most of them and want to free some memory -// Note however that this implies an allocation and copying the remaining -// elements, so only do this if it frees enough memory to be worthwhile! -#define dg_dynarr_shrink_to_fit(a) \ - dg__dynarr_shrink_to_fit(dg__dynarr_unp(a)) - - -#if (DG_DYNARR_INDEX_CHECK_LEVEL == 1) || (DG_DYNARR_INDEX_CHECK_LEVEL == 3) - - // removes and returns the last element of the array - #define dg_dynarr_pop(a) \ - (dg__dynarr_check_notempty((a), "Don't pop an empty array!"), \ - (a).p[((a).md.cnt > 0) ? (--(a).md.cnt) : 0]) - - // returns the last element of the array - #define dg_dynarr_last(a) \ - (dg__dynarr_check_notempty((a), "Don't call da_last() on an empty array!"), \ - (a).p[((a).md.cnt > 0) ? ((a).md.cnt-1) : 0]) - -#elif (DG_DYNARR_INDEX_CHECK_LEVEL == 0) || (DG_DYNARR_INDEX_CHECK_LEVEL == 2) - - // removes and returns the last element of the array - #define dg_dynarr_pop(a) \ - (dg__dynarr_check_notempty((a), "Don't pop an empty array!"), \ - (a).p[--(a).md.cnt]) - - // returns the last element of the array - #define dg_dynarr_last(a) \ - (dg__dynarr_check_notempty((a), "Don't call da_last() on an empty array!"), \ - (a).p[(a).md.cnt-1]) - -#else // invalid DG_DYNARR_INDEX_CHECK_LEVEL - #error Invalid index check level DG_DYNARR_INDEX_CHECK_LEVEL (must be 0-3) ! -#endif // DG_DYNARR_INDEX_CHECK_LEVEL - -// returns the pointer *to* the last element of the array -// (in contrast to dg_dynarr_end() which returns a pointer *after* the last element) -// returns NULL if array is empty -#define dg_dynarr_lastptr(a) \ - (((a).md.cnt > 0) ? ((a).p + (a).md.cnt - 1) : NULL) - -// get element at index idx (like a.p[idx]), but with checks -// (unless you disabled them with #define DG_DYNARR_INDEX_CHECK_LEVEL 0) -#define dg_dynarr_get(a, idx) \ - (dg__dynarr_checkidx((a),(idx)), (a).p[dg__dynarr_idx((a).md, (idx))]) - -// get pointer to element at index idx (like &a.p[idx]), but with checks -// (unless you disabled them with #define DG_DYNARR_INDEX_CHECK_LEVEL 0) -// if index-checks are disabled, it returns NULL on invalid index (else it asserts() before returning) -#define dg_dynarr_getptr(a, idx) \ - (dg__dynarr_checkidx((a),(idx)), \ - ((size_t)(idx) < (a).md.cnt) ? ((a).p+(size_t)(idx)) : NULL) - -// returns a pointer to the first element of the array -// (together with dg_dynarr_end() you can do C++-style iterating) -#define dg_dynarr_begin(a) \ - ((a).p) - -// returns a pointer to the past-the-end element of the array -// Allows C++-style iterating, in case you're into that kind of thing: -// for(T *it=dg_dynarr_begin(a), *end=dg_dynarr_end(a); it!=end; ++it) foo(*it); -// (see dg_dynarr_lastptr() to get a pointer *to* the last element) -#define dg_dynarr_end(a) \ - ((a).p + (a).md.cnt) - - -// returns (logical) number of elements currently in the array -#define dg_dynarr_count(a) \ - ((a).md.cnt) - -// get the current reserved capacity of the array -#define dg_dynarr_capacity(a) \ - ((a).md.cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB) - -// returns 1 if the array is empty, else 0 -#define dg_dynarr_empty(a) \ - ((a).md.cnt == 0) - -// returns 1 if the last (re)allocation when inserting failed (Out Of Memory) -// or if the array has never allocated any memory yet, else 0 -// deleting the contents when growing fails instead of keeping old may seem -// a bit uncool, but it's simple and OOM should rarely happen on modern systems -// anyway - after all you need to deplete both RAM and swap/pagefile.sys -// or deplete the address space, which /might/ happen with 32bit applications -// but probably not with 64bit (at least in the foreseeable future) -#define dg_dynarr_oom(a) \ - ((a).md.cap == 0) - - -// sort a using the given qsort()-comparator cmp -// (just a slim wrapper around qsort()) -#define dg_dynarr_sort(a, cmp) \ - qsort((a).p, (a).md.cnt, sizeof((a).p[0]), (cmp)) - - -// ######### Implementation-Details that are not part of the API ########## - -#include // size_t, malloc(), free(), realloc() -#include // memset(), memcpy(), memmove() - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - size_t cnt; // logical number of elements - size_t cap; // cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB is actual capacity (in elements, *not* bytes!) - // if(cap & DG__DYNARR_SIZE_T_MSB) the current memory is not allocated by dg_dynarr, - // but was set with dg_dynarr_init_external() - // that's handy to give an array a base-element storage on the stack, for example - // TODO: alternatively, we could introduce a flag field to this struct and use that, - // so we don't have to calculate & everytime cap is needed -} dg__dynarr_md; - -// I used to have the following in an enum, but MSVC assumes enums are always 32bit ints -static const size_t DG__DYNARR_SIZE_T_MSB = ((size_t)1) << (sizeof(size_t)*8 - 1); -static const size_t DG__DYNARR_SIZE_T_ALL_BUT_MSB = (((size_t)1) << (sizeof(size_t)*8 - 1))-1; - -// "unpack" the elements of an array struct for use with helper functions -// (to void** arr, dg__dynarr_md* md, size_t itemsize) -#define dg__dynarr_unp(a) \ - (void**)&(a).p, &(a).md, sizeof((a).p[0]) - -// MSVC warns about "conditional expression is constant" when using the -// do { ... } while(0) idiom in macros.. -#ifdef _MSC_VER - #if _MSC_VER >= 1400 // MSVC 2005 and newer - // people claim MSVC 2005 and newer support __pragma, even though it's only documented - // for 2008+ (https://msdn.microsoft.com/en-us/library/d9x1s805%28v=vs.90%29.aspx) - // the following workaround is based on - // http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/ - #define DG__DYNARR_WHILE0 \ - __pragma(warning(push)) \ - __pragma(warning(disable:4127)) \ - while(0) \ - __pragma(warning(pop)) - #else // older MSVC versions don't support __pragma - I heard this helps for them - #define DG__DYNARR_WHILE0 while(0,0) - #endif - -#else // other compilers - - #define DG__DYNARR_WHILE0 while(0) - -#endif // _MSC_VER - - -#if (DG_DYNARR_INDEX_CHECK_LEVEL == 2) || (DG_DYNARR_INDEX_CHECK_LEVEL == 3) - - #define dg__dynarr_checkidx(a,i) \ - DG_DYNARR_ASSERT((size_t)i < a.md.cnt, "index out of bounds!") - - // special case for insert operations: == cnt is also ok, insert will append then - #define dg__dynarr_checkidxle(a,i) \ - DG_DYNARR_ASSERT((size_t)i <= a.md.cnt, "index out of bounds!") - - #define dg__dynarr_check_notempty(a, msg) \ - DG_DYNARR_ASSERT(a.md.cnt > 0, msg) - -#elif (DG_DYNARR_INDEX_CHECK_LEVEL == 0) || (DG_DYNARR_INDEX_CHECK_LEVEL == 1) - - // no assertions that check if index is valid - #define dg__dynarr_checkidx(a,i) (void)0 - #define dg__dynarr_checkidxle(a,i) (void)0 - - #define dg__dynarr_check_notempty(a, msg) (void)0 - -#else // invalid DG_DYNARR_INDEX_CHECK_LEVEL - #error Invalid index check level DG_DYNARR_INDEX_CHECK_LEVEL (must be 0-3) ! -#endif // DG_DYNARR_INDEX_CHECK_LEVEL - - -#if (DG_DYNARR_INDEX_CHECK_LEVEL == 1) || (DG_DYNARR_INDEX_CHECK_LEVEL == 3) - - // the given index, if valid, else 0 - #define dg__dynarr_idx(md,i) \ - (((size_t)(i) < md.cnt) ? (size_t)(i) : 0) - -#elif (DG_DYNARR_INDEX_CHECK_LEVEL == 0) || (DG_DYNARR_INDEX_CHECK_LEVEL == 2) - - // don't check and default to 0 if invalid, but just use the given value - #define dg__dynarr_idx(md,i) (size_t)(i) - -#else // invalid DG_DYNARR_INDEX_CHECK_LEVEL - #error Invalid index check level DG_DYNARR_INDEX_CHECK_LEVEL (must be 0-3) ! -#endif // DG_DYNARR_INDEX_CHECK_LEVEL - -// the functions allocating/freeing memory are not implemented inline, but -// in the #ifdef DG_DYNARR_IMPLEMENTATION section -// one reason is that dg__dynarr_grow has the most code in it, the other is -// that windows has weird per-dll heaps so free() or realloc() should be -// called from code in the same dll that allocated the memory - these kind -// of wrapper functions that end up compiled into the exe or *one* dll -// (instead of inline functions compiled into everything) should ensure that. - -DG_DYNARR_DEF void -dg__dynarr_free(void** p, dg__dynarr_md* md); - -DG_DYNARR_DEF void -dg__dynarr_shrink_to_fit(void** arr, dg__dynarr_md* md, size_t itemsize); - -// grow array to have enough space for at least min_needed elements -// if it fails (OOM), the array will be deleted, a.p will be NULL, a.md.cap and a.md.cnt will be 0 -// and the functions returns 0; else (on success) it returns 1 -DG_DYNARR_DEF int -dg__dynarr_grow(void** arr, dg__dynarr_md* md, size_t itemsize, size_t min_needed); - - -// the following functions are implemented inline, because they're quite short -// and mosty implemented in functions so the macros don't get too ugly - -DG_DYNARR_INLINE void -dg__dynarr_init(void** p, dg__dynarr_md* md, void* buf, size_t buf_cap) -{ - *p = buf; - md->cnt = 0; - if(buf == NULL) md->cap = 0; - else md->cap = (DG__DYNARR_SIZE_T_MSB | buf_cap); -} - -DG_DYNARR_INLINE int -dg__dynarr_maybegrow(void** arr, dg__dynarr_md* md, size_t itemsize, size_t min_needed) -{ - if((md->cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB) >= min_needed) return 1; - else return dg__dynarr_grow(arr, md, itemsize, min_needed); -} - -DG_DYNARR_INLINE int -dg__dynarr_maybegrowadd(void** arr, dg__dynarr_md* md, size_t itemsize, size_t num_add) -{ - size_t min_needed = md->cnt+num_add; - if((md->cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB) >= min_needed) return 1; - else return dg__dynarr_grow(arr, md, itemsize, min_needed); -} - -DG_DYNARR_INLINE int -dg__dynarr_insert(void** arr, dg__dynarr_md* md, size_t itemsize, size_t idx, size_t n, int init0) -{ - // allow idx == md->cnt to append - size_t oldCount = md->cnt; - size_t newCount = oldCount+n; - if(idx <= oldCount && dg__dynarr_maybegrow(arr, md, itemsize, newCount)) - { - unsigned char* p = (unsigned char*)*arr; // *arr might have changed in dg__dynarr_grow()! - // move all existing items after a[idx] to a[idx+n] - if(idx < oldCount) memmove(p+(idx+n)*itemsize, p+idx*itemsize, itemsize*(oldCount - idx)); - - // if the memory is supposed to be zeroed, do that - if(init0) memset(p+idx*itemsize, 0, n*itemsize); - - md->cnt = newCount; - return 1; - } - return 0; -} - -DG_DYNARR_INLINE int -dg__dynarr_add(void** arr, dg__dynarr_md* md, size_t itemsize, size_t n, int init0) -{ - size_t cnt = md->cnt; - if(dg__dynarr_maybegrow(arr, md, itemsize, cnt+n)) - { - unsigned char* p = (unsigned char*)*arr; // *arr might have changed in dg__dynarr_grow()! - // if the memory is supposed to be zeroed, do that - if(init0) memset(p+cnt*itemsize, 0, n*itemsize); - - md->cnt += n; - return 1; - } - return 0; -} - -DG_DYNARR_INLINE void -dg__dynarr_delete(void** arr, dg__dynarr_md* md, size_t itemsize, size_t idx, size_t n) -{ - size_t cnt = md->cnt; - if(idx < cnt) - { - if(idx+n >= cnt) md->cnt = idx; // removing last element(s) => just reduce count - else - { - unsigned char* p = (unsigned char*)*arr; - // move all items following a[idx+n] to a[idx] - memmove(p+itemsize*idx, p+itemsize*(idx+n), itemsize*(cnt - (idx+n))); - md->cnt -= n; - } - } -} - -DG_DYNARR_INLINE void -dg__dynarr_deletefast(void** arr, dg__dynarr_md* md, size_t itemsize, size_t idx, size_t n) -{ - size_t cnt = md->cnt; - if(idx < cnt) - { - if(idx+n >= cnt) md->cnt = idx; // removing last element(s) => just reduce count - else - { - unsigned char* p = (unsigned char*)*arr; - // copy the last n items to a[idx] - but handle the case that - // the array has less than n elements left after the deleted elements - size_t numItemsAfterDeleted = cnt - (idx+n); - size_t m = (n < numItemsAfterDeleted) ? n : numItemsAfterDeleted; - memcpy(p+itemsize*idx, p+itemsize*(cnt - m), itemsize*m); - md->cnt -= n; - } - } -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // DG__DYNARR_H - - -// ############## Implementation of non-inline functions ############## - -#ifdef DG_DYNARR_IMPLEMENTATION - -// by default, C's malloc(), realloc() and free() is used to allocate/free heap memory. -// you can #define DG_DYNARR_MALLOC, DG_DYNARR_REALLOC and DG_DYNARR_FREE -// to provide alternative implementations like Win32 Heap(Re)Alloc/HeapFree -// -#ifndef DG_DYNARR_MALLOC - #define DG_DYNARR_MALLOC(elemSize, numElems) malloc(elemSize*numElems) - - // oldNumElems is not used here, but maybe you need it for your allocator - // to copy the old elements over - #define DG_DYNARR_REALLOC(ptr, elemSize, oldNumElems, newCapacity) \ - realloc(ptr, elemSize*newCapacity); - - #define DG_DYNARR_FREE(ptr) free(ptr) -#endif - -// you can #define DG_DYNARR_OUT_OF_MEMORY to some code that will be executed -// if allocating memory fails -#ifndef DG_DYNARR_OUT_OF_MEMORY - #define DG_DYNARR_OUT_OF_MEMORY DG_DYNARR_ASSERT(0, "Out of Memory!"); -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -DG_DYNARR_DEF void -dg__dynarr_free(void** p, dg__dynarr_md* md) -{ - // only free memory if it doesn't point to external memory - if(!(md->cap & DG__DYNARR_SIZE_T_MSB)) - { - DG_DYNARR_FREE(*p); - *p = NULL; - md->cap = 0; - } - md->cnt = 0; -} - - -DG_DYNARR_DEF int -dg__dynarr_grow(void** arr, dg__dynarr_md* md, size_t itemsize, size_t min_needed) -{ - size_t cap = md->cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB; - - DG_DYNARR_ASSERT(min_needed > cap, "dg__dynarr_grow() should only be called if storage actually needs to grow!"); - - if(min_needed < DG__DYNARR_SIZE_T_MSB) - { - size_t newcap = (cap > 4) ? (2*cap) : 8; // allocate for at least 8 elements - // make sure not to set DG__DYNARR_SIZE_T_MSB (unlikely anyway) - if(newcap >= DG__DYNARR_SIZE_T_MSB) newcap = DG__DYNARR_SIZE_T_MSB-1; - if(min_needed > newcap) newcap = min_needed; - - // the memory was allocated externally, don't free it, just copy contents - if(md->cap & DG__DYNARR_SIZE_T_MSB) - { - void* p = DG_DYNARR_MALLOC(itemsize, newcap); - if(p != NULL) memcpy(p, *arr, itemsize*md->cnt); - *arr = p; - } - else - { - void* p = DG_DYNARR_REALLOC(*arr, itemsize, md->cnt, newcap); - if(p == NULL) DG_DYNARR_FREE(*arr); // realloc failed, at least don't leak memory - *arr = p; - } - - // TODO: handle OOM by setting highest bit of count and keeping old data? - - if(*arr) md->cap = newcap; - else - { - md->cap = 0; - md->cnt = 0; - - DG_DYNARR_OUT_OF_MEMORY ; - - return 0; - } - return 1; - } - DG_DYNARR_ASSERT(min_needed < DG__DYNARR_SIZE_T_MSB, "Arrays must stay below SIZE_T_MAX/2 elements!"); - return 0; -} - -DG_DYNARR_DEF void -dg__dynarr_shrink_to_fit(void** arr, dg__dynarr_md* md, size_t itemsize) -{ - // only do this if we allocated the memory ourselves - if(!(md->cap & DG__DYNARR_SIZE_T_MSB)) - { - size_t cnt = md->cnt; - if(cnt == 0) dg__dynarr_free(arr, md); - else if((md->cap & DG__DYNARR_SIZE_T_ALL_BUT_MSB) > cnt) - { - void* p = DG_DYNARR_MALLOC(itemsize, cnt); - if(p != NULL) - { - memcpy(p, *arr, cnt*itemsize); - md->cap = cnt; - DG_DYNARR_FREE(*arr); - *arr = p; - } - } - } -} - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // DG_DYNARR_IMPLEMENTATION diff --git a/src/client/refresh/gl4/header/HandmadeMath.h b/src/client/refresh/gl4/header/HandmadeMath.h deleted file mode 100644 index 9d7ee3f0..00000000 --- a/src/client/refresh/gl4/header/HandmadeMath.h +++ /dev/null @@ -1,2453 +0,0 @@ -/* - HandmadeMath.h v1.5.0 - - This is a single header file with a bunch of useful functions for game and - graphics math operations. - - ============================================================================= - - You MUST - - #define HANDMADE_MATH_IMPLEMENTATION - - in EXACTLY one C or C++ file that includes this header, BEFORE the - include, like this: - - #define HANDMADE_MATH_IMPLEMENTATION - #include "HandmadeMath.h" - - All other files should just #include "HandmadeMath.h" without the #define. - - ============================================================================= - - To disable SSE intrinsics, you MUST - - #define HANDMADE_MATH_NO_SSE - - in EXACTLY one C or C++ file that includes this header, BEFORE the - include, like this: - - #define HANDMADE_MATH_IMPLEMENTATION - #define HANDMADE_MATH_NO_SSE - #include "HandmadeMath.h" - - ============================================================================= - - To use HandmadeMath without the CRT, you MUST - - #define HMM_SINF MySinF - #define HMM_COSF MyCosF - #define HMM_TANF MyTanF - #define HMM_SQRTF MySqrtF - #define HMM_EXPF MyExpF - #define HMM_LOGF MyLogF - #define HMM_ACOSF MyACosF - #define HMM_ATANF MyATanF - #define HMM_ATAN2F MYATan2F - - Provide your own implementations of SinF, CosF, TanF, ACosF, ATanF, ATan2F, - ExpF, and LogF in EXACTLY one C or C++ file that includes this header, - BEFORE the include, like this: - - #define HMM_SINF MySinF - #define HMM_COSF MyCosF - #define HMM_TANF MyTanF - #define HMM_SQRTF MySqrtF - #define HMM_EXPF MyExpF - #define HMM_LOGF MyLogF - #define HMM_ACOSF MyACosF - #define HMM_ATANF MyATanF - #define HMM_ATAN2F MyATan2F - #define HANDMADE_MATH_IMPLEMENTATION - #include "HandmadeMath.h" - - If you do not define all of these, HandmadeMath.h will use the - versions of these functions that are provided by the CRT. - - ============================================================================= - - Version History: - 0.2 (*) Updated documentation - (*) Better C compliance - (*) Prefix all handmade math functions - (*) Better operator overloading - 0.2a - (*) Prefixed Macros - 0.2b - (*) Disabled warning 4201 on MSVC as it is legal is C11 - (*) Removed the f at the end of HMM_PI to get 64bit precision - 0.3 - (*) Added +=, -=, *=, /= for hmm_vec2, hmm_vec3, hmm_vec4 - 0.4 - (*) SSE Optimized HMM_SqrtF - (*) SSE Optimized HMM_RSqrtF - (*) Removed CRT - 0.5 - (*) Added scalar multiplication and division for vectors - and matrices - (*) Added matrix subtraction and += for hmm_mat4 - (*) Reconciled all headers and implementations - (*) Tidied up, and filled in a few missing operators - 0.5.1 - (*) Ensured column-major order for matrices throughout - (*) Fixed HMM_Translate producing row-major matrices - 0.5.2 - (*) Fixed SSE code in HMM_SqrtF - (*) Fixed SSE code in HMM_RSqrtF - 0.6 - (*) Added Unit testing - (*) Made HMM_Power faster - (*) Fixed possible efficiency problem with HMM_Normalize - (*) RENAMED HMM_LengthSquareRoot to HMM_LengthSquared - (*) RENAMED HMM_RSqrtF to HMM_RSquareRootF - (*) RENAMED HMM_SqrtF to HMM_SquareRootF - (*) REMOVED Inner function (user should use Dot now) - (*) REMOVED HMM_FastInverseSquareRoot function declaration - 0.7 - (*) REMOVED HMM_LengthSquared in HANDMADE_MATH_IMPLEMENTATION (should - use HMM_LengthSquaredVec3, or HANDMADE_MATH_CPP_MODE for function - overloaded version) - (*) REMOVED HMM_Length in HANDMADE_MATH_IMPLEMENTATION (should use - HMM_LengthVec3, HANDMADE_MATH_CPP_MODE for function - overloaded version) - (*) REMOVED HMM_Normalize in HANDMADE_MATH_IMPLEMENTATION (should use - HMM_NormalizeVec3, or HANDMADE_MATH_CPP_MODE for function - overloaded version) - (*) Added HMM_LengthSquaredVec2 - (*) Added HMM_LengthSquaredVec4 - (*) Addd HMM_LengthVec2 - (*) Added HMM_LengthVec4 - (*) Added HMM_NormalizeVec2 - (*) Added HMM_NormalizeVec4 - 1.0 - (*) Lots of testing! - 1.1 - (*) Quaternion support - (*) Added type hmm_quaternion - (*) Added HMM_Quaternion - (*) Added HMM_QuaternionV4 - (*) Added HMM_AddQuaternion - (*) Added HMM_SubtractQuaternion - (*) Added HMM_MultiplyQuaternion - (*) Added HMM_MultiplyQuaternionF - (*) Added HMM_DivideQuaternionF - (*) Added HMM_InverseQuaternion - (*) Added HMM_DotQuaternion - (*) Added HMM_NormalizeQuaternion - (*) Added HMM_Slerp - (*) Added HMM_QuaternionToMat4 - (*) Added HMM_QuaternionFromAxisAngle - 1.1.1 - (*) Resolved compiler warnings on gcc and g++ - 1.1.2 - (*) Fixed invalid HMMDEF's in the function definitions - 1.1.3 - (*) Fixed compile error in C mode - 1.1.4 - (*) Fixed SSE being included on platforms that don't support it - (*) Fixed divide-by-zero errors when normalizing zero vectors. - 1.1.5 - (*) Add Width and Height to HMM_Vec2 - (*) Made it so you can supply your own SqrtF - 1.2.0 - (*) Added equality functions for HMM_Vec2, HMM_Vec3, and HMM_Vec4. - (*) Added HMM_EqualsVec2, HMM_EqualsVec3, and HMM_EqualsVec4 - (*) Added C++ overloaded HMM_Equals for all three - (*) Added C++ == and != operators for all three - (*) SSE'd HMM_MultiplyMat4 (this is _WAY_ faster) - (*) SSE'd HMM_Transpose - 1.3.0 - (*) Remove need to #define HANDMADE_MATH_CPP_MODE - 1.4.0 - (*) Fixed bug when using HandmadeMath in C mode - (*) SSEd all vec4 operations - (*) Removed all zero-ing - 1.5.0 - (*) Changed internal structure for better performance and inlining. - (*) As a result, HANDMADE_MATH_NO_INLINE has been removed and no - longer has any effect. - - - LICENSE - - This software is in the public domain. Where that dedication is not - recognized, you are granted a perpetual, irrevocable license to copy, - distribute, and modify this file as you see fit. - - CREDITS - - Written by Zakary Strange (zak@strangedev.net && @strangezak) - - Functionality: - Matt Mascarenhas (@miblo_) - Aleph - FieryDrake (@fierydrake) - Gingerbill (@TheGingerBill) - Ben Visness (@bvisness) - Trinton Bullard (@Peliex_Dev) - - Fixes: - Jeroen van Rijn (@J_vanRijn) - Kiljacken (@Kiljacken) - Insofaras (@insofaras) - Daniel Gibson (@DanielGibson) -*/ - - -/* let's figure out if SSE is really available (unless disabled anyway) - (it isn't on non-x86/x86_64 platforms or even x86 without explicit SSE support) - => only use "#ifdef HANDMADE_MATH__USE_SSE" to check for SSE support below this block! */ -#ifndef HANDMADE_MATH_NO_SSE - -# ifdef _MSC_VER - /* MSVC supports SSE in amd64 mode or _M_IX86_FP >= 1 (2 means SSE2) */ -# if defined(_M_AMD64) || ( defined(_M_IX86_FP) && _M_IX86_FP >= 1 ) -# define HANDMADE_MATH__USE_SSE 1 -# endif -# else /* not MSVC, probably GCC, clang, icc or something that doesn't support SSE anyway */ -# ifdef __SSE__ /* they #define __SSE__ if it's supported */ -# define HANDMADE_MATH__USE_SSE 1 -# endif /* __SSE__ */ -# endif /* not _MSC_VER */ - -#endif /* #ifndef HANDMADE_MATH_NO_SSE */ - -#include // This is for types - -#ifdef HANDMADE_MATH__USE_SSE -#include -#endif - -#ifndef HANDMADE_MATH_H -#define HANDMADE_MATH_H - -#ifdef _MSC_VER -#pragma warning(disable:4201) -#endif - -#ifdef __clang__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wgnu-anonymous-struct" -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define HMM_INLINE static inline -#define HMM_EXTERN extern - -#if !defined(HMM_SINF) || !defined(HMM_COSF) || !defined(HMM_TANF) || \ - !defined(HMM_SQRTF) || !defined(HMM_EXPF) || !defined(HMM_LOGF) || \ - !defined(HMM_ACOSF) || !defined(HMM_ATANF)|| !defined(HMM_ATAN2F) -#include -#endif - -#ifndef HMM_SINF -#define HMM_SINF sinf -#endif - -#ifndef HMM_COSF -#define HMM_COSF cosf -#endif - -#ifndef HMM_TANF -#define HMM_TANF tanf -#endif - -#ifndef HMM_SQRTF -#define HMM_SQRTF sqrtf -#endif - -#ifndef HMM_EXPF -#define HMM_EXPF expf -#endif - -#ifndef HMM_LOGF -#define HMM_LOGF logf -#endif - -#ifndef HMM_ACOSF -#define HMM_ACOSF acosf -#endif - -#ifndef HMM_ATANF -#define HMM_ATANF atanf -#endif - -#ifndef HMM_ATAN2F -#define HMM_ATAN2F atan2f -#endif - -#define HMM_PI32 3.14159265359f -#define HMM_PI 3.14159265358979323846 - -#define HMM_MIN(a, b) (a) > (b) ? (b) : (a) -#define HMM_MAX(a, b) (a) < (b) ? (b) : (a) -#define HMM_ABS(a) ((a) > 0 ? (a) : -(a)) -#define HMM_MOD(a, m) ((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)) -#define HMM_SQUARE(x) ((x) * (x)) - -typedef union hmm_vec2 -{ - struct - { - float X, Y; - }; - - struct - { - float U, V; - }; - - struct - { - float Left, Right; - }; - - struct - { - float Width, Height; - }; - - float Elements[2]; -} hmm_vec2; - -typedef union hmm_vec3 -{ - struct - { - float X, Y, Z; - }; - - struct - { - float U, V, W; - }; - - struct - { - float R, G, B; - }; - - struct - { - hmm_vec2 XY; - float Ignored0_; - }; - - struct - { - float Ignored1_; - hmm_vec2 YZ; - }; - - struct - { - hmm_vec2 UV; - float Ignored2_; - }; - - struct - { - float Ignored3_; - hmm_vec2 VW; - }; - - float Elements[3]; -} hmm_vec3; - -typedef union hmm_vec4 -{ - struct - { - union - { - hmm_vec3 XYZ; - struct - { - float X, Y, Z; - }; - }; - - float W; - }; - struct - { - union - { - hmm_vec3 RGB; - struct - { - float R, G, B; - }; - }; - - float A; - }; - - struct - { - hmm_vec2 XY; - float Ignored0_; - float Ignored1_; - }; - - struct - { - float Ignored2_; - hmm_vec2 YZ; - float Ignored3_; - }; - - struct - { - float Ignored4_; - float Ignored5_; - hmm_vec2 ZW; - }; - - float Elements[4]; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 InternalElementsSSE; -#endif -} hmm_vec4; - -typedef union hmm_mat4 -{ - float Elements[4][4]; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 Rows[4]; -#endif -} hmm_mat4; - -typedef union hmm_quaternion -{ - struct - { - union - { - hmm_vec3 XYZ; - struct - { - float X, Y, Z; - }; - }; - - float W; - }; - - float Elements[4]; -} hmm_quaternion; - -typedef int32_t hmm_bool; - -typedef hmm_vec2 hmm_v2; -typedef hmm_vec3 hmm_v3; -typedef hmm_vec4 hmm_v4; -typedef hmm_mat4 hmm_m4; - - -/* - * Floating-point math functions - */ - -HMM_INLINE float HMM_SinF(float Radians) -{ - float Result = HMM_SINF(Radians); - - return (Result); -} - -HMM_INLINE float HMM_CosF(float Radians) -{ - float Result = HMM_COSF(Radians); - - return (Result); -} - -HMM_INLINE float HMM_TanF(float Radians) -{ - float Result = HMM_TANF(Radians); - - return (Result); -} - -HMM_INLINE float HMM_ACosF(float Radians) -{ - float Result = HMM_ACOSF(Radians); - - return (Result); -} - -HMM_INLINE float HMM_ATanF(float Radians) -{ - float Result = HMM_ATANF(Radians); - - return (Result); -} - -HMM_INLINE float HMM_ATan2F(float Left, float Right) -{ - float Result = HMM_ATAN2F(Left, Right); - - return (Result); -} - -HMM_INLINE float HMM_ExpF(float Float) -{ - float Result = HMM_EXPF(Float); - - return (Result); -} - -HMM_INLINE float HMM_LogF(float Float) -{ - float Result = HMM_LOGF(Float); - - return (Result); -} - -HMM_INLINE float HMM_SquareRootF(float Float) -{ - float Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 In = _mm_set_ss(Float); - __m128 Out = _mm_sqrt_ss(In); - Result = _mm_cvtss_f32(Out); -#else - Result = HMM_SQRTF(Float); -#endif - - return(Result); -} - -HMM_INLINE float HMM_RSquareRootF(float Float) -{ - float Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 In = _mm_set_ss(Float); - __m128 Out = _mm_rsqrt_ss(In); - Result = _mm_cvtss_f32(Out); -#else - Result = 1.0f/HMM_SquareRootF(Float); -#endif - - return(Result); -} - -HMM_EXTERN float HMM_Power(float Base, int Exponent); - -HMM_INLINE float HMM_PowerF(float Base, float Exponent) -{ - float Result = HMM_EXPF(Exponent * HMM_LOGF(Base)); - - return (Result); -} - - -/* - * Utility functions - */ -HMM_INLINE float HMM_ToRadians(float Degrees) -{ - float Result = Degrees * (HMM_PI32 / 180.0f); - - return (Result); -} - -HMM_INLINE float HMM_Lerp(float A, float Time, float B) -{ - float Result = (1.0f - Time) * A + Time * B; - - return (Result); -} - -HMM_INLINE float HMM_Clamp(float Min, float Value, float Max) -{ - float Result = Value; - - if(Result < Min) - { - Result = Min; - } - else if(Result > Max) - { - Result = Max; - } - - return (Result); -} - - -/* - * Vector initialization - */ - -HMM_INLINE hmm_vec2 HMM_Vec2(float X, float Y) -{ - hmm_vec2 Result; - - Result.X = X; - Result.Y = Y; - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_Vec2i(int X, int Y) -{ - hmm_vec2 Result; - - Result.X = (float)X; - Result.Y = (float)Y; - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Vec3(float X, float Y, float Z) -{ - hmm_vec3 Result; - - Result.X = X; - Result.Y = Y; - Result.Z = Z; - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Vec3i(int X, int Y, int Z) -{ - hmm_vec3 Result; - - Result.X = (float)X; - Result.Y = (float)Y; - Result.Z = (float)Z; - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Vec4(float X, float Y, float Z, float W) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_setr_ps(X, Y, Z, W); -#else - Result.X = X; - Result.Y = Y; - Result.Z = Z; - Result.W = W; -#endif - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Vec4i(int X, int Y, int Z, int W) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_setr_ps((float)X, (float)Y, (float)Z, (float)W); -#else - Result.X = (float)X; - Result.Y = (float)Y; - Result.Z = (float)Z; - Result.W = (float)W; -#endif - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Vec4v(hmm_vec3 Vector, float W) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_setr_ps(Vector.X, Vector.Y, Vector.Z, W); -#else - Result.XYZ = Vector; - Result.W = W; -#endif - - return (Result); -} - - -/* - * Binary vector operations - */ - -HMM_INLINE hmm_vec2 HMM_AddVec2(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result; - - Result.X = Left.X + Right.X; - Result.Y = Left.Y + Right.Y; - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_AddVec3(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result; - - Result.X = Left.X + Right.X; - Result.Y = Left.Y + Right.Y; - Result.Z = Left.Z + Right.Z; - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_AddVec4(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_add_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - Result.X = Left.X + Right.X; - Result.Y = Left.Y + Right.Y; - Result.Z = Left.Z + Right.Z; - Result.W = Left.W + Right.W; -#endif - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_SubtractVec2(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result; - - Result.X = Left.X - Right.X; - Result.Y = Left.Y - Right.Y; - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_SubtractVec3(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result; - - Result.X = Left.X - Right.X; - Result.Y = Left.Y - Right.Y; - Result.Z = Left.Z - Right.Z; - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_SubtractVec4(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_sub_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - Result.X = Left.X - Right.X; - Result.Y = Left.Y - Right.Y; - Result.Z = Left.Z - Right.Z; - Result.W = Left.W - Right.W; -#endif - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_MultiplyVec2(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result; - - Result.X = Left.X * Right.X; - Result.Y = Left.Y * Right.Y; - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_MultiplyVec2f(hmm_vec2 Left, float Right) -{ - hmm_vec2 Result; - - Result.X = Left.X * Right; - Result.Y = Left.Y * Right; - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_MultiplyVec3(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result; - - Result.X = Left.X * Right.X; - Result.Y = Left.Y * Right.Y; - Result.Z = Left.Z * Right.Z; - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_MultiplyVec3f(hmm_vec3 Left, float Right) -{ - hmm_vec3 Result; - - Result.X = Left.X * Right; - Result.Y = Left.Y * Right; - Result.Z = Left.Z * Right; - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_MultiplyVec4(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - Result.X = Left.X * Right.X; - Result.Y = Left.Y * Right.Y; - Result.Z = Left.Z * Right.Z; - Result.W = Left.W * Right.W; -#endif - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_MultiplyVec4f(hmm_vec4 Left, float Right) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 Scalar = _mm_set1_ps(Right); - Result.InternalElementsSSE = _mm_mul_ps(Left.InternalElementsSSE, Scalar); -#else - Result.X = Left.X * Right; - Result.Y = Left.Y * Right; - Result.Z = Left.Z * Right; - Result.W = Left.W * Right; -#endif - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_DivideVec2(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result; - - Result.X = Left.X / Right.X; - Result.Y = Left.Y / Right.Y; - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_DivideVec2f(hmm_vec2 Left, float Right) -{ - hmm_vec2 Result; - - Result.X = Left.X / Right; - Result.Y = Left.Y / Right; - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_DivideVec3(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result; - - Result.X = Left.X / Right.X; - Result.Y = Left.Y / Right.Y; - Result.Z = Left.Z / Right.Z; - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_DivideVec3f(hmm_vec3 Left, float Right) -{ - hmm_vec3 Result; - - Result.X = Left.X / Right; - Result.Y = Left.Y / Right; - Result.Z = Left.Z / Right; - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_DivideVec4(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Right.InternalElementsSSE); -#else - Result.X = Left.X / Right.X; - Result.Y = Left.Y / Right.Y; - Result.Z = Left.Z / Right.Z; - Result.W = Left.W / Right.W; -#endif - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_DivideVec4f(hmm_vec4 Left, float Right) -{ - hmm_vec4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 Scalar = _mm_set1_ps(Right); - Result.InternalElementsSSE = _mm_div_ps(Left.InternalElementsSSE, Scalar); -#else - Result.X = Left.X / Right; - Result.Y = Left.Y / Right; - Result.Z = Left.Z / Right; - Result.W = Left.W / Right; -#endif - - return (Result); -} - -HMM_INLINE hmm_bool HMM_EqualsVec2(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y); - - return (Result); -} - -HMM_INLINE hmm_bool HMM_EqualsVec3(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z); - - return (Result); -} - -HMM_INLINE hmm_bool HMM_EqualsVec4(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_bool Result = (Left.X == Right.X && Left.Y == Right.Y && Left.Z == Right.Z && Left.W == Right.W); - - return (Result); -} - -HMM_INLINE float HMM_DotVec2(hmm_vec2 VecOne, hmm_vec2 VecTwo) -{ - float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y); - - return (Result); -} - -HMM_INLINE float HMM_DotVec3(hmm_vec3 VecOne, hmm_vec3 VecTwo) -{ - float Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z); - - return (Result); -} - -HMM_INLINE float HMM_DotVec4(hmm_vec4 VecOne, hmm_vec4 VecTwo) -{ - float Result; - - // NOTE(zak): IN the future if we wanna check what version SSE is support - // we can use _mm_dp_ps (4.3) but for now we will use the old way. - // Or a r = _mm_mul_ps(v1, v2), r = _mm_hadd_ps(r, r), r = _mm_hadd_ps(r, r) for SSE3 -#ifdef HANDMADE_MATH__USE_SSE - __m128 SSEResultOne = _mm_mul_ps(VecOne.InternalElementsSSE, VecTwo.InternalElementsSSE); - __m128 SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(2, 3, 0, 1)); - SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); - SSEResultTwo = _mm_shuffle_ps(SSEResultOne, SSEResultOne, _MM_SHUFFLE(0, 1, 2, 3)); - SSEResultOne = _mm_add_ps(SSEResultOne, SSEResultTwo); - _mm_store_ss(&Result, SSEResultOne); -#else - Result = (VecOne.X * VecTwo.X) + (VecOne.Y * VecTwo.Y) + (VecOne.Z * VecTwo.Z) + (VecOne.W * VecTwo.W); -#endif - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Cross(hmm_vec3 VecOne, hmm_vec3 VecTwo) -{ - hmm_vec3 Result; - - Result.X = (VecOne.Y * VecTwo.Z) - (VecOne.Z * VecTwo.Y); - Result.Y = (VecOne.Z * VecTwo.X) - (VecOne.X * VecTwo.Z); - Result.Z = (VecOne.X * VecTwo.Y) - (VecOne.Y * VecTwo.X); - - return (Result); -} - - -/* - * Unary vector operations - */ - -HMM_INLINE float HMM_LengthSquaredVec2(hmm_vec2 A) -{ - float Result = HMM_DotVec2(A, A); - - return(Result); -} - -HMM_INLINE float HMM_LengthSquaredVec3(hmm_vec3 A) -{ - float Result = HMM_DotVec3(A, A); - - return (Result); -} - -HMM_INLINE float HMM_LengthSquaredVec4(hmm_vec4 A) -{ - float Result = HMM_DotVec4(A, A); - - return (Result); -} - -HMM_INLINE float HMM_LengthVec2(hmm_vec2 A) -{ - float Result = HMM_SquareRootF(HMM_LengthSquaredVec2(A)); - - return (Result); -} - -HMM_INLINE float HMM_LengthVec3(hmm_vec3 A) -{ - float Result = HMM_SquareRootF(HMM_LengthSquaredVec3(A)); - - return (Result); -} - -HMM_INLINE float HMM_LengthVec4(hmm_vec4 A) -{ - float Result = HMM_SquareRootF(HMM_LengthSquaredVec4(A)); - - return(Result); -} - -HMM_INLINE hmm_vec2 HMM_NormalizeVec2(hmm_vec2 A) -{ - hmm_vec2 Result = {0}; - - float VectorLength = HMM_LengthVec2(A); - - /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ - if (VectorLength != 0.0f) - { - Result.X = A.X * (1.0f / VectorLength); - Result.Y = A.Y * (1.0f / VectorLength); - } - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_NormalizeVec3(hmm_vec3 A) -{ - hmm_vec3 Result = {0}; - - float VectorLength = HMM_LengthVec3(A); - - /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ - if (VectorLength != 0.0f) - { - Result.X = A.X * (1.0f / VectorLength); - Result.Y = A.Y * (1.0f / VectorLength); - Result.Z = A.Z * (1.0f / VectorLength); - } - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_NormalizeVec4(hmm_vec4 A) -{ - hmm_vec4 Result = {0}; - - float VectorLength = HMM_LengthVec4(A); - - /* NOTE(kiljacken): We need a zero check to not divide-by-zero */ - if (VectorLength != 0.0f) - { - float Multiplier = 1.0f / VectorLength; - -#ifdef HANDMADE_MATH__USE_SSE - __m128 SSEMultiplier = _mm_set1_ps(Multiplier); - Result.InternalElementsSSE = _mm_mul_ps(A.InternalElementsSSE, SSEMultiplier); -#else - Result.X = A.X * Multiplier; - Result.Y = A.Y * Multiplier; - Result.Z = A.Z * Multiplier; - Result.W = A.W * Multiplier; -#endif - } - - return (Result); -} - - -/* - * SSE stuff - */ - -#ifdef HANDMADE_MATH__USE_SSE -HMM_INLINE __m128 HMM_LinearCombineSSE(__m128 Left, hmm_mat4 Right) -{ - __m128 Result; - Result = _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x00), Right.Rows[0]); - Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0x55), Right.Rows[1])); - Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xaa), Right.Rows[2])); - Result = _mm_add_ps(Result, _mm_mul_ps(_mm_shuffle_ps(Left, Left, 0xff), Right.Rows[3])); - - return (Result); -} -#endif - - -/* - * Matrix functions - */ - -HMM_INLINE hmm_mat4 HMM_Mat4(void) -{ - hmm_mat4 Result = {0}; - - return (Result); -} - -HMM_INLINE hmm_mat4 HMM_Mat4d(float Diagonal) -{ - hmm_mat4 Result = HMM_Mat4(); - - Result.Elements[0][0] = Diagonal; - Result.Elements[1][1] = Diagonal; - Result.Elements[2][2] = Diagonal; - Result.Elements[3][3] = Diagonal; - - return (Result); -} - -#ifdef HANDMADE_MATH__USE_SSE -HMM_INLINE hmm_mat4 HMM_Transpose(hmm_mat4 Matrix) -{ - hmm_mat4 Result = Matrix; - - _MM_TRANSPOSE4_PS(Result.Rows[0], Result.Rows[1], Result.Rows[2], Result.Rows[3]); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_Transpose(hmm_mat4 Matrix); -#endif - -#ifdef HANDMADE_MATH__USE_SSE -HMM_INLINE hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result; - - Result.Rows[0] = _mm_add_ps(Left.Rows[0], Right.Rows[0]); - Result.Rows[1] = _mm_add_ps(Left.Rows[1], Right.Rows[1]); - Result.Rows[2] = _mm_add_ps(Left.Rows[2], Right.Rows[2]); - Result.Rows[3] = _mm_add_ps(Left.Rows[3], Right.Rows[3]); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right); -#endif - -#ifdef HANDMADE_MATH__USE_SSE -HMM_INLINE hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result; - - Result.Rows[0] = _mm_sub_ps(Left.Rows[0], Right.Rows[0]); - Result.Rows[1] = _mm_sub_ps(Left.Rows[1], Right.Rows[1]); - Result.Rows[2] = _mm_sub_ps(Left.Rows[2], Right.Rows[2]); - Result.Rows[3] = _mm_sub_ps(Left.Rows[3], Right.Rows[3]); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right); -#endif - -HMM_EXTERN hmm_mat4 HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right); - -#ifdef HANDMADE_MATH__USE_SSE -HMM_INLINE hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar) -{ - hmm_mat4 Result; - - __m128 SSEScalar = _mm_set1_ps(Scalar); - Result.Rows[0] = _mm_mul_ps(Matrix.Rows[0], SSEScalar); - Result.Rows[1] = _mm_mul_ps(Matrix.Rows[1], SSEScalar); - Result.Rows[2] = _mm_mul_ps(Matrix.Rows[2], SSEScalar); - Result.Rows[3] = _mm_mul_ps(Matrix.Rows[3], SSEScalar); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar); -#endif - -HMM_EXTERN hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector); - -#ifdef HANDMADE_MATH__USE_SSE -HMM_INLINE hmm_mat4 HMM_DivideMat4f(hmm_mat4 Matrix, float Scalar) -{ - hmm_mat4 Result; - - __m128 SSEScalar = _mm_set1_ps(Scalar); - Result.Rows[0] = _mm_div_ps(Matrix.Rows[0], SSEScalar); - Result.Rows[1] = _mm_div_ps(Matrix.Rows[1], SSEScalar); - Result.Rows[2] = _mm_div_ps(Matrix.Rows[2], SSEScalar); - Result.Rows[3] = _mm_div_ps(Matrix.Rows[3], SSEScalar); - - return (Result); -} -#else -HMM_EXTERN hmm_mat4 HMM_DivideMat4f(hmm_mat4 Matrix, float Scalar); -#endif - - -/* - * Common graphics transformations - */ - -HMM_INLINE hmm_mat4 HMM_Orthographic(float Left, float Right, float Bottom, float Top, float Near, float Far) -{ - hmm_mat4 Result = HMM_Mat4(); - - Result.Elements[0][0] = 2.0f / (Right - Left); - Result.Elements[1][1] = 2.0f / (Top - Bottom); - Result.Elements[2][2] = 2.0f / (Near - Far); - Result.Elements[3][3] = 1.0f; - - Result.Elements[3][0] = (Left + Right) / (Left - Right); - Result.Elements[3][1] = (Bottom + Top) / (Bottom - Top); - Result.Elements[3][2] = (Far + Near) / (Near - Far); - - return (Result); -} - -HMM_INLINE hmm_mat4 HMM_Perspective(float FOV, float AspectRatio, float Near, float Far) -{ - hmm_mat4 Result = HMM_Mat4(); - - float TanThetaOver2 = HMM_TanF(FOV * (HMM_PI32 / 360.0f)); - - Result.Elements[0][0] = 1.0f / TanThetaOver2; - Result.Elements[1][1] = AspectRatio / TanThetaOver2; - Result.Elements[2][3] = -1.0f; - Result.Elements[2][2] = (Near + Far) / (Near - Far); - Result.Elements[3][2] = (2.0f * Near * Far) / (Near - Far); - Result.Elements[3][3] = 0.0f; - - return (Result); -} - -HMM_INLINE hmm_mat4 HMM_Translate(hmm_vec3 Translation) -{ - hmm_mat4 Result = HMM_Mat4d(1.0f); - - Result.Elements[3][0] = Translation.X; - Result.Elements[3][1] = Translation.Y; - Result.Elements[3][2] = Translation.Z; - - return (Result); -} - -HMM_EXTERN hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis); - -HMM_INLINE hmm_mat4 HMM_Scale(hmm_vec3 Scale) -{ - hmm_mat4 Result = HMM_Mat4d(1.0f); - - Result.Elements[0][0] = Scale.X; - Result.Elements[1][1] = Scale.Y; - Result.Elements[2][2] = Scale.Z; - - return (Result); -} - -HMM_EXTERN hmm_mat4 HMM_LookAt(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up); - - -/* - * Quaternion operations - */ - -HMM_INLINE hmm_quaternion HMM_Quaternion(float X, float Y, float Z, float W) -{ - hmm_quaternion Result; - - Result.X = X; - Result.Y = Y; - Result.Z = Z; - Result.W = W; - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_QuaternionV4(hmm_vec4 Vector) -{ - hmm_quaternion Result; - - Result.X = Vector.X; - Result.Y = Vector.Y; - Result.Z = Vector.Z; - Result.W = Vector.W; - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_AddQuaternion(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result; - - Result.X = Left.X + Right.X; - Result.Y = Left.Y + Right.Y; - Result.Z = Left.Z + Right.Z; - Result.W = Left.W + Right.W; - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_SubtractQuaternion(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result; - - Result.X = Left.X - Right.X; - Result.Y = Left.Y - Right.Y; - Result.Z = Left.Z - Right.Z; - Result.W = Left.W - Right.W; - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_MultiplyQuaternion(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result; - - Result.X = (Left.X * Right.W) + (Left.Y * Right.Z) - (Left.Z * Right.Y) + (Left.W * Right.X); - Result.Y = (-Left.X * Right.Z) + (Left.Y * Right.W) + (Left.Z * Right.X) + (Left.W * Right.Y); - Result.Z = (Left.X * Right.Y) - (Left.Y * Right.X) + (Left.Z * Right.W) + (Left.W * Right.Z); - Result.W = (-Left.X * Right.X) - (Left.Y * Right.Y) - (Left.Z * Right.Z) + (Left.W * Right.W); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_MultiplyQuaternionF(hmm_quaternion Left, float Multiplicative) -{ - hmm_quaternion Result; - - Result.X = Left.X * Multiplicative; - Result.Y = Left.Y * Multiplicative; - Result.Z = Left.Z * Multiplicative; - Result.W = Left.W * Multiplicative; - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_DivideQuaternionF(hmm_quaternion Left, float Dividend) -{ - hmm_quaternion Result; - - Result.X = Left.X / Dividend; - Result.Y = Left.Y / Dividend; - Result.Z = Left.Z / Dividend; - Result.W = Left.W / Dividend; - - return (Result); -} - -HMM_EXTERN hmm_quaternion HMM_InverseQuaternion(hmm_quaternion Left); - -HMM_INLINE float HMM_DotQuaternion(hmm_quaternion Left, hmm_quaternion Right) -{ - float Result = (Left.X * Right.X) + (Left.Y * Right.Y) + (Left.Z * Right.Z) + (Left.W * Right.W); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_NormalizeQuaternion(hmm_quaternion Left) -{ - hmm_quaternion Result; - - float Length = HMM_SquareRootF(HMM_DotQuaternion(Left, Left)); - Result = HMM_DivideQuaternionF(Left, Length); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_NLerp(hmm_quaternion Left, float Time, hmm_quaternion Right) -{ - hmm_quaternion Result; - - Result.X = HMM_Lerp(Left.X, Time, Right.X); - Result.Y = HMM_Lerp(Left.Y, Time, Right.Y); - Result.Z = HMM_Lerp(Left.Z, Time, Right.Z); - Result.W = HMM_Lerp(Left.W, Time, Right.W); - - Result = HMM_NormalizeQuaternion(Result); - - return (Result); -} - -HMM_EXTERN hmm_quaternion HMM_Slerp(hmm_quaternion Left, float Time, hmm_quaternion Right); -HMM_EXTERN hmm_mat4 HMM_QuaternionToMat4(hmm_quaternion Left); -HMM_EXTERN hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float AngleOfRotation); - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -HMM_INLINE float HMM_Length(hmm_vec2 A) -{ - float Result = HMM_LengthVec2(A); - - return (Result); -} - -HMM_INLINE float HMM_Length(hmm_vec3 A) -{ - float Result = HMM_LengthVec3(A); - - return (Result); -} - -HMM_INLINE float HMM_Length(hmm_vec4 A) -{ - float Result = HMM_LengthVec4(A); - - return (Result); -} - -HMM_INLINE float HMM_LengthSquared(hmm_vec2 A) -{ - float Result = HMM_LengthSquaredVec2(A); - - return (Result); -} - -HMM_INLINE float HMM_LengthSquared(hmm_vec3 A) -{ - float Result = HMM_LengthSquaredVec3(A); - - return (Result); -} - -HMM_INLINE float HMM_LengthSquared(hmm_vec4 A) -{ - float Result = HMM_LengthSquaredVec4(A); - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_Normalize(hmm_vec2 A) -{ - hmm_vec2 Result = HMM_NormalizeVec2(A); - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Normalize(hmm_vec3 A) -{ - hmm_vec3 Result = HMM_NormalizeVec3(A); - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Normalize(hmm_vec4 A) -{ - hmm_vec4 Result = HMM_NormalizeVec4(A); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_Normalize(hmm_quaternion A) -{ - hmm_quaternion Result = HMM_NormalizeQuaternion(A); - - return (Result); -} - -HMM_INLINE float HMM_Dot(hmm_vec2 VecOne, hmm_vec2 VecTwo) -{ - float Result = HMM_DotVec2(VecOne, VecTwo); - - return (Result); -} - -HMM_INLINE float HMM_Dot(hmm_vec3 VecOne, hmm_vec3 VecTwo) -{ - float Result = HMM_DotVec3(VecOne, VecTwo); - - return (Result); -} - -HMM_INLINE float HMM_Dot(hmm_vec4 VecOne, hmm_vec4 VecTwo) -{ - float Result = HMM_DotVec4(VecOne, VecTwo); - - return (Result); -} - -HMM_INLINE float HMM_Dot(hmm_quaternion QuatOne, hmm_quaternion QuatTwo) -{ - float Result = HMM_DotQuaternion(QuatOne, QuatTwo); - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_Add(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_AddVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Add(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_AddVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Add(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_AddVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 HMM_Add(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result = HMM_AddMat4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_Add(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result = HMM_AddQuaternion(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_Subtract(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_SubtractVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Subtract(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_SubtractVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Subtract(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_SubtractVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 HMM_Subtract(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result = HMM_SubtractMat4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_Subtract(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result = HMM_SubtractQuaternion(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_Multiply(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_MultiplyVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_Multiply(hmm_vec2 Left, float Right) -{ - hmm_vec2 Result = HMM_MultiplyVec2f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Multiply(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_MultiplyVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Multiply(hmm_vec3 Left, float Right) -{ - hmm_vec3 Result = HMM_MultiplyVec3f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Multiply(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_MultiplyVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Multiply(hmm_vec4 Left, float Right) -{ - hmm_vec4 Result = HMM_MultiplyVec4f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 HMM_Multiply(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result = HMM_MultiplyMat4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 HMM_Multiply(hmm_mat4 Left, float Right) -{ - hmm_mat4 Result = HMM_MultiplyMat4f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Multiply(hmm_mat4 Matrix, hmm_vec4 Vector) -{ - hmm_vec4 Result = HMM_MultiplyMat4ByVec4(Matrix, Vector); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_Multiply(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result = HMM_MultiplyQuaternion(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_Multiply(hmm_quaternion Left, float Right) -{ - hmm_quaternion Result = HMM_MultiplyQuaternionF(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_Divide(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_DivideVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 HMM_Divide(hmm_vec2 Left, float Right) -{ - hmm_vec2 Result = HMM_DivideVec2f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Divide(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_DivideVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 HMM_Divide(hmm_vec3 Left, float Right) -{ - hmm_vec3 Result = HMM_DivideVec3f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Divide(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_DivideVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 HMM_Divide(hmm_vec4 Left, float Right) -{ - hmm_vec4 Result = HMM_DivideVec4f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 HMM_Divide(hmm_mat4 Left, float Right) -{ - hmm_mat4 Result = HMM_DivideMat4f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion HMM_Divide(hmm_quaternion Left, float Right) -{ - hmm_quaternion Result = HMM_DivideQuaternionF(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_bool HMM_Equals(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_bool Result = HMM_EqualsVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_bool HMM_Equals(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_bool Result = HMM_EqualsVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_bool HMM_Equals(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_bool Result = HMM_EqualsVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 operator+(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_AddVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 operator+(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_AddVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 operator+(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_AddVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 operator+(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result = HMM_AddMat4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion operator+(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result = HMM_AddQuaternion(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 operator-(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_SubtractVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 operator-(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_SubtractVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 operator-(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_SubtractVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 operator-(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result = HMM_SubtractMat4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion operator-(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result = HMM_SubtractQuaternion(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_MultiplyVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_MultiplyVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_MultiplyVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result = HMM_MultiplyMat4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, hmm_quaternion Right) -{ - hmm_quaternion Result = HMM_MultiplyQuaternion(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 operator*(hmm_vec2 Left, float Right) -{ - hmm_vec2 Result = HMM_MultiplyVec2f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 operator*(hmm_vec3 Left, float Right) -{ - hmm_vec3 Result = HMM_MultiplyVec3f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 operator*(hmm_vec4 Left, float Right) -{ - hmm_vec4 Result = HMM_MultiplyVec4f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 operator*(hmm_mat4 Left, float Right) -{ - hmm_mat4 Result = HMM_MultiplyMat4f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion operator*(hmm_quaternion Left, float Right) -{ - hmm_quaternion Result = HMM_MultiplyQuaternionF(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 operator*(float Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_MultiplyVec2f(Right, Left); - - return (Result); -} - -HMM_INLINE hmm_vec3 operator*(float Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_MultiplyVec3f(Right, Left); - - return (Result); -} - -HMM_INLINE hmm_vec4 operator*(float Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_MultiplyVec4f(Right, Left); - - return (Result); -} - -HMM_INLINE hmm_mat4 operator*(float Left, hmm_mat4 Right) -{ - hmm_mat4 Result = HMM_MultiplyMat4f(Right, Left); - - return (Result); -} - -HMM_INLINE hmm_quaternion operator*(float Left, hmm_quaternion Right) -{ - hmm_quaternion Result = HMM_MultiplyQuaternionF(Right, Left); - - return (Result); -} - -HMM_INLINE hmm_vec4 operator*(hmm_mat4 Matrix, hmm_vec4 Vector) -{ - hmm_vec4 Result = HMM_MultiplyMat4ByVec4(Matrix, Vector); - - return (Result); -} - -HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, hmm_vec2 Right) -{ - hmm_vec2 Result = HMM_DivideVec2(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, hmm_vec3 Right) -{ - hmm_vec3 Result = HMM_DivideVec3(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, hmm_vec4 Right) -{ - hmm_vec4 Result = HMM_DivideVec4(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 operator/(hmm_vec2 Left, float Right) -{ - hmm_vec2 Result = HMM_DivideVec2f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec3 operator/(hmm_vec3 Left, float Right) -{ - hmm_vec3 Result = HMM_DivideVec3f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec4 operator/(hmm_vec4 Left, float Right) -{ - hmm_vec4 Result = HMM_DivideVec4f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_mat4 operator/(hmm_mat4 Left, float Right) -{ - hmm_mat4 Result = HMM_DivideMat4f(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_quaternion operator/(hmm_quaternion Left, float Right) -{ - hmm_quaternion Result = HMM_DivideQuaternionF(Left, Right); - - return (Result); -} - -HMM_INLINE hmm_vec2 &operator+=(hmm_vec2 &Left, hmm_vec2 Right) -{ - return (Left = Left + Right); -} - -HMM_INLINE hmm_vec3 &operator+=(hmm_vec3 &Left, hmm_vec3 Right) -{ - return (Left = Left + Right); -} - -HMM_INLINE hmm_vec4 &operator+=(hmm_vec4 &Left, hmm_vec4 Right) -{ - return (Left = Left + Right); -} - -HMM_INLINE hmm_mat4 &operator+=(hmm_mat4 &Left, hmm_mat4 Right) -{ - return (Left = Left + Right); -} - -HMM_INLINE hmm_quaternion &operator+=(hmm_quaternion &Left, hmm_quaternion Right) -{ - return (Left = Left + Right); -} - -HMM_INLINE hmm_vec2 &operator-=(hmm_vec2 &Left, hmm_vec2 Right) -{ - return (Left = Left - Right); -} - -HMM_INLINE hmm_vec3 &operator-=(hmm_vec3 &Left, hmm_vec3 Right) -{ - return (Left = Left - Right); -} - -HMM_INLINE hmm_vec4 &operator-=(hmm_vec4 &Left, hmm_vec4 Right) -{ - return (Left = Left - Right); -} - -HMM_INLINE hmm_mat4 &operator-=(hmm_mat4 &Left, hmm_mat4 Right) -{ - return (Left = Left - Right); -} - -HMM_INLINE hmm_quaternion &operator-=(hmm_quaternion &Left, hmm_quaternion Right) -{ - return (Left = Left - Right); -} - -HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, hmm_vec2 Right) -{ - return (Left = Left * Right); -} - -HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, hmm_vec3 Right) -{ - return (Left = Left * Right); -} - -HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, hmm_vec4 Right) -{ - return (Left = Left * Right); -} - -HMM_INLINE hmm_vec2 &operator*=(hmm_vec2 &Left, float Right) -{ - return (Left = Left * Right); -} - -HMM_INLINE hmm_vec3 &operator*=(hmm_vec3 &Left, float Right) -{ - return (Left = Left * Right); -} - -HMM_INLINE hmm_vec4 &operator*=(hmm_vec4 &Left, float Right) -{ - return (Left = Left * Right); -} - -HMM_INLINE hmm_mat4 &operator*=(hmm_mat4 &Left, float Right) -{ - return (Left = Left * Right); -} - -HMM_INLINE hmm_quaternion &operator*=(hmm_quaternion &Left, float Right) -{ - return (Left = Left * Right); -} - -HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, hmm_vec2 Right) -{ - return (Left = Left / Right); -} - -HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, hmm_vec3 Right) -{ - return (Left = Left / Right); -} - -HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, hmm_vec4 Right) -{ - return (Left = Left / Right); -} - -HMM_INLINE hmm_vec2 &operator/=(hmm_vec2 &Left, float Right) -{ - return (Left = Left / Right); -} - -HMM_INLINE hmm_vec3 &operator/=(hmm_vec3 &Left, float Right) -{ - return (Left = Left / Right); -} - -HMM_INLINE hmm_vec4 &operator/=(hmm_vec4 &Left, float Right) -{ - return (Left = Left / Right); -} - -HMM_INLINE hmm_mat4 &operator/=(hmm_mat4 &Left, float Right) -{ - return (Left = Left / Right); -} - -HMM_INLINE hmm_quaternion &operator/=(hmm_quaternion &Left, float Right) -{ - return (Left = Left / Right); -} - -HMM_INLINE hmm_bool operator==(hmm_vec2 Left, hmm_vec2 Right) -{ - return HMM_EqualsVec2(Left, Right); -} - -HMM_INLINE hmm_bool operator==(hmm_vec3 Left, hmm_vec3 Right) -{ - return HMM_EqualsVec3(Left, Right); -} - -HMM_INLINE hmm_bool operator==(hmm_vec4 Left, hmm_vec4 Right) -{ - return HMM_EqualsVec4(Left, Right); -} - -HMM_INLINE hmm_bool operator!=(hmm_vec2 Left, hmm_vec2 Right) -{ - return !HMM_EqualsVec2(Left, Right); -} - -HMM_INLINE hmm_bool operator!=(hmm_vec3 Left, hmm_vec3 Right) -{ - return !HMM_EqualsVec3(Left, Right); -} - -HMM_INLINE hmm_bool operator!=(hmm_vec4 Left, hmm_vec4 Right) -{ - return !HMM_EqualsVec4(Left, Right); -} - -#endif /* __cplusplus */ - -#ifdef __clang__ -#pragma GCC diagnostic pop -#endif - -#endif /* HANDMADE_MATH_H */ - -#ifdef HANDMADE_MATH_IMPLEMENTATION - -float HMM_Power(float Base, int Exponent) -{ - float Result = 1.0f; - float Mul = Exponent < 0 ? 1.f / Base : Base; - unsigned int X = Exponent < 0 ? -Exponent : Exponent; - while (X) - { - if (X & 1) - { - Result *= Mul; - } - - Mul *= Mul; - X >>= 1; - } - - return (Result); -} - -#ifndef HANDMADE_MATH__USE_SSE -hmm_mat4 HMM_Transpose(hmm_mat4 Matrix) -{ - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Rows][Columns] = Matrix.Elements[Columns][Rows]; - } - } - - return (Result); -} -#endif - -#ifndef HANDMADE_MATH__USE_SSE -hmm_mat4 HMM_AddMat4(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] + Right.Elements[Columns][Rows]; - } - } - - return (Result); -} -#endif - -#ifndef HANDMADE_MATH__USE_SSE -hmm_mat4 HMM_SubtractMat4(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Columns][Rows] = Left.Elements[Columns][Rows] - Right.Elements[Columns][Rows]; - } - } - - return (Result); -} -#endif - -hmm_mat4 HMM_MultiplyMat4(hmm_mat4 Left, hmm_mat4 Right) -{ - hmm_mat4 Result; - -#ifdef HANDMADE_MATH__USE_SSE - hmm_mat4 TransposedLeft = HMM_Transpose(Left); - hmm_mat4 TransposedRight = HMM_Transpose(Right); - - Result.Rows[0] = HMM_LinearCombineSSE(TransposedLeft.Rows[0], TransposedRight); - Result.Rows[1] = HMM_LinearCombineSSE(TransposedLeft.Rows[1], TransposedRight); - Result.Rows[2] = HMM_LinearCombineSSE(TransposedLeft.Rows[2], TransposedRight); - Result.Rows[3] = HMM_LinearCombineSSE(TransposedLeft.Rows[3], TransposedRight); - - Result = HMM_Transpose(Result); -#else - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - float Sum = 0; - int CurrentMatrice; - for(CurrentMatrice = 0; CurrentMatrice < 4; ++CurrentMatrice) - { - Sum += Left.Elements[CurrentMatrice][Rows] * Right.Elements[Columns][CurrentMatrice]; - } - - Result.Elements[Columns][Rows] = Sum; - } - } -#endif - - return (Result); -} - -#ifndef HANDMADE_MATH__USE_SSE -hmm_mat4 HMM_MultiplyMat4f(hmm_mat4 Matrix, float Scalar) -{ - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] * Scalar; - } - } - - return (Result); -} -#endif - -hmm_vec4 HMM_MultiplyMat4ByVec4(hmm_mat4 Matrix, hmm_vec4 Vector) -{ - hmm_vec4 Result; - - int Columns, Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - float Sum = 0; - for(Columns = 0; Columns < 4; ++Columns) - { - Sum += Matrix.Elements[Columns][Rows] * Vector.Elements[Columns]; - } - - Result.Elements[Rows] = Sum; - } - - return (Result); -} - -#ifndef HANDMADE_MATH__USE_SSE -hmm_mat4 HMM_DivideMat4f(hmm_mat4 Matrix, float Scalar) -{ - hmm_mat4 Result; - - int Columns; - for(Columns = 0; Columns < 4; ++Columns) - { - int Rows; - for(Rows = 0; Rows < 4; ++Rows) - { - Result.Elements[Columns][Rows] = Matrix.Elements[Columns][Rows] / Scalar; - } - } - - return (Result); -} -#endif - -hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis) -{ - hmm_mat4 Result = HMM_Mat4d(1.0f); - - Axis = HMM_NormalizeVec3(Axis); - - float SinTheta = HMM_SinF(HMM_ToRadians(Angle)); - float CosTheta = HMM_CosF(HMM_ToRadians(Angle)); - float CosValue = 1.0f - CosTheta; - - Result.Elements[0][0] = (Axis.X * Axis.X * CosValue) + CosTheta; - Result.Elements[0][1] = (Axis.X * Axis.Y * CosValue) + (Axis.Z * SinTheta); - Result.Elements[0][2] = (Axis.X * Axis.Z * CosValue) - (Axis.Y * SinTheta); - - Result.Elements[1][0] = (Axis.Y * Axis.X * CosValue) - (Axis.Z * SinTheta); - Result.Elements[1][1] = (Axis.Y * Axis.Y * CosValue) + CosTheta; - Result.Elements[1][2] = (Axis.Y * Axis.Z * CosValue) + (Axis.X * SinTheta); - - Result.Elements[2][0] = (Axis.Z * Axis.X * CosValue) + (Axis.Y * SinTheta); - Result.Elements[2][1] = (Axis.Z * Axis.Y * CosValue) - (Axis.X * SinTheta); - Result.Elements[2][2] = (Axis.Z * Axis.Z * CosValue) + CosTheta; - - return (Result); -} - -hmm_mat4 HMM_LookAt(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up) -{ - hmm_mat4 Result; - - hmm_vec3 F = HMM_NormalizeVec3(HMM_SubtractVec3(Center, Eye)); - hmm_vec3 S = HMM_NormalizeVec3(HMM_Cross(F, Up)); - hmm_vec3 U = HMM_Cross(S, F); - - Result.Elements[0][0] = S.X; - Result.Elements[0][1] = U.X; - Result.Elements[0][2] = -F.X; - - Result.Elements[1][0] = S.Y; - Result.Elements[1][1] = U.Y; - Result.Elements[1][2] = -F.Y; - - Result.Elements[2][0] = S.Z; - Result.Elements[2][1] = U.Z; - Result.Elements[2][2] = -F.Z; - - Result.Elements[3][0] = -HMM_DotVec3(S, Eye); - Result.Elements[3][1] = -HMM_DotVec3(U, Eye); - Result.Elements[3][2] = HMM_DotVec3(F, Eye); - Result.Elements[3][3] = 1.0f; - - return (Result); -} - -hmm_quaternion HMM_InverseQuaternion(hmm_quaternion Left) -{ - hmm_quaternion Conjugate; - hmm_quaternion Result; - float Norm = 0; - float NormSquared = 0; - - Conjugate.X = -Left.X; - Conjugate.Y = -Left.Y; - Conjugate.Z = -Left.Z; - Conjugate.W = Left.W; - - Norm = HMM_SquareRootF(HMM_DotQuaternion(Left, Left)); - NormSquared = Norm * Norm; - - Result.X = Conjugate.X / NormSquared; - Result.Y = Conjugate.Y / NormSquared; - Result.Z = Conjugate.Z / NormSquared; - Result.W = Conjugate.W / NormSquared; - - return (Result); -} - -hmm_quaternion HMM_Slerp(hmm_quaternion Left, float Time, hmm_quaternion Right) -{ - hmm_quaternion Result; - hmm_quaternion QuaternionLeft; - hmm_quaternion QuaternionRight; - - float Cos_Theta = HMM_DotQuaternion(Left, Right); - float Angle = HMM_ACosF(Cos_Theta); - - float S1 = HMM_SinF((1.0f - Time) * Angle); - float S2 = HMM_SinF(Time * Angle); - float Is = 1.0f / HMM_SinF(Angle); - - QuaternionLeft = HMM_MultiplyQuaternionF(Left, S1); - QuaternionRight = HMM_MultiplyQuaternionF(Right, S2); - - Result = HMM_AddQuaternion(QuaternionLeft, QuaternionRight); - Result = HMM_MultiplyQuaternionF(Result, Is); - - return (Result); -} - -hmm_mat4 HMM_QuaternionToMat4(hmm_quaternion Left) -{ - hmm_mat4 Result; - Result = HMM_Mat4d(1); - - hmm_quaternion NormalizedQuaternion = HMM_NormalizeQuaternion(Left); - - float XX, YY, ZZ, - XY, XZ, YZ, - WX, WY, WZ; - - XX = NormalizedQuaternion.X * NormalizedQuaternion.X; - YY = NormalizedQuaternion.Y * NormalizedQuaternion.Y; - ZZ = NormalizedQuaternion.Z * NormalizedQuaternion.Z; - XY = NormalizedQuaternion.X * NormalizedQuaternion.Y; - XZ = NormalizedQuaternion.X * NormalizedQuaternion.Z; - YZ = NormalizedQuaternion.Y * NormalizedQuaternion.Z; - WX = NormalizedQuaternion.W * NormalizedQuaternion.X; - WY = NormalizedQuaternion.W * NormalizedQuaternion.Y; - WZ = NormalizedQuaternion.W * NormalizedQuaternion.Z; - - Result.Elements[0][0] = 1.0f - 2.0f * (YY + ZZ); - Result.Elements[0][1] = 2.0f * (XY + WZ); - Result.Elements[0][2] = 2.0f * (XZ - WY); - - Result.Elements[1][0] = 2.0f * (XY - WZ); - Result.Elements[1][1] = 1.0f - 2.0f * (XX + ZZ); - Result.Elements[1][2] = 2.0f * (YZ + WX); - - Result.Elements[2][0] = 2.0f * (XZ + WY); - Result.Elements[2][1] = 2.0f * (YZ - WX); - Result.Elements[2][2] = 1.0f - 2.0f * (XX + YY); - - return (Result); -} - -hmm_quaternion HMM_QuaternionFromAxisAngle(hmm_vec3 Axis, float AngleOfRotation) -{ - hmm_quaternion Result; - - hmm_vec3 RotatedVector; - - float AxisNorm = 0; - float SineOfRotation = 0; - - AxisNorm = HMM_SquareRootF(HMM_DotVec3(Axis, Axis)); - SineOfRotation = HMM_SinF(AngleOfRotation / 2.0f); - RotatedVector = HMM_MultiplyVec3f(Axis, SineOfRotation); - - Result.W = HMM_CosF(AngleOfRotation / 2.0f); - Result.XYZ = HMM_DivideVec3f(RotatedVector, AxisNorm); - - return (Result); -} - -#endif /* HANDMADE_MATH_IMPLEMENTATION */ diff --git a/src/client/refresh/gl4/header/local.h b/src/client/refresh/gl4/header/local.h index ca8cad49..81886259 100644 --- a/src/client/refresh/gl4/header/local.h +++ b/src/client/refresh/gl4/header/local.h @@ -56,7 +56,7 @@ #include "../../ref_shared.h" -#include "HandmadeMath.h" +#include "../../files/HandmadeMath.h" #if 0 // only use this for development .. #define STUB_ONCE(msg) do { \