mirror of
https://github.com/thepigeongenerator/sdl_template.git
synced 2025-12-19 10:55:44 +01:00
replace spaces with tabs
This commit is contained in:
@@ -26,143 +26,143 @@
|
||||
|
||||
// define the dynamic array structure
|
||||
typedef struct {
|
||||
DYNARR_TYPE* dat; // contains the data of the dynamic array
|
||||
size_t count; // contains the amount of elements of the dynamic array
|
||||
size_t cap; // contains the capacity of the dynamic array
|
||||
DYNARR_TYPE* dat; // contains the data of the dynamic array
|
||||
size_t count; // contains the amount of elements of the dynamic array
|
||||
size_t cap; // contains the capacity of the dynamic array
|
||||
} DYNARR_NAME;
|
||||
|
||||
// cleans up the resources associated with the array, do not use after this step. This is undefined behaviour
|
||||
DYNARR_LINKAGE void DYNARR_FUNC(free)(DYNARR_NAME* arr) {
|
||||
free(arr->dat); // free(NULL) is allowed
|
||||
*arr = (DYNARR_NAME){0}; // zero out all fields to re-initialize
|
||||
free(arr->dat); // free(NULL) is allowed
|
||||
*arr = (DYNARR_NAME){0}; // zero out all fields to re-initialize
|
||||
}
|
||||
|
||||
// sets the capacity exactly, does not respect capacity scaling use `resize` if capacity scaling must be respected
|
||||
// returns 0 upon success, 1 upon failure
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize_exact)(DYNARR_NAME* arr, size_t ncap) {
|
||||
if (ncap < arr->count) return 1; // the new capacity is smaller than the count, this is very likely unintentional
|
||||
if (ncap == arr->cap) return 0; // the capacity is already the new capacity; no work needs to be done
|
||||
if (ncap == 0) {
|
||||
DYNARR_FUNC(free)(arr);
|
||||
return 0;
|
||||
}
|
||||
if (ncap < arr->count) return 1; // the new capacity is smaller than the count, this is very likely unintentional
|
||||
if (ncap == arr->cap) return 0; // the capacity is already the new capacity; no work needs to be done
|
||||
if (ncap == 0) {
|
||||
DYNARR_FUNC(free)(arr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// (re)allocate the memory for the array
|
||||
DYNARR_TYPE* nptr = realloc(arr->dat, ncap * sizeof(DYNARR_TYPE)); // if dat is NULL, behaviour is equivalent to "malloc"
|
||||
// (re)allocate the memory for the array
|
||||
DYNARR_TYPE* nptr = realloc(arr->dat, ncap * sizeof(DYNARR_TYPE)); // if dat is NULL, behaviour is equivalent to "malloc"
|
||||
|
||||
// if memory (re)allocation failed; return
|
||||
if (nptr == NULL)
|
||||
return 1;
|
||||
// if memory (re)allocation failed; return
|
||||
if (nptr == NULL)
|
||||
return 1;
|
||||
|
||||
arr->dat = nptr;
|
||||
arr->cap = ncap;
|
||||
return 0;
|
||||
arr->dat = nptr;
|
||||
arr->cap = ncap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DYNARR_LINKAGE DYNARR_NAME DYNARR_FUNC(init)(void) {
|
||||
return (DYNARR_NAME){0};
|
||||
return (DYNARR_NAME){0};
|
||||
}
|
||||
|
||||
// resizes the capacity, respects capacity scaling, use `resize_exact` if this behaviour isn't desirable (often it is)
|
||||
// returns 0 upon success, 1 upon failure
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize)(DYNARR_NAME* arr, size_t ncap) {
|
||||
if (ncap < arr->count) return 1; // the new count is less than the current count, this is very likely unintentional
|
||||
if (ncap == arr->cap) return 0; // the current capacity has already been set to this
|
||||
if (ncap == 0) {
|
||||
DYNARR_FUNC(free)(arr);
|
||||
return 0;
|
||||
}
|
||||
if (ncap < arr->count) return 1; // the new count is less than the current count, this is very likely unintentional
|
||||
if (ncap == arr->cap) return 0; // the current capacity has already been set to this
|
||||
if (ncap == 0) {
|
||||
DYNARR_FUNC(free)(arr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert the capacity into a power of 2 by selecting the most significan bit
|
||||
ncap--; // first remove 1, to decrease the most significant bit
|
||||
for (uint16_t i = 1; i < SIZE_WIDTH; i <<= 1) // loop through each bit in size_t
|
||||
ncap |= ncap >> i; // OR together the shifted result
|
||||
ncap++; // finally, add one so 0111 -> 1000
|
||||
// convert the capacity into a power of 2 by selecting the most significan bit
|
||||
ncap--; // first remove 1, to decrease the most significant bit
|
||||
for (uint16_t i = 1; i < SIZE_WIDTH; i <<= 1) // loop through each bit in size_t
|
||||
ncap |= ncap >> i; // OR together the shifted result
|
||||
ncap++; // finally, add one so 0111 -> 1000
|
||||
|
||||
// calculates what the new size should be by adding the amount of items to the count
|
||||
// assumes scaling factor is 2
|
||||
return DYNARR_FUNC(resize_exact)(arr, ncap);
|
||||
// calculates what the new size should be by adding the amount of items to the count
|
||||
// assumes scaling factor is 2
|
||||
return DYNARR_FUNC(resize_exact)(arr, ncap);
|
||||
}
|
||||
|
||||
// adds an item to the dynamic array, doubles the capacity if the new count exceeds the maximum
|
||||
// `dat` is not allowed to overlap with the selected range in the array
|
||||
// returns non-zero upon failure
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(add_bulk)(DYNARR_NAME* arr, DYNARR_TYPE* dat, size_t datcount, size_t idx) {
|
||||
if (idx > arr->count) return 1; // the index is greater than the count
|
||||
if (DYNARR_COUNT_MAX - datcount < arr->count) return 1; // the count will overflow
|
||||
if (datcount == 0) return 0; // the count is zero, nothing needs to be done
|
||||
if (idx > arr->count) return 1; // the index is greater than the count
|
||||
if (DYNARR_COUNT_MAX - datcount < arr->count) return 1; // the count will overflow
|
||||
if (datcount == 0) return 0; // the count is zero, nothing needs to be done
|
||||
|
||||
size_t orgcount = arr->count;
|
||||
arr->count += datcount;
|
||||
size_t orgcount = arr->count;
|
||||
arr->count += datcount;
|
||||
|
||||
// resize the array if the new count has hit the capacity
|
||||
if (arr->cap <= arr->count) {
|
||||
// resize the array to the new count using resize (count cannot be a zero-value at this point)
|
||||
if (DYNARR_FUNC(resize)(arr, arr->count))
|
||||
return 1;
|
||||
}
|
||||
// resize the array if the new count has hit the capacity
|
||||
if (arr->cap <= arr->count) {
|
||||
// resize the array to the new count using resize (count cannot be a zero-value at this point)
|
||||
if (DYNARR_FUNC(resize)(arr, arr->count))
|
||||
return 1;
|
||||
}
|
||||
|
||||
// move the data stored at the current position if we must insert
|
||||
if (idx < orgcount)
|
||||
memmove(&arr->dat[datcount + idx], &arr->dat[idx], (orgcount - idx) * sizeof(DYNARR_TYPE));
|
||||
memcpy(&arr->dat[idx], dat, datcount * sizeof(DYNARR_TYPE)); // copy the original data to the index (do not overlap)
|
||||
return 0;
|
||||
// move the data stored at the current position if we must insert
|
||||
if (idx < orgcount)
|
||||
memmove(&arr->dat[datcount + idx], &arr->dat[idx], (orgcount - idx) * sizeof(DYNARR_TYPE));
|
||||
memcpy(&arr->dat[idx], dat, datcount * sizeof(DYNARR_TYPE)); // copy the original data to the index (do not overlap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// adds an item to the dynamic array, doubles the capacity if the new count exceeds the maximum
|
||||
// returns 0 upon success, 1 upon failure
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(add)(DYNARR_NAME* arr, DYNARR_TYPE item) {
|
||||
return DYNARR_FUNC(add_bulk)(arr, &item, 1, arr->count);
|
||||
return DYNARR_FUNC(add_bulk)(arr, &item, 1, arr->count);
|
||||
}
|
||||
|
||||
// trims the parts of the dynamic array that isn't in use (does not respect scaling)
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(shrink)(DYNARR_NAME* arr) {
|
||||
if (arr->cap == arr->count) return 0; // return success if no work needs to be done
|
||||
return DYNARR_FUNC(resize_exact)(arr, arr->count);
|
||||
if (arr->cap == arr->count) return 0; // return success if no work needs to be done
|
||||
return DYNARR_FUNC(resize_exact)(arr, arr->count);
|
||||
}
|
||||
|
||||
// removes a block of indices from sidx..eidx (inclusive) does not shrink the array afterwards, use `remove_bulk` instead if this is undesirable behaviour
|
||||
// returns non-zero value upon failure
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove_bulk_noshrink)(DYNARR_NAME* arr, size_t sidx, size_t eidx) {
|
||||
if (arr->count == 0) return 0; // no work needs to be done
|
||||
if (arr->count <= sidx) return 1; // start index is out of bounds
|
||||
if (arr->count <= eidx) return 1; // end index is out of bounds
|
||||
if (eidx < sidx) return 1; // end index must be greater than or equal to start index
|
||||
if (arr->count == 0) return 0; // no work needs to be done
|
||||
if (arr->count <= sidx) return 1; // start index is out of bounds
|
||||
if (arr->count <= eidx) return 1; // end index is out of bounds
|
||||
if (eidx < sidx) return 1; // end index must be greater than or equal to start index
|
||||
|
||||
_Bool move = eidx < arr->count - 1; // calculate if we should move the memory after what has been removed
|
||||
arr->count -= eidx - sidx + 1; // should always be less than or equal to count
|
||||
_Bool move = eidx < arr->count - 1; // calculate if we should move the memory after what has been removed
|
||||
arr->count -= eidx - sidx + 1; // should always be less than or equal to count
|
||||
|
||||
if (move)
|
||||
memmove(&arr->dat[sidx], &arr->dat[eidx + 1], arr->count - sidx);
|
||||
if (move)
|
||||
memmove(&arr->dat[sidx], &arr->dat[eidx + 1], arr->count - sidx);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// removes a block of indices from sidx..eidx (inclusive)
|
||||
// resizes the array if the new size is a quarter of the original size if this is undesirable, use `remove_bulk_noshrink` instead
|
||||
// returns non-zero value upon failure
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove_bulk)(DYNARR_NAME* arr, size_t sidx, size_t eidx) {
|
||||
if (DYNARR_FUNC(remove_bulk_noshrink)(arr, sidx, eidx))
|
||||
return 1;
|
||||
if (DYNARR_FUNC(remove_bulk_noshrink)(arr, sidx, eidx))
|
||||
return 1;
|
||||
|
||||
// shrink the array when the new size is a quarter of the original size
|
||||
if (arr->count < arr->cap / 4)
|
||||
return DYNARR_FUNC(shrink)(arr);
|
||||
// shrink the array when the new size is a quarter of the original size
|
||||
if (arr->count < arr->cap / 4)
|
||||
return DYNARR_FUNC(shrink)(arr);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// removes an item from the dynamic array from a certain index, does not shrink the array afterwards, if this is undesirable, use `remove` instead
|
||||
// returns non-zero value upon failure
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove_noshrink)(DYNARR_NAME* arr, size_t idx) {
|
||||
return DYNARR_FUNC(remove_bulk_noshrink)(arr, idx, idx);
|
||||
return DYNARR_FUNC(remove_bulk_noshrink)(arr, idx, idx);
|
||||
}
|
||||
|
||||
// removes an item from the dynamic array from a certain index
|
||||
// resizes the array if the new size is a quarter of the original size if this is undesirable, use `remove_noshrink` instead
|
||||
// returns non-zero value upon failure
|
||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove)(DYNARR_NAME* arr, size_t idx) {
|
||||
return DYNARR_FUNC(remove_bulk)(arr, idx, idx);
|
||||
return DYNARR_FUNC(remove_bulk)(arr, idx, idx);
|
||||
}
|
||||
|
||||
// clean up all defined definitions so they can be used again later
|
||||
|
||||
@@ -4,62 +4,62 @@
|
||||
|
||||
// stores a 2D point using a floating-point number
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float x;
|
||||
float y;
|
||||
} float2;
|
||||
|
||||
// adds one float2 to another
|
||||
static inline float2 float2_add(float2 v1, float2 v2) {
|
||||
return (float2){v1.x + v2.x, v1.y + v2.y};
|
||||
return (float2){v1.x + v2.x, v1.y + v2.y};
|
||||
}
|
||||
|
||||
// subtracts one float2 from another
|
||||
static inline float2 float2_sub(float2 v1, float2 v2) {
|
||||
return (float2){v1.x - v2.x, v1.y - v2.y};
|
||||
return (float2){v1.x - v2.x, v1.y - v2.y};
|
||||
}
|
||||
|
||||
// multiplies one float2 by another
|
||||
static inline float2 float2_mul(float2 v1, float2 v2) {
|
||||
return (float2){v1.x * v2.x, v1.y * v2.y};
|
||||
return (float2){v1.x * v2.x, v1.y * v2.y};
|
||||
}
|
||||
|
||||
// divides one float2 by another
|
||||
static inline float2 float2_div(float2 v1, float2 v2) {
|
||||
return (float2){v1.x / v2.x, v1.y / v2.y};
|
||||
return (float2){v1.x / v2.x, v1.y / v2.y};
|
||||
}
|
||||
|
||||
// preforms a scalar multiplication upon the float2 (multiplies the float2 by some value)
|
||||
static inline float2 float2_mul_s(float2 v, float n) {
|
||||
return (float2){v.x * n, v.y * n};
|
||||
return (float2){v.x * n, v.y * n};
|
||||
}
|
||||
|
||||
// preforms a scalar division upon the float2 (divides the float2 by some value)
|
||||
static inline float2 float2_div_s(float2 v, float n) {
|
||||
return (float2){v.x / n, v.y / n};
|
||||
return (float2){v.x / n, v.y / n};
|
||||
}
|
||||
|
||||
// negates the float2 (-v)
|
||||
static inline float2 float2_neg(float2 v) {
|
||||
return (float2){-v.x, -v.y};
|
||||
return (float2){-v.x, -v.y};
|
||||
}
|
||||
|
||||
// gets the squared magnitude/length of float2
|
||||
static inline float float2_mag2(float2 v) {
|
||||
return (v.x * v.x) + (v.y * v.y);
|
||||
return (v.x * v.x) + (v.y * v.y);
|
||||
}
|
||||
|
||||
// gets the length of float2 (length)
|
||||
static inline float float2_mag(float2 v) {
|
||||
return sqrtf(float2_mag2(v));
|
||||
return sqrtf(float2_mag2(v));
|
||||
}
|
||||
|
||||
// normalizes the float2
|
||||
static inline float2 float2_norm(float2 v) {
|
||||
float s = 1.0F / float2_mag(v); // get the scaling factor
|
||||
return float2_mul_s(v, s); // scale the vector by the scaling factor (slightly more efficient than dividing)
|
||||
float s = 1.0F / float2_mag(v); // get the scaling factor
|
||||
return float2_mul_s(v, s); // scale the vector by the scaling factor (slightly more efficient than dividing)
|
||||
}
|
||||
|
||||
// gets the dot product of two float2s
|
||||
static inline float float2_dot(float2 v1, float2 v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y;
|
||||
return v1.x * v2.x + v1.y * v2.y;
|
||||
}
|
||||
|
||||
@@ -4,62 +4,62 @@
|
||||
|
||||
// stores a 3D point using a floating-point number
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} float3;
|
||||
|
||||
// adds one float3 to another
|
||||
static inline float3 float3_add(float3 v1, float3 v2) {
|
||||
return (float3){v1.x + v2.x, v1.y + v2.y, v1.z + v2.z};
|
||||
return (float3){v1.x + v2.x, v1.y + v2.y, v1.z + v2.z};
|
||||
}
|
||||
|
||||
// subtracts one float3 from another
|
||||
static inline float3 float3_sub(float3 v1, float3 v2) {
|
||||
return (float3){v1.x - v2.x, v1.y - v2.y, v1.z - v2.z};
|
||||
return (float3){v1.x - v2.x, v1.y - v2.y, v1.z - v2.z};
|
||||
}
|
||||
|
||||
// multiplies one float3 by another
|
||||
static inline float3 float3_mul(float3 v1, float3 v2) {
|
||||
return (float3){v1.x * v2.x, v1.y * v2.y, v1.z * v2.z};
|
||||
return (float3){v1.x * v2.x, v1.y * v2.y, v1.z * v2.z};
|
||||
}
|
||||
|
||||
// divides one float3 by another
|
||||
static inline float3 float3_div(float3 v1, float3 v2) {
|
||||
return (float3){v1.x / v2.x, v1.y / v2.y, v1.z / v2.z};
|
||||
return (float3){v1.x / v2.x, v1.y / v2.y, v1.z / v2.z};
|
||||
}
|
||||
|
||||
// preforms a scalar multiplication upon the float3 (multiplies the float3 by some value)
|
||||
static inline float3 float3_mul_s(float3 v, float n) {
|
||||
return (float3){v.x * n, v.y * n, v.z * n};
|
||||
return (float3){v.x * n, v.y * n, v.z * n};
|
||||
}
|
||||
|
||||
// preforms a scalar division upon the float3 (divides the float3 by some value)
|
||||
static inline float3 float3_div_s(float3 v, float n) {
|
||||
return (float3){v.x / n, v.y / n, v.z / n};
|
||||
return (float3){v.x / n, v.y / n, v.z / n};
|
||||
}
|
||||
|
||||
static inline float3 float3_neg(float3 v) {
|
||||
return (float3){-v.x, -v.y, -v.z};
|
||||
return (float3){-v.x, -v.y, -v.z};
|
||||
}
|
||||
|
||||
// gets the squared magnitude/length of float3
|
||||
static inline float float3_mag2(float3 v) {
|
||||
return (v.x * v.x) + (v.y * v.y) + (v.z * v.z);
|
||||
return (v.x * v.x) + (v.y * v.y) + (v.z * v.z);
|
||||
}
|
||||
|
||||
// gets the length of float3 (length)
|
||||
static inline float float3_mag(float3 v) {
|
||||
return sqrtf(float3_mag2(v));
|
||||
return sqrtf(float3_mag2(v));
|
||||
}
|
||||
|
||||
// normalizes the float3
|
||||
static inline float3 float3_norm(float3 v) {
|
||||
float s = 1.0F / float3_mag(v); // get the scaling factor
|
||||
return float3_mul_s(v, s); // scale the vector by the scaling factor (slightly more efficient than dividing)
|
||||
float s = 1.0F / float3_mag(v); // get the scaling factor
|
||||
return float3_mul_s(v, s); // scale the vector by the scaling factor (slightly more efficient than dividing)
|
||||
}
|
||||
|
||||
// gets the dot product of two float3s
|
||||
static inline float float3_dot(float3 v1, float3 v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||
}
|
||||
|
||||
@@ -4,63 +4,63 @@
|
||||
|
||||
// stores a 3D point using a floating-point number
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} float4;
|
||||
|
||||
// adds one float4 to another
|
||||
static inline float4 float4_add(float4 v1, float4 v2) {
|
||||
return (float4){v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w};
|
||||
return (float4){v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w};
|
||||
}
|
||||
|
||||
// subtracts one float4 from another
|
||||
static inline float4 float4_sub(float4 v1, float4 v2) {
|
||||
return (float4){v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w};
|
||||
return (float4){v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w};
|
||||
}
|
||||
|
||||
// multiplies one float4 by another
|
||||
static inline float4 float4_mul(float4 v1, float4 v2) {
|
||||
return (float4){v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w};
|
||||
return (float4){v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w};
|
||||
}
|
||||
|
||||
// divides one float4 by another
|
||||
static inline float4 float4_div(float4 v1, float4 v2) {
|
||||
return (float4){v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w};
|
||||
return (float4){v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w};
|
||||
}
|
||||
|
||||
// preforms a scalar multiplication upon the float4 (multiplies the float4 by some value)
|
||||
static inline float4 float4_mul_s(float4 v, float n) {
|
||||
return (float4){v.x * n, v.y * n, v.z * n, v.w * n};
|
||||
return (float4){v.x * n, v.y * n, v.z * n, v.w * n};
|
||||
}
|
||||
|
||||
// preforms a scalar division upon the float4 (divides the float4 by some value)
|
||||
static inline float4 float4_div_s(float4 v, float n) {
|
||||
return (float4){v.x / n, v.y / n, v.z / n, v.w / n};
|
||||
return (float4){v.x / n, v.y / n, v.z / n, v.w / n};
|
||||
}
|
||||
|
||||
static inline float4 float4_neg(float4 v) {
|
||||
return (float4){-v.x, -v.y, -v.z, -v.w};
|
||||
return (float4){-v.x, -v.y, -v.z, -v.w};
|
||||
}
|
||||
|
||||
// gets the squared magnitude/length of float4
|
||||
static inline float float4_mag2(float4 v) {
|
||||
return (v.x * v.x) + (v.y * v.y) + (v.z * v.z) + (v.w * v.w);
|
||||
return (v.x * v.x) + (v.y * v.y) + (v.z * v.z) + (v.w * v.w);
|
||||
}
|
||||
|
||||
// gets the length of float4 (length)
|
||||
static inline float float4_mag(float4 v) {
|
||||
return sqrtf(float4_mag2(v));
|
||||
return sqrtf(float4_mag2(v));
|
||||
}
|
||||
|
||||
// normalizes the float4
|
||||
static inline float4 float4_norm(float4 v) {
|
||||
float s = 1.0F / float4_mag(v); // get the scaling factor
|
||||
return float4_mul_s(v, s); // scale the vector by the scaling factor (slightly more efficient than dividing)
|
||||
float s = 1.0F / float4_mag(v); // get the scaling factor
|
||||
return float4_mul_s(v, s); // scale the vector by the scaling factor (slightly more efficient than dividing)
|
||||
}
|
||||
|
||||
// gets the dot product of two float4s
|
||||
static inline float float4_dot(float4 v1, float4 v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
|
||||
}
|
||||
|
||||
@@ -5,89 +5,89 @@
|
||||
|
||||
// converts a float3 to a quaternion
|
||||
static inline float4 quat_from_float3(float3 v) {
|
||||
return (float4){
|
||||
.w = 0.0F,
|
||||
.x = v.x,
|
||||
.y = v.y,
|
||||
.z = v.z,
|
||||
};
|
||||
return (float4){
|
||||
.w = 0.0F,
|
||||
.x = v.x,
|
||||
.y = v.y,
|
||||
.z = v.z,
|
||||
};
|
||||
}
|
||||
|
||||
// converts euler angles into quaternion (ordered roll, pitch, yaw) (in radians)
|
||||
static inline float4 quat_from_euler(float3 euler) {
|
||||
euler = float3_mul_s(euler, 0.5F); // half the angles due to quaternions using θ/2 in the formula
|
||||
float cx = cosf(euler.x), sx = sinf(euler.x);
|
||||
float cy = cosf(euler.y), sy = sinf(euler.y);
|
||||
float cz = cosf(euler.z), sz = sinf(euler.z);
|
||||
euler = float3_mul_s(euler, 0.5F); // half the angles due to quaternions using θ/2 in the formula
|
||||
float cx = cosf(euler.x), sx = sinf(euler.x);
|
||||
float cy = cosf(euler.y), sy = sinf(euler.y);
|
||||
float cz = cosf(euler.z), sz = sinf(euler.z);
|
||||
|
||||
return (float4){
|
||||
.w = cx * cy * cz - sx * sy * sz,
|
||||
.x = sx * cy * cz + cx * sy * sz,
|
||||
.y = cx * sy * cz - sx * cy * sz,
|
||||
.z = cx * cy * sz + sx * sy * cz,
|
||||
};
|
||||
return (float4){
|
||||
.w = cx * cy * cz - sx * sy * sz,
|
||||
.x = sx * cy * cz + cx * sy * sz,
|
||||
.y = cx * sy * cz - sx * cy * sz,
|
||||
.z = cx * cy * sz + sx * sy * cz,
|
||||
};
|
||||
}
|
||||
|
||||
// converts quaternion into euler angles (ordered as roll, pitch, yaw)
|
||||
static inline float3 quat_to_euler(float4 q) {
|
||||
// warn: do not read from these variables until set
|
||||
float3 euler;
|
||||
float a, b;
|
||||
// warn: do not read from these variables until set
|
||||
float3 euler;
|
||||
float a, b;
|
||||
|
||||
// compute the roll (Φ)
|
||||
a = 2 * (q.w * q.x + q.y * q.z); // sin(r)•cos(p)
|
||||
b = 1 - 2 * (q.x * q.x + q.y * q.y); // cos(r)•cos(p)
|
||||
euler.x = atan2f(a, b);
|
||||
// compute the roll (Φ)
|
||||
a = 2 * (q.w * q.x + q.y * q.z); // sin(r)•cos(p)
|
||||
b = 1 - 2 * (q.x * q.x + q.y * q.y); // cos(r)•cos(p)
|
||||
euler.x = atan2f(a, b);
|
||||
|
||||
// compute the pitch (θ)
|
||||
a = 2 * (q.w * q.y - q.z * q.x);
|
||||
euler.y = fabsf(a) >= 1 ? copysignf(M_PI_2, a) : asinf(a); // if |a| >=1, sgn(a)•(π/2), else asin(a)
|
||||
// compute the pitch (θ)
|
||||
a = 2 * (q.w * q.y - q.z * q.x);
|
||||
euler.y = fabsf(a) >= 1 ? copysignf(M_PI_2, a) : asinf(a); // if |a| >=1, sgn(a)•(π/2), else asin(a)
|
||||
|
||||
// compute the yaw (ψ)
|
||||
a = 2 * (q.w * q.z + q.x * q.y); // sin(y)•cos(y)
|
||||
b = 1 - 2 * (q.y * q.y + q.z * q.z); // cos(y)•cos(y)
|
||||
euler.z = atan2f(a, b);
|
||||
// compute the yaw (ψ)
|
||||
a = 2 * (q.w * q.z + q.x * q.y); // sin(y)•cos(y)
|
||||
b = 1 - 2 * (q.y * q.y + q.z * q.z); // cos(y)•cos(y)
|
||||
euler.z = atan2f(a, b);
|
||||
|
||||
// return the final angles
|
||||
return euler;
|
||||
// return the final angles
|
||||
return euler;
|
||||
}
|
||||
|
||||
// multiplies two quaternions
|
||||
static inline float4 quat_mul(float4 q1, float4 q2) {
|
||||
return (float4){
|
||||
.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z,
|
||||
.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y,
|
||||
.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z,
|
||||
.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x,
|
||||
};
|
||||
return (float4){
|
||||
.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z,
|
||||
.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y,
|
||||
.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z,
|
||||
.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x,
|
||||
};
|
||||
}
|
||||
|
||||
// get the conjugate of the quaternion (negates the vector portion)
|
||||
static inline float4 quat_conj(float4 q) {
|
||||
return (float4){
|
||||
.w = q.w,
|
||||
.x = -q.x,
|
||||
.y = -q.y,
|
||||
.z = -q.z,
|
||||
};
|
||||
return (float4){
|
||||
.w = q.w,
|
||||
.x = -q.x,
|
||||
.y = -q.y,
|
||||
.z = -q.z,
|
||||
};
|
||||
}
|
||||
|
||||
// get the multiplicative inverse of the quaternion (conj / mag²)
|
||||
static inline float4 quat_inv(float4 q) {
|
||||
float mag2 = float4_mag2(q);
|
||||
if (mag2 == 0.0F) return (float4){0};
|
||||
mag2 = 1.0F / mag2;
|
||||
return float4_mul_s(quat_conj(q), mag2);
|
||||
float mag2 = float4_mag2(q);
|
||||
if (mag2 == 0.0F) return (float4){0};
|
||||
mag2 = 1.0F / mag2;
|
||||
return float4_mul_s(quat_conj(q), mag2);
|
||||
}
|
||||
|
||||
// rotates a vector by the quaternion (q must be a unit quaternion (normalized))
|
||||
static inline float3 quat_rot(float4 q, float3 v) {
|
||||
q = quat_mul(quat_mul(q, quat_from_float3(v)), quat_conj(q)); // q•v•q¯¹ (using conjugate for q⁻¹, as for unit quaternions this is the same as the multiplicative inverse)
|
||||
return (float3){q.x, q.y, q.z};
|
||||
q = quat_mul(quat_mul(q, quat_from_float3(v)), quat_conj(q)); // q•v•q¯¹ (using conjugate for q⁻¹, as for unit quaternions this is the same as the multiplicative inverse)
|
||||
return (float3){q.x, q.y, q.z};
|
||||
}
|
||||
|
||||
// rotates a vector by the quaternion, q may be non-normalized
|
||||
static inline float3 quat_rot_s(float4 q, float3 v) {
|
||||
q = quat_mul(quat_mul(q, quat_from_float3(v)), quat_inv(q)); // q•v•q¯¹
|
||||
return (float3){q.x, q.y, q.z};
|
||||
q = quat_mul(quat_mul(q, quat_from_float3(v)), quat_inv(q)); // q•v•q¯¹
|
||||
return (float3){q.x, q.y, q.z};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user