mirror of
https://github.com/thepigeongenerator/sdl_template.git
synced 2025-12-17 05:55:47 +01:00
replace spaces with tabs
This commit is contained in:
60
src/error.c
60
src/error.c
@@ -11,61 +11,61 @@
|
|||||||
// writes the arguments to the specified buffer
|
// writes the arguments to the specified buffer
|
||||||
// using a macro instead of an inline function because fmt otherwise gets horribly messed up
|
// using a macro instead of an inline function because fmt otherwise gets horribly messed up
|
||||||
#define write_args(buf, fmt) \
|
#define write_args(buf, fmt) \
|
||||||
va_list args; \
|
va_list args; \
|
||||||
va_start(args, fmt); \
|
va_start(args, fmt); \
|
||||||
(void)vsnprintf(buf, PRINT_BUFFER_SIZE, fmt, args); \
|
(void)vsnprintf(buf, PRINT_BUFFER_SIZE, fmt, args); \
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
static gamestatus status = STATUS_RUNNING;
|
static gamestatus status = STATUS_RUNNING;
|
||||||
|
|
||||||
void set_gamestatus(gamestatus nstatus) {
|
void set_gamestatus(gamestatus nstatus) {
|
||||||
status = nstatus;
|
status = nstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
gamestatus get_gamestatus(void) {
|
gamestatus get_gamestatus(void) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug(char const* fmt, ...) {
|
void debug(char const* fmt, ...) {
|
||||||
char const* env = getenv("DEBUG");
|
char const* env = getenv("DEBUG");
|
||||||
if (env == NULL || *env != '1')
|
if (env == NULL || *env != '1')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char buf[PRINT_BUFFER_SIZE] = {0};
|
char buf[PRINT_BUFFER_SIZE] = {0};
|
||||||
write_args(buf, fmt);
|
write_args(buf, fmt);
|
||||||
|
|
||||||
(void)fprintf(stdout, "\033[95m%s\033[0m\n", buf);
|
(void)fprintf(stdout, "\033[95m%s\033[0m\n", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void info(char const* fmt, ...) {
|
void info(char const* fmt, ...) {
|
||||||
char buf[PRINT_BUFFER_SIZE] = {0};
|
char buf[PRINT_BUFFER_SIZE] = {0};
|
||||||
write_args(buf, fmt);
|
write_args(buf, fmt);
|
||||||
(void)fprintf(stdout, "\033[0m%s\033[0m\n", buf); // write colour here for consistency
|
(void)fprintf(stdout, "\033[0m%s\033[0m\n", buf); // write colour here for consistency
|
||||||
}
|
}
|
||||||
|
|
||||||
void warn(char const* fmt, ...) {
|
void warn(char const* fmt, ...) {
|
||||||
char buf[PRINT_BUFFER_SIZE] = {0};
|
char buf[PRINT_BUFFER_SIZE] = {0};
|
||||||
write_args(buf, fmt);
|
write_args(buf, fmt);
|
||||||
(void)fprintf(stderr, "\033[93mW: %s\033[0m\n", buf);
|
(void)fprintf(stderr, "\033[93mW: %s\033[0m\n", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void error(char const* fmt, ...) {
|
void error(char const* fmt, ...) {
|
||||||
char buf[PRINT_BUFFER_SIZE] = {0};
|
char buf[PRINT_BUFFER_SIZE] = {0};
|
||||||
write_args(buf, fmt);
|
write_args(buf, fmt);
|
||||||
(void)fprintf(stderr, "\033[mW: %s\033[0m", buf);
|
(void)fprintf(stderr, "\033[mW: %s\033[0m", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn void fatal(gamestatus error_code, char const* fname, uint32_t ln, char const* fmt, ...) {
|
noreturn void fatal(gamestatus error_code, char const* fname, uint32_t ln, char const* fmt, ...) {
|
||||||
char buf1[PRINT_BUFFER_SIZE] = {0};
|
char buf1[PRINT_BUFFER_SIZE] = {0};
|
||||||
write_args(buf1, fmt);
|
write_args(buf1, fmt);
|
||||||
|
|
||||||
char buf2[PRINT_BUFFER_SIZE * 2] = {0};
|
char buf2[PRINT_BUFFER_SIZE * 2] = {0};
|
||||||
sprintf(buf2, "%s\n at %s:%u (exitcode: %u)", buf1, fname, ln, error_code);
|
sprintf(buf2, "%s\n at %s:%u (exitcode: %u)", buf1, fname, ln, error_code);
|
||||||
|
|
||||||
(void)fprintf(stderr, "\033[91mE: %s\033[0m\n", buf2);
|
(void)fprintf(stderr, "\033[91mE: %s\033[0m\n", buf2);
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "something went wrong! :O", buf2, NULL);
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "something went wrong! :O", buf2, NULL);
|
||||||
|
|
||||||
// set status, but exit immediately, as code is not allowed to execute beyond this point
|
// set status, but exit immediately, as code is not allowed to execute beyond this point
|
||||||
set_gamestatus(error_code);
|
set_gamestatus(error_code);
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* defines statuses in the 0..127, any higher/negative values are POSIX-reserved.
|
/* defines statuses in the 0..127, any higher/negative values are POSIX-reserved.
|
||||||
* The max value (or -1) shall mean the application is running, anything else shall mean an exit code of some kind */
|
* The max value (or -1) shall mean the application is running, anything else shall mean an exit code of some kind */
|
||||||
enum {
|
enum {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
STATUS_SUCCESS = 0, // 0; successful exit
|
STATUS_SUCCESS = 0, // 0; successful exit
|
||||||
STATUS_ERROR = 1, // miscellaneous error
|
STATUS_ERROR = 1, // miscellaneous error
|
||||||
ERROR_INIT = STATUS_ERROR | 2, // initialisation error
|
ERROR_INIT = STATUS_ERROR | 2, // initialisation error
|
||||||
@@ -24,7 +24,7 @@ enum {
|
|||||||
ERROR_SDL_AUDIO_INIT = ERROR_SDL_INIT | 8, // audio initialization error
|
ERROR_SDL_AUDIO_INIT = ERROR_SDL_INIT | 8, // audio initialization error
|
||||||
|
|
||||||
STATUS_RUNNING = -1,
|
STATUS_RUNNING = -1,
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
typedef int8_t gamestatus;
|
typedef int8_t gamestatus;
|
||||||
|
|
||||||
|
|||||||
@@ -10,19 +10,19 @@
|
|||||||
#include "gametime.h"
|
#include "gametime.h"
|
||||||
|
|
||||||
void game_init(gamedata* dat) {
|
void game_init(gamedata* dat) {
|
||||||
*dat = (gamedata){
|
*dat = (gamedata){
|
||||||
gametime_new(),
|
gametime_new(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_update(gamedata* dat) {
|
void game_update(gamedata* dat) {
|
||||||
gametime_update(&dat->time);
|
gametime_update(&dat->time);
|
||||||
uint8_t const* keys = SDL_GetKeyboardState(NULL);
|
uint8_t const* keys = SDL_GetKeyboardState(NULL);
|
||||||
|
|
||||||
if (keys[SDL_SCANCODE_ESCAPE])
|
if (keys[SDL_SCANCODE_ESCAPE])
|
||||||
set_gamestatus(STATUS_SUCCESS);
|
set_gamestatus(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_free(gamedata* dat) {
|
void game_free(gamedata* dat) {
|
||||||
*dat = (gamedata){0};
|
*dat = (gamedata){0};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#define TAUf (M_PIf * 2.0F) // τ constant as a 32-bit floating point
|
#define TAUf (M_PIf * 2.0F) // τ constant as a 32-bit floating point
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gametime time;
|
gametime time;
|
||||||
} gamedata;
|
} gamedata;
|
||||||
|
|
||||||
void game_init(gamedata*); // initializes everything needed to start the game; outputs to game_data
|
void game_init(gamedata*); // initializes everything needed to start the game; outputs to game_data
|
||||||
|
|||||||
@@ -3,35 +3,35 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct timespec ts; // stores the time at the current update
|
struct timespec ts; // stores the time at the current update
|
||||||
double sec; // stores the current time in seconds
|
double sec; // stores the current time in seconds
|
||||||
float scale; // multiplier for the time calculation, default value is 1.0
|
float scale; // multiplier for the time calculation, default value is 1.0
|
||||||
float delta; // the time that it took between updates
|
float delta; // the time that it took between updates
|
||||||
} gametime;
|
} gametime;
|
||||||
|
|
||||||
// initializes the gametime struct
|
// initializes the gametime struct
|
||||||
static inline gametime gametime_new(void) {
|
static inline gametime gametime_new(void) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
timespec_get(&ts, TIME_UTC);
|
timespec_get(&ts, TIME_UTC);
|
||||||
|
|
||||||
return (gametime){
|
return (gametime){
|
||||||
ts,
|
ts,
|
||||||
0.0,
|
0.0,
|
||||||
1.0F,
|
1.0F,
|
||||||
0.0F,
|
0.0F,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// updates the internal variables
|
// updates the internal variables
|
||||||
static inline void gametime_update(gametime* gt) {
|
static inline void gametime_update(gametime* gt) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
timespec_get(&ts, TIME_UTC);
|
timespec_get(&ts, TIME_UTC);
|
||||||
gt->sec = (double)ts.tv_nsec * 1e-9; // calculate the current time in seconds
|
gt->sec = (double)ts.tv_nsec * 1e-9; // calculate the current time in seconds
|
||||||
gt->delta = ((double)(ts.tv_nsec - gt->ts.tv_nsec) * 1e-9) * gt->scale; // calculate how much time has passed between this and last frame
|
gt->delta = ((double)(ts.tv_nsec - gt->ts.tv_nsec) * 1e-9) * gt->scale; // calculate how much time has passed between this and last frame
|
||||||
gt->ts = ts; // update the game's timespec
|
gt->ts = ts; // update the game's timespec
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets how many times the game updates per second
|
// gets how many times the game updates per second
|
||||||
static inline float gametime_get_ups(gametime* gt) {
|
static inline float gametime_get_ups(gametime* gt) {
|
||||||
return 1.0F / gt->delta;
|
return 1.0F / gt->delta;
|
||||||
}
|
}
|
||||||
|
|||||||
68
src/main.c
68
src/main.c
@@ -15,52 +15,52 @@ static renderdata rdat;
|
|||||||
|
|
||||||
// initialize the game
|
// initialize the game
|
||||||
static void init(void) {
|
static void init(void) {
|
||||||
// initialize SDL
|
// initialize SDL
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
|
||||||
fatal(ERROR_SDL_INIT, __FILE_NAME__, __LINE__, "SDL could not initialize! SDL Error: %s", SDL_GetError());
|
fatal(ERROR_SDL_INIT, __FILE_NAME__, __LINE__, "SDL could not initialize! SDL Error: %s", SDL_GetError());
|
||||||
|
|
||||||
// initialize other game components
|
// initialize other game components
|
||||||
gt = gametime_new();
|
gt = gametime_new();
|
||||||
game_init(&gdat);
|
game_init(&gdat);
|
||||||
render_init(&rdat, &gdat);
|
render_init(&rdat, &gdat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform the updates to the game
|
// perform the updates to the game
|
||||||
static void update(void) {
|
static void update(void) {
|
||||||
// update the input
|
// update the input
|
||||||
{
|
{
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
while (SDL_PollEvent(&e)) {
|
while (SDL_PollEvent(&e)) {
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
set_gamestatus(STATUS_SUCCESS);
|
set_gamestatus(STATUS_SUCCESS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform updates
|
// perform updates
|
||||||
gametime_update(>);
|
gametime_update(>);
|
||||||
game_update(&gdat);
|
game_update(&gdat);
|
||||||
render_update(&rdat);
|
render_update(&rdat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// entry-point of the application
|
// entry-point of the application
|
||||||
int32_t main(int32_t argc, char** argv) {
|
int32_t main(int32_t argc, char** argv) {
|
||||||
(void)argc, (void)argv;
|
(void)argc, (void)argv;
|
||||||
|
|
||||||
init();
|
init();
|
||||||
debug("successfully initialized!");
|
debug("successfully initialized!");
|
||||||
|
|
||||||
while (get_gamestatus() == STATUS_RUNNING)
|
while (get_gamestatus() == STATUS_RUNNING)
|
||||||
update();
|
update();
|
||||||
|
|
||||||
debug("done! starting to free resources...");
|
debug("done! starting to free resources...");
|
||||||
game_free(&gdat);
|
game_free(&gdat);
|
||||||
render_free(&rdat);
|
render_free(&rdat);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
gamestatus exit_code = get_gamestatus();
|
gamestatus exit_code = get_gamestatus();
|
||||||
debug("quitting with an exit code of %u", exit_code);
|
debug("quitting with an exit code of %u", exit_code);
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,143 +26,143 @@
|
|||||||
|
|
||||||
// define the dynamic array structure
|
// define the dynamic array structure
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DYNARR_TYPE* dat; // contains the data 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 count; // contains the amount of elements of the dynamic array
|
||||||
size_t cap; // contains the capacity of the dynamic array
|
size_t cap; // contains the capacity of the dynamic array
|
||||||
} DYNARR_NAME;
|
} DYNARR_NAME;
|
||||||
|
|
||||||
// cleans up the resources associated with the array, do not use after this step. This is undefined behaviour
|
// 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) {
|
DYNARR_LINKAGE void DYNARR_FUNC(free)(DYNARR_NAME* arr) {
|
||||||
free(arr->dat); // free(NULL) is allowed
|
free(arr->dat); // free(NULL) is allowed
|
||||||
*arr = (DYNARR_NAME){0}; // zero out all fields to re-initialize
|
*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
|
// sets the capacity exactly, does not respect capacity scaling use `resize` if capacity scaling must be respected
|
||||||
// returns 0 upon success, 1 upon failure
|
// returns 0 upon success, 1 upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize_exact)(DYNARR_NAME* arr, size_t ncap) {
|
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->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 == arr->cap) return 0; // the capacity is already the new capacity; no work needs to be done
|
||||||
if (ncap == 0) {
|
if (ncap == 0) {
|
||||||
DYNARR_FUNC(free)(arr);
|
DYNARR_FUNC(free)(arr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (re)allocate the memory for the array
|
// (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"
|
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 memory (re)allocation failed; return
|
||||||
if (nptr == NULL)
|
if (nptr == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
arr->dat = nptr;
|
arr->dat = nptr;
|
||||||
arr->cap = ncap;
|
arr->cap = ncap;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DYNARR_LINKAGE DYNARR_NAME DYNARR_FUNC(init)(void) {
|
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)
|
// 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
|
// returns 0 upon success, 1 upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize)(DYNARR_NAME* arr, size_t ncap) {
|
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->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 == arr->cap) return 0; // the current capacity has already been set to this
|
||||||
if (ncap == 0) {
|
if (ncap == 0) {
|
||||||
DYNARR_FUNC(free)(arr);
|
DYNARR_FUNC(free)(arr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert the capacity into a power of 2 by selecting the most significan bit
|
// convert the capacity into a power of 2 by selecting the most significan bit
|
||||||
ncap--; // first remove 1, to decrease the most significant 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
|
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 |= ncap >> i; // OR together the shifted result
|
||||||
ncap++; // finally, add one so 0111 -> 1000
|
ncap++; // finally, add one so 0111 -> 1000
|
||||||
|
|
||||||
// calculates what the new size should be by adding the amount of items to the count
|
// calculates what the new size should be by adding the amount of items to the count
|
||||||
// assumes scaling factor is 2
|
// assumes scaling factor is 2
|
||||||
return DYNARR_FUNC(resize_exact)(arr, ncap);
|
return DYNARR_FUNC(resize_exact)(arr, ncap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds an item to the dynamic array, doubles the capacity if the new count exceeds the maximum
|
// 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
|
// `dat` is not allowed to overlap with the selected range in the array
|
||||||
// returns non-zero upon failure
|
// 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) {
|
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 (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 (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 (datcount == 0) return 0; // the count is zero, nothing needs to be done
|
||||||
|
|
||||||
size_t orgcount = arr->count;
|
size_t orgcount = arr->count;
|
||||||
arr->count += datcount;
|
arr->count += datcount;
|
||||||
|
|
||||||
// resize the array if the new count has hit the capacity
|
// resize the array if the new count has hit the capacity
|
||||||
if (arr->cap <= arr->count) {
|
if (arr->cap <= arr->count) {
|
||||||
// resize the array to the new count using resize (count cannot be a zero-value at this point)
|
// 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))
|
if (DYNARR_FUNC(resize)(arr, arr->count))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// move the data stored at the current position if we must insert
|
// move the data stored at the current position if we must insert
|
||||||
if (idx < orgcount)
|
if (idx < orgcount)
|
||||||
memmove(&arr->dat[datcount + idx], &arr->dat[idx], (orgcount - idx) * sizeof(DYNARR_TYPE));
|
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)
|
memcpy(&arr->dat[idx], dat, datcount * sizeof(DYNARR_TYPE)); // copy the original data to the index (do not overlap)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds an item to the dynamic array, doubles the capacity if the new count exceeds the maximum
|
// adds an item to the dynamic array, doubles the capacity if the new count exceeds the maximum
|
||||||
// returns 0 upon success, 1 upon failure
|
// returns 0 upon success, 1 upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(add)(DYNARR_NAME* arr, DYNARR_TYPE item) {
|
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)
|
// 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) {
|
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
|
if (arr->cap == arr->count) return 0; // return success if no work needs to be done
|
||||||
return DYNARR_FUNC(resize_exact)(arr, arr->count);
|
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
|
// 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
|
// returns non-zero value upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove_bulk_noshrink)(DYNARR_NAME* arr, size_t sidx, size_t eidx) {
|
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 == 0) return 0; // no work needs to be done
|
||||||
if (arr->count <= sidx) return 1; // start index is out of bounds
|
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 (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 (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
|
_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
|
arr->count -= eidx - sidx + 1; // should always be less than or equal to count
|
||||||
|
|
||||||
if (move)
|
if (move)
|
||||||
memmove(&arr->dat[sidx], &arr->dat[eidx + 1], arr->count - sidx);
|
memmove(&arr->dat[sidx], &arr->dat[eidx + 1], arr->count - sidx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes a block of indices from sidx..eidx (inclusive)
|
// 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
|
// 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
|
// returns non-zero value upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove_bulk)(DYNARR_NAME* arr, size_t sidx, size_t eidx) {
|
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))
|
if (DYNARR_FUNC(remove_bulk_noshrink)(arr, sidx, eidx))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// shrink the array when the new size is a quarter of the original size
|
// shrink the array when the new size is a quarter of the original size
|
||||||
if (arr->count < arr->cap / 4)
|
if (arr->count < arr->cap / 4)
|
||||||
return DYNARR_FUNC(shrink)(arr);
|
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
|
// 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
|
// returns non-zero value upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove_noshrink)(DYNARR_NAME* arr, size_t idx) {
|
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
|
// 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
|
// 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
|
// returns non-zero value upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove)(DYNARR_NAME* arr, size_t idx) {
|
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
|
// 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
|
// stores a 2D point using a floating-point number
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
} float2;
|
} float2;
|
||||||
|
|
||||||
// adds one float2 to another
|
// adds one float2 to another
|
||||||
static inline float2 float2_add(float2 v1, float2 v2) {
|
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
|
// subtracts one float2 from another
|
||||||
static inline float2 float2_sub(float2 v1, float2 v2) {
|
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
|
// multiplies one float2 by another
|
||||||
static inline float2 float2_mul(float2 v1, float2 v2) {
|
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
|
// divides one float2 by another
|
||||||
static inline float2 float2_div(float2 v1, float2 v2) {
|
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)
|
// preforms a scalar multiplication upon the float2 (multiplies the float2 by some value)
|
||||||
static inline float2 float2_mul_s(float2 v, float n) {
|
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)
|
// preforms a scalar division upon the float2 (divides the float2 by some value)
|
||||||
static inline float2 float2_div_s(float2 v, float n) {
|
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)
|
// negates the float2 (-v)
|
||||||
static inline float2 float2_neg(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
|
// gets the squared magnitude/length of float2
|
||||||
static inline float float2_mag2(float2 v) {
|
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)
|
// gets the length of float2 (length)
|
||||||
static inline float float2_mag(float2 v) {
|
static inline float float2_mag(float2 v) {
|
||||||
return sqrtf(float2_mag2(v));
|
return sqrtf(float2_mag2(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalizes the float2
|
// normalizes the float2
|
||||||
static inline float2 float2_norm(float2 v) {
|
static inline float2 float2_norm(float2 v) {
|
||||||
float s = 1.0F / float2_mag(v); // get the scaling factor
|
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)
|
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
|
// gets the dot product of two float2s
|
||||||
static inline float float2_dot(float2 v1, float2 v2) {
|
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
|
// stores a 3D point using a floating-point number
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
} float3;
|
} float3;
|
||||||
|
|
||||||
// adds one float3 to another
|
// adds one float3 to another
|
||||||
static inline float3 float3_add(float3 v1, float3 v2) {
|
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
|
// subtracts one float3 from another
|
||||||
static inline float3 float3_sub(float3 v1, float3 v2) {
|
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
|
// multiplies one float3 by another
|
||||||
static inline float3 float3_mul(float3 v1, float3 v2) {
|
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
|
// divides one float3 by another
|
||||||
static inline float3 float3_div(float3 v1, float3 v2) {
|
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)
|
// preforms a scalar multiplication upon the float3 (multiplies the float3 by some value)
|
||||||
static inline float3 float3_mul_s(float3 v, float n) {
|
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)
|
// preforms a scalar division upon the float3 (divides the float3 by some value)
|
||||||
static inline float3 float3_div_s(float3 v, float n) {
|
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) {
|
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
|
// gets the squared magnitude/length of float3
|
||||||
static inline float float3_mag2(float3 v) {
|
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)
|
// gets the length of float3 (length)
|
||||||
static inline float float3_mag(float3 v) {
|
static inline float float3_mag(float3 v) {
|
||||||
return sqrtf(float3_mag2(v));
|
return sqrtf(float3_mag2(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalizes the float3
|
// normalizes the float3
|
||||||
static inline float3 float3_norm(float3 v) {
|
static inline float3 float3_norm(float3 v) {
|
||||||
float s = 1.0F / float3_mag(v); // get the scaling factor
|
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)
|
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
|
// gets the dot product of two float3s
|
||||||
static inline float float3_dot(float3 v1, float3 v2) {
|
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
|
// stores a 3D point using a floating-point number
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
float z;
|
float z;
|
||||||
float w;
|
float w;
|
||||||
} float4;
|
} float4;
|
||||||
|
|
||||||
// adds one float4 to another
|
// adds one float4 to another
|
||||||
static inline float4 float4_add(float4 v1, float4 v2) {
|
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
|
// subtracts one float4 from another
|
||||||
static inline float4 float4_sub(float4 v1, float4 v2) {
|
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
|
// multiplies one float4 by another
|
||||||
static inline float4 float4_mul(float4 v1, float4 v2) {
|
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
|
// divides one float4 by another
|
||||||
static inline float4 float4_div(float4 v1, float4 v2) {
|
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)
|
// preforms a scalar multiplication upon the float4 (multiplies the float4 by some value)
|
||||||
static inline float4 float4_mul_s(float4 v, float n) {
|
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)
|
// preforms a scalar division upon the float4 (divides the float4 by some value)
|
||||||
static inline float4 float4_div_s(float4 v, float n) {
|
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) {
|
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
|
// gets the squared magnitude/length of float4
|
||||||
static inline float float4_mag2(float4 v) {
|
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)
|
// gets the length of float4 (length)
|
||||||
static inline float float4_mag(float4 v) {
|
static inline float float4_mag(float4 v) {
|
||||||
return sqrtf(float4_mag2(v));
|
return sqrtf(float4_mag2(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalizes the float4
|
// normalizes the float4
|
||||||
static inline float4 float4_norm(float4 v) {
|
static inline float4 float4_norm(float4 v) {
|
||||||
float s = 1.0F / float4_mag(v); // get the scaling factor
|
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)
|
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
|
// gets the dot product of two float4s
|
||||||
static inline float float4_dot(float4 v1, float4 v2) {
|
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
|
// converts a float3 to a quaternion
|
||||||
static inline float4 quat_from_float3(float3 v) {
|
static inline float4 quat_from_float3(float3 v) {
|
||||||
return (float4){
|
return (float4){
|
||||||
.w = 0.0F,
|
.w = 0.0F,
|
||||||
.x = v.x,
|
.x = v.x,
|
||||||
.y = v.y,
|
.y = v.y,
|
||||||
.z = v.z,
|
.z = v.z,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// converts euler angles into quaternion (ordered roll, pitch, yaw) (in radians)
|
// converts euler angles into quaternion (ordered roll, pitch, yaw) (in radians)
|
||||||
static inline float4 quat_from_euler(float3 euler) {
|
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
|
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 cx = cosf(euler.x), sx = sinf(euler.x);
|
||||||
float cy = cosf(euler.y), sy = sinf(euler.y);
|
float cy = cosf(euler.y), sy = sinf(euler.y);
|
||||||
float cz = cosf(euler.z), sz = sinf(euler.z);
|
float cz = cosf(euler.z), sz = sinf(euler.z);
|
||||||
|
|
||||||
return (float4){
|
return (float4){
|
||||||
.w = cx * cy * cz - sx * sy * sz,
|
.w = cx * cy * cz - sx * sy * sz,
|
||||||
.x = sx * cy * cz + cx * sy * sz,
|
.x = sx * cy * cz + cx * sy * sz,
|
||||||
.y = cx * sy * cz - sx * cy * sz,
|
.y = cx * sy * cz - sx * cy * sz,
|
||||||
.z = cx * cy * sz + sx * sy * cz,
|
.z = cx * cy * sz + sx * sy * cz,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// converts quaternion into euler angles (ordered as roll, pitch, yaw)
|
// converts quaternion into euler angles (ordered as roll, pitch, yaw)
|
||||||
static inline float3 quat_to_euler(float4 q) {
|
static inline float3 quat_to_euler(float4 q) {
|
||||||
// warn: do not read from these variables until set
|
// warn: do not read from these variables until set
|
||||||
float3 euler;
|
float3 euler;
|
||||||
float a, b;
|
float a, b;
|
||||||
|
|
||||||
// compute the roll (Φ)
|
// compute the roll (Φ)
|
||||||
a = 2 * (q.w * q.x + q.y * q.z); // sin(r)•cos(p)
|
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)
|
b = 1 - 2 * (q.x * q.x + q.y * q.y); // cos(r)•cos(p)
|
||||||
euler.x = atan2f(a, b);
|
euler.x = atan2f(a, b);
|
||||||
|
|
||||||
// compute the pitch (θ)
|
// compute the pitch (θ)
|
||||||
a = 2 * (q.w * q.y - q.z * q.x);
|
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)
|
euler.y = fabsf(a) >= 1 ? copysignf(M_PI_2, a) : asinf(a); // if |a| >=1, sgn(a)•(π/2), else asin(a)
|
||||||
|
|
||||||
// compute the yaw (ψ)
|
// compute the yaw (ψ)
|
||||||
a = 2 * (q.w * q.z + q.x * q.y); // sin(y)•cos(y)
|
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)
|
b = 1 - 2 * (q.y * q.y + q.z * q.z); // cos(y)•cos(y)
|
||||||
euler.z = atan2f(a, b);
|
euler.z = atan2f(a, b);
|
||||||
|
|
||||||
// return the final angles
|
// return the final angles
|
||||||
return euler;
|
return euler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiplies two quaternions
|
// multiplies two quaternions
|
||||||
static inline float4 quat_mul(float4 q1, float4 q2) {
|
static inline float4 quat_mul(float4 q1, float4 q2) {
|
||||||
return (float4){
|
return (float4){
|
||||||
.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z,
|
.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,
|
.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,
|
.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,
|
.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)
|
// get the conjugate of the quaternion (negates the vector portion)
|
||||||
static inline float4 quat_conj(float4 q) {
|
static inline float4 quat_conj(float4 q) {
|
||||||
return (float4){
|
return (float4){
|
||||||
.w = q.w,
|
.w = q.w,
|
||||||
.x = -q.x,
|
.x = -q.x,
|
||||||
.y = -q.y,
|
.y = -q.y,
|
||||||
.z = -q.z,
|
.z = -q.z,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the multiplicative inverse of the quaternion (conj / mag²)
|
// get the multiplicative inverse of the quaternion (conj / mag²)
|
||||||
static inline float4 quat_inv(float4 q) {
|
static inline float4 quat_inv(float4 q) {
|
||||||
float mag2 = float4_mag2(q);
|
float mag2 = float4_mag2(q);
|
||||||
if (mag2 == 0.0F) return (float4){0};
|
if (mag2 == 0.0F) return (float4){0};
|
||||||
mag2 = 1.0F / mag2;
|
mag2 = 1.0F / mag2;
|
||||||
return float4_mul_s(quat_conj(q), mag2);
|
return float4_mul_s(quat_conj(q), mag2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotates a vector by the quaternion (q must be a unit quaternion (normalized))
|
// rotates a vector by the quaternion (q must be a unit quaternion (normalized))
|
||||||
static inline float3 quat_rot(float4 q, float3 v) {
|
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)
|
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};
|
return (float3){q.x, q.y, q.z};
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotates a vector by the quaternion, q may be non-normalized
|
// rotates a vector by the quaternion, q may be non-normalized
|
||||||
static inline float3 quat_rot_s(float4 q, float3 v) {
|
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¯¹
|
q = quat_mul(quat_mul(q, quat_from_float3(v)), quat_inv(q)); // q•v•q¯¹
|
||||||
return (float3){q.x, q.y, q.z};
|
return (float3){q.x, q.y, q.z};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,171 +20,171 @@
|
|||||||
#include "../error.h"
|
#include "../error.h"
|
||||||
|
|
||||||
static void audiomixer(void* const userdata, uint8_t* const stream, int32_t const len) {
|
static void audiomixer(void* const userdata, uint8_t* const stream, int32_t const len) {
|
||||||
memset(stream, 0, len); // clear the playing audio
|
memset(stream, 0, len); // clear the playing audio
|
||||||
audiodevice* const dev = userdata; // retreive the callback data
|
audiodevice* const dev = userdata; // retreive the callback data
|
||||||
|
|
||||||
// return if dev is null, since it can fail to initialize
|
// return if dev is null, since it can fail to initialize
|
||||||
if (dev == NULL) return;
|
if (dev == NULL) return;
|
||||||
|
|
||||||
struct audioplayer* prev = NULL;
|
struct audioplayer* prev = NULL;
|
||||||
struct audioplayer* curr = dev->audio_players;
|
struct audioplayer* curr = dev->audio_players;
|
||||||
while (curr != NULL) {
|
while (curr != NULL) {
|
||||||
// if the current audio fragment has reached the end of their data
|
// if the current audio fragment has reached the end of their data
|
||||||
if (curr->len == 0) {
|
if (curr->len == 0) {
|
||||||
struct audioplayer* ncurr = curr->nxt;
|
struct audioplayer* ncurr = curr->nxt;
|
||||||
|
|
||||||
// free the memory allocated to it and assign the next to to the currently playing
|
// free the memory allocated to it and assign the next to to the currently playing
|
||||||
free(curr);
|
free(curr);
|
||||||
curr = ncurr;
|
curr = ncurr;
|
||||||
|
|
||||||
// write to the audio device if prev hasn't been set yet
|
// write to the audio device if prev hasn't been set yet
|
||||||
if (prev == NULL)
|
if (prev == NULL)
|
||||||
dev->audio_players = curr;
|
dev->audio_players = curr;
|
||||||
else
|
else
|
||||||
prev->nxt = curr;
|
prev->nxt = curr;
|
||||||
|
|
||||||
// continue so if curr is now NULL, the loop stops
|
// continue so if curr is now NULL, the loop stops
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate how much of the current audio player we should mix into the stream
|
// calculate how much of the current audio player we should mix into the stream
|
||||||
uint32_t const mixlen = SDL_min(curr->len, (uint32_t)len);
|
uint32_t const mixlen = SDL_min(curr->len, (uint32_t)len);
|
||||||
|
|
||||||
// mix the current buffer into the stream, and update the audio player values accordingly
|
// mix the current buffer into the stream, and update the audio player values accordingly
|
||||||
SDL_MixAudioFormat(stream, curr->buf, dev->fmt, mixlen, SDL_MIX_MAXVOLUME);
|
SDL_MixAudioFormat(stream, curr->buf, dev->fmt, mixlen, SDL_MIX_MAXVOLUME);
|
||||||
curr->buf += mixlen;
|
curr->buf += mixlen;
|
||||||
curr->len -= mixlen;
|
curr->len -= mixlen;
|
||||||
|
|
||||||
// increment the current node
|
// increment the current node
|
||||||
prev = curr;
|
prev = curr;
|
||||||
curr = curr->nxt;
|
curr = curr->nxt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int8_t audio_cvt(audiodevice const* dev, SDL_AudioSpec const* spec, uint8_t** bufptr, uint32_t* len) {
|
static int8_t audio_cvt(audiodevice const* dev, SDL_AudioSpec const* spec, uint8_t** bufptr, uint32_t* len) {
|
||||||
// init the converter
|
// init the converter
|
||||||
SDL_AudioCVT cvt;
|
SDL_AudioCVT cvt;
|
||||||
SDL_BuildAudioCVT(&cvt, spec->format, spec->channels, spec->freq, dev->fmt, dev->channels, dev->freq);
|
SDL_BuildAudioCVT(&cvt, spec->format, spec->channels, spec->freq, dev->fmt, dev->channels, dev->freq);
|
||||||
cvt.len = (*len) * spec->channels; // calculate the size of the source data in bytes by multiplying the length by the amount of channels (warn: uint32_t -> int32_t)
|
cvt.len = (*len) * spec->channels; // calculate the size of the source data in bytes by multiplying the length by the amount of channels (warn: uint32_t -> int32_t)
|
||||||
cvt.buf = realloc(*bufptr, cvt.len * cvt.len_mult); // grow the inputted buffer for the conversion
|
cvt.buf = realloc(*bufptr, cvt.len * cvt.len_mult); // grow the inputted buffer for the conversion
|
||||||
|
|
||||||
// ensure the conversion buffer reallocation goes correctly
|
// ensure the conversion buffer reallocation goes correctly
|
||||||
if (cvt.buf == NULL) {
|
if (cvt.buf == NULL) {
|
||||||
error("%s:%u something went wrong whilst growing the audio buffer whilst converting!", __FILE_NAME__, __LINE__);
|
error("%s:%u something went wrong whilst growing the audio buffer whilst converting!", __FILE_NAME__, __LINE__);
|
||||||
free(*bufptr);
|
free(*bufptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// converts the audio to the new format
|
// converts the audio to the new format
|
||||||
if (!SDL_ConvertAudio(&cvt)) {
|
if (!SDL_ConvertAudio(&cvt)) {
|
||||||
error("something went wrong when loading/converting an audio buffer! SDL Error: %s", SDL_GetError());
|
error("something went wrong when loading/converting an audio buffer! SDL Error: %s", SDL_GetError());
|
||||||
free(cvt.buf);
|
free(cvt.buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*len = cvt.len;
|
*len = cvt.len;
|
||||||
|
|
||||||
*bufptr = realloc(cvt.buf, cvt.len_cvt);
|
*bufptr = realloc(cvt.buf, cvt.len_cvt);
|
||||||
if (*bufptr == NULL) {
|
if (*bufptr == NULL) {
|
||||||
warn("%s:%u something went wrong whilst shrinking the audio buffer whilst converting!", __FILE_NAME__, __LINE__);
|
warn("%s:%u something went wrong whilst shrinking the audio buffer whilst converting!", __FILE_NAME__, __LINE__);
|
||||||
*bufptr = cvt.buf; // use the conversion buffer, as this one will be valid if realloc fails
|
*bufptr = cvt.buf; // use the conversion buffer, as this one will be valid if realloc fails
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
audiodevice* audio_device_init(int32_t freq, SDL_AudioFormat fmt, uint8_t channels, uint16_t samples) {
|
audiodevice* audio_device_init(int32_t freq, SDL_AudioFormat fmt, uint8_t channels, uint16_t samples) {
|
||||||
audiodevice* dev = malloc(sizeof(audiodevice));
|
audiodevice* dev = malloc(sizeof(audiodevice));
|
||||||
|
|
||||||
if (dev == NULL) {
|
if (dev == NULL) {
|
||||||
error("%s:%u null pointer when allocating memory for the audio device!", __FILE_NAME__, __LINE__);
|
error("%s:%u null pointer when allocating memory for the audio device!", __FILE_NAME__, __LINE__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// define the audio specification
|
// define the audio specification
|
||||||
SDL_AudioSpec spec = {freq, fmt, channels, 0, samples, 0, 0, NULL, NULL};
|
SDL_AudioSpec spec = {freq, fmt, channels, 0, samples, 0, 0, NULL, NULL};
|
||||||
spec.callback = audiomixer;
|
spec.callback = audiomixer;
|
||||||
spec.userdata = dev;
|
spec.userdata = dev;
|
||||||
|
|
||||||
// create the audio device
|
// create the audio device
|
||||||
*dev = (audiodevice){
|
*dev = (audiodevice){
|
||||||
NULL,
|
NULL,
|
||||||
SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0),
|
SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0),
|
||||||
freq,
|
freq,
|
||||||
fmt,
|
fmt,
|
||||||
channels,
|
channels,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (dev->id < 1) {
|
if (dev->id < 1) {
|
||||||
error("%s:%u audio device failed to open! SDL Error: %s", __FILE_NAME__, __LINE__, SDL_GetError());
|
error("%s:%u audio device failed to open! SDL Error: %s", __FILE_NAME__, __LINE__, SDL_GetError());
|
||||||
free(dev);
|
free(dev);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// default state of the device is paused, so we unpause it here
|
// default state of the device is paused, so we unpause it here
|
||||||
SDL_PauseAudioDevice(dev->id, 0);
|
SDL_PauseAudioDevice(dev->id, 0);
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_play(audiodevice* dev, audiodata const* audio) {
|
void audio_play(audiodevice* dev, audiodata const* audio) {
|
||||||
if (dev == NULL) return; // dev might fail to initialize
|
if (dev == NULL) return; // dev might fail to initialize
|
||||||
if (audio->len == 0) return; // audio might fail to initialize
|
if (audio->len == 0) return; // audio might fail to initialize
|
||||||
|
|
||||||
// create an audio player
|
// create an audio player
|
||||||
struct audioplayer* player = malloc(sizeof(struct audioplayer));
|
struct audioplayer* player = malloc(sizeof(struct audioplayer));
|
||||||
*player = (struct audioplayer){
|
*player = (struct audioplayer){
|
||||||
dev->audio_players, // set nxt to the first item in dev (can be NULL, this is fine)
|
dev->audio_players, // set nxt to the first item in dev (can be NULL, this is fine)
|
||||||
audio->buf,
|
audio->buf,
|
||||||
audio->len,
|
audio->len,
|
||||||
};
|
};
|
||||||
|
|
||||||
// assign ourselves to the first item
|
// assign ourselves to the first item
|
||||||
dev->audio_players = player;
|
dev->audio_players = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_device_free(audiodevice* dev) {
|
void audio_device_free(audiodevice* dev) {
|
||||||
if (dev == NULL) return;
|
if (dev == NULL) return;
|
||||||
SDL_CloseAudioDevice(dev->id);
|
SDL_CloseAudioDevice(dev->id);
|
||||||
|
|
||||||
struct audioplayer* curr = dev->audio_players;
|
struct audioplayer* curr = dev->audio_players;
|
||||||
|
|
||||||
// free all audio players
|
// free all audio players
|
||||||
while (curr != NULL) {
|
while (curr != NULL) {
|
||||||
dev->audio_players = curr->nxt; // use audio_players in dev as a cache
|
dev->audio_players = curr->nxt; // use audio_players in dev as a cache
|
||||||
free(curr);
|
free(curr);
|
||||||
curr = dev->audio_players;
|
curr = dev->audio_players;
|
||||||
}
|
}
|
||||||
|
|
||||||
// free the audio device itself
|
// free the audio device itself
|
||||||
free(dev);
|
free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
audiodata audio_wav_load(audiodevice const* dev, char const* fpath) {
|
audiodata audio_wav_load(audiodevice const* dev, char const* fpath) {
|
||||||
if (dev == NULL) return (audiodata){0};
|
if (dev == NULL) return (audiodata){0};
|
||||||
SDL_AudioSpec spec;
|
SDL_AudioSpec spec;
|
||||||
audiodata audio;
|
audiodata audio;
|
||||||
|
|
||||||
debug("loading audio file '%s'...", fpath);
|
debug("loading audio file '%s'...", fpath);
|
||||||
|
|
||||||
if (!fexists(fpath)) {
|
if (!fexists(fpath)) {
|
||||||
error("%s:%u couldn't find audio file '%s'!", __FILE_NAME__, __LINE__, fpath);
|
error("%s:%u couldn't find audio file '%s'!", __FILE_NAME__, __LINE__, fpath);
|
||||||
return (audiodata){0};
|
return (audiodata){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// load and parse the audio to the correct format
|
// load and parse the audio to the correct format
|
||||||
SDL_LoadWAV(fpath, &spec, &audio.buf, &audio.len);
|
SDL_LoadWAV(fpath, &spec, &audio.buf, &audio.len);
|
||||||
if (!!audio_cvt(dev, &spec, &audio.buf, &audio.len)) {
|
if (!!audio_cvt(dev, &spec, &audio.buf, &audio.len)) {
|
||||||
free(audio.buf);
|
free(audio.buf);
|
||||||
return (audiodata){0};
|
return (audiodata){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the time in miliseconds of the audio fragment
|
// calculate the time in miliseconds of the audio fragment
|
||||||
audio.ms = 1000 * (((audio.len) / (SDL_AUDIO_BITSIZE(dev->fmt) / 8)) / spec.channels / dev->freq);
|
audio.ms = 1000 * (((audio.len) / (SDL_AUDIO_BITSIZE(dev->fmt) / 8)) / spec.channels / dev->freq);
|
||||||
|
|
||||||
return audio;
|
return audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_wav_unload(audiodata* audio) {
|
void audio_wav_unload(audiodata* audio) {
|
||||||
free(audio->buf);
|
free(audio->buf);
|
||||||
*audio = (audiodata){0}; // zero out all audio data
|
*audio = (audiodata){0}; // zero out all audio data
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,24 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct audiodata {
|
struct audiodata {
|
||||||
uint8_t* buf; // pointer to the audio buffer
|
uint8_t* buf; // pointer to the audio buffer
|
||||||
uint32_t len; // length in bytes of the audio buffer
|
uint32_t len; // length in bytes of the audio buffer
|
||||||
uint32_t ms; // length in miliseconds of the audio buffer
|
uint32_t ms; // length in miliseconds of the audio buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
// contains the data of the audio fragments to be played
|
// contains the data of the audio fragments to be played
|
||||||
struct audioplayer {
|
struct audioplayer {
|
||||||
struct audioplayer* nxt; // pointer to the next audioplayer (may be null)
|
struct audioplayer* nxt; // pointer to the next audioplayer (may be null)
|
||||||
uint8_t* buf; // pointer to the current item in the buffer to be played
|
uint8_t* buf; // pointer to the current item in the buffer to be played
|
||||||
uint32_t len; // the length in bytes that the buffer has remaining
|
uint32_t len; // the length in bytes that the buffer has remaining
|
||||||
};
|
};
|
||||||
|
|
||||||
struct audiodevice {
|
struct audiodevice {
|
||||||
struct audioplayer* audio_players;
|
struct audioplayer* audio_players;
|
||||||
SDL_AudioDeviceID id;
|
SDL_AudioDeviceID id;
|
||||||
int32_t freq;
|
int32_t freq;
|
||||||
SDL_AudioFormat fmt;
|
SDL_AudioFormat fmt;
|
||||||
uint8_t channels;
|
uint8_t channels;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct audiodata audiodata;
|
typedef struct audiodata audiodata;
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
// stores colour in a rgba format, each channel being a 8 bits wide.
|
// stores colour in a rgba format, each channel being a 8 bits wide.
|
||||||
typedef union {
|
typedef union {
|
||||||
uint32_t packed;
|
uint32_t packed;
|
||||||
struct {
|
struct {
|
||||||
uint8_t a;
|
uint8_t a;
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
uint8_t g;
|
uint8_t g;
|
||||||
uint8_t r;
|
uint8_t r;
|
||||||
};
|
};
|
||||||
} colour32;
|
} colour32;
|
||||||
|
|
||||||
#define COLOUR32_BLACK ((colour32){0x000000FF})
|
#define COLOUR32_BLACK ((colour32){0x000000FF})
|
||||||
@@ -26,7 +26,7 @@ typedef union {
|
|||||||
|
|
||||||
// sets the render colour to a colour32 value
|
// sets the render colour to a colour32 value
|
||||||
static inline void set_colour32(SDL_Renderer* const renderer, colour32 const c) {
|
static inline void set_colour32(SDL_Renderer* const renderer, colour32 const c) {
|
||||||
(void)SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a);
|
(void)SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// american macros:
|
// american macros:
|
||||||
|
|||||||
@@ -19,22 +19,22 @@ typedef uint8_t colour8;
|
|||||||
|
|
||||||
// gets the red channel in 32 bit colour space
|
// gets the red channel in 32 bit colour space
|
||||||
static inline uint8_t colour8_red32(colour8 const colour) {
|
static inline uint8_t colour8_red32(colour8 const colour) {
|
||||||
return (colour >> 5) * (255 / 7);
|
return (colour >> 5) * (255 / 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the green channel in 32 bit colour space
|
// gets the green channel in 32 bit colour space
|
||||||
static inline uint8_t colour8_green32(colour8 const colour) {
|
static inline uint8_t colour8_green32(colour8 const colour) {
|
||||||
return ((colour >> 2) & 7) * (255 / 7);
|
return ((colour >> 2) & 7) * (255 / 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the blue channel in 32 bit colour space
|
// gets the blue channel in 32 bit colour space
|
||||||
static inline uint8_t colour8_blue32(colour8 const colour) {
|
static inline uint8_t colour8_blue32(colour8 const colour) {
|
||||||
return (colour & 3) * (255 / 3);
|
return (colour & 3) * (255 / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the render colour to a colour8 value
|
// sets the render colour to a colour8 value
|
||||||
static inline void set_colour8(SDL_Renderer* const renderer, colour8 const c) {
|
static inline void set_colour8(SDL_Renderer* const renderer, colour8 const c) {
|
||||||
(void)SDL_SetRenderDrawColor(renderer, colour8_red32(c), colour8_green32(c), colour8_blue32(c), 0xFF);
|
(void)SDL_SetRenderDrawColor(renderer, colour8_red32(c), colour8_green32(c), colour8_blue32(c), 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// american macros:
|
// american macros:
|
||||||
|
|||||||
@@ -12,32 +12,32 @@
|
|||||||
#include "colour/colour32.h"
|
#include "colour/colour32.h"
|
||||||
|
|
||||||
void render_init(renderdata* const rdat, gamedata const* const gdat) {
|
void render_init(renderdata* const rdat, gamedata const* const gdat) {
|
||||||
SDL_Window* const window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 500, 500, SDL_WINDOW_SHOWN);
|
SDL_Window* const window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 500, 500, SDL_WINDOW_SHOWN);
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
fatal(ERROR_SDL_RENDERING_INIT, __FILE_NAME__, __LINE__, "failed to create a window. SDL Error: %s", SDL_GetError());
|
fatal(ERROR_SDL_RENDERING_INIT, __FILE_NAME__, __LINE__, "failed to create a window. SDL Error: %s", SDL_GetError());
|
||||||
|
|
||||||
// render using vsync to limit updates to the refresh rate of the monitor
|
// render using vsync to limit updates to the refresh rate of the monitor
|
||||||
SDL_Renderer* const renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
|
SDL_Renderer* const renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
|
||||||
if (renderer == NULL)
|
if (renderer == NULL)
|
||||||
fatal(ERROR_SDL_RENDERING_INIT, __FILE_NAME__, __LINE__, "failed to create a renderer. SDL Error: %s", SDL_GetError());
|
fatal(ERROR_SDL_RENDERING_INIT, __FILE_NAME__, __LINE__, "failed to create a renderer. SDL Error: %s", SDL_GetError());
|
||||||
|
|
||||||
*rdat = (renderdata){
|
*rdat = (renderdata){
|
||||||
window,
|
window,
|
||||||
renderer,
|
renderer,
|
||||||
gdat,
|
gdat,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_update(renderdata const* const rdat) {
|
void render_update(renderdata const* const rdat) {
|
||||||
set_colour32(rdat->renderer, COLOUR32_BLACK);
|
set_colour32(rdat->renderer, COLOUR32_BLACK);
|
||||||
SDL_RenderClear(rdat->renderer);
|
SDL_RenderClear(rdat->renderer);
|
||||||
|
|
||||||
// present the renderer
|
// present the renderer
|
||||||
SDL_RenderPresent(rdat->renderer);
|
SDL_RenderPresent(rdat->renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_free(renderdata* const rdat) {
|
void render_free(renderdata* const rdat) {
|
||||||
SDL_DestroyRenderer(rdat->renderer);
|
SDL_DestroyRenderer(rdat->renderer);
|
||||||
SDL_DestroyWindow(rdat->window);
|
SDL_DestroyWindow(rdat->window);
|
||||||
*rdat = (renderdata){0};
|
*rdat = (renderdata){0};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
// contains the data necessary for rendering
|
// contains the data necessary for rendering
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
SDL_Renderer* renderer;
|
SDL_Renderer* renderer;
|
||||||
gamedata const* gdat;
|
gamedata const* gdat;
|
||||||
} renderdata;
|
} renderdata;
|
||||||
|
|
||||||
void render_init(renderdata*, gamedata const*); // initializes the renderer, outputs to render_data
|
void render_init(renderdata*, gamedata const*); // initializes the renderer, outputs to render_data
|
||||||
|
|||||||
Reference in New Issue
Block a user