From 6b8af9cf83851c075c6c9514b1deaa931c2b19a4 Mon Sep 17 00:00:00 2001 From: Thomas Guillermo Albers Raviola Date: Fri, 16 Jan 2026 23:02:32 +0100 Subject: Initial commit --- 09-september/tomcat/particles/particles.c | 153 ++++++++++++++++++++++++++++++ 09-september/tomcat/particles/particles.h | 62 ++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 09-september/tomcat/particles/particles.c create mode 100644 09-september/tomcat/particles/particles.h (limited to '09-september/tomcat/particles') diff --git a/09-september/tomcat/particles/particles.c b/09-september/tomcat/particles/particles.c new file mode 100644 index 0000000..5e99e06 --- /dev/null +++ b/09-september/tomcat/particles/particles.c @@ -0,0 +1,153 @@ +#include "particles.h" +#include "../util/util_time.h" +#include "../util/util.h" + +#include +#include + +ParticleManager particles; + +static int compare_particles(const void *_a, const void *_b); + +void Particles_Init() +{ + memset( &particles, 0, sizeof(ParticleManager) ); +} + +ParticleSystem *Particles_AddSystem() +{ + if(particles.num_systems >= MAX_PARTICLES_SYSTEMS) + return NULL; + + ParticleSystem *s = malloc( sizeof(ParticleSystem) ); + particles.systems[particles.num_systems] = s; + memset( s, 0, sizeof(ParticleSystem) ); + + particles.num_systems += 1; + + return s; +} + +void Particles_RemoveSystem(ParticleSystem *system) +{ + int index = &system - particles.systems; + + if(index > MAX_PARTICLES_SYSTEMS || index < 0) + { + fprintf(stderr, "Invalid particle system!\n"); + return; + } + /* TODO: Finish this function */ +} + +void Particles_EmitParticle(ParticleSystem *system, Particle *p) +{ + if(system->num_particles >= MAX_PARTICLES_PER_SYSTEM) + return; + + Particle *dest = &system->particles[system->num_particles]; + memcpy(dest, p, sizeof(Particle)); + + system->num_particles += 1; +} + +void Particles_Update(const Vec3 *camera_position) +{ + Particle *c = NULL; /* Current particle */ + ParticleSystem *s = NULL; /* Current particle system */ + Texture *t = NULL; /* Texture of the current system */ + Vec3 d; /* Vector for calculating the distance to the camera */ + Vec3 velocity; + + int i, j; + for(i = 0; i < particles.num_systems; i++) + { + s = particles.systems[i]; + t = s->texture; + + /* We ceil it so we dont truncate the decimal part and get always 0 */ + int particles_to_emit = (int)ceil( s->emit_rate * Time_GetFrameTime() ); + + /* Emit the automatically emited particles */ + for(j = 0; j < particles_to_emit; j++) + { + velocity.x = Util_RandomF(0.0f, 50.0f); + velocity.y = Util_RandomF(0.0f, 50.0f); + velocity.z = Util_RandomF(0.0f, 50.0f); + velocity = vec3_normalize(&velocity); + + if(s->num_particles >= MAX_PARTICLES_PER_SYSTEM) + break; /* So we dont overflow */ + + c = &s->particles[s->num_particles ++]; + memset(c, 0, sizeof(Particle)); + + c->life_length = s->life_length; + c->position = s->position; + c->scale = 10.0f; + c->weight = s->weight; + c->velocity = vec3_scalar_mul(&velocity, s->speed); + } + + for(j = 0; j < s->num_particles; j++) + { + c = &s->particles[j]; + + /* Update each particle -.- */ + c->velocity.y += c->weight * Time_GetFrameTime(); + Vec3 velocity = vec3_scalar_mul(&c->velocity, Time_GetFrameTime()); + c->position = vec3_add(&c->position, &velocity); + + /* Update animations + * How far into its life the particle is */ + float life_factor = c->elapsed_time / c->life_length; + /* How many different stages there are */ + int stage_count = t->number_of_rows * t->number_of_rows; + float atlas_progression = life_factor * stage_count; + int index = floor(atlas_progression); + + int column = index % t->number_of_rows; + int row = index / t->number_of_rows; + c->tex_offset.x = (float)column / t->number_of_rows; + c->tex_offset.y = (float)row / t->number_of_rows; + /* End of animation update */ + + c->elapsed_time += Time_GetFrameTime(); + + if(c->elapsed_time > c->life_length) + { + /* "Kill" the particle by overriding it with the last particle on the array */ + memmove( c, &s->particles[s->num_particles], sizeof(Particle) ); + s->num_particles -= 1; + } + else + { + d = vec3_sub(camera_position, &c->position); + c->distance_to_camera = vec3_length2(&d); + } + } + /*Sort all particles on system by distance to camera */ + qsort(s->particles, s->num_particles, sizeof(Particle), compare_particles); + } +} + +void Particles_Shutdown() +{ + int i; + for(i = 0; i < particles.num_systems; i++) + { + if(particles.systems[i]) + free(particles.systems[i]); + } + memset(&particles, 0, sizeof(ParticleManager)); +} + +static int compare_particles(const void *_a, const void *_b) +{ + Particle *a = (Particle *)_a; + Particle *b = (Particle *)_b; + + if(a->distance_to_camera < b->distance_to_camera) return -1; + if(a->distance_to_camera > b->distance_to_camera) return 1; + return 0; +} diff --git a/09-september/tomcat/particles/particles.h b/09-september/tomcat/particles/particles.h new file mode 100644 index 0000000..8404ff4 --- /dev/null +++ b/09-september/tomcat/particles/particles.h @@ -0,0 +1,62 @@ +#ifndef PARTICLES_H +#define PARTICLES_H + +#include "../renderer/renderer_types.h" +#include "../math/vector.h" + +#define MAX_PARTICLES_PER_SYSTEM 10000 +#define MAX_PARTICLES_SYSTEMS 10 + +typedef struct _Particle +{ + Vec3 position; + Vec3 velocity; + + Vec2 tex_offset; /* Used for animating */ + + GLfloat weight; /* How does the gravity affect the particle (In theory it should be a vector)*/ + GLfloat life_length; + GLfloat rotation; + GLfloat scale; + GLfloat distance_to_camera; /* Used for sorting the systems */ + + GLfloat elapsed_time; +} Particle; + +typedef struct _ParticleSystem +{ + Vec3 position; + + GLint emit_rate; + GLfloat speed; + GLfloat weight; + GLfloat life_length; + + bool additive; /* Additive vs alpha blending */ + + Texture *texture; + Particle particles[MAX_PARTICLES_PER_SYSTEM]; + int num_particles; + +} ParticleSystem; + +typedef struct +{ + ParticleSystem *systems[MAX_PARTICLES_SYSTEMS]; + int num_systems; +} ParticleManager; + +extern ParticleManager particles; + +extern void Particles_Init(); + +extern ParticleSystem *Particles_AddSystem(); +extern void Particles_RemoveSystem(ParticleSystem *system); +/* Used for manual emission */ +extern void Particles_EmitParticle(ParticleSystem *system, Particle *p); +/* Removes a particle if it "dies" */ +extern void Particles_Update(const Vec3 *camera_position); +/* We need to delete all dynamically allocated particles that still remains */ +extern void Particles_Shutdown(); + +#endif // PARTICLES_H -- cgit v1.2.3