summaryrefslogtreecommitdiff
path: root/modules/sparkler/particles.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/sparkler/particles.c')
-rw-r--r--modules/sparkler/particles.c342
1 files changed, 0 insertions, 342 deletions
diff --git a/modules/sparkler/particles.c b/modules/sparkler/particles.c
deleted file mode 100644
index 0eb260e..0000000
--- a/modules/sparkler/particles.c
+++ /dev/null
@@ -1,342 +0,0 @@
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <math.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "fb.h"
-
-#include "chunker.h"
-#include "container.h"
-#include "bsp.h"
-#include "list.h"
-#include "particle.h"
-#include "particles.h"
-#include "v3f.h"
-
-#define ZCONST 0.4f
-
-/* private particle with all the particles bookkeeping... */
-typedef struct _particle_t {
- list_head_t siblings; /* sibling particles */
- list_head_t children; /* children particles */
-
- particle_props_t props; /* we reference this in the public particle, I might change
- * the way props are allocated so coding everything to use a
- * reference for now. It may make sense to have props allocated
- * separately via their own chunker, and perform some mass operations
- * against the list of chunks rather than chasing the pointers of
- * the particle heirarchy. TODO
- */
- particle_t public; /* the public particle_t is embedded */
-
- uint8_t context[]; /* particle type-specific context [public.ops.context_size] */
-} _particle_t;
-
-struct particles_t {
- chunker_t *chunker; /* chunker for variably-sized particle allocation (includes context) */
- list_head_t active; /* top-level active list of particles heirarchy */
- bsp_t *bsp; /* bsp spatial index of the particles */
-};
-
-
-/* create a new particle system */
-particles_t * particles_new(void)
-{
- particles_t *particles;
-
- particles = calloc(1, sizeof(particles_t));
- if (!particles) {
- return NULL;
- }
-
- particles->chunker = chunker_new(sizeof(_particle_t) * 128);
- if (!particles->chunker) {
- return NULL;
- }
-
- particles->bsp = bsp_new();
- if (!particles->bsp) {
- return NULL;
- }
-
- INIT_LIST_HEAD(&particles->active);
-
- return particles;
-}
-
-
-/* TODO: add a public interface for destroying particles? for now we just return PARTICLE_DEAD in the sim */
-static inline void _particles_free_particle(particles_t *particles, _particle_t *p)
-{
- assert(p);
-
- particle_cleanup(particles, &p->public);
- chunker_free(p);
-}
-
-
-static inline void _particles_free(particles_t *particles, list_head_t *list)
-{
- _particle_t *p, *_p;
-
- assert(particles);
- assert(list);
-
- list_for_each_entry_safe(p, _p, list, siblings) {
- _particles_free(particles, &p->children);
- _particles_free_particle(particles, p);
- }
-}
-
-
-/* free up all the particles */
-void particles_free(particles_t *particles)
-{
- assert(particles);
-
- _particles_free(particles, &particles->active);
-}
-
-
-/* reclaim a dead particle, moving it to the free list */
-static void particles_reap_particle(particles_t *particles, _particle_t *particle)
-{
- assert(particles);
- assert(particle);
-
- if (!list_empty(&particle->children)) {
- /* adopt any orphaned children using the global parts list */
- list_splice(&particle->children, &particles->active);
- }
-
- list_del(&particle->siblings);
- bsp_delete_occupant(particles->bsp, &particle->public.occupant);
- _particles_free_particle(particles, particle);
-}
-
-
-/* add a particle to the specified list */
-static inline int _particles_add_particle(particles_t *particles, list_head_t *list, particle_props_t *props, particle_ops_t *ops)
-{
- _particle_t *p;
-
- assert(particles);
- assert(ops);
- assert(list);
-
- p = chunker_alloc(particles->chunker, sizeof(_particle_t) + ops->context_size);
- if (!p) {
- return 0;
- }
-
- INIT_LIST_HEAD(&p->children);
- INIT_LIST_HEAD(&p->siblings);
-
- /* inherit the parent's properties and ops if they're not explicitly provided */
- if (props) {
- p->props = *props;
- } else {
- p->props.of_use = 0;
- }
-
- p->public.props = &p->props;
- p->public.ops = ops;
-
- if (ops->context_size) {
- p->public.ctxt = p->context;
- }
-
- if (!particle_init(particles, &p->public)) {
- /* XXX FIXME this shouldn't be normal, we don't want to allocate
- * particles that cannot be initialized. the rockets today set a cap
- * by failing initialization, that's silly. */
- chunker_free(p);
- return 0;
- }
-
- p->public.props->of_use = 1;
- list_add(&p->siblings, list);
- bsp_add_occupant(particles->bsp, &p->public.occupant, &p->props.position);
-
- return 1;
-}
-
-
-/* add a new "top-level" particle of the specified props and ops taking from the provided parts list */
-int particles_add_particle(particles_t *particles, particle_props_t *props, particle_ops_t *ops)
-{
- assert(particles);
-
- return _particles_add_particle(particles, &particles->active, props, ops);
-}
-
-
-/* spawn a new child particle from a parent, initializing it via inheritance if desired */
-void particles_spawn_particle(particles_t *particles, particle_t *parent, particle_props_t *props, particle_ops_t *ops)
-{
- _particle_t *p = container_of(parent, _particle_t, public);
-
- assert(particles);
- assert(parent);
-
- _particles_add_particle(particles, &p->children, props ? props : parent->props, ops ? ops : parent->ops);
-}
-
-
-/* plural version of particle_add(); adds multiple "top-level" particles of uniform props and ops */
-void particles_add_particles(particles_t *particles, particle_props_t *props, particle_ops_t *ops, int num)
-{
- int i;
-
- assert(particles);
-
- for (i = 0; i < num; i++) {
- _particles_add_particle(particles, &particles->active, props, ops);
- }
-}
-
-
-/* Simple accessor to get the bsp pointer, the bsp is special because we don't want to do
- * callbacks per-occupant, so the bsp_occupant_t and search functions are used directly by
- * the per-particle code needing nearest-neighbor search. that requires an accessor since
- * particles_t is opaque. This seemed less shitty than opening up particles_t.
- */
-bsp_t * particles_bsp(particles_t *particles)
-{
- assert(particles);
- assert(particles->bsp);
-
- return particles->bsp;
-}
-
-
-static inline void _particles_draw(particles_t *particles, list_head_t *list, fb_fragment_t *fragment)
-{
- float w2 = fragment->width * .5f, h2 = fragment->height * .5f;
- _particle_t *p;
-
- assert(particles);
- assert(list);
- assert(fragment);
-
- list_for_each_entry(p, list, siblings) {
- int x, y;
-
- /* project the 3d coordinates onto the 2d plane */
- x = (p->props.position.x / (p->props.position.z - ZCONST) * w2) + w2;
- y = (p->props.position.y / (p->props.position.z - ZCONST) * h2) + h2;
-
- particle_draw(particles, &p->public, x, y, fragment);
-
- if (!list_empty(&p->children)) {
- _particles_draw(particles, &p->children, fragment);
- }
- }
-}
-
-
-/* draw all of the particles, currently called in heirarchical order */
-void particles_draw(particles_t *particles, fb_fragment_t *fragment)
-{
- assert(particles);
-
- _particles_draw(particles, &particles->active, fragment);
-}
-
-
-static inline particle_status_t _particles_sim(particles_t *particles, list_head_t *list)
-{
- particle_status_t ret = PARTICLE_DEAD, s;
- _particle_t *p, *_p;
-
- assert(particles);
- assert(list);
-
- list_for_each_entry_safe(p, _p, list, siblings) {
- if ((s = particle_sim(particles, &p->public)) == PARTICLE_ALIVE) {
- ret = PARTICLE_ALIVE;
-
- if (!list_empty(&p->children) &&
- _particles_sim(particles, &p->children) == PARTICLE_ALIVE) {
- ret = PARTICLE_ALIVE;
- }
- } else {
- particles_reap_particle(particles, p);
- }
- }
-
- return ret;
-}
-
-
-/* simulate the particles, call the sim method of every particle in the heirarchy, this is what makes the particles dynamic */
-/* if any paticle is still living, we return PARTICLE_ALIVE, to inform the caller when everything's dead */
-particle_status_t particles_sim(particles_t *particles)
-{
- assert(particles);
-
- return _particles_sim(particles, &particles->active);
-}
-
-
-static inline void _particles_age(particles_t *particles, list_head_t *list)
-{
- _particle_t *p;
-
- assert(particles);
- assert(list);
-
- /* TODO: since this *only* involves the properties struct, if they were
- * allocated from a separate slab containing only properties, it'd be
- * more efficient to iterate across property arrays and skip inactive
- * entries. This heirarchical pointer-chasing recursion isn't
- * particularly good for cache utilization.
- */
- list_for_each_entry(p, list, siblings) {
-#if 1
- if (p->props.mass > 0.0f) {
- /* gravity, TODO: mass isn't applied. */
- static v3f_t gravity = v3f_init(0.0f, -0.05f, 0.0f);
-
- p->props.direction = v3f_add(&p->props.direction, &gravity);
- p->props.direction = v3f_normalize(&p->props.direction);
- }
-#endif
-
-#if 1
- /* some drag/resistance proportional to velocity TODO: integrate mass */
- if (p->props.velocity > 0.0f) {
- p->props.velocity -= ((p->props.velocity * p->props.velocity * p->props.drag));
- if (p->props.velocity < 0.0f) {
- p->props.velocity = 0;
- }
- }
-#endif
-
- /* regular movement */
- if (p->props.velocity > 0.0f) {
- v3f_t movement = v3f_mult_scalar(&p->props.direction, p->props.velocity);
-
- p->props.position = v3f_add(&p->props.position, &movement);
- bsp_move_occupant(particles->bsp, &p->public.occupant, &p->props.position);
- }
-
- if (!list_empty(&p->children)) {
- _particles_age(particles, &p->children);
- }
- }
-}
-
-
-/* advance time for all the particles (move them), this doesn't currently invoke any part-specific helpers, it's just applying
- * physics-type stuff, moving particles according to their velocities, directions, mass, drag, gravity etc... */
-void particles_age(particles_t *particles)
-{
- assert(particles);
-
- _particles_age(particles, &particles->active);
-}
© All Rights Reserved