2022-12-28 16:50:54 -06:00
|
|
|
#include "particle.h"
|
2023-02-02 17:52:15 -06:00
|
|
|
#include "stb_ds.h"
|
2023-12-29 19:08:53 -06:00
|
|
|
#include "render.h"
|
2024-01-01 17:30:42 -06:00
|
|
|
#include "2dphysics.h"
|
2024-01-04 09:46:28 -06:00
|
|
|
#include "math.h"
|
2024-05-06 21:59:22 -05:00
|
|
|
#include "log.h"
|
2023-12-29 19:08:53 -06:00
|
|
|
|
|
|
|
emitter *make_emitter() {
|
2024-01-04 08:14:37 -06:00
|
|
|
emitter *e = calloc(sizeof(*e),1);
|
|
|
|
|
2023-12-29 19:08:53 -06:00
|
|
|
e->max = 20;
|
2024-05-06 21:59:22 -05:00
|
|
|
arrsetcap(e->particles, 10);
|
2023-12-29 19:08:53 -06:00
|
|
|
for (int i = 0; i < arrlen(e->particles); i++)
|
|
|
|
e->particles[i].life = 0;
|
|
|
|
|
|
|
|
e->life = 10;
|
2024-01-02 07:55:22 -06:00
|
|
|
e->tte = lerp(e->explosiveness, e->life/e->max, 0);
|
2024-01-01 17:30:42 -06:00
|
|
|
e->scale = 1;
|
|
|
|
e->speed = 20;
|
2024-07-21 15:03:43 -05:00
|
|
|
e->color = (HMM_Vec4){1,1,1,1};
|
2024-07-18 17:09:35 -05:00
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
return e;
|
2022-12-28 16:50:54 -06:00
|
|
|
}
|
|
|
|
|
2024-01-14 10:24:31 -06:00
|
|
|
void emitter_free(emitter *e)
|
2023-12-29 19:08:53 -06:00
|
|
|
{
|
|
|
|
arrfree(e->particles);
|
2024-05-06 21:59:22 -05:00
|
|
|
arrfree(e->verts);
|
|
|
|
free(e);
|
2022-12-28 16:50:54 -06:00
|
|
|
}
|
|
|
|
|
2024-01-04 09:46:28 -06:00
|
|
|
/* Variate a value around variance. Variance between 0 and 1. */
|
|
|
|
|
|
|
|
float variate(float val, float variance)
|
|
|
|
{
|
|
|
|
return val + val*(frand(variance)-(variance/2));
|
|
|
|
}
|
|
|
|
|
2024-05-12 18:36:14 -05:00
|
|
|
int emitter_spawn(emitter *e, transform *t)
|
2023-12-29 19:08:53 -06:00
|
|
|
{
|
2024-05-10 07:55:53 -05:00
|
|
|
if (arrlen(e->particles) == e->max) return 0;
|
|
|
|
particle p = {0};
|
2024-01-01 17:30:42 -06:00
|
|
|
p.life = e->life;
|
2024-05-12 18:36:14 -05:00
|
|
|
p.pos = (HMM_Vec4){t->pos.x,t->pos.y,t->pos.z,0};
|
2024-05-15 07:54:19 -05:00
|
|
|
HMM_Vec3 up = transform_direction(t, vFWD);
|
2024-05-12 18:36:14 -05:00
|
|
|
float newan = (frand(e->divergence)-(e->divergence/2))*HMM_TurnToRad;
|
|
|
|
HMM_Vec2 v2n = HMM_V2Rotate((HMM_Vec2){0,1}, newan);
|
|
|
|
HMM_Vec3 norm = (HMM_Vec3){v2n.x, v2n.y,0};
|
|
|
|
p.v = HMM_MulV4F((HMM_Vec4){norm.x,norm.y,norm.z,0}, variate(e->speed, e->variation));
|
2024-07-21 15:03:43 -05:00
|
|
|
p.angle = e->tumble;
|
|
|
|
p.av = e->tumble_rate;
|
2024-05-06 21:59:22 -05:00
|
|
|
p.scale = variate(e->scale*t->scale.x, e->scale_var);
|
2024-01-01 17:30:42 -06:00
|
|
|
arrput(e->particles,p);
|
|
|
|
return 1;
|
2023-12-29 19:08:53 -06:00
|
|
|
}
|
|
|
|
|
2024-05-12 18:36:14 -05:00
|
|
|
void emitter_emit(emitter *e, int count, transform *t)
|
2023-12-29 19:08:53 -06:00
|
|
|
{
|
|
|
|
for (int i = 0; i < count; i++)
|
2024-05-06 21:59:22 -05:00
|
|
|
emitter_spawn(e, t);
|
2023-12-29 19:08:53 -06:00
|
|
|
}
|
|
|
|
|
2024-07-21 15:03:43 -05:00
|
|
|
void emitter_draw(emitter *e, sg_buffer *b)
|
2023-12-29 19:08:53 -06:00
|
|
|
{
|
2024-07-21 15:03:43 -05:00
|
|
|
if (arrlen(e->particles) == 0) return;
|
2024-05-06 21:59:22 -05:00
|
|
|
arrsetlen(e->verts, arrlen(e->particles));
|
|
|
|
for (int i = 0; i < arrlen(e->particles); i++) {
|
2024-01-04 09:46:28 -06:00
|
|
|
if (e->particles[i].time >= e->particles[i].life) continue;
|
2024-05-06 21:59:22 -05:00
|
|
|
particle *p = e->particles+i;
|
|
|
|
e->verts[i].pos = p->pos.xy;
|
|
|
|
e->verts[i].angle = p->angle;
|
|
|
|
e->verts[i].scale = p->scale;
|
2024-07-21 15:03:43 -05:00
|
|
|
if (p->time < e->grow_for)
|
2024-05-06 21:59:22 -05:00
|
|
|
e->verts[i].scale = lerp(p->time/e->grow_for, 0, p->scale);
|
2024-01-04 09:46:28 -06:00
|
|
|
else if (p->time > (p->life - e->shrink_for))
|
2024-07-21 15:03:43 -05:00
|
|
|
e->verts[i].scale = lerp((p->time-(p->life-e->shrink_for))/e->shrink_for, p->scale, 0);
|
2024-05-10 07:55:53 -05:00
|
|
|
e->verts[i].color = p->color;
|
2024-01-03 12:29:27 -06:00
|
|
|
}
|
2024-01-03 08:38:17 -06:00
|
|
|
|
2024-05-06 21:59:22 -05:00
|
|
|
sg_range verts;
|
|
|
|
verts.ptr = e->verts;
|
|
|
|
verts.size = sizeof(*e->verts)*arrlen(e->verts);
|
2024-07-18 17:09:35 -05:00
|
|
|
if (sg_query_buffer_will_overflow(*b, verts.size)) {
|
|
|
|
sg_destroy_buffer(*b);
|
|
|
|
*b = sg_make_buffer(&(sg_buffer_desc){
|
2024-05-06 21:59:22 -05:00
|
|
|
.size = verts.size,
|
2024-05-10 07:55:53 -05:00
|
|
|
.type = SG_BUFFERTYPE_STORAGEBUFFER,
|
2024-05-06 21:59:22 -05:00
|
|
|
.usage = SG_USAGE_STREAM
|
|
|
|
});
|
2024-05-10 07:55:53 -05:00
|
|
|
}
|
2024-01-03 08:38:17 -06:00
|
|
|
|
2024-07-18 17:09:35 -05:00
|
|
|
sg_append_buffer(*b, &verts);
|
2023-12-29 19:08:53 -06:00
|
|
|
}
|
|
|
|
|
2024-05-12 18:36:14 -05:00
|
|
|
void emitter_step(emitter *e, double dt, transform *t) {
|
2024-05-06 21:59:22 -05:00
|
|
|
HMM_Vec4 g_accel = HMM_MulV4F((HMM_Vec4){cpSpaceGetGravity(space).x, cpSpaceGetGravity(space).y, 0, 0}, dt);
|
|
|
|
|
|
|
|
for (int i = 0; i < arrlen(e->particles); i++) {
|
2024-01-04 09:46:28 -06:00
|
|
|
if (e->particles[i].time >= e->particles[i].life) continue;
|
2024-05-06 21:59:22 -05:00
|
|
|
|
2024-07-21 15:03:43 -05:00
|
|
|
if (e->warp_mask & gravmask)
|
|
|
|
e->particles[i].v = HMM_AddV4(e->particles[i].v, g_accel);
|
2024-01-04 08:14:37 -06:00
|
|
|
|
2024-01-03 12:29:27 -06:00
|
|
|
e->particles[i].pos = HMM_AddV4(e->particles[i].pos, HMM_MulV4F(e->particles[i].v, dt));
|
|
|
|
e->particles[i].angle += e->particles[i].av*dt;
|
2024-01-04 09:46:28 -06:00
|
|
|
e->particles[i].time += dt;
|
2024-07-21 15:03:43 -05:00
|
|
|
e->particles[i].color = e->color;
|
|
|
|
//e->particles[i].color = sample_sampler(&e->color, e->particles[i].time/e->particles[i].life);
|
2024-01-03 12:29:27 -06:00
|
|
|
e->particles[i].scale = e->scale;
|
2024-05-06 21:59:22 -05:00
|
|
|
|
2024-01-04 09:46:28 -06:00
|
|
|
if (e->particles[i].time >= e->particles[i].life)
|
|
|
|
arrdelswap(e->particles, i);
|
2024-05-10 07:55:53 -05:00
|
|
|
// else if (query_point(e->particles[i].pos.xy))
|
|
|
|
// arrdelswap(e->particles,i);
|
2023-12-29 19:08:53 -06:00
|
|
|
}
|
2022-12-28 16:50:54 -06:00
|
|
|
|
2023-12-29 19:08:53 -06:00
|
|
|
e->tte-=dt;
|
2024-05-10 07:55:53 -05:00
|
|
|
float step = lerp(e->explosiveness, e->life/e->max,0);
|
|
|
|
while (e->tte <= 0) {
|
|
|
|
e->tte += step;
|
|
|
|
if (!emitter_spawn(e, t)) break;
|
2023-05-12 13:22:05 -05:00
|
|
|
}
|
2023-02-02 17:52:15 -06:00
|
|
|
}
|