From c4e4ff058719d5e8ae61d7d0fdf97dae3240b40c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Wed, 14 Sep 2022 08:02:35 +0000 Subject: [PATCH] update tracker pos conditionally + optimisations --- code/game/src/debug_ui_actions.c | 6 + code/game/src/entity.c | 3 +- code/game/src/items.c | 4 +- code/game/src/packets/pkt_00_init.c | 4 +- code/game/src/world/worldgen/worldgen_test.c | 12 +- code/modules/modules/systems.c | 19 +- code/modules/source/system_items.c | 9 +- code/modules/source/system_vehicle.c | 4 +- code/vendors/librg.h | 1851 +++++++++--------- 9 files changed, 961 insertions(+), 951 deletions(-) diff --git a/code/game/src/debug_ui_actions.c b/code/game/src/debug_ui_actions.c index 88fa8a1..8bb9dd9 100644 --- a/code/game/src/debug_ui_actions.c +++ b/code/game/src/debug_ui_actions.c @@ -16,6 +16,7 @@ ActSpawnCar(void) { Position const* origin = ecs_get(world_ecs(), plr, Position); Position * dest = ecs_get_mut(world_ecs(), e, Position); *dest = *origin; + entity_set_position(e, dest->x, dest->y); debug_replay_special_action(RPKIND_SPAWN_CAR); } @@ -28,6 +29,7 @@ ActSpawnIcemaker(void) { Position const* origin = ecs_get(world_ecs(), plr, Position); Position * dest = ecs_get_mut(world_ecs(), e, Position); *dest = *origin; + entity_set_position(e, dest->x, dest->y); debug_replay_special_action(RPKIND_SPAWN_ICEMAKER_ITEM); } @@ -40,6 +42,7 @@ ActSpawnChest(void) { Position const* origin = ecs_get(world_ecs(), plr, Position); Position * dest = ecs_get_mut(world_ecs(), e, Position); *dest = *origin; + entity_set_position(e, dest->x, dest->y); debug_replay_special_action(RPKIND_SPAWN_CHEST); } @@ -52,6 +55,7 @@ ActSpawnBelt(void) { Position const* origin = ecs_get(world_ecs(), plr, Position); Position * dest = ecs_get_mut(world_ecs(), e, Position); *dest = *origin; + entity_set_position(e, dest->x, dest->y); debug_replay_special_action(RPKIND_SPAWN_BELT); } @@ -67,6 +71,8 @@ ActSpawnCirclingDriver(void) { Position *dest = ecs_get_mut(world_ecs(), e, Position); *veh_dest = *origin; *dest = *origin; + entity_set_position(ve, veh_dest->x, veh_dest->y); + entity_set_position(e, dest->x, dest->y); Input *input = ecs_get_mut(world_ecs(), e, Input); zpl_zero_item(input); diff --git a/code/game/src/entity.c b/code/game/src/entity.c index be2ddb7..5e4dc7f 100644 --- a/code/game/src/entity.c +++ b/code/game/src/entity.c @@ -20,6 +20,7 @@ uint64_t entity_spawn(uint16_t class_id) { #if 1 pos->x=(float)(rand() % world_dim()); pos->y=(float)(rand() % world_dim()); + entity_set_position(e, pos->x, pos->y); #else pos->x=350.0f; pos->y=88.0f; @@ -63,7 +64,7 @@ void entity_set_position(uint64_t ent_id, float x, float y) { Position *p = ecs_get_mut(world_ecs(), ent_id, Position); p->x = x; p->y = y; - + librg_entity_chunk_set(world_tracker(), ent_id, librg_chunk_from_realpos(world_tracker(), x, y, 0)); entity_wake(ent_id); } diff --git a/code/game/src/items.c b/code/game/src/items.c index 361d611..ab59494 100644 --- a/code/game/src/items.c +++ b/code/game/src/items.c @@ -86,9 +86,7 @@ void item_use(ecs_world_t *ecs, ItemDrop *it, Position p, uint64_t udata) { ecs_entity_t e = entity_spawn_id(desc->place_item.id); ZPL_ASSERT(world_entity_valid(e)); - Position *pos = ecs_get_mut(ecs, e, Position); - pos->x = p.x; - pos->y = p.y; + entity_set_position(e, p.x, p.y); it->quantity--; }break; diff --git a/code/game/src/packets/pkt_00_init.c b/code/game/src/packets/pkt_00_init.c index 17e3d66..09f1a57 100644 --- a/code/game/src/packets/pkt_00_init.c +++ b/code/game/src/packets/pkt_00_init.c @@ -7,6 +7,7 @@ #include "entity_view.h" #include "camera.h" #include "player.h" +#include "entity.h" #include "modules/components.h" #include "modules/systems.h" @@ -31,8 +32,7 @@ int32_t pkt_00_init_handler(pkt_header *header) { Position *pos = ecs_get_mut(world_ecs(), ent_id, Position); #if 1 - pos->x = world_dim()/2.0f + rand()%15*15.0f; - pos->y = world_dim()/2.0f + rand()%15*15.0f; + entity_set_position(ent_id, world_dim()/2.0f + rand()%15*15.0f, world_dim()/2.0f + rand()%15*15.0f); #else pos->x = rand()%world_dim(); pos->y = rand()%world_dim(); diff --git a/code/game/src/world/worldgen/worldgen_test.c b/code/game/src/world/worldgen/worldgen_test.c index 81cb590..0696545 100644 --- a/code/game/src/world/worldgen/worldgen_test.c +++ b/code/game/src/world/worldgen/worldgen_test.c @@ -8,6 +8,7 @@ #include "world/perlin.h" #include "modules/components.h" +#include "entity.h" #include "vehicle.h" #include "items.h" #include "world/blocks_info.h" @@ -133,6 +134,9 @@ static WORLD_BLOCK_OBSERVER(shaper_noise05b) { return world_perlin_cond_offset(block_idx, 0.05, 32, 0) ? shaper(data, id, block_idx) : BLOCK_INVALID; } +static WORLD_BLOCK_OBSERVER(shaper_noise01b) { + return world_perlin_cond_offset(block_idx, 0.01, 32, 0) ? shaper(data, id, block_idx) : BLOCK_INVALID; +} #else static WORLD_BLOCK_OBSERVER(shaper_noise80) { return rand()%10 < 8 ? shaper(id, block_idx) : BLOCK_INVALID; @@ -177,7 +181,7 @@ int32_t worldgen_test(world_data *wld) { // ground world_fill_rect(world->data, grnd_id, 1, 1, world->dim-2, world->dim-2, NULL); world_fill_rect(world->data, dirt_id, 1, 1, world->dim-2, world->dim-2, shaper_noise05); - world_fill_rect(world->outer_data, tree_id, 1, 1, world->dim-2, world->dim-2, shaper_noise05b); + world_fill_rect(world->outer_data, tree_id, 1, 1, world->dim-2, world->dim-2, shaper_noise01b); // water #if 1 @@ -215,6 +219,7 @@ int32_t worldgen_test(world_data *wld) { Position *dest = ecs_get_mut(world_ecs(), e, Position); dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); + entity_set_position(e, dest->x, dest->y); } #endif @@ -226,6 +231,7 @@ int32_t worldgen_test(world_data *wld) { Position *dest = ecs_get_mut(world_ecs(), e, Position); dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); + entity_set_position(e, dest->x, dest->y); } for (int i=0; ix = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); + entity_set_position(e, dest->x, dest->y); } for (int i=0; ix = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); + entity_set_position(e, dest->x, dest->y); } for (int i=0; ix = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); + entity_set_position(e, dest->x, dest->y); } for (int i=0; ix = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE); + entity_set_position(e, dest->x, dest->y); } #endif diff --git a/code/modules/modules/systems.c b/code/modules/modules/systems.c index 7af0846..260119f 100644 --- a/code/modules/modules/systems.c +++ b/code/modules/modules/systems.c @@ -57,8 +57,7 @@ void IntegratePositions(ecs_iter_t *it) { } #endif - p[i].x += v[i].x * safe_dt(it); - p[i].y += v[i].y * safe_dt(it); + entity_set_position(it->entities[i], p[i].x+v[i].x*safe_dt(it), p[i].y+v[i].y*safe_dt(it)); } { @@ -70,20 +69,6 @@ void IntegratePositions(ecs_iter_t *it) { } } -void UpdateTrackerPos(ecs_iter_t *it) { - Position *p = ecs_field(it, Position, 1); - - for (int i = 0; i < it->count; i++){ - librg_entity_chunk_set(world_tracker(), it->entities[i], librg_chunk_from_realpos(world_tracker(), p[i].x, p[i].y, 0)); - - { - debug_v2 a = {p[i].x-2.5f, p[i].y-2.5f}; - debug_v2 b = {p[i].x+2.5f, p[i].y+2.5f}; - debug_push_rect(a, b, 0x00FFFFFF); - } - } -} - #define HAZARD_BLOCK_TIME 1.0f #define HAZARD_BLOCK_DMG 5.0f @@ -228,8 +213,6 @@ void SystemsImport(ecs_world_t *ecs) { ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input); - ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position, components.Velocity); - ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle); ECS_SYSTEM(ecs, DisableWorldEdit, EcsPostUpdate); diff --git a/code/modules/source/system_items.c b/code/modules/source/system_items.c index 48d6dd9..6d4bb8b 100644 --- a/code/modules/source/system_items.c +++ b/code/modules/source/system_items.c @@ -3,7 +3,7 @@ #define ITEM_PICK_RADIUS 25.0f #define ITEM_MERGER_RADIUS 75.0f #define ITEM_ATTRACT_RADIUS 75.0f -#define ITEM_ATTRACT_FORCE 0.63f +#define ITEM_ATTRACT_FORCE 6.f #define ITEM_CONTAINER_REACH_RADIUS 105.0f @@ -13,6 +13,7 @@ void PickItem(ecs_iter_t *it) { for (int i = 0; i < it->count; i++) { if (inv[i].pickup_time > game_time()) continue; + inv[i].pickup_time = game_time() + 0.5f; size_t ents_count; int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2); @@ -20,6 +21,7 @@ void PickItem(ecs_iter_t *it) { ItemDrop *drop = 0; if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) { Position *p2 = ecs_get_mut(it->world, ents[j], Position); + Velocity *v2 = ecs_get_mut(it->world, ents[j], Velocity); float dx = p2->x - p[i].x; float dy = p2->y - p[i].y; @@ -43,9 +45,8 @@ void PickItem(ecs_iter_t *it) { } } } else if (range <= ITEM_ATTRACT_RADIUS) { - entity_set_position(ents[j], - zpl_lerp(p2->x, p[i].x, ITEM_ATTRACT_FORCE*it->delta_time), - zpl_lerp(p2->y, p[i].y, ITEM_ATTRACT_FORCE*it->delta_time)); + v2->x = (p[i].x - p2->x) * ITEM_ATTRACT_FORCE; + v2->y = (p[i].y - p2->y) * ITEM_ATTRACT_FORCE; } } } diff --git a/code/modules/source/system_vehicle.c b/code/modules/source/system_vehicle.c index be2993f..9f69dbe 100644 --- a/code/modules/source/system_vehicle.c +++ b/code/modules/source/system_vehicle.c @@ -155,11 +155,9 @@ void VehicleHandling(ecs_iter_t *it) { // NOTE(zaklaus): Update passenger position { - Position *p2 = ecs_get_mut(it->world, pe, Position); Velocity *v2 = ecs_get_mut(it->world, pe, Velocity); - *p2 = p[i]; + entity_set_position(pe, p[i].x+v[i].x, p[i].y+v[i].y); *v2 = v[i]; - entity_wake(pe); } } diff --git a/code/vendors/librg.h b/code/vendors/librg.h index dcad1d6..5840343 100644 --- a/code/vendors/librg.h +++ b/code/vendors/librg.h @@ -6598,224 +6598,224 @@ LIBRG_END_C_DECLS } ZPL_END_C_DECLS - // file: header/essentials/collections/hashtable.h - - /** @file hashtable.c - @brief Instantiated hash table - @defgroup hashtable Instantiated hash table - - - This is an attempt to implement a templated hash table - NOTE: The key is always a zpl_u64 for simplicity and you will _probably_ _never_ need anything bigger. - - Hash table type and function declaration, call: ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE) - Hash table function definitions, call: ZPL_TABLE_DEFINE(NAME, FUNC, VALUE) - - PREFIX - a prefix for function prototypes e.g. extern, static, etc. - NAME - Name of the Hash Table - FUNC - the name will prefix function names - VALUE - the type of the value to be stored - - tablename_init(NAME * h, zpl_allocator a); - tablename_destroy(NAME * h); - tablename_get(NAME * h, zpl_u64 key); - tablename_set(NAME * h, zpl_u64 key, VALUE value); - tablename_grow(NAME * h); - tablename_map(NAME * h, void (*map_proc)(zpl_u64 key, VALUE value)) - tablename_map_mut(NAME * h, void (*map_proc)(zpl_u64 key, VALUE * value)) - tablename_rehash(NAME * h, zpl_isize new_count); - tablename_remove(NAME * h, zpl_u64 key); - - @{ - */ - - - ZPL_BEGIN_C_DECLS - - typedef struct zpl_hash_table_find_result { - zpl_isize hash_index; - zpl_isize entry_prev; - zpl_isize entry_index; - } zpl_hash_table_find_result; - - #define ZPL_TABLE(PREFIX, NAME, FUNC, VALUE) \ - ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE); \ - ZPL_TABLE_DEFINE(NAME, FUNC, VALUE); - - #define ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE) \ - typedef struct ZPL_JOIN2(NAME, Entry) { \ - zpl_u64 key; \ - zpl_isize next; \ - VALUE value; \ - } ZPL_JOIN2(NAME, Entry); \ - \ - typedef struct NAME { \ - zpl_array(zpl_isize) hashes; \ - zpl_array(ZPL_JOIN2(NAME, Entry)) entries; \ - } NAME; \ - \ - PREFIX void ZPL_JOIN2(FUNC, init)(NAME * h, zpl_allocator a); \ - PREFIX void ZPL_JOIN2(FUNC, destroy)(NAME * h); \ - PREFIX VALUE *ZPL_JOIN2(FUNC, get)(NAME * h, zpl_u64 key); \ - PREFIX zpl_isize ZPL_JOIN2(FUNC, slot)(NAME * h, zpl_u64 key); \ - PREFIX void ZPL_JOIN2(FUNC, set)(NAME * h, zpl_u64 key, VALUE value); \ - PREFIX void ZPL_JOIN2(FUNC, grow)(NAME * h); \ - PREFIX void ZPL_JOIN2(FUNC, rehash)(NAME * h, zpl_isize new_count); \ - PREFIX void ZPL_JOIN2(FUNC, rehash_fast)(NAME * h); \ - PREFIX void ZPL_JOIN2(FUNC, map)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE value)); \ - PREFIX void ZPL_JOIN2(FUNC, map_mut)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE * value)); \ - PREFIX void ZPL_JOIN2(FUNC, remove)(NAME * h, zpl_u64 key); \ - PREFIX void ZPL_JOIN2(FUNC, remove_entry)(NAME * h, zpl_isize idx); - - #define ZPL_TABLE_DEFINE(NAME, FUNC, VALUE) \ - void ZPL_JOIN2(FUNC, init)(NAME * h, zpl_allocator a) { \ - zpl_array_init(h->hashes, a); \ - zpl_array_init(h->entries, a); \ - } \ - \ - void ZPL_JOIN2(FUNC, destroy)(NAME * h) { \ - if (h->entries) zpl_array_free(h->entries); \ - if (h->hashes) zpl_array_free(h->hashes); \ - } \ - \ - zpl_isize ZPL_JOIN2(FUNC, slot)(NAME * h, zpl_u64 key) { \ - for (zpl_isize i = 0; i < zpl_array_count(h->entries); i++) {\ - if (h->entries[i].key == key) {\ - return i; \ - } \ - }\ - return -1;\ - }\ - \ - zpl_internal zpl_isize ZPL_JOIN2(FUNC, _add_entry)(NAME * h, zpl_u64 key) { \ - zpl_isize index; \ - ZPL_JOIN2(NAME, Entry) e = { 0 }; \ - e.key = key; \ - e.next = -1; \ - index = zpl_array_count(h->entries); \ - zpl_array_append(h->entries, e); \ - return index; \ - } \ - \ - zpl_internal zpl_hash_table_find_result ZPL_JOIN2(FUNC, _find)(NAME * h, zpl_u64 key) { \ - zpl_hash_table_find_result r = { -1, -1, -1 }; \ - if (zpl_array_count(h->hashes) > 0) { \ - r.hash_index = key % zpl_array_count(h->hashes); \ - r.entry_index = h->hashes[r.hash_index]; \ - while (r.entry_index >= 0) { \ - if (h->entries[r.entry_index].key == key) return r; \ - r.entry_prev = r.entry_index; \ - r.entry_index = h->entries[r.entry_index].next; \ - } \ - } \ - return r; \ - } \ - \ - zpl_internal zpl_b32 ZPL_JOIN2(FUNC, _full)(NAME * h) { \ - return 0.75f * zpl_array_count(h->hashes) < zpl_array_count(h->entries); \ - } \ - \ - void ZPL_JOIN2(FUNC, grow)(NAME * h) { \ - zpl_isize new_count = ZPL_ARRAY_GROW_FORMULA(zpl_array_count(h->entries)); \ - ZPL_JOIN2(FUNC, rehash)(h, new_count); \ - } \ - \ - void ZPL_JOIN2(FUNC, rehash)(NAME * h, zpl_isize new_count) { \ - zpl_isize i, j; \ - NAME nh = { 0 }; \ - ZPL_JOIN2(FUNC, init)(&nh, zpl_array_allocator(h->hashes)); \ - zpl_array_resize(nh.hashes, new_count); \ - zpl_array_reserve(nh.entries, zpl_array_count(h->entries)); \ - for (i = 0; i < new_count; i++) nh.hashes[i] = -1; \ - for (i = 0; i < zpl_array_count(h->entries); i++) { \ - ZPL_JOIN2(NAME, Entry) * e; \ - zpl_hash_table_find_result fr; \ - if (zpl_array_count(nh.hashes) == 0) ZPL_JOIN2(FUNC, grow)(&nh); \ - e = &h->entries[i]; \ - fr = ZPL_JOIN2(FUNC, _find)(&nh, e->key); \ - j = ZPL_JOIN2(FUNC, _add_entry)(&nh, e->key); \ - if (fr.entry_prev < 0) \ - nh.hashes[fr.hash_index] = j; \ - else \ - nh.entries[fr.entry_prev].next = j; \ - nh.entries[j].next = fr.entry_index; \ - nh.entries[j].value = e->value; \ - } \ - ZPL_JOIN2(FUNC, destroy)(h); \ - h->hashes = nh.hashes; \ - h->entries = nh.entries; \ - } \ - \ - void ZPL_JOIN2(FUNC, rehash_fast)(NAME * h) { \ - zpl_isize i; \ - for (i = 0; i < zpl_array_count(h->entries); i++) h->entries[i].next = -1; \ - for (i = 0; i < zpl_array_count(h->hashes); i++) h->hashes[i] = -1; \ - for (i = 0; i < zpl_array_count(h->entries); i++) { \ - ZPL_JOIN2(NAME, Entry) * e; \ - zpl_hash_table_find_result fr; \ - e = &h->entries[i]; \ - fr = ZPL_JOIN2(FUNC, _find)(h, e->key); \ - if (fr.entry_prev < 0) \ - h->hashes[fr.hash_index] = i; \ - else \ - h->entries[fr.entry_prev].next = i; \ - } \ - } \ - \ - VALUE *ZPL_JOIN2(FUNC, get)(NAME * h, zpl_u64 key) { \ - zpl_isize index = ZPL_JOIN2(FUNC, _find)(h, key).entry_index; \ - if (index >= 0) return &h->entries[index].value; \ - return NULL; \ - } \ - \ - void ZPL_JOIN2(FUNC, remove)(NAME * h, zpl_u64 key) { \ - zpl_hash_table_find_result fr = ZPL_JOIN2(FUNC, _find)(h, key); \ - if (fr.entry_index >= 0) { \ - zpl_array_remove_at(h->entries, fr.entry_index); \ - ZPL_JOIN2(FUNC, rehash_fast)(h); \ - } \ - } \ - \ - void ZPL_JOIN2(FUNC, remove_entry)(NAME * h, zpl_isize idx) { \ - zpl_array_remove_at(h->entries, idx); \ - } \ - \ - void ZPL_JOIN2(FUNC, map)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE value)) { \ - ZPL_ASSERT_NOT_NULL(h); \ - ZPL_ASSERT_NOT_NULL(map_proc); \ - for (zpl_isize i = 0; i < zpl_array_count(h->entries); ++i) { \ - map_proc(h->entries[i].key, h->entries[i].value); \ - } \ - } \ - void ZPL_JOIN2(FUNC, map_mut)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE * value)) { \ - ZPL_ASSERT_NOT_NULL(h); \ - ZPL_ASSERT_NOT_NULL(map_proc); \ - for (zpl_isize i = 0; i < zpl_array_count(h->entries); ++i) { \ - map_proc(h->entries[i].key, &h->entries[i].value); \ - } \ - } \ - \ - void ZPL_JOIN2(FUNC, set)(NAME * h, zpl_u64 key, VALUE value) { \ - zpl_isize index; \ - zpl_hash_table_find_result fr; \ - if (zpl_array_count(h->hashes) == 0) ZPL_JOIN2(FUNC, grow)(h); \ - fr = ZPL_JOIN2(FUNC, _find)(h, key); \ - if (fr.entry_index >= 0) { \ - index = fr.entry_index; \ - } else { \ - index = ZPL_JOIN2(FUNC, _add_entry)(h, key); \ - if (fr.entry_prev >= 0) { \ - h->entries[fr.entry_prev].next = index; \ - } else { \ - h->hashes[fr.hash_index] = index; \ - } \ - } \ - h->entries[index].value = value; \ - if (ZPL_JOIN2(FUNC, _full)(h)) ZPL_JOIN2(FUNC, grow)(h); \ - }\ - - //! @} - + // file: header/essentials/collections/hashtable.h + + /** @file hashtable.c + @brief Instantiated hash table + @defgroup hashtable Instantiated hash table + + + This is an attempt to implement a templated hash table + NOTE: The key is always a zpl_u64 for simplicity and you will _probably_ _never_ need anything bigger. + + Hash table type and function declaration, call: ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE) + Hash table function definitions, call: ZPL_TABLE_DEFINE(NAME, FUNC, VALUE) + + PREFIX - a prefix for function prototypes e.g. extern, static, etc. + NAME - Name of the Hash Table + FUNC - the name will prefix function names + VALUE - the type of the value to be stored + + tablename_init(NAME * h, zpl_allocator a); + tablename_destroy(NAME * h); + tablename_get(NAME * h, zpl_u64 key); + tablename_set(NAME * h, zpl_u64 key, VALUE value); + tablename_grow(NAME * h); + tablename_map(NAME * h, void (*map_proc)(zpl_u64 key, VALUE value)) + tablename_map_mut(NAME * h, void (*map_proc)(zpl_u64 key, VALUE * value)) + tablename_rehash(NAME * h, zpl_isize new_count); + tablename_remove(NAME * h, zpl_u64 key); + + @{ + */ + + + ZPL_BEGIN_C_DECLS + + typedef struct zpl_hash_table_find_result { + zpl_isize hash_index; + zpl_isize entry_prev; + zpl_isize entry_index; + } zpl_hash_table_find_result; + + #define ZPL_TABLE(PREFIX, NAME, FUNC, VALUE) \ + ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE); \ + ZPL_TABLE_DEFINE(NAME, FUNC, VALUE); + + #define ZPL_TABLE_DECLARE(PREFIX, NAME, FUNC, VALUE) \ + typedef struct ZPL_JOIN2(NAME, Entry) { \ + zpl_u64 key; \ + zpl_isize next; \ + VALUE value; \ + } ZPL_JOIN2(NAME, Entry); \ + \ + typedef struct NAME { \ + zpl_array(zpl_isize) hashes; \ + zpl_array(ZPL_JOIN2(NAME, Entry)) entries; \ + } NAME; \ + \ + PREFIX void ZPL_JOIN2(FUNC, init)(NAME * h, zpl_allocator a); \ + PREFIX void ZPL_JOIN2(FUNC, destroy)(NAME * h); \ + PREFIX VALUE *ZPL_JOIN2(FUNC, get)(NAME * h, zpl_u64 key); \ + PREFIX zpl_isize ZPL_JOIN2(FUNC, slot)(NAME * h, zpl_u64 key); \ + PREFIX void ZPL_JOIN2(FUNC, set)(NAME * h, zpl_u64 key, VALUE value); \ + PREFIX void ZPL_JOIN2(FUNC, grow)(NAME * h); \ + PREFIX void ZPL_JOIN2(FUNC, rehash)(NAME * h, zpl_isize new_count); \ + PREFIX void ZPL_JOIN2(FUNC, rehash_fast)(NAME * h); \ + PREFIX void ZPL_JOIN2(FUNC, map)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE value)); \ + PREFIX void ZPL_JOIN2(FUNC, map_mut)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE * value)); \ + PREFIX void ZPL_JOIN2(FUNC, remove)(NAME * h, zpl_u64 key); \ + PREFIX void ZPL_JOIN2(FUNC, remove_entry)(NAME * h, zpl_isize idx); + + #define ZPL_TABLE_DEFINE(NAME, FUNC, VALUE) \ + void ZPL_JOIN2(FUNC, init)(NAME * h, zpl_allocator a) { \ + zpl_array_init(h->hashes, a); \ + zpl_array_init(h->entries, a); \ + } \ + \ + void ZPL_JOIN2(FUNC, destroy)(NAME * h) { \ + if (h->entries) zpl_array_free(h->entries); \ + if (h->hashes) zpl_array_free(h->hashes); \ + } \ + \ + zpl_isize ZPL_JOIN2(FUNC, slot)(NAME * h, zpl_u64 key) { \ + for (zpl_isize i = 0; i < zpl_array_count(h->entries); i++) {\ + if (h->entries[i].key == key) {\ + return i; \ + } \ + }\ + return -1;\ + }\ + \ + zpl_internal zpl_isize ZPL_JOIN2(FUNC, _add_entry)(NAME * h, zpl_u64 key) { \ + zpl_isize index; \ + ZPL_JOIN2(NAME, Entry) e = { 0 }; \ + e.key = key; \ + e.next = -1; \ + index = zpl_array_count(h->entries); \ + zpl_array_append(h->entries, e); \ + return index; \ + } \ + \ + zpl_internal zpl_hash_table_find_result ZPL_JOIN2(FUNC, _find)(NAME * h, zpl_u64 key) { \ + zpl_hash_table_find_result r = { -1, -1, -1 }; \ + if (zpl_array_count(h->hashes) > 0) { \ + r.hash_index = key % zpl_array_count(h->hashes); \ + r.entry_index = h->hashes[r.hash_index]; \ + while (r.entry_index >= 0) { \ + if (h->entries[r.entry_index].key == key) return r; \ + r.entry_prev = r.entry_index; \ + r.entry_index = h->entries[r.entry_index].next; \ + } \ + } \ + return r; \ + } \ + \ + zpl_internal zpl_b32 ZPL_JOIN2(FUNC, _full)(NAME * h) { \ + return 0.75f * zpl_array_count(h->hashes) < zpl_array_count(h->entries); \ + } \ + \ + void ZPL_JOIN2(FUNC, grow)(NAME * h) { \ + zpl_isize new_count = ZPL_ARRAY_GROW_FORMULA(zpl_array_count(h->entries)); \ + ZPL_JOIN2(FUNC, rehash)(h, new_count); \ + } \ + \ + void ZPL_JOIN2(FUNC, rehash)(NAME * h, zpl_isize new_count) { \ + zpl_isize i, j; \ + NAME nh = { 0 }; \ + ZPL_JOIN2(FUNC, init)(&nh, zpl_array_allocator(h->hashes)); \ + zpl_array_resize(nh.hashes, new_count); \ + zpl_array_reserve(nh.entries, zpl_array_count(h->entries)); \ + for (i = 0; i < new_count; i++) nh.hashes[i] = -1; \ + for (i = 0; i < zpl_array_count(h->entries); i++) { \ + ZPL_JOIN2(NAME, Entry) * e; \ + zpl_hash_table_find_result fr; \ + if (zpl_array_count(nh.hashes) == 0) ZPL_JOIN2(FUNC, grow)(&nh); \ + e = &h->entries[i]; \ + fr = ZPL_JOIN2(FUNC, _find)(&nh, e->key); \ + j = ZPL_JOIN2(FUNC, _add_entry)(&nh, e->key); \ + if (fr.entry_prev < 0) \ + nh.hashes[fr.hash_index] = j; \ + else \ + nh.entries[fr.entry_prev].next = j; \ + nh.entries[j].next = fr.entry_index; \ + nh.entries[j].value = e->value; \ + } \ + ZPL_JOIN2(FUNC, destroy)(h); \ + h->hashes = nh.hashes; \ + h->entries = nh.entries; \ + } \ + \ + void ZPL_JOIN2(FUNC, rehash_fast)(NAME * h) { \ + zpl_isize i; \ + for (i = 0; i < zpl_array_count(h->entries); i++) h->entries[i].next = -1; \ + for (i = 0; i < zpl_array_count(h->hashes); i++) h->hashes[i] = -1; \ + for (i = 0; i < zpl_array_count(h->entries); i++) { \ + ZPL_JOIN2(NAME, Entry) * e; \ + zpl_hash_table_find_result fr; \ + e = &h->entries[i]; \ + fr = ZPL_JOIN2(FUNC, _find)(h, e->key); \ + if (fr.entry_prev < 0) \ + h->hashes[fr.hash_index] = i; \ + else \ + h->entries[fr.entry_prev].next = i; \ + } \ + } \ + \ + VALUE *ZPL_JOIN2(FUNC, get)(NAME * h, zpl_u64 key) { \ + zpl_isize index = ZPL_JOIN2(FUNC, _find)(h, key).entry_index; \ + if (index >= 0) return &h->entries[index].value; \ + return NULL; \ + } \ + \ + void ZPL_JOIN2(FUNC, remove)(NAME * h, zpl_u64 key) { \ + zpl_hash_table_find_result fr = ZPL_JOIN2(FUNC, _find)(h, key); \ + if (fr.entry_index >= 0) { \ + zpl_array_remove_at(h->entries, fr.entry_index); \ + ZPL_JOIN2(FUNC, rehash_fast)(h); \ + } \ + } \ + \ + void ZPL_JOIN2(FUNC, remove_entry)(NAME * h, zpl_isize idx) { \ + zpl_array_remove_at(h->entries, idx); \ + } \ + \ + void ZPL_JOIN2(FUNC, map)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE value)) { \ + ZPL_ASSERT_NOT_NULL(h); \ + ZPL_ASSERT_NOT_NULL(map_proc); \ + for (zpl_isize i = 0; i < zpl_array_count(h->entries); ++i) { \ + map_proc(h->entries[i].key, h->entries[i].value); \ + } \ + } \ + void ZPL_JOIN2(FUNC, map_mut)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE * value)) { \ + ZPL_ASSERT_NOT_NULL(h); \ + ZPL_ASSERT_NOT_NULL(map_proc); \ + for (zpl_isize i = 0; i < zpl_array_count(h->entries); ++i) { \ + map_proc(h->entries[i].key, &h->entries[i].value); \ + } \ + } \ + \ + void ZPL_JOIN2(FUNC, set)(NAME * h, zpl_u64 key, VALUE value) { \ + zpl_isize index; \ + zpl_hash_table_find_result fr; \ + if (zpl_array_count(h->hashes) == 0) ZPL_JOIN2(FUNC, grow)(h); \ + fr = ZPL_JOIN2(FUNC, _find)(h, key); \ + if (fr.entry_index >= 0) { \ + index = fr.entry_index; \ + } else { \ + index = ZPL_JOIN2(FUNC, _add_entry)(h, key); \ + if (fr.entry_prev >= 0) { \ + h->entries[fr.entry_prev].next = index; \ + } else { \ + h->hashes[fr.hash_index] = index; \ + } \ + } \ + h->entries[index].value = value; \ + if (ZPL_JOIN2(FUNC, _full)(h)) ZPL_JOIN2(FUNC, grow)(h); \ + }\ + + //! @} + ZPL_END_C_DECLS # if defined(ZPL_MODULE_CORE) // file: header/core/memory_virtual.h @@ -8743,701 +8743,701 @@ LIBRG_END_C_DECLS #endif #if defined(ZPL_MODULE_MATH) - // file: header/math.h - - /** @file math.c - @brief Math operations - @defgroup math Math operations - - OpenGL gamedev friendly library for math. - - @{ - */ - - ZPL_BEGIN_C_DECLS - - typedef union zpl_vec2 { - struct { - zpl_f32 x, y; - }; - struct { - zpl_f32 s, t; - }; - zpl_f32 e[2]; - } zpl_vec2; - - typedef union zpl_vec3 { - struct { - zpl_f32 x, y, z; - }; - struct { - zpl_f32 r, g, b; - }; - struct { - zpl_f32 s, t, p; - }; - - zpl_vec2 xy; - zpl_vec2 st; - zpl_f32 e[3]; - } zpl_vec3; - - typedef union zpl_vec4 { - struct { - zpl_f32 x, y, z, w; - }; - struct { - zpl_f32 r, g, b, a; - }; - struct { - zpl_f32 s, t, p, q; - }; - struct { - zpl_vec2 xy, zw; - }; - struct { - zpl_vec2 st, pq; - }; - zpl_vec3 xyz; - zpl_vec3 rgb; - zpl_f32 e[4]; - } zpl_vec4; - - typedef union zpl_mat2 { - struct { - zpl_vec2 x, y; - }; - zpl_vec2 col[2]; - zpl_f32 e[4]; - } zpl_mat2; - - typedef union zpl_mat3 { - struct { - zpl_vec3 x, y, z; - }; - zpl_vec3 col[3]; - zpl_f32 e[9]; - } zpl_mat3; - - typedef union zpl_mat4 { - struct { - zpl_vec4 x, y, z, w; - }; - zpl_vec4 col[4]; - zpl_f32 e[16]; - } zpl_mat4; - - typedef union zpl_quat { - struct { - zpl_f32 x, y, z, w; - }; - zpl_vec4 xyzw; - zpl_vec3 xyz; - zpl_f32 e[4]; - } zpl_quat; - - typedef union zpl_plane { - struct { - zpl_f32 a, b, c, d; - }; - zpl_vec4 xyzw; - zpl_vec3 n; - zpl_f32 e[4]; - } zpl_plane; - - typedef struct zpl_frustum { - zpl_plane x1; - zpl_plane x2; - zpl_plane y1; - zpl_plane y2; - zpl_plane z1; - zpl_plane z2; - } zpl_frustum; - - typedef zpl_f32 zpl_float2[2]; - typedef zpl_f32 zpl_float3[3]; - typedef zpl_f32 zpl_float4[4]; - - typedef struct zpl_rect2 { - zpl_vec2 pos, dim; - } zpl_rect2; - typedef struct zpl_rect3 { - zpl_vec3 pos, dim; - } zpl_rect3; - - typedef struct zpl_aabb2 { - zpl_vec2 min, max; - } zpl_aabb2; - typedef struct zpl_aabb3 { - zpl_vec3 min, max; - } zpl_aabb3; - - typedef short zpl_half; - - #ifndef ZPL_CONSTANTS - #define ZPL_CONSTANTS - #define ZPL_EPSILON 1.19209290e-7f - #define ZPL_ZERO 0.0f - #define ZPL_ONE 1.0f - #define ZPL_TWO_THIRDS 0.666666666666666666666666666666666666667f - - #define ZPL_TAU 6.28318530717958647692528676655900576f - #define ZPL_PI 3.14159265358979323846264338327950288f - #define ZPL_ONE_OVER_TAU 0.636619772367581343075535053490057448f - #define ZPL_ONE_OVER_PI 0.159154943091895335768883763372514362f - - #define ZPL_TAU_OVER_2 3.14159265358979323846264338327950288f - #define ZPL_TAU_OVER_4 1.570796326794896619231321691639751442f - #define ZPL_TAU_OVER_8 0.785398163397448309615660845819875721f - - #define ZPL_E 2.71828182845904523536f - #define ZPL_SQRT_TWO 1.41421356237309504880168872420969808f - #define ZPL_SQRT_THREE 1.73205080756887729352744634150587236f - #define ZPL_SQRT_FIVE 2.23606797749978969640917366873127623f - - #define ZPL_LOG_TWO 0.693147180559945309417232121458176568f - #define ZPL_LOG_TEN 2.30258509299404568401799145468436421f - #endif // ZPL_CONSTANTS - - #ifndef zpl_square - #define zpl_square(x) ((x) * (x)) - #endif - - #ifndef zpl_cube - #define zpl_cube(x) ((x) * (x) * (x)) - #endif - - #ifndef zpl_sign - #define zpl_sign(x) ((x) >= 0.0f ? 1.0f : -1.0f) - #endif - - #ifndef zpl_sign0 - #define zpl_sign0(x) ((x == 0.0f) ? 0.0f : ((x) >= 0.0f ? 1.0f : -1.0f)) - #endif - - ZPL_DEF zpl_f32 zpl_to_radians(zpl_f32 degrees); - ZPL_DEF zpl_f32 zpl_to_degrees(zpl_f32 radians); - - /* NOTE: Because to interpolate angles */ - ZPL_DEF zpl_f32 zpl_angle_diff(zpl_f32 radians_a, zpl_f32 radians_b); - - ZPL_DEF zpl_f32 zpl_copy_sign(zpl_f32 x, zpl_f32 y); - ZPL_DEF zpl_f32 zpl_remainder(zpl_f32 x, zpl_f32 y); - ZPL_DEF zpl_f32 zpl_mod(zpl_f32 x, zpl_f32 y); - ZPL_DEF zpl_f64 zpl_copy_sign64(zpl_f64 x, zpl_f64 y); - ZPL_DEF zpl_f64 zpl_floor64(zpl_f64 x); - ZPL_DEF zpl_f64 zpl_ceil64(zpl_f64 x); - ZPL_DEF zpl_f64 zpl_round64(zpl_f64 x); - ZPL_DEF zpl_f64 zpl_remainder64(zpl_f64 x, zpl_f64 y); - ZPL_DEF zpl_f64 zpl_abs64(zpl_f64 x); - ZPL_DEF zpl_f64 zpl_sign64(zpl_f64 x); - ZPL_DEF zpl_f64 zpl_mod64(zpl_f64 x, zpl_f64 y); - ZPL_DEF zpl_f32 zpl_sqrt(zpl_f32 a); - ZPL_DEF zpl_f32 zpl_rsqrt(zpl_f32 a); - ZPL_DEF zpl_f32 zpl_quake_rsqrt(zpl_f32 a); /* NOTE: It's probably better to use 1.0f/zpl_sqrt(a) - * And for simd, there is usually isqrt functions too! - */ - ZPL_DEF zpl_f32 zpl_sin(zpl_f32 radians); - ZPL_DEF zpl_f32 zpl_cos(zpl_f32 radians); - ZPL_DEF zpl_f32 zpl_tan(zpl_f32 radians); - ZPL_DEF zpl_f32 zpl_arcsin(zpl_f32 a); - ZPL_DEF zpl_f32 zpl_arccos(zpl_f32 a); - ZPL_DEF zpl_f32 zpl_arctan(zpl_f32 a); - ZPL_DEF zpl_f32 zpl_arctan2(zpl_f32 y, zpl_f32 x); - - ZPL_DEF zpl_f32 zpl_exp(zpl_f32 x); - ZPL_DEF zpl_f32 zpl_exp2(zpl_f32 x); - ZPL_DEF zpl_f32 zpl_log(zpl_f32 x); - ZPL_DEF zpl_f32 zpl_log2(zpl_f32 x); - ZPL_DEF zpl_f32 zpl_fast_exp(zpl_f32 x); /* NOTE: Only valid from -1 <= x <= +1 */ - ZPL_DEF zpl_f32 zpl_fast_exp2(zpl_f32 x); /* NOTE: Only valid from -1 <= x <= +1 */ - ZPL_DEF zpl_f32 zpl_pow(zpl_f32 x, zpl_f32 y); /* x^y */ - - ZPL_DEF zpl_f32 zpl_round(zpl_f32 x); - ZPL_DEF zpl_f32 zpl_floor(zpl_f32 x); - ZPL_DEF zpl_f32 zpl_ceil(zpl_f32 x); - - ZPL_DEF zpl_f32 zpl_half_to_float(zpl_half value); - ZPL_DEF zpl_half zpl_float_to_half(zpl_f32 value); - - ZPL_DEF zpl_vec2 zpl_vec2f_zero(void); - ZPL_DEF zpl_vec2 zpl_vec2f(zpl_f32 x, zpl_f32 y); - ZPL_DEF zpl_vec2 zpl_vec2fv(zpl_f32 x[2]); - - ZPL_DEF zpl_vec3 zpl_vec3f_zero(void); - ZPL_DEF zpl_vec3 zpl_vec3f(zpl_f32 x, zpl_f32 y, zpl_f32 z); - ZPL_DEF zpl_vec3 zpl_vec3fv(zpl_f32 x[3]); - - ZPL_DEF zpl_vec4 zpl_vec4f_zero(void); - ZPL_DEF zpl_vec4 zpl_vec4f(zpl_f32 x, zpl_f32 y, zpl_f32 z, zpl_f32 w); - ZPL_DEF zpl_vec4 zpl_vec4fv(zpl_f32 x[4]); - - ZPL_DEF zpl_f32 zpl_vec2_max(zpl_vec2 v); - ZPL_DEF zpl_f32 zpl_vec2_side(zpl_vec2 p, zpl_vec2 q, zpl_vec2 r); - ZPL_DEF void zpl_vec2_add(zpl_vec2 *d, zpl_vec2 v0, zpl_vec2 v1); - ZPL_DEF void zpl_vec2_sub(zpl_vec2 *d, zpl_vec2 v0, zpl_vec2 v1); - ZPL_DEF void zpl_vec2_mul(zpl_vec2 *d, zpl_vec2 v, zpl_f32 s); - ZPL_DEF void zpl_vec2_div(zpl_vec2 *d, zpl_vec2 v, zpl_f32 s); - - ZPL_DEF zpl_f32 zpl_vec3_max(zpl_vec3 v); - ZPL_DEF void zpl_vec3_add(zpl_vec3 *d, zpl_vec3 v0, zpl_vec3 v1); - ZPL_DEF void zpl_vec3_sub(zpl_vec3 *d, zpl_vec3 v0, zpl_vec3 v1); - ZPL_DEF void zpl_vec3_mul(zpl_vec3 *d, zpl_vec3 v, zpl_f32 s); - ZPL_DEF void zpl_vec3_div(zpl_vec3 *d, zpl_vec3 v, zpl_f32 s); - - ZPL_DEF void zpl_vec4_add(zpl_vec4 *d, zpl_vec4 v0, zpl_vec4 v1); - ZPL_DEF void zpl_vec4_sub(zpl_vec4 *d, zpl_vec4 v0, zpl_vec4 v1); - ZPL_DEF void zpl_vec4_mul(zpl_vec4 *d, zpl_vec4 v, zpl_f32 s); - ZPL_DEF void zpl_vec4_div(zpl_vec4 *d, zpl_vec4 v, zpl_f32 s); - - ZPL_DEF void zpl_vec2_addeq(zpl_vec2 *d, zpl_vec2 v); - ZPL_DEF void zpl_vec2_subeq(zpl_vec2 *d, zpl_vec2 v); - ZPL_DEF void zpl_vec2_muleq(zpl_vec2 *d, zpl_f32 s); - ZPL_DEF void zpl_vec2_diveq(zpl_vec2 *d, zpl_f32 s); - - ZPL_DEF void zpl_vec3_addeq(zpl_vec3 *d, zpl_vec3 v); - ZPL_DEF void zpl_vec3_subeq(zpl_vec3 *d, zpl_vec3 v); - ZPL_DEF void zpl_vec3_muleq(zpl_vec3 *d, zpl_f32 s); - ZPL_DEF void zpl_vec3_diveq(zpl_vec3 *d, zpl_f32 s); - - ZPL_DEF void zpl_vec4_addeq(zpl_vec4 *d, zpl_vec4 v); - ZPL_DEF void zpl_vec4_subeq(zpl_vec4 *d, zpl_vec4 v); - ZPL_DEF void zpl_vec4_muleq(zpl_vec4 *d, zpl_f32 s); - ZPL_DEF void zpl_vec4_diveq(zpl_vec4 *d, zpl_f32 s); - - ZPL_DEF zpl_f32 zpl_vec2_dot(zpl_vec2 v0, zpl_vec2 v1); - ZPL_DEF zpl_f32 zpl_vec3_dot(zpl_vec3 v0, zpl_vec3 v1); - ZPL_DEF zpl_f32 zpl_vec4_dot(zpl_vec4 v0, zpl_vec4 v1); - - ZPL_DEF void zpl_vec2_cross(zpl_f32 *d, zpl_vec2 v0, zpl_vec2 v1); - ZPL_DEF void zpl_vec3_cross(zpl_vec3 *d, zpl_vec3 v0, zpl_vec3 v1); - - ZPL_DEF zpl_f32 zpl_vec2_mag2(zpl_vec2 v); - ZPL_DEF zpl_f32 zpl_vec3_mag2(zpl_vec3 v); - ZPL_DEF zpl_f32 zpl_vec4_mag2(zpl_vec4 v); - - ZPL_DEF zpl_f32 zpl_vec2_mag(zpl_vec2 v); - ZPL_DEF zpl_f32 zpl_vec3_mag(zpl_vec3 v); - ZPL_DEF zpl_f32 zpl_vec4_mag(zpl_vec4 v); - - ZPL_DEF void zpl_vec2_norm(zpl_vec2 *d, zpl_vec2 v); - ZPL_DEF void zpl_vec3_norm(zpl_vec3 *d, zpl_vec3 v); - ZPL_DEF void zpl_vec4_norm(zpl_vec4 *d, zpl_vec4 v); - - ZPL_DEF void zpl_vec2_norm0(zpl_vec2 *d, zpl_vec2 v); - ZPL_DEF void zpl_vec3_norm0(zpl_vec3 *d, zpl_vec3 v); - ZPL_DEF void zpl_vec4_norm0(zpl_vec4 *d, zpl_vec4 v); - - ZPL_DEF void zpl_vec2_reflect(zpl_vec2 *d, zpl_vec2 i, zpl_vec2 n); - ZPL_DEF void zpl_vec3_reflect(zpl_vec3 *d, zpl_vec3 i, zpl_vec3 n); - ZPL_DEF void zpl_vec2_refract(zpl_vec2 *d, zpl_vec2 i, zpl_vec2 n, zpl_f32 eta); - ZPL_DEF void zpl_vec3_refract(zpl_vec3 *d, zpl_vec3 i, zpl_vec3 n, zpl_f32 eta); - - ZPL_DEF zpl_f32 zpl_vec2_aspect_ratio(zpl_vec2 v); - - ZPL_DEF void zpl_mat2_identity(zpl_mat2 *m); - ZPL_DEF void zpl_float22_identity(zpl_f32 m[2][2]); - - ZPL_DEF void zpl_mat2_transpose(zpl_mat2 *m); - ZPL_DEF void zpl_mat2_mul(zpl_mat2 *out, zpl_mat2 *m1, zpl_mat2 *m2); - ZPL_DEF void zpl_mat2_mul_vec2(zpl_vec2 *out, zpl_mat2 *m, zpl_vec2 in); - ZPL_DEF void zpl_mat2_inverse(zpl_mat2 *out, zpl_mat2 *in); - ZPL_DEF zpl_f32 zpl_mat2_determinate(zpl_mat2 *m); - - ZPL_DEF zpl_mat2 *zpl_mat2_v(zpl_vec2 m[2]); - ZPL_DEF zpl_mat2 *zpl_mat2_f(zpl_f32 m[2][2]); - ZPL_DEF zpl_float2 *zpl_float22_m(zpl_mat2 *m); - ZPL_DEF zpl_float2 *zpl_float22_v(zpl_vec2 m[2]); - ZPL_DEF zpl_float2 *zpl_float22_4(zpl_f32 m[4]); - - ZPL_DEF void zpl_float22_transpose(zpl_f32 (*vec)[2]); - ZPL_DEF void zpl_float22_mul(zpl_f32 (*out)[2], zpl_f32 (*mat1)[2], zpl_f32 (*mat2)[2]); - ZPL_DEF void zpl_float22_mul_vec2(zpl_vec2 *out, zpl_f32 m[2][2], zpl_vec2 in); - - ZPL_DEF void zpl_mat3_identity(zpl_mat3 *m); - ZPL_DEF void zpl_float33_identity(zpl_f32 m[3][3]); - - ZPL_DEF void zpl_mat3_transpose(zpl_mat3 *m); - ZPL_DEF void zpl_mat3_mul(zpl_mat3 *out, zpl_mat3 *m1, zpl_mat3 *m2); - ZPL_DEF void zpl_mat3_mul_vec3(zpl_vec3 *out, zpl_mat3 *m, zpl_vec3 in); - ZPL_DEF void zpl_mat3_inverse(zpl_mat3 *out, zpl_mat3 *in); - ZPL_DEF zpl_f32 zpl_mat3_determinate(zpl_mat3 *m); - - ZPL_DEF zpl_mat3 *zpl_mat3_v(zpl_vec3 m[3]); - ZPL_DEF zpl_mat3 *zpl_mat3_f(zpl_f32 m[3][3]); - - ZPL_DEF zpl_float3 *zpl_float33_m(zpl_mat3 *m); - ZPL_DEF zpl_float3 *zpl_float33_v(zpl_vec3 m[3]); - ZPL_DEF zpl_float3 *zpl_float33_9(zpl_f32 m[9]); - - ZPL_DEF void zpl_float33_transpose(zpl_f32 (*vec)[3]); - ZPL_DEF void zpl_float33_mul(zpl_f32 (*out)[3], zpl_f32 (*mat1)[3], zpl_f32 (*mat2)[3]); - ZPL_DEF void zpl_float33_mul_vec3(zpl_vec3 *out, zpl_f32 m[3][3], zpl_vec3 in); - - ZPL_DEF void zpl_mat4_identity(zpl_mat4 *m); - ZPL_DEF void zpl_float44_identity(zpl_f32 m[4][4]); - ZPL_DEF void zpl_mat4_copy(zpl_mat4* out, zpl_mat4* m); - - ZPL_DEF void zpl_mat4_transpose(zpl_mat4 *m); - ZPL_DEF void zpl_mat4_mul(zpl_mat4 *out, zpl_mat4 *m1, zpl_mat4 *m2); - ZPL_DEF void zpl_mat4_mul_vec4(zpl_vec4 *out, zpl_mat4 *m, zpl_vec4 in); - ZPL_DEF void zpl_mat4_inverse(zpl_mat4 *out, zpl_mat4 *in); - - ZPL_DEF zpl_mat4 *zpl_mat4_v(zpl_vec4 m[4]); - ZPL_DEF zpl_mat4 *zpl_mat4_f(zpl_f32 m[4][4]); - - ZPL_DEF zpl_float4 *zpl_float44_m(zpl_mat4 *m); - ZPL_DEF zpl_float4 *zpl_float44_v(zpl_vec4 m[4]); - ZPL_DEF zpl_float4 *zpl_float44_16(zpl_f32 m[16]); - - ZPL_DEF void zpl_float44_transpose(zpl_f32 (*vec)[4]); - ZPL_DEF void zpl_float44_mul(zpl_f32 (*out)[4], zpl_f32 (*mat1)[4], zpl_f32 (*mat2)[4]); - ZPL_DEF void zpl_float44_mul_vec4(zpl_vec4 *out, zpl_f32 m[4][4], zpl_vec4 in); - - ZPL_DEF void zpl_mat4_axis_angle(zpl_mat4* out, zpl_vec3 v, zpl_f32 angle_radians); - ZPL_DEF void zpl_mat4_to_translate(zpl_mat4* out, zpl_vec3 v); - ZPL_DEF void zpl_mat4_to_rotate(zpl_mat4* out, zpl_vec3 v, zpl_f32 angle_radians); - ZPL_DEF void zpl_mat4_to_scale(zpl_mat4* out, zpl_vec3 v); - ZPL_DEF void zpl_mat4_to_scalef(zpl_mat4* out, zpl_f32 s); - ZPL_DEF void zpl_mat4_translate(zpl_mat4* out, zpl_vec3 v); - ZPL_DEF void zpl_mat4_rotate(zpl_mat4* out, zpl_vec3 v, zpl_f32 angle_radians); - ZPL_DEF void zpl_mat4_scale(zpl_mat4* out, zpl_vec3 v); - ZPL_DEF void zpl_mat4_scalef(zpl_mat4 *out, zpl_f32 s); - ZPL_DEF void zpl_mat4_ortho2d(zpl_mat4 *out, zpl_f32 left, zpl_f32 right, zpl_f32 bottom, zpl_f32 top); - ZPL_DEF void zpl_mat4_ortho3d(zpl_mat4 *out, zpl_f32 left, zpl_f32 right, zpl_f32 bottom, zpl_f32 top, zpl_f32 z_near, zpl_f32 z_far); - ZPL_DEF void zpl_mat4_perspective(zpl_mat4 *out, zpl_f32 fovy, zpl_f32 aspect, zpl_f32 z_near, zpl_f32 z_far); - ZPL_DEF void zpl_mat4_infinite_perspective(zpl_mat4 *out, zpl_f32 fovy, zpl_f32 aspect, zpl_f32 z_near); - - ZPL_DEF void zpl_mat4_ortho2d_dx(zpl_mat4 *out, zpl_f32 left, zpl_f32 right, zpl_f32 bottom, zpl_f32 top); - ZPL_DEF void zpl_mat4_ortho3d_dx(zpl_mat4 *out, zpl_f32 left, zpl_f32 right, zpl_f32 bottom, zpl_f32 top, zpl_f32 z_near, zpl_f32 z_far); - ZPL_DEF void zpl_mat4_perspective_dx(zpl_mat4 *out, zpl_f32 fovy, zpl_f32 aspect, zpl_f32 z_near, zpl_f32 z_far); - ZPL_DEF void zpl_mat4_infinite_perspective_dx(zpl_mat4 *out, zpl_f32 fovy, zpl_f32 aspect, zpl_f32 z_near); - - ZPL_DEF void zpl_mat4_look_at(zpl_mat4 *out, zpl_vec3 eye, zpl_vec3 centre, zpl_vec3 up); - - ZPL_DEF void zpl_mat4_look_at_lh(zpl_mat4 *out, zpl_vec3 eye, zpl_vec3 centre, zpl_vec3 up); - - ZPL_DEF zpl_quat zpl_quatf(zpl_f32 x, zpl_f32 y, zpl_f32 z, zpl_f32 w); - ZPL_DEF zpl_quat zpl_quatfv(zpl_f32 e[4]); - ZPL_DEF zpl_quat zpl_quat_axis_angle(zpl_vec3 axis, zpl_f32 angle_radians); - ZPL_DEF zpl_quat zpl_quat_euler_angles(zpl_f32 pitch, zpl_f32 yaw, zpl_f32 roll); - ZPL_DEF zpl_quat zpl_quat_identity(void); - - ZPL_DEF void zpl_quat_add(zpl_quat *d, zpl_quat q0, zpl_quat q1); - ZPL_DEF void zpl_quat_sub(zpl_quat *d, zpl_quat q0, zpl_quat q1); - ZPL_DEF void zpl_quat_mul(zpl_quat *d, zpl_quat q0, zpl_quat q1); - ZPL_DEF void zpl_quat_div(zpl_quat *d, zpl_quat q0, zpl_quat q1); - - ZPL_DEF void zpl_quat_mulf(zpl_quat *d, zpl_quat q, zpl_f32 s); - ZPL_DEF void zpl_quat_divf(zpl_quat *d, zpl_quat q, zpl_f32 s); - - ZPL_DEF void zpl_quat_addeq(zpl_quat *d, zpl_quat q); - ZPL_DEF void zpl_quat_subeq(zpl_quat *d, zpl_quat q); - ZPL_DEF void zpl_quat_muleq(zpl_quat *d, zpl_quat q); - ZPL_DEF void zpl_quat_diveq(zpl_quat *d, zpl_quat q); - - ZPL_DEF void zpl_quat_muleqf(zpl_quat *d, zpl_f32 s); - ZPL_DEF void zpl_quat_diveqf(zpl_quat *d, zpl_f32 s); - - ZPL_DEF zpl_f32 zpl_quat_dot(zpl_quat q0, zpl_quat q1); - ZPL_DEF zpl_f32 zpl_quat_mag(zpl_quat q); - - ZPL_DEF void zpl_quat_norm(zpl_quat *d, zpl_quat q); - ZPL_DEF void zpl_quat_conj(zpl_quat *d, zpl_quat q); - ZPL_DEF void zpl_quat_inverse(zpl_quat *d, zpl_quat q); - - ZPL_DEF void zpl_quat_axis(zpl_vec3 *axis, zpl_quat q); - ZPL_DEF zpl_f32 zpl_quat_angle(zpl_quat q); - - ZPL_DEF zpl_f32 zpl_quat_pitch(zpl_quat q); - ZPL_DEF zpl_f32 zpl_quat_yaw(zpl_quat q); - ZPL_DEF zpl_f32 zpl_quat_roll(zpl_quat q); - - /* NOTE: Rotate v by q */ - ZPL_DEF void zpl_quat_rotate_vec3(zpl_vec3 *d, zpl_quat q, zpl_vec3 v); - ZPL_DEF void zpl_mat4_from_quat(zpl_mat4 *out, zpl_quat q); - ZPL_DEF void zpl_quat_from_mat4(zpl_quat *out, zpl_mat4 *m); - - /* Plane math. */ - ZPL_DEF zpl_f32 zpl_plane_distance(zpl_plane* p, zpl_vec3 v); - - /* Frustum culling. */ - ZPL_DEF void zpl_frustum_create(zpl_frustum* out, zpl_mat4* camera, zpl_mat4* proj); - ZPL_DEF zpl_b8 zpl_frustum_sphere_inside(zpl_frustum* frustum, zpl_vec3 center, zpl_f32 radius); - ZPL_DEF zpl_b8 zpl_frustum_point_inside(zpl_frustum* frustum, zpl_vec3 point); - ZPL_DEF zpl_b8 zpl_frustum_box_inside(zpl_frustum* frustum, zpl_aabb3 box); - - /* Interpolations */ - ZPL_DEF zpl_f32 zpl_lerp(zpl_f32 a, zpl_f32 b, zpl_f32 t); - ZPL_DEF zpl_f32 zpl_unlerp(zpl_f32 t, zpl_f32 a, zpl_f32 b); - ZPL_DEF zpl_f32 zpl_smooth_step(zpl_f32 a, zpl_f32 b, zpl_f32 t); - ZPL_DEF zpl_f32 zpl_smoother_step(zpl_f32 a, zpl_f32 b, zpl_f32 t); - - ZPL_DEF void zpl_vec2_lerp(zpl_vec2 *d, zpl_vec2 a, zpl_vec2 b, zpl_f32 t); - ZPL_DEF void zpl_vec3_lerp(zpl_vec3 *d, zpl_vec3 a, zpl_vec3 b, zpl_f32 t); - ZPL_DEF void zpl_vec4_lerp(zpl_vec4 *d, zpl_vec4 a, zpl_vec4 b, zpl_f32 t); - - ZPL_DEF void zpl_vec2_cslerp(zpl_vec2 *d, zpl_vec2 a, zpl_vec2 v0, zpl_vec2 b, zpl_vec2 v1, zpl_f32 t); - ZPL_DEF void zpl_vec3_cslerp(zpl_vec3 *d, zpl_vec3 a, zpl_vec3 v0, zpl_vec3 b, zpl_vec3 v1, zpl_f32 t); - ZPL_DEF void zpl_vec2_dcslerp(zpl_vec2 *d, zpl_vec2 a, zpl_vec2 v0, zpl_vec2 b, zpl_vec2 v1, zpl_f32 t); - ZPL_DEF void zpl_vec3_dcslerp(zpl_vec3 *d, zpl_vec3 a, zpl_vec3 v0, zpl_vec3 b, zpl_vec3 v1, zpl_f32 t); - - ZPL_DEF void zpl_quat_lerp(zpl_quat *d, zpl_quat a, zpl_quat b, zpl_f32 t); - ZPL_DEF void zpl_quat_nlerp(zpl_quat *d, zpl_quat a, zpl_quat b, zpl_f32 t); - ZPL_DEF void zpl_quat_slerp(zpl_quat *d, zpl_quat a, zpl_quat b, zpl_f32 t); - ZPL_DEF void zpl_quat_nquad(zpl_quat *d, zpl_quat p, zpl_quat a, zpl_quat b, zpl_quat q, zpl_f32 t); - ZPL_DEF void zpl_quat_squad(zpl_quat *d, zpl_quat p, zpl_quat a, zpl_quat b, zpl_quat q, zpl_f32 t); - ZPL_DEF void zpl_quat_slerp_approx(zpl_quat *d, zpl_quat a, zpl_quat b, zpl_f32 t); - ZPL_DEF void zpl_quat_squad_approx(zpl_quat *d, zpl_quat p, zpl_quat a, zpl_quat b, zpl_quat q, zpl_f32 t); - - /* rects */ - ZPL_DEF zpl_rect2 zpl_rect2f(zpl_vec2 pos, zpl_vec2 dim); - ZPL_DEF zpl_rect3 zpl_rect3f(zpl_vec3 pos, zpl_vec3 dim); - - ZPL_DEF zpl_aabb2 zpl_aabb2f(zpl_f32 minx, zpl_f32 miny, zpl_f32 maxx, zpl_f32 maxy); - ZPL_DEF zpl_aabb3 zpl_aabb3f(zpl_f32 minx, zpl_f32 miny, zpl_f32 minz, zpl_f32 maxx, zpl_f32 maxy, zpl_f32 maxz); - - ZPL_DEF zpl_aabb2 zpl_aabb2_rect2(zpl_rect2 a); - ZPL_DEF zpl_aabb3 zpl_aabb3_rect3(zpl_rect3 a); - ZPL_DEF zpl_rect2 zpl_rect2_aabb2(zpl_aabb2 a); - ZPL_DEF zpl_rect3 zpl_rect3_aabb3(zpl_aabb3 a); - - ZPL_DEF int zpl_rect2_contains(zpl_rect2 a, zpl_f32 x, zpl_f32 y); - ZPL_DEF int zpl_rect2_contains_vec2(zpl_rect2 a, zpl_vec2 p); - ZPL_DEF int zpl_rect2_intersects(zpl_rect2 a, zpl_rect2 b); - ZPL_DEF int zpl_rect2_intersection_result(zpl_rect2 a, zpl_rect2 b, zpl_rect2 *intersection); - ZPL_DEF int zpl_aabb2_contains(zpl_aabb2 a, zpl_f32 x, zpl_f32 y); - ZPL_DEF int zpl_aabb3_contains(zpl_aabb3 a, zpl_f32 x, zpl_f32 y, zpl_f32 z); - - /* rectangle partitioning: based on https://halt.software/dead-simple-layouts/ */ - ZPL_DEF zpl_aabb2 zpl_aabb2_cut_left(zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_cut_right(zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_cut_top(zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_cut_bottom(zpl_aabb2 *a, zpl_f32 b); - - ZPL_DEF zpl_aabb2 zpl_aabb2_get_left(const zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_get_right(const zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_get_top(const zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_get_bottom(const zpl_aabb2 *a, zpl_f32 b); - - ZPL_DEF zpl_aabb2 zpl_aabb2_add_left(const zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_add_right(const zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_add_top(const zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_add_bottom(const zpl_aabb2 *a, zpl_f32 b); - - ZPL_DEF zpl_aabb2 zpl_aabb2_contract(const zpl_aabb2 *a, zpl_f32 b); - ZPL_DEF zpl_aabb2 zpl_aabb2_expand(const zpl_aabb2 *a, zpl_f32 b); - - //! @} - ZPL_END_C_DECLS - #if defined(__cplusplus) - ZPL_INLINE bool operator==(zpl_vec2 a, zpl_vec2 b) { return (a.x == b.x) && (a.y == b.y); } - ZPL_INLINE bool operator!=(zpl_vec2 a, zpl_vec2 b) { return !operator==(a, b); } - - ZPL_INLINE zpl_vec2 operator+(zpl_vec2 a) { return a; } - ZPL_INLINE zpl_vec2 operator-(zpl_vec2 a) { zpl_vec2 r = {-a.x, -a.y}; return r; } - - ZPL_INLINE zpl_vec2 operator+(zpl_vec2 a, zpl_vec2 b) { zpl_vec2 r; zpl_vec2_add(&r, a, b); return r; } - ZPL_INLINE zpl_vec2 operator-(zpl_vec2 a, zpl_vec2 b) { zpl_vec2 r; zpl_vec2_sub(&r, a, b); return r; } - - ZPL_INLINE zpl_vec2 operator*(zpl_vec2 a, float scalar) { zpl_vec2 r; zpl_vec2_mul(&r, a, scalar); return r; } - ZPL_INLINE zpl_vec2 operator*(float scalar, zpl_vec2 a) { return operator*(a, scalar); } - - ZPL_INLINE zpl_vec2 operator/(zpl_vec2 a, float scalar) { return operator*(a, 1.0f/scalar); } - - /* Hadamard Product */ - ZPL_INLINE zpl_vec2 operator*(zpl_vec2 a, zpl_vec2 b) { zpl_vec2 r = {a.x*b.x, a.y*b.y}; return r; } - ZPL_INLINE zpl_vec2 operator/(zpl_vec2 a, zpl_vec2 b) { zpl_vec2 r = {a.x/b.x, a.y/b.y}; return r; } - - ZPL_INLINE zpl_vec2 &operator+=(zpl_vec2 &a, zpl_vec2 b) { return (a = a + b); } - ZPL_INLINE zpl_vec2 &operator-=(zpl_vec2 &a, zpl_vec2 b) { return (a = a - b); } - ZPL_INLINE zpl_vec2 &operator*=(zpl_vec2 &a, float scalar) { return (a = a * scalar); } - ZPL_INLINE zpl_vec2 &operator/=(zpl_vec2 &a, float scalar) { return (a = a / scalar); } - - - ZPL_INLINE bool operator==(zpl_vec3 a, zpl_vec3 b) { return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); } - ZPL_INLINE bool operator!=(zpl_vec3 a, zpl_vec3 b) { return !operator==(a, b); } - - ZPL_INLINE zpl_vec3 operator+(zpl_vec3 a) { return a; } - ZPL_INLINE zpl_vec3 operator-(zpl_vec3 a) { zpl_vec3 r = {-a.x, -a.y, -a.z}; return r; } - - ZPL_INLINE zpl_vec3 operator+(zpl_vec3 a, zpl_vec3 b) { zpl_vec3 r; zpl_vec3_add(&r, a, b); return r; } - ZPL_INLINE zpl_vec3 operator-(zpl_vec3 a, zpl_vec3 b) { zpl_vec3 r; zpl_vec3_sub(&r, a, b); return r; } - - ZPL_INLINE zpl_vec3 operator*(zpl_vec3 a, float scalar) { zpl_vec3 r; zpl_vec3_mul(&r, a, scalar); return r; } - ZPL_INLINE zpl_vec3 operator*(float scalar, zpl_vec3 a) { return operator*(a, scalar); } - - ZPL_INLINE zpl_vec3 operator/(zpl_vec3 a, float scalar) { return operator*(a, 1.0f/scalar); } - - /* Hadamard Product */ - ZPL_INLINE zpl_vec3 operator*(zpl_vec3 a, zpl_vec3 b) { zpl_vec3 r = {a.x*b.x, a.y*b.y, a.z*b.z}; return r; } - ZPL_INLINE zpl_vec3 operator/(zpl_vec3 a, zpl_vec3 b) { zpl_vec3 r = {a.x/b.x, a.y/b.y, a.z/b.z}; return r; } - - ZPL_INLINE zpl_vec3 &operator+=(zpl_vec3 &a, zpl_vec3 b) { return (a = a + b); } - ZPL_INLINE zpl_vec3 &operator-=(zpl_vec3 &a, zpl_vec3 b) { return (a = a - b); } - ZPL_INLINE zpl_vec3 &operator*=(zpl_vec3 &a, float scalar) { return (a = a * scalar); } - ZPL_INLINE zpl_vec3 &operator/=(zpl_vec3 &a, float scalar) { return (a = a / scalar); } - - - ZPL_INLINE bool operator==(zpl_vec4 a, zpl_vec4 b) { return (a.x == b.x) && (a.y == b.y) && (a.z == b.z) && (a.w == b.w); } - ZPL_INLINE bool operator!=(zpl_vec4 a, zpl_vec4 b) { return !operator==(a, b); } - - ZPL_INLINE zpl_vec4 operator+(zpl_vec4 a) { return a; } - ZPL_INLINE zpl_vec4 operator-(zpl_vec4 a) { zpl_vec4 r = {-a.x, -a.y, -a.z, -a.w}; return r; } - - ZPL_INLINE zpl_vec4 operator+(zpl_vec4 a, zpl_vec4 b) { zpl_vec4 r; zpl_vec4_add(&r, a, b); return r; } - ZPL_INLINE zpl_vec4 operator-(zpl_vec4 a, zpl_vec4 b) { zpl_vec4 r; zpl_vec4_sub(&r, a, b); return r; } - - ZPL_INLINE zpl_vec4 operator*(zpl_vec4 a, float scalar) { zpl_vec4 r; zpl_vec4_mul(&r, a, scalar); return r; } - ZPL_INLINE zpl_vec4 operator*(float scalar, zpl_vec4 a) { return operator*(a, scalar); } - - ZPL_INLINE zpl_vec4 operator/(zpl_vec4 a, float scalar) { return operator*(a, 1.0f/scalar); } - - /* Hadamard Product */ - ZPL_INLINE zpl_vec4 operator*(zpl_vec4 a, zpl_vec4 b) { zpl_vec4 r = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return r; } - ZPL_INLINE zpl_vec4 operator/(zpl_vec4 a, zpl_vec4 b) { zpl_vec4 r = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return r; } - - ZPL_INLINE zpl_vec4 &operator+=(zpl_vec4 &a, zpl_vec4 b) { return (a = a + b); } - ZPL_INLINE zpl_vec4 &operator-=(zpl_vec4 &a, zpl_vec4 b) { return (a = a - b); } - ZPL_INLINE zpl_vec4 &operator*=(zpl_vec4 &a, float scalar) { return (a = a * scalar); } - ZPL_INLINE zpl_vec4 &operator/=(zpl_vec4 &a, float scalar) { return (a = a / scalar); } - - - ZPL_INLINE zpl_mat2 operator+(zpl_mat2 const &a, zpl_mat2 const &b) { - int i, j; - zpl_mat2 r = {0}; - for (j = 0; j < 2; j++) { - for (i = 0; i < 2; i++) - r.e[2*j+i] = a.e[2*j+i] + b.e[2*j+i]; - } - return r; - } - - ZPL_INLINE zpl_mat2 operator-(zpl_mat2 const &a, zpl_mat2 const &b) { - int i, j; - zpl_mat2 r = {0}; - for (j = 0; j < 2; j++) { - for (i = 0; i < 2; i++) - r.e[2*j+i] = a.e[2*j+i] - b.e[2*j+i]; - } - return r; - } - - ZPL_INLINE zpl_mat2 operator*(zpl_mat2 const &a, zpl_mat2 const &b) { zpl_mat2 r; zpl_mat2_mul(&r, (zpl_mat2 *)&a, (zpl_mat2 *)&b); return r; } - ZPL_INLINE zpl_vec2 operator*(zpl_mat2 const &a, zpl_vec2 v) { zpl_vec2 r; zpl_mat2_mul_vec2(&r, (zpl_mat2 *)&a, v); return r; } - ZPL_INLINE zpl_mat2 operator*(zpl_mat2 const &a, float scalar) { - zpl_mat2 r = {0}; - int i; - for (i = 0; i < 2*2; i++) r.e[i] = a.e[i] * scalar; - return r; - } - ZPL_INLINE zpl_mat2 operator*(float scalar, zpl_mat2 const &a) { return operator*(a, scalar); } - ZPL_INLINE zpl_mat2 operator/(zpl_mat2 const &a, float scalar) { return operator*(a, 1.0f/scalar); } - - ZPL_INLINE zpl_mat2& operator+=(zpl_mat2& a, zpl_mat2 const &b) { return (a = a + b); } - ZPL_INLINE zpl_mat2& operator-=(zpl_mat2& a, zpl_mat2 const &b) { return (a = a - b); } - ZPL_INLINE zpl_mat2& operator*=(zpl_mat2& a, zpl_mat2 const &b) { return (a = a * b); } - - - - ZPL_INLINE zpl_mat3 operator+(zpl_mat3 const &a, zpl_mat3 const &b) { - int i, j; - zpl_mat3 r = {0}; - for (j = 0; j < 3; j++) { - for (i = 0; i < 3; i++) - r.e[3*j+i] = a.e[3*j+i] + b.e[3*j+i]; - } - return r; - } - - ZPL_INLINE zpl_mat3 operator-(zpl_mat3 const &a, zpl_mat3 const &b) { - int i, j; - zpl_mat3 r = {0}; - for (j = 0; j < 3; j++) { - for (i = 0; i < 3; i++) - r.e[3*j+i] = a.e[3*j+i] - b.e[3*j+i]; - } - return r; - } - - ZPL_INLINE zpl_mat3 operator*(zpl_mat3 const &a, zpl_mat3 const &b) { zpl_mat3 r; zpl_mat3_mul(&r, (zpl_mat3 *)&a, (zpl_mat3 *)&b); return r; } - ZPL_INLINE zpl_vec3 operator*(zpl_mat3 const &a, zpl_vec3 v) { zpl_vec3 r; zpl_mat3_mul_vec3(&r, (zpl_mat3 *)&a, v); return r; } - ZPL_INLINE zpl_mat3 operator*(zpl_mat3 const &a, float scalar) { - zpl_mat3 r = {0}; - int i; - for (i = 0; i < 3*3; i++) r.e[i] = a.e[i] * scalar; - return r; - } - ZPL_INLINE zpl_mat3 operator*(float scalar, zpl_mat3 const &a) { return operator*(a, scalar); } - ZPL_INLINE zpl_mat3 operator/(zpl_mat3 const &a, float scalar) { return operator*(a, 1.0f/scalar); } - - ZPL_INLINE zpl_mat3& operator+=(zpl_mat3& a, zpl_mat3 const &b) { return (a = a + b); } - ZPL_INLINE zpl_mat3& operator-=(zpl_mat3& a, zpl_mat3 const &b) { return (a = a - b); } - ZPL_INLINE zpl_mat3& operator*=(zpl_mat3& a, zpl_mat3 const &b) { return (a = a * b); } - - - - ZPL_INLINE zpl_mat4 operator+(zpl_mat4 const &a, zpl_mat4 const &b) { - int i, j; - zpl_mat4 r = {0}; - for (j = 0; j < 4; j++) { - for (i = 0; i < 4; i++) - r.e[4*j+i] = a.e[4*j+i] + b.e[4*j+i]; - } - return r; - } - - ZPL_INLINE zpl_mat4 operator-(zpl_mat4 const &a, zpl_mat4 const &b) { - int i, j; - zpl_mat4 r = {0}; - for (j = 0; j < 4; j++) { - for (i = 0; i < 4; i++) - r.e[4*j+i] = a.e[4*j+i] - b.e[4*j+i]; - } - return r; - } - - ZPL_INLINE zpl_mat4 operator*(zpl_mat4 const &a, zpl_mat4 const &b) { zpl_mat4 r; zpl_mat4_mul(&r, (zpl_mat4 *)&a, (zpl_mat4 *)&b); return r; } - ZPL_INLINE zpl_vec4 operator*(zpl_mat4 const &a, zpl_vec4 v) { zpl_vec4 r; zpl_mat4_mul_vec4(&r, (zpl_mat4 *)&a, v); return r; } - ZPL_INLINE zpl_mat4 operator*(zpl_mat4 const &a, float scalar) { - zpl_mat4 r = {0}; - int i; - for (i = 0; i < 4*4; i++) r.e[i] = a.e[i] * scalar; - return r; - } - ZPL_INLINE zpl_mat4 operator*(float scalar, zpl_mat4 const &a) { return operator*(a, scalar); } - ZPL_INLINE zpl_mat4 operator/(zpl_mat4 const &a, float scalar) { return operator*(a, 1.0f/scalar); } - - ZPL_INLINE zpl_mat4& operator+=(zpl_mat4 &a, zpl_mat4 const &b) { return (a = a + b); } - ZPL_INLINE zpl_mat4& operator-=(zpl_mat4 &a, zpl_mat4 const &b) { return (a = a - b); } - ZPL_INLINE zpl_mat4& operator*=(zpl_mat4 &a, zpl_mat4 const &b) { return (a = a * b); } - - - - ZPL_INLINE bool operator==(zpl_quat a, zpl_quat b) { return a.xyzw == b.xyzw; } - ZPL_INLINE bool operator!=(zpl_quat a, zpl_quat b) { return !operator==(a, b); } - - ZPL_INLINE zpl_quat operator+(zpl_quat q) { return q; } - ZPL_INLINE zpl_quat operator-(zpl_quat q) { return zpl_quatf(-q.x, -q.y, -q.z, -q.w); } - - ZPL_INLINE zpl_quat operator+(zpl_quat a, zpl_quat b) { zpl_quat r; zpl_quat_add(&r, a, b); return r; } - ZPL_INLINE zpl_quat operator-(zpl_quat a, zpl_quat b) { zpl_quat r; zpl_quat_sub(&r, a, b); return r; } - - ZPL_INLINE zpl_quat operator*(zpl_quat a, zpl_quat b) { zpl_quat r; zpl_quat_mul(&r, a, b); return r; } - ZPL_INLINE zpl_quat operator*(zpl_quat q, float s) { zpl_quat r; zpl_quat_mulf(&r, q, s); return r; } - ZPL_INLINE zpl_quat operator*(float s, zpl_quat q) { return operator*(q, s); } - ZPL_INLINE zpl_quat operator/(zpl_quat q, float s) { zpl_quat r; zpl_quat_divf(&r, q, s); return r; } - - ZPL_INLINE zpl_quat &operator+=(zpl_quat &a, zpl_quat b) { zpl_quat_addeq(&a, b); return a; } - ZPL_INLINE zpl_quat &operator-=(zpl_quat &a, zpl_quat b) { zpl_quat_subeq(&a, b); return a; } - ZPL_INLINE zpl_quat &operator*=(zpl_quat &a, zpl_quat b) { zpl_quat_muleq(&a, b); return a; } - ZPL_INLINE zpl_quat &operator/=(zpl_quat &a, zpl_quat b) { zpl_quat_diveq(&a, b); return a; } - - ZPL_INLINE zpl_quat &operator*=(zpl_quat &a, float b) { zpl_quat_muleqf(&a, b); return a; } - ZPL_INLINE zpl_quat &operator/=(zpl_quat &a, float b) { zpl_quat_diveqf(&a, b); return a; } - - /* Rotate v by a */ - ZPL_INLINE zpl_vec3 operator*(zpl_quat q, zpl_vec3 v) { zpl_vec3 r; zpl_quat_rotate_vec3(&r, q, v); return r; } + // file: header/math.h + + /** @file math.c + @brief Math operations + @defgroup math Math operations + + OpenGL gamedev friendly library for math. + + @{ + */ + + ZPL_BEGIN_C_DECLS + + typedef union zpl_vec2 { + struct { + zpl_f32 x, y; + }; + struct { + zpl_f32 s, t; + }; + zpl_f32 e[2]; + } zpl_vec2; + + typedef union zpl_vec3 { + struct { + zpl_f32 x, y, z; + }; + struct { + zpl_f32 r, g, b; + }; + struct { + zpl_f32 s, t, p; + }; + + zpl_vec2 xy; + zpl_vec2 st; + zpl_f32 e[3]; + } zpl_vec3; + + typedef union zpl_vec4 { + struct { + zpl_f32 x, y, z, w; + }; + struct { + zpl_f32 r, g, b, a; + }; + struct { + zpl_f32 s, t, p, q; + }; + struct { + zpl_vec2 xy, zw; + }; + struct { + zpl_vec2 st, pq; + }; + zpl_vec3 xyz; + zpl_vec3 rgb; + zpl_f32 e[4]; + } zpl_vec4; + + typedef union zpl_mat2 { + struct { + zpl_vec2 x, y; + }; + zpl_vec2 col[2]; + zpl_f32 e[4]; + } zpl_mat2; + + typedef union zpl_mat3 { + struct { + zpl_vec3 x, y, z; + }; + zpl_vec3 col[3]; + zpl_f32 e[9]; + } zpl_mat3; + + typedef union zpl_mat4 { + struct { + zpl_vec4 x, y, z, w; + }; + zpl_vec4 col[4]; + zpl_f32 e[16]; + } zpl_mat4; + + typedef union zpl_quat { + struct { + zpl_f32 x, y, z, w; + }; + zpl_vec4 xyzw; + zpl_vec3 xyz; + zpl_f32 e[4]; + } zpl_quat; + + typedef union zpl_plane { + struct { + zpl_f32 a, b, c, d; + }; + zpl_vec4 xyzw; + zpl_vec3 n; + zpl_f32 e[4]; + } zpl_plane; + + typedef struct zpl_frustum { + zpl_plane x1; + zpl_plane x2; + zpl_plane y1; + zpl_plane y2; + zpl_plane z1; + zpl_plane z2; + } zpl_frustum; + + typedef zpl_f32 zpl_float2[2]; + typedef zpl_f32 zpl_float3[3]; + typedef zpl_f32 zpl_float4[4]; + + typedef struct zpl_rect2 { + zpl_vec2 pos, dim; + } zpl_rect2; + typedef struct zpl_rect3 { + zpl_vec3 pos, dim; + } zpl_rect3; + + typedef struct zpl_aabb2 { + zpl_vec2 min, max; + } zpl_aabb2; + typedef struct zpl_aabb3 { + zpl_vec3 min, max; + } zpl_aabb3; + + typedef short zpl_half; + + #ifndef ZPL_CONSTANTS + #define ZPL_CONSTANTS + #define ZPL_EPSILON 1.19209290e-7f + #define ZPL_ZERO 0.0f + #define ZPL_ONE 1.0f + #define ZPL_TWO_THIRDS 0.666666666666666666666666666666666666667f + + #define ZPL_TAU 6.28318530717958647692528676655900576f + #define ZPL_PI 3.14159265358979323846264338327950288f + #define ZPL_ONE_OVER_TAU 0.636619772367581343075535053490057448f + #define ZPL_ONE_OVER_PI 0.159154943091895335768883763372514362f + + #define ZPL_TAU_OVER_2 3.14159265358979323846264338327950288f + #define ZPL_TAU_OVER_4 1.570796326794896619231321691639751442f + #define ZPL_TAU_OVER_8 0.785398163397448309615660845819875721f + + #define ZPL_E 2.71828182845904523536f + #define ZPL_SQRT_TWO 1.41421356237309504880168872420969808f + #define ZPL_SQRT_THREE 1.73205080756887729352744634150587236f + #define ZPL_SQRT_FIVE 2.23606797749978969640917366873127623f + + #define ZPL_LOG_TWO 0.693147180559945309417232121458176568f + #define ZPL_LOG_TEN 2.30258509299404568401799145468436421f + #endif // ZPL_CONSTANTS + + #ifndef zpl_square + #define zpl_square(x) ((x) * (x)) + #endif + + #ifndef zpl_cube + #define zpl_cube(x) ((x) * (x) * (x)) + #endif + + #ifndef zpl_sign + #define zpl_sign(x) ((x) >= 0.0f ? 1.0f : -1.0f) + #endif + + #ifndef zpl_sign0 + #define zpl_sign0(x) ((x == 0.0f) ? 0.0f : ((x) >= 0.0f ? 1.0f : -1.0f)) + #endif + + ZPL_DEF zpl_f32 zpl_to_radians(zpl_f32 degrees); + ZPL_DEF zpl_f32 zpl_to_degrees(zpl_f32 radians); + + /* NOTE: Because to interpolate angles */ + ZPL_DEF zpl_f32 zpl_angle_diff(zpl_f32 radians_a, zpl_f32 radians_b); + + ZPL_DEF zpl_f32 zpl_copy_sign(zpl_f32 x, zpl_f32 y); + ZPL_DEF zpl_f32 zpl_remainder(zpl_f32 x, zpl_f32 y); + ZPL_DEF zpl_f32 zpl_mod(zpl_f32 x, zpl_f32 y); + ZPL_DEF zpl_f64 zpl_copy_sign64(zpl_f64 x, zpl_f64 y); + ZPL_DEF zpl_f64 zpl_floor64(zpl_f64 x); + ZPL_DEF zpl_f64 zpl_ceil64(zpl_f64 x); + ZPL_DEF zpl_f64 zpl_round64(zpl_f64 x); + ZPL_DEF zpl_f64 zpl_remainder64(zpl_f64 x, zpl_f64 y); + ZPL_DEF zpl_f64 zpl_abs64(zpl_f64 x); + ZPL_DEF zpl_f64 zpl_sign64(zpl_f64 x); + ZPL_DEF zpl_f64 zpl_mod64(zpl_f64 x, zpl_f64 y); + ZPL_DEF zpl_f32 zpl_sqrt(zpl_f32 a); + ZPL_DEF zpl_f32 zpl_rsqrt(zpl_f32 a); + ZPL_DEF zpl_f32 zpl_quake_rsqrt(zpl_f32 a); /* NOTE: It's probably better to use 1.0f/zpl_sqrt(a) + * And for simd, there is usually isqrt functions too! + */ + ZPL_DEF zpl_f32 zpl_sin(zpl_f32 radians); + ZPL_DEF zpl_f32 zpl_cos(zpl_f32 radians); + ZPL_DEF zpl_f32 zpl_tan(zpl_f32 radians); + ZPL_DEF zpl_f32 zpl_arcsin(zpl_f32 a); + ZPL_DEF zpl_f32 zpl_arccos(zpl_f32 a); + ZPL_DEF zpl_f32 zpl_arctan(zpl_f32 a); + ZPL_DEF zpl_f32 zpl_arctan2(zpl_f32 y, zpl_f32 x); + + ZPL_DEF zpl_f32 zpl_exp(zpl_f32 x); + ZPL_DEF zpl_f32 zpl_exp2(zpl_f32 x); + ZPL_DEF zpl_f32 zpl_log(zpl_f32 x); + ZPL_DEF zpl_f32 zpl_log2(zpl_f32 x); + ZPL_DEF zpl_f32 zpl_fast_exp(zpl_f32 x); /* NOTE: Only valid from -1 <= x <= +1 */ + ZPL_DEF zpl_f32 zpl_fast_exp2(zpl_f32 x); /* NOTE: Only valid from -1 <= x <= +1 */ + ZPL_DEF zpl_f32 zpl_pow(zpl_f32 x, zpl_f32 y); /* x^y */ + + ZPL_DEF zpl_f32 zpl_round(zpl_f32 x); + ZPL_DEF zpl_f32 zpl_floor(zpl_f32 x); + ZPL_DEF zpl_f32 zpl_ceil(zpl_f32 x); + + ZPL_DEF zpl_f32 zpl_half_to_float(zpl_half value); + ZPL_DEF zpl_half zpl_float_to_half(zpl_f32 value); + + ZPL_DEF zpl_vec2 zpl_vec2f_zero(void); + ZPL_DEF zpl_vec2 zpl_vec2f(zpl_f32 x, zpl_f32 y); + ZPL_DEF zpl_vec2 zpl_vec2fv(zpl_f32 x[2]); + + ZPL_DEF zpl_vec3 zpl_vec3f_zero(void); + ZPL_DEF zpl_vec3 zpl_vec3f(zpl_f32 x, zpl_f32 y, zpl_f32 z); + ZPL_DEF zpl_vec3 zpl_vec3fv(zpl_f32 x[3]); + + ZPL_DEF zpl_vec4 zpl_vec4f_zero(void); + ZPL_DEF zpl_vec4 zpl_vec4f(zpl_f32 x, zpl_f32 y, zpl_f32 z, zpl_f32 w); + ZPL_DEF zpl_vec4 zpl_vec4fv(zpl_f32 x[4]); + + ZPL_DEF zpl_f32 zpl_vec2_max(zpl_vec2 v); + ZPL_DEF zpl_f32 zpl_vec2_side(zpl_vec2 p, zpl_vec2 q, zpl_vec2 r); + ZPL_DEF void zpl_vec2_add(zpl_vec2 *d, zpl_vec2 v0, zpl_vec2 v1); + ZPL_DEF void zpl_vec2_sub(zpl_vec2 *d, zpl_vec2 v0, zpl_vec2 v1); + ZPL_DEF void zpl_vec2_mul(zpl_vec2 *d, zpl_vec2 v, zpl_f32 s); + ZPL_DEF void zpl_vec2_div(zpl_vec2 *d, zpl_vec2 v, zpl_f32 s); + + ZPL_DEF zpl_f32 zpl_vec3_max(zpl_vec3 v); + ZPL_DEF void zpl_vec3_add(zpl_vec3 *d, zpl_vec3 v0, zpl_vec3 v1); + ZPL_DEF void zpl_vec3_sub(zpl_vec3 *d, zpl_vec3 v0, zpl_vec3 v1); + ZPL_DEF void zpl_vec3_mul(zpl_vec3 *d, zpl_vec3 v, zpl_f32 s); + ZPL_DEF void zpl_vec3_div(zpl_vec3 *d, zpl_vec3 v, zpl_f32 s); + + ZPL_DEF void zpl_vec4_add(zpl_vec4 *d, zpl_vec4 v0, zpl_vec4 v1); + ZPL_DEF void zpl_vec4_sub(zpl_vec4 *d, zpl_vec4 v0, zpl_vec4 v1); + ZPL_DEF void zpl_vec4_mul(zpl_vec4 *d, zpl_vec4 v, zpl_f32 s); + ZPL_DEF void zpl_vec4_div(zpl_vec4 *d, zpl_vec4 v, zpl_f32 s); + + ZPL_DEF void zpl_vec2_addeq(zpl_vec2 *d, zpl_vec2 v); + ZPL_DEF void zpl_vec2_subeq(zpl_vec2 *d, zpl_vec2 v); + ZPL_DEF void zpl_vec2_muleq(zpl_vec2 *d, zpl_f32 s); + ZPL_DEF void zpl_vec2_diveq(zpl_vec2 *d, zpl_f32 s); + + ZPL_DEF void zpl_vec3_addeq(zpl_vec3 *d, zpl_vec3 v); + ZPL_DEF void zpl_vec3_subeq(zpl_vec3 *d, zpl_vec3 v); + ZPL_DEF void zpl_vec3_muleq(zpl_vec3 *d, zpl_f32 s); + ZPL_DEF void zpl_vec3_diveq(zpl_vec3 *d, zpl_f32 s); + + ZPL_DEF void zpl_vec4_addeq(zpl_vec4 *d, zpl_vec4 v); + ZPL_DEF void zpl_vec4_subeq(zpl_vec4 *d, zpl_vec4 v); + ZPL_DEF void zpl_vec4_muleq(zpl_vec4 *d, zpl_f32 s); + ZPL_DEF void zpl_vec4_diveq(zpl_vec4 *d, zpl_f32 s); + + ZPL_DEF zpl_f32 zpl_vec2_dot(zpl_vec2 v0, zpl_vec2 v1); + ZPL_DEF zpl_f32 zpl_vec3_dot(zpl_vec3 v0, zpl_vec3 v1); + ZPL_DEF zpl_f32 zpl_vec4_dot(zpl_vec4 v0, zpl_vec4 v1); + + ZPL_DEF void zpl_vec2_cross(zpl_f32 *d, zpl_vec2 v0, zpl_vec2 v1); + ZPL_DEF void zpl_vec3_cross(zpl_vec3 *d, zpl_vec3 v0, zpl_vec3 v1); + + ZPL_DEF zpl_f32 zpl_vec2_mag2(zpl_vec2 v); + ZPL_DEF zpl_f32 zpl_vec3_mag2(zpl_vec3 v); + ZPL_DEF zpl_f32 zpl_vec4_mag2(zpl_vec4 v); + + ZPL_DEF zpl_f32 zpl_vec2_mag(zpl_vec2 v); + ZPL_DEF zpl_f32 zpl_vec3_mag(zpl_vec3 v); + ZPL_DEF zpl_f32 zpl_vec4_mag(zpl_vec4 v); + + ZPL_DEF void zpl_vec2_norm(zpl_vec2 *d, zpl_vec2 v); + ZPL_DEF void zpl_vec3_norm(zpl_vec3 *d, zpl_vec3 v); + ZPL_DEF void zpl_vec4_norm(zpl_vec4 *d, zpl_vec4 v); + + ZPL_DEF void zpl_vec2_norm0(zpl_vec2 *d, zpl_vec2 v); + ZPL_DEF void zpl_vec3_norm0(zpl_vec3 *d, zpl_vec3 v); + ZPL_DEF void zpl_vec4_norm0(zpl_vec4 *d, zpl_vec4 v); + + ZPL_DEF void zpl_vec2_reflect(zpl_vec2 *d, zpl_vec2 i, zpl_vec2 n); + ZPL_DEF void zpl_vec3_reflect(zpl_vec3 *d, zpl_vec3 i, zpl_vec3 n); + ZPL_DEF void zpl_vec2_refract(zpl_vec2 *d, zpl_vec2 i, zpl_vec2 n, zpl_f32 eta); + ZPL_DEF void zpl_vec3_refract(zpl_vec3 *d, zpl_vec3 i, zpl_vec3 n, zpl_f32 eta); + + ZPL_DEF zpl_f32 zpl_vec2_aspect_ratio(zpl_vec2 v); + + ZPL_DEF void zpl_mat2_identity(zpl_mat2 *m); + ZPL_DEF void zpl_float22_identity(zpl_f32 m[2][2]); + + ZPL_DEF void zpl_mat2_transpose(zpl_mat2 *m); + ZPL_DEF void zpl_mat2_mul(zpl_mat2 *out, zpl_mat2 *m1, zpl_mat2 *m2); + ZPL_DEF void zpl_mat2_mul_vec2(zpl_vec2 *out, zpl_mat2 *m, zpl_vec2 in); + ZPL_DEF void zpl_mat2_inverse(zpl_mat2 *out, zpl_mat2 *in); + ZPL_DEF zpl_f32 zpl_mat2_determinate(zpl_mat2 *m); + + ZPL_DEF zpl_mat2 *zpl_mat2_v(zpl_vec2 m[2]); + ZPL_DEF zpl_mat2 *zpl_mat2_f(zpl_f32 m[2][2]); + ZPL_DEF zpl_float2 *zpl_float22_m(zpl_mat2 *m); + ZPL_DEF zpl_float2 *zpl_float22_v(zpl_vec2 m[2]); + ZPL_DEF zpl_float2 *zpl_float22_4(zpl_f32 m[4]); + + ZPL_DEF void zpl_float22_transpose(zpl_f32 (*vec)[2]); + ZPL_DEF void zpl_float22_mul(zpl_f32 (*out)[2], zpl_f32 (*mat1)[2], zpl_f32 (*mat2)[2]); + ZPL_DEF void zpl_float22_mul_vec2(zpl_vec2 *out, zpl_f32 m[2][2], zpl_vec2 in); + + ZPL_DEF void zpl_mat3_identity(zpl_mat3 *m); + ZPL_DEF void zpl_float33_identity(zpl_f32 m[3][3]); + + ZPL_DEF void zpl_mat3_transpose(zpl_mat3 *m); + ZPL_DEF void zpl_mat3_mul(zpl_mat3 *out, zpl_mat3 *m1, zpl_mat3 *m2); + ZPL_DEF void zpl_mat3_mul_vec3(zpl_vec3 *out, zpl_mat3 *m, zpl_vec3 in); + ZPL_DEF void zpl_mat3_inverse(zpl_mat3 *out, zpl_mat3 *in); + ZPL_DEF zpl_f32 zpl_mat3_determinate(zpl_mat3 *m); + + ZPL_DEF zpl_mat3 *zpl_mat3_v(zpl_vec3 m[3]); + ZPL_DEF zpl_mat3 *zpl_mat3_f(zpl_f32 m[3][3]); + + ZPL_DEF zpl_float3 *zpl_float33_m(zpl_mat3 *m); + ZPL_DEF zpl_float3 *zpl_float33_v(zpl_vec3 m[3]); + ZPL_DEF zpl_float3 *zpl_float33_9(zpl_f32 m[9]); + + ZPL_DEF void zpl_float33_transpose(zpl_f32 (*vec)[3]); + ZPL_DEF void zpl_float33_mul(zpl_f32 (*out)[3], zpl_f32 (*mat1)[3], zpl_f32 (*mat2)[3]); + ZPL_DEF void zpl_float33_mul_vec3(zpl_vec3 *out, zpl_f32 m[3][3], zpl_vec3 in); + + ZPL_DEF void zpl_mat4_identity(zpl_mat4 *m); + ZPL_DEF void zpl_float44_identity(zpl_f32 m[4][4]); + ZPL_DEF void zpl_mat4_copy(zpl_mat4* out, zpl_mat4* m); + + ZPL_DEF void zpl_mat4_transpose(zpl_mat4 *m); + ZPL_DEF void zpl_mat4_mul(zpl_mat4 *out, zpl_mat4 *m1, zpl_mat4 *m2); + ZPL_DEF void zpl_mat4_mul_vec4(zpl_vec4 *out, zpl_mat4 *m, zpl_vec4 in); + ZPL_DEF void zpl_mat4_inverse(zpl_mat4 *out, zpl_mat4 *in); + + ZPL_DEF zpl_mat4 *zpl_mat4_v(zpl_vec4 m[4]); + ZPL_DEF zpl_mat4 *zpl_mat4_f(zpl_f32 m[4][4]); + + ZPL_DEF zpl_float4 *zpl_float44_m(zpl_mat4 *m); + ZPL_DEF zpl_float4 *zpl_float44_v(zpl_vec4 m[4]); + ZPL_DEF zpl_float4 *zpl_float44_16(zpl_f32 m[16]); + + ZPL_DEF void zpl_float44_transpose(zpl_f32 (*vec)[4]); + ZPL_DEF void zpl_float44_mul(zpl_f32 (*out)[4], zpl_f32 (*mat1)[4], zpl_f32 (*mat2)[4]); + ZPL_DEF void zpl_float44_mul_vec4(zpl_vec4 *out, zpl_f32 m[4][4], zpl_vec4 in); + + ZPL_DEF void zpl_mat4_axis_angle(zpl_mat4* out, zpl_vec3 v, zpl_f32 angle_radians); + ZPL_DEF void zpl_mat4_to_translate(zpl_mat4* out, zpl_vec3 v); + ZPL_DEF void zpl_mat4_to_rotate(zpl_mat4* out, zpl_vec3 v, zpl_f32 angle_radians); + ZPL_DEF void zpl_mat4_to_scale(zpl_mat4* out, zpl_vec3 v); + ZPL_DEF void zpl_mat4_to_scalef(zpl_mat4* out, zpl_f32 s); + ZPL_DEF void zpl_mat4_translate(zpl_mat4* out, zpl_vec3 v); + ZPL_DEF void zpl_mat4_rotate(zpl_mat4* out, zpl_vec3 v, zpl_f32 angle_radians); + ZPL_DEF void zpl_mat4_scale(zpl_mat4* out, zpl_vec3 v); + ZPL_DEF void zpl_mat4_scalef(zpl_mat4 *out, zpl_f32 s); + ZPL_DEF void zpl_mat4_ortho2d(zpl_mat4 *out, zpl_f32 left, zpl_f32 right, zpl_f32 bottom, zpl_f32 top); + ZPL_DEF void zpl_mat4_ortho3d(zpl_mat4 *out, zpl_f32 left, zpl_f32 right, zpl_f32 bottom, zpl_f32 top, zpl_f32 z_near, zpl_f32 z_far); + ZPL_DEF void zpl_mat4_perspective(zpl_mat4 *out, zpl_f32 fovy, zpl_f32 aspect, zpl_f32 z_near, zpl_f32 z_far); + ZPL_DEF void zpl_mat4_infinite_perspective(zpl_mat4 *out, zpl_f32 fovy, zpl_f32 aspect, zpl_f32 z_near); + + ZPL_DEF void zpl_mat4_ortho2d_dx(zpl_mat4 *out, zpl_f32 left, zpl_f32 right, zpl_f32 bottom, zpl_f32 top); + ZPL_DEF void zpl_mat4_ortho3d_dx(zpl_mat4 *out, zpl_f32 left, zpl_f32 right, zpl_f32 bottom, zpl_f32 top, zpl_f32 z_near, zpl_f32 z_far); + ZPL_DEF void zpl_mat4_perspective_dx(zpl_mat4 *out, zpl_f32 fovy, zpl_f32 aspect, zpl_f32 z_near, zpl_f32 z_far); + ZPL_DEF void zpl_mat4_infinite_perspective_dx(zpl_mat4 *out, zpl_f32 fovy, zpl_f32 aspect, zpl_f32 z_near); + + ZPL_DEF void zpl_mat4_look_at(zpl_mat4 *out, zpl_vec3 eye, zpl_vec3 centre, zpl_vec3 up); + + ZPL_DEF void zpl_mat4_look_at_lh(zpl_mat4 *out, zpl_vec3 eye, zpl_vec3 centre, zpl_vec3 up); + + ZPL_DEF zpl_quat zpl_quatf(zpl_f32 x, zpl_f32 y, zpl_f32 z, zpl_f32 w); + ZPL_DEF zpl_quat zpl_quatfv(zpl_f32 e[4]); + ZPL_DEF zpl_quat zpl_quat_axis_angle(zpl_vec3 axis, zpl_f32 angle_radians); + ZPL_DEF zpl_quat zpl_quat_euler_angles(zpl_f32 pitch, zpl_f32 yaw, zpl_f32 roll); + ZPL_DEF zpl_quat zpl_quat_identity(void); + + ZPL_DEF void zpl_quat_add(zpl_quat *d, zpl_quat q0, zpl_quat q1); + ZPL_DEF void zpl_quat_sub(zpl_quat *d, zpl_quat q0, zpl_quat q1); + ZPL_DEF void zpl_quat_mul(zpl_quat *d, zpl_quat q0, zpl_quat q1); + ZPL_DEF void zpl_quat_div(zpl_quat *d, zpl_quat q0, zpl_quat q1); + + ZPL_DEF void zpl_quat_mulf(zpl_quat *d, zpl_quat q, zpl_f32 s); + ZPL_DEF void zpl_quat_divf(zpl_quat *d, zpl_quat q, zpl_f32 s); + + ZPL_DEF void zpl_quat_addeq(zpl_quat *d, zpl_quat q); + ZPL_DEF void zpl_quat_subeq(zpl_quat *d, zpl_quat q); + ZPL_DEF void zpl_quat_muleq(zpl_quat *d, zpl_quat q); + ZPL_DEF void zpl_quat_diveq(zpl_quat *d, zpl_quat q); + + ZPL_DEF void zpl_quat_muleqf(zpl_quat *d, zpl_f32 s); + ZPL_DEF void zpl_quat_diveqf(zpl_quat *d, zpl_f32 s); + + ZPL_DEF zpl_f32 zpl_quat_dot(zpl_quat q0, zpl_quat q1); + ZPL_DEF zpl_f32 zpl_quat_mag(zpl_quat q); + + ZPL_DEF void zpl_quat_norm(zpl_quat *d, zpl_quat q); + ZPL_DEF void zpl_quat_conj(zpl_quat *d, zpl_quat q); + ZPL_DEF void zpl_quat_inverse(zpl_quat *d, zpl_quat q); + + ZPL_DEF void zpl_quat_axis(zpl_vec3 *axis, zpl_quat q); + ZPL_DEF zpl_f32 zpl_quat_angle(zpl_quat q); + + ZPL_DEF zpl_f32 zpl_quat_pitch(zpl_quat q); + ZPL_DEF zpl_f32 zpl_quat_yaw(zpl_quat q); + ZPL_DEF zpl_f32 zpl_quat_roll(zpl_quat q); + + /* NOTE: Rotate v by q */ + ZPL_DEF void zpl_quat_rotate_vec3(zpl_vec3 *d, zpl_quat q, zpl_vec3 v); + ZPL_DEF void zpl_mat4_from_quat(zpl_mat4 *out, zpl_quat q); + ZPL_DEF void zpl_quat_from_mat4(zpl_quat *out, zpl_mat4 *m); + + /* Plane math. */ + ZPL_DEF zpl_f32 zpl_plane_distance(zpl_plane* p, zpl_vec3 v); + + /* Frustum culling. */ + ZPL_DEF void zpl_frustum_create(zpl_frustum* out, zpl_mat4* camera, zpl_mat4* proj); + ZPL_DEF zpl_b8 zpl_frustum_sphere_inside(zpl_frustum* frustum, zpl_vec3 center, zpl_f32 radius); + ZPL_DEF zpl_b8 zpl_frustum_point_inside(zpl_frustum* frustum, zpl_vec3 point); + ZPL_DEF zpl_b8 zpl_frustum_box_inside(zpl_frustum* frustum, zpl_aabb3 box); + + /* Interpolations */ + ZPL_DEF zpl_f32 zpl_lerp(zpl_f32 a, zpl_f32 b, zpl_f32 t); + ZPL_DEF zpl_f32 zpl_unlerp(zpl_f32 t, zpl_f32 a, zpl_f32 b); + ZPL_DEF zpl_f32 zpl_smooth_step(zpl_f32 a, zpl_f32 b, zpl_f32 t); + ZPL_DEF zpl_f32 zpl_smoother_step(zpl_f32 a, zpl_f32 b, zpl_f32 t); + + ZPL_DEF void zpl_vec2_lerp(zpl_vec2 *d, zpl_vec2 a, zpl_vec2 b, zpl_f32 t); + ZPL_DEF void zpl_vec3_lerp(zpl_vec3 *d, zpl_vec3 a, zpl_vec3 b, zpl_f32 t); + ZPL_DEF void zpl_vec4_lerp(zpl_vec4 *d, zpl_vec4 a, zpl_vec4 b, zpl_f32 t); + + ZPL_DEF void zpl_vec2_cslerp(zpl_vec2 *d, zpl_vec2 a, zpl_vec2 v0, zpl_vec2 b, zpl_vec2 v1, zpl_f32 t); + ZPL_DEF void zpl_vec3_cslerp(zpl_vec3 *d, zpl_vec3 a, zpl_vec3 v0, zpl_vec3 b, zpl_vec3 v1, zpl_f32 t); + ZPL_DEF void zpl_vec2_dcslerp(zpl_vec2 *d, zpl_vec2 a, zpl_vec2 v0, zpl_vec2 b, zpl_vec2 v1, zpl_f32 t); + ZPL_DEF void zpl_vec3_dcslerp(zpl_vec3 *d, zpl_vec3 a, zpl_vec3 v0, zpl_vec3 b, zpl_vec3 v1, zpl_f32 t); + + ZPL_DEF void zpl_quat_lerp(zpl_quat *d, zpl_quat a, zpl_quat b, zpl_f32 t); + ZPL_DEF void zpl_quat_nlerp(zpl_quat *d, zpl_quat a, zpl_quat b, zpl_f32 t); + ZPL_DEF void zpl_quat_slerp(zpl_quat *d, zpl_quat a, zpl_quat b, zpl_f32 t); + ZPL_DEF void zpl_quat_nquad(zpl_quat *d, zpl_quat p, zpl_quat a, zpl_quat b, zpl_quat q, zpl_f32 t); + ZPL_DEF void zpl_quat_squad(zpl_quat *d, zpl_quat p, zpl_quat a, zpl_quat b, zpl_quat q, zpl_f32 t); + ZPL_DEF void zpl_quat_slerp_approx(zpl_quat *d, zpl_quat a, zpl_quat b, zpl_f32 t); + ZPL_DEF void zpl_quat_squad_approx(zpl_quat *d, zpl_quat p, zpl_quat a, zpl_quat b, zpl_quat q, zpl_f32 t); + + /* rects */ + ZPL_DEF zpl_rect2 zpl_rect2f(zpl_vec2 pos, zpl_vec2 dim); + ZPL_DEF zpl_rect3 zpl_rect3f(zpl_vec3 pos, zpl_vec3 dim); + + ZPL_DEF zpl_aabb2 zpl_aabb2f(zpl_f32 minx, zpl_f32 miny, zpl_f32 maxx, zpl_f32 maxy); + ZPL_DEF zpl_aabb3 zpl_aabb3f(zpl_f32 minx, zpl_f32 miny, zpl_f32 minz, zpl_f32 maxx, zpl_f32 maxy, zpl_f32 maxz); + + ZPL_DEF zpl_aabb2 zpl_aabb2_rect2(zpl_rect2 a); + ZPL_DEF zpl_aabb3 zpl_aabb3_rect3(zpl_rect3 a); + ZPL_DEF zpl_rect2 zpl_rect2_aabb2(zpl_aabb2 a); + ZPL_DEF zpl_rect3 zpl_rect3_aabb3(zpl_aabb3 a); + + ZPL_DEF int zpl_rect2_contains(zpl_rect2 a, zpl_f32 x, zpl_f32 y); + ZPL_DEF int zpl_rect2_contains_vec2(zpl_rect2 a, zpl_vec2 p); + ZPL_DEF int zpl_rect2_intersects(zpl_rect2 a, zpl_rect2 b); + ZPL_DEF int zpl_rect2_intersection_result(zpl_rect2 a, zpl_rect2 b, zpl_rect2 *intersection); + ZPL_DEF int zpl_aabb2_contains(zpl_aabb2 a, zpl_f32 x, zpl_f32 y); + ZPL_DEF int zpl_aabb3_contains(zpl_aabb3 a, zpl_f32 x, zpl_f32 y, zpl_f32 z); + + /* rectangle partitioning: based on https://halt.software/dead-simple-layouts/ */ + ZPL_DEF zpl_aabb2 zpl_aabb2_cut_left(zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_cut_right(zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_cut_top(zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_cut_bottom(zpl_aabb2 *a, zpl_f32 b); + + ZPL_DEF zpl_aabb2 zpl_aabb2_get_left(const zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_get_right(const zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_get_top(const zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_get_bottom(const zpl_aabb2 *a, zpl_f32 b); + + ZPL_DEF zpl_aabb2 zpl_aabb2_add_left(const zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_add_right(const zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_add_top(const zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_add_bottom(const zpl_aabb2 *a, zpl_f32 b); + + ZPL_DEF zpl_aabb2 zpl_aabb2_contract(const zpl_aabb2 *a, zpl_f32 b); + ZPL_DEF zpl_aabb2 zpl_aabb2_expand(const zpl_aabb2 *a, zpl_f32 b); + + //! @} + ZPL_END_C_DECLS + #if defined(__cplusplus) + ZPL_INLINE bool operator==(zpl_vec2 a, zpl_vec2 b) { return (a.x == b.x) && (a.y == b.y); } + ZPL_INLINE bool operator!=(zpl_vec2 a, zpl_vec2 b) { return !operator==(a, b); } + + ZPL_INLINE zpl_vec2 operator+(zpl_vec2 a) { return a; } + ZPL_INLINE zpl_vec2 operator-(zpl_vec2 a) { zpl_vec2 r = {-a.x, -a.y}; return r; } + + ZPL_INLINE zpl_vec2 operator+(zpl_vec2 a, zpl_vec2 b) { zpl_vec2 r; zpl_vec2_add(&r, a, b); return r; } + ZPL_INLINE zpl_vec2 operator-(zpl_vec2 a, zpl_vec2 b) { zpl_vec2 r; zpl_vec2_sub(&r, a, b); return r; } + + ZPL_INLINE zpl_vec2 operator*(zpl_vec2 a, float scalar) { zpl_vec2 r; zpl_vec2_mul(&r, a, scalar); return r; } + ZPL_INLINE zpl_vec2 operator*(float scalar, zpl_vec2 a) { return operator*(a, scalar); } + + ZPL_INLINE zpl_vec2 operator/(zpl_vec2 a, float scalar) { return operator*(a, 1.0f/scalar); } + + /* Hadamard Product */ + ZPL_INLINE zpl_vec2 operator*(zpl_vec2 a, zpl_vec2 b) { zpl_vec2 r = {a.x*b.x, a.y*b.y}; return r; } + ZPL_INLINE zpl_vec2 operator/(zpl_vec2 a, zpl_vec2 b) { zpl_vec2 r = {a.x/b.x, a.y/b.y}; return r; } + + ZPL_INLINE zpl_vec2 &operator+=(zpl_vec2 &a, zpl_vec2 b) { return (a = a + b); } + ZPL_INLINE zpl_vec2 &operator-=(zpl_vec2 &a, zpl_vec2 b) { return (a = a - b); } + ZPL_INLINE zpl_vec2 &operator*=(zpl_vec2 &a, float scalar) { return (a = a * scalar); } + ZPL_INLINE zpl_vec2 &operator/=(zpl_vec2 &a, float scalar) { return (a = a / scalar); } + + + ZPL_INLINE bool operator==(zpl_vec3 a, zpl_vec3 b) { return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); } + ZPL_INLINE bool operator!=(zpl_vec3 a, zpl_vec3 b) { return !operator==(a, b); } + + ZPL_INLINE zpl_vec3 operator+(zpl_vec3 a) { return a; } + ZPL_INLINE zpl_vec3 operator-(zpl_vec3 a) { zpl_vec3 r = {-a.x, -a.y, -a.z}; return r; } + + ZPL_INLINE zpl_vec3 operator+(zpl_vec3 a, zpl_vec3 b) { zpl_vec3 r; zpl_vec3_add(&r, a, b); return r; } + ZPL_INLINE zpl_vec3 operator-(zpl_vec3 a, zpl_vec3 b) { zpl_vec3 r; zpl_vec3_sub(&r, a, b); return r; } + + ZPL_INLINE zpl_vec3 operator*(zpl_vec3 a, float scalar) { zpl_vec3 r; zpl_vec3_mul(&r, a, scalar); return r; } + ZPL_INLINE zpl_vec3 operator*(float scalar, zpl_vec3 a) { return operator*(a, scalar); } + + ZPL_INLINE zpl_vec3 operator/(zpl_vec3 a, float scalar) { return operator*(a, 1.0f/scalar); } + + /* Hadamard Product */ + ZPL_INLINE zpl_vec3 operator*(zpl_vec3 a, zpl_vec3 b) { zpl_vec3 r = {a.x*b.x, a.y*b.y, a.z*b.z}; return r; } + ZPL_INLINE zpl_vec3 operator/(zpl_vec3 a, zpl_vec3 b) { zpl_vec3 r = {a.x/b.x, a.y/b.y, a.z/b.z}; return r; } + + ZPL_INLINE zpl_vec3 &operator+=(zpl_vec3 &a, zpl_vec3 b) { return (a = a + b); } + ZPL_INLINE zpl_vec3 &operator-=(zpl_vec3 &a, zpl_vec3 b) { return (a = a - b); } + ZPL_INLINE zpl_vec3 &operator*=(zpl_vec3 &a, float scalar) { return (a = a * scalar); } + ZPL_INLINE zpl_vec3 &operator/=(zpl_vec3 &a, float scalar) { return (a = a / scalar); } + + + ZPL_INLINE bool operator==(zpl_vec4 a, zpl_vec4 b) { return (a.x == b.x) && (a.y == b.y) && (a.z == b.z) && (a.w == b.w); } + ZPL_INLINE bool operator!=(zpl_vec4 a, zpl_vec4 b) { return !operator==(a, b); } + + ZPL_INLINE zpl_vec4 operator+(zpl_vec4 a) { return a; } + ZPL_INLINE zpl_vec4 operator-(zpl_vec4 a) { zpl_vec4 r = {-a.x, -a.y, -a.z, -a.w}; return r; } + + ZPL_INLINE zpl_vec4 operator+(zpl_vec4 a, zpl_vec4 b) { zpl_vec4 r; zpl_vec4_add(&r, a, b); return r; } + ZPL_INLINE zpl_vec4 operator-(zpl_vec4 a, zpl_vec4 b) { zpl_vec4 r; zpl_vec4_sub(&r, a, b); return r; } + + ZPL_INLINE zpl_vec4 operator*(zpl_vec4 a, float scalar) { zpl_vec4 r; zpl_vec4_mul(&r, a, scalar); return r; } + ZPL_INLINE zpl_vec4 operator*(float scalar, zpl_vec4 a) { return operator*(a, scalar); } + + ZPL_INLINE zpl_vec4 operator/(zpl_vec4 a, float scalar) { return operator*(a, 1.0f/scalar); } + + /* Hadamard Product */ + ZPL_INLINE zpl_vec4 operator*(zpl_vec4 a, zpl_vec4 b) { zpl_vec4 r = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return r; } + ZPL_INLINE zpl_vec4 operator/(zpl_vec4 a, zpl_vec4 b) { zpl_vec4 r = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return r; } + + ZPL_INLINE zpl_vec4 &operator+=(zpl_vec4 &a, zpl_vec4 b) { return (a = a + b); } + ZPL_INLINE zpl_vec4 &operator-=(zpl_vec4 &a, zpl_vec4 b) { return (a = a - b); } + ZPL_INLINE zpl_vec4 &operator*=(zpl_vec4 &a, float scalar) { return (a = a * scalar); } + ZPL_INLINE zpl_vec4 &operator/=(zpl_vec4 &a, float scalar) { return (a = a / scalar); } + + + ZPL_INLINE zpl_mat2 operator+(zpl_mat2 const &a, zpl_mat2 const &b) { + int i, j; + zpl_mat2 r = {0}; + for (j = 0; j < 2; j++) { + for (i = 0; i < 2; i++) + r.e[2*j+i] = a.e[2*j+i] + b.e[2*j+i]; + } + return r; + } + + ZPL_INLINE zpl_mat2 operator-(zpl_mat2 const &a, zpl_mat2 const &b) { + int i, j; + zpl_mat2 r = {0}; + for (j = 0; j < 2; j++) { + for (i = 0; i < 2; i++) + r.e[2*j+i] = a.e[2*j+i] - b.e[2*j+i]; + } + return r; + } + + ZPL_INLINE zpl_mat2 operator*(zpl_mat2 const &a, zpl_mat2 const &b) { zpl_mat2 r; zpl_mat2_mul(&r, (zpl_mat2 *)&a, (zpl_mat2 *)&b); return r; } + ZPL_INLINE zpl_vec2 operator*(zpl_mat2 const &a, zpl_vec2 v) { zpl_vec2 r; zpl_mat2_mul_vec2(&r, (zpl_mat2 *)&a, v); return r; } + ZPL_INLINE zpl_mat2 operator*(zpl_mat2 const &a, float scalar) { + zpl_mat2 r = {0}; + int i; + for (i = 0; i < 2*2; i++) r.e[i] = a.e[i] * scalar; + return r; + } + ZPL_INLINE zpl_mat2 operator*(float scalar, zpl_mat2 const &a) { return operator*(a, scalar); } + ZPL_INLINE zpl_mat2 operator/(zpl_mat2 const &a, float scalar) { return operator*(a, 1.0f/scalar); } + + ZPL_INLINE zpl_mat2& operator+=(zpl_mat2& a, zpl_mat2 const &b) { return (a = a + b); } + ZPL_INLINE zpl_mat2& operator-=(zpl_mat2& a, zpl_mat2 const &b) { return (a = a - b); } + ZPL_INLINE zpl_mat2& operator*=(zpl_mat2& a, zpl_mat2 const &b) { return (a = a * b); } + + + + ZPL_INLINE zpl_mat3 operator+(zpl_mat3 const &a, zpl_mat3 const &b) { + int i, j; + zpl_mat3 r = {0}; + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) + r.e[3*j+i] = a.e[3*j+i] + b.e[3*j+i]; + } + return r; + } + + ZPL_INLINE zpl_mat3 operator-(zpl_mat3 const &a, zpl_mat3 const &b) { + int i, j; + zpl_mat3 r = {0}; + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) + r.e[3*j+i] = a.e[3*j+i] - b.e[3*j+i]; + } + return r; + } + + ZPL_INLINE zpl_mat3 operator*(zpl_mat3 const &a, zpl_mat3 const &b) { zpl_mat3 r; zpl_mat3_mul(&r, (zpl_mat3 *)&a, (zpl_mat3 *)&b); return r; } + ZPL_INLINE zpl_vec3 operator*(zpl_mat3 const &a, zpl_vec3 v) { zpl_vec3 r; zpl_mat3_mul_vec3(&r, (zpl_mat3 *)&a, v); return r; } + ZPL_INLINE zpl_mat3 operator*(zpl_mat3 const &a, float scalar) { + zpl_mat3 r = {0}; + int i; + for (i = 0; i < 3*3; i++) r.e[i] = a.e[i] * scalar; + return r; + } + ZPL_INLINE zpl_mat3 operator*(float scalar, zpl_mat3 const &a) { return operator*(a, scalar); } + ZPL_INLINE zpl_mat3 operator/(zpl_mat3 const &a, float scalar) { return operator*(a, 1.0f/scalar); } + + ZPL_INLINE zpl_mat3& operator+=(zpl_mat3& a, zpl_mat3 const &b) { return (a = a + b); } + ZPL_INLINE zpl_mat3& operator-=(zpl_mat3& a, zpl_mat3 const &b) { return (a = a - b); } + ZPL_INLINE zpl_mat3& operator*=(zpl_mat3& a, zpl_mat3 const &b) { return (a = a * b); } + + + + ZPL_INLINE zpl_mat4 operator+(zpl_mat4 const &a, zpl_mat4 const &b) { + int i, j; + zpl_mat4 r = {0}; + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++) + r.e[4*j+i] = a.e[4*j+i] + b.e[4*j+i]; + } + return r; + } + + ZPL_INLINE zpl_mat4 operator-(zpl_mat4 const &a, zpl_mat4 const &b) { + int i, j; + zpl_mat4 r = {0}; + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++) + r.e[4*j+i] = a.e[4*j+i] - b.e[4*j+i]; + } + return r; + } + + ZPL_INLINE zpl_mat4 operator*(zpl_mat4 const &a, zpl_mat4 const &b) { zpl_mat4 r; zpl_mat4_mul(&r, (zpl_mat4 *)&a, (zpl_mat4 *)&b); return r; } + ZPL_INLINE zpl_vec4 operator*(zpl_mat4 const &a, zpl_vec4 v) { zpl_vec4 r; zpl_mat4_mul_vec4(&r, (zpl_mat4 *)&a, v); return r; } + ZPL_INLINE zpl_mat4 operator*(zpl_mat4 const &a, float scalar) { + zpl_mat4 r = {0}; + int i; + for (i = 0; i < 4*4; i++) r.e[i] = a.e[i] * scalar; + return r; + } + ZPL_INLINE zpl_mat4 operator*(float scalar, zpl_mat4 const &a) { return operator*(a, scalar); } + ZPL_INLINE zpl_mat4 operator/(zpl_mat4 const &a, float scalar) { return operator*(a, 1.0f/scalar); } + + ZPL_INLINE zpl_mat4& operator+=(zpl_mat4 &a, zpl_mat4 const &b) { return (a = a + b); } + ZPL_INLINE zpl_mat4& operator-=(zpl_mat4 &a, zpl_mat4 const &b) { return (a = a - b); } + ZPL_INLINE zpl_mat4& operator*=(zpl_mat4 &a, zpl_mat4 const &b) { return (a = a * b); } + + + + ZPL_INLINE bool operator==(zpl_quat a, zpl_quat b) { return a.xyzw == b.xyzw; } + ZPL_INLINE bool operator!=(zpl_quat a, zpl_quat b) { return !operator==(a, b); } + + ZPL_INLINE zpl_quat operator+(zpl_quat q) { return q; } + ZPL_INLINE zpl_quat operator-(zpl_quat q) { return zpl_quatf(-q.x, -q.y, -q.z, -q.w); } + + ZPL_INLINE zpl_quat operator+(zpl_quat a, zpl_quat b) { zpl_quat r; zpl_quat_add(&r, a, b); return r; } + ZPL_INLINE zpl_quat operator-(zpl_quat a, zpl_quat b) { zpl_quat r; zpl_quat_sub(&r, a, b); return r; } + + ZPL_INLINE zpl_quat operator*(zpl_quat a, zpl_quat b) { zpl_quat r; zpl_quat_mul(&r, a, b); return r; } + ZPL_INLINE zpl_quat operator*(zpl_quat q, float s) { zpl_quat r; zpl_quat_mulf(&r, q, s); return r; } + ZPL_INLINE zpl_quat operator*(float s, zpl_quat q) { return operator*(q, s); } + ZPL_INLINE zpl_quat operator/(zpl_quat q, float s) { zpl_quat r; zpl_quat_divf(&r, q, s); return r; } + + ZPL_INLINE zpl_quat &operator+=(zpl_quat &a, zpl_quat b) { zpl_quat_addeq(&a, b); return a; } + ZPL_INLINE zpl_quat &operator-=(zpl_quat &a, zpl_quat b) { zpl_quat_subeq(&a, b); return a; } + ZPL_INLINE zpl_quat &operator*=(zpl_quat &a, zpl_quat b) { zpl_quat_muleq(&a, b); return a; } + ZPL_INLINE zpl_quat &operator/=(zpl_quat &a, zpl_quat b) { zpl_quat_diveq(&a, b); return a; } + + ZPL_INLINE zpl_quat &operator*=(zpl_quat &a, float b) { zpl_quat_muleqf(&a, b); return a; } + ZPL_INLINE zpl_quat &operator/=(zpl_quat &a, float b) { zpl_quat_diveqf(&a, b); return a; } + + /* Rotate v by a */ + ZPL_INLINE zpl_vec3 operator*(zpl_quat q, zpl_vec3 v) { zpl_vec3 r; zpl_quat_rotate_vec3(&r, q, v); return r; } #endif #endif @@ -21520,11 +21520,13 @@ int32_t librg_world_query(librg_world *world, int64_t owner_id, uint8_t chunk_ra size_t buffer_limit = *entity_amount; size_t total_count = zpl_array_count(wld->entity_map.entries); - librg_table_i64 results = {0}; - librg_table_tbl dimensions = {0}; + static librg_table_i64 results = {0}; + static librg_table_tbl dimensions = {0}; - librg_table_i64_init(&results, wld->allocator); - librg_table_tbl_init(&dimensions, wld->allocator); + if (!results.entries) { + librg_table_i64_init(&results, wld->allocator); + librg_table_tbl_init(&dimensions, wld->allocator); + } /* generate a map of visible chunks (only counting owned entities) */ for (size_t i=0; i < total_count; ++i) { @@ -21621,8 +21623,19 @@ int32_t librg_world_query(librg_world *world, int64_t owner_id, uint8_t chunk_ra for (int i = 0; i < zpl_array_count(dimensions.entries); ++i) librg_table_i64_destroy(&dimensions.entries[i].value); - librg_table_tbl_destroy(&dimensions); - librg_table_i64_destroy(&results); + // NOTE(zaklaus): clear out our streaming snapshot + // TODO(zaklaus): move this to zpl + { + zpl_array_clear(results.hashes); + zpl_array_clear(results.entries); + } + + // NOTE(zaklaus): clear out our streaming snapshot + // TODO(zaklaus): move this to zpl + { + zpl_array_clear(dimensions.hashes); + zpl_array_clear(dimensions.entries); + } *entity_amount = LIBRG_MIN(buffer_limit, count); return LIBRG_MAX(0, (int32_t)(count - buffer_limit));