From e092599816eda8a0a340655c3e66ae49e2a987e2 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Tue, 28 Nov 2023 23:17:40 +0000 Subject: [PATCH] freelist --- source/engine/freelist.h | 60 ++++++++++++++++++++++++++++++++++++++++ source/engine/particle.c | 32 +++++++-------------- source/engine/particle.h | 30 ++++++++++---------- source/engine/sprite.c | 35 ++++++++++++----------- 4 files changed, 101 insertions(+), 56 deletions(-) create mode 100644 source/engine/freelist.h diff --git a/source/engine/freelist.h b/source/engine/freelist.h new file mode 100644 index 0000000..3b8a4b6 --- /dev/null +++ b/source/engine/freelist.h @@ -0,0 +1,60 @@ +#ifndef FREELIST_H +#define FREELIST_H + +/* Given a pointer to a struct, create a free list + Struct must have a 'next' field +*/ + +struct freelistheader +{ + unsigned int first; + unsigned int len; +}; + +#define freelist_header(p) ((struct freelistheader*)p-1) +static inline void *freelist_make(struct freelistheader *list, size_t elemsize, unsigned int n) +{ + list = malloc(elemsize*n*sizeof(struct freelistheader)); + list->first = 0; + list->len = n; + return list+1; +} + +static inline unsigned int freelist_check(struct freelistheader *h, void *data, size_t elemsize) +{ + if (h->first > h->len) return -1; + unsigned int id = h->first; + return id; +} + +#define freelist_size(p,l) do{p = freelist_make(p,sizeof(*p),l); for(int i = 0; i < l; i++) { p[i].next = i+1; }}while(0) +#define freelist_len(p) (freelist_header(p)->len) +#define freelist_first(p) (freelist_header(p)->first) +#define freelist_grab(i,p) do{i=freelist_header(p)->first; freelist_header(p)->first = p[i].next; p[i].next = -1;}while(0) +#define freelist_kill(p,i) do{p[i].next = freelist_first(p);freelist_first(p)=i;}while(0) +#define freelist_free(p) (free(freelist_header(p))) + +struct link_header +{ + int len; + void *head; + void *last; +}; + +static inline void *add_link(struct link_header *h, size_t size) +{ + void *n = malloc(size); + return n; +} +#define link_header(p) ((struct link_header*)p-1) +#define link_head(p) (link_header(p)->head) +#define link_last(p) (link_header(p)->last) +#define link_add(p,v) do{ +#define link_each(p,fn) do {void *f = p; while (link_header(p)->head != NULL) { fn(p); p = p->next; }; p = f; }while(0) +#define link_e(p,i) ( + +#define stack_size(p,n) (p = malloc(sizeof(p)*n)) +#define stack_push(p,v) () +#define stack_pop(p) () + +#endif diff --git a/source/engine/particle.c b/source/engine/particle.c index 3185f53..aa0abeb 100644 --- a/source/engine/particle.c +++ b/source/engine/particle.c @@ -1,20 +1,10 @@ #include "particle.h" #include "stb_ds.h" +#include "freelist.h" struct emitter make_emitter() { struct emitter e = {0}; - return e; -} - -struct emitter set_emitter(struct emitter e) { - arrsetlen(e.particles, e.max); - - e.first = &e.particles[0]; - - for (int i = 0; i < arrlen(e.particles) - 1; i++) { - e.particles[i].next = &e.particles[i + 1]; - } - + arrsetcap(e.particles, 200); return e; } @@ -23,26 +13,24 @@ void free_emitter(struct emitter e) { } void start_emitter(struct emitter e) { + } void pause_emitter(struct emitter e) { + } void stop_emitter(struct emitter e) { + } void emitter_step(struct emitter e, double dt) { for (int i = 0; i < arrlen(e.particles); i++) { - if (e.particles[i].life <= 0) - continue; + e.particles[i].pos = HMM_AddV3(e.particles[i].pos, HMM_MulV3F(e.particles[i].v, dt)); + e.particles[i].angle = HMM_MulQ(e.particles[i].angle, HMM_MulQF(e.particles[i].angle, dt)); + e.particles[i].life -= dt; - e.particles[i].pos = cpvadd(e.particles[i].pos, cpvmult(e.particles[i].v, dt)); - e.particles[i].angle += e.particles[i].av * dt; - e.particles[i].life -= dt; - - if (e.particles[i].life <= 0) { - e.particles[i].next = e.first; - e.first = &e.particles[i]; - } + if (e.particles[i].life <= 0) + arrdelswap(e.particles, i); } } diff --git a/source/engine/particle.h b/source/engine/particle.h index de2c785..a1d8731 100644 --- a/source/engine/particle.h +++ b/source/engine/particle.h @@ -1,27 +1,25 @@ #ifndef PARTICLE_H #define PARTICLE_H -#include +#include "HandmadeMath.h" struct particle { - cpVect pos; - cpVect v; /* velocity */ - double angle; - double av; /* angular velocity */ + HMM_Vec3 pos; + HMM_Vec3 v; /* velocity */ + HMM_Quat angle; + HMM_Quat av; /* angular velocity */ - - union { - double life; - struct particle *next; - }; + union { + double life; + unsigned int next; + }; }; struct emitter { - struct particle *particles; - struct particle *first; - int max; - double life; - void (*seeder)(struct particle *p); /* Called to initialize each particle */ + struct particle *particles; + int max; + double life; + void (*seeder)(struct particle *p); /* Called to initialize each particle */ }; struct emitter make_emitter(); @@ -33,4 +31,4 @@ void stop_emitter(struct emitter e); void emitter_step(struct emitter e, double dt); -#endif \ No newline at end of file +#endif diff --git a/source/engine/sprite.c b/source/engine/sprite.c index 144d463..216e065 100644 --- a/source/engine/sprite.c +++ b/source/engine/sprite.c @@ -13,14 +13,14 @@ #include #include #include "HandmadeMath.h" +#include "freelist.h" #include "sprite.sglsl.h" #include "9slice.sglsl.h" struct TextureOptions TEX_SPRITE = {1, 0, 0}; -static struct sprite *sprites; -static int first = -1; +static struct sprite *sprites = NULL; static sg_shader shader_sprite; static sg_pipeline pip_sprite; @@ -59,29 +59,21 @@ int make_sprite(int go) { .size = {1.f, 1.f}, .tex = texture_loadfromfile(NULL), .go = go, - .next = -1, .layer = 0, + .next = -1, .enabled = 1}; - int slot = 0; - if (first < 0) { - arrput(sprites, sprite); - slot = arrlen(sprites)-1; - } else { - slot = first; - first = id2sprite(first)->next; - *id2sprite(slot) = sprite; - } - - return slot; + int id; + freelist_grab(id, sprites); + sprites[id] = sprite; + return id; } void sprite_delete(int id) { struct sprite *sp = id2sprite(id); sp->go = -1; sp->enabled = 0; - sp->next = first; - first = id; + freelist_kill(sprites,id); } void sprite_enabled(int id, int e) { @@ -132,8 +124,9 @@ void sprite_draw_all() { static int *layers; if (layers) arrfree(layers); - for (int i = 0; i < arrlen(sprites); i++) - if (sprites[i].go >= 0 && sprites[i].enabled) arrpush(layers, i); + for (int i = 0; i < freelist_len(sprites); i++) + if (sprites[i].next == -1 && sprites[i].go >= 0 && sprites[i].enabled) + arrpush(layers, i); if (arrlen(layers) == 0) return; if (arrlen(layers) > 1) @@ -144,6 +137,10 @@ void sprite_draw_all() { } void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) { + if (!sprite) { + YughWarn("NO SPRITE!"); + return; + } sprite->tex = texture_loadfromfile(path); sprite_setframe(sprite, &frame); } @@ -154,6 +151,8 @@ void sprite_settex(struct sprite *sprite, struct Texture *tex) { } void sprite_initialize() { + freelist_size(sprites, 500); + shader_sprite = sg_make_shader(sprite_shader_desc(sg_query_backend())); pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){