summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/sparkler/bsp.c56
-rw-r--r--src/modules/sparkler/bsp.h2
-rw-r--r--src/modules/sparkler/burst.c27
-rw-r--r--src/modules/sparkler/list.h2
-rw-r--r--src/modules/sparkler/particle.c6
-rw-r--r--src/modules/sparkler/particle.h31
-rw-r--r--src/modules/sparkler/particles.c152
-rw-r--r--src/modules/sparkler/particles.h6
-rw-r--r--src/modules/sparkler/rocket.c8
-rw-r--r--src/modules/sparkler/simple.c6
-rw-r--r--src/modules/sparkler/spark.c6
-rw-r--r--src/modules/sparkler/sparkler.c78
-rw-r--r--src/modules/sparkler/xplode.c6
13 files changed, 333 insertions, 53 deletions
diff --git a/src/modules/sparkler/bsp.c b/src/modules/sparkler/bsp.c
index ae5a20e..f55501a 100644
--- a/src/modules/sparkler/bsp.c
+++ b/src/modules/sparkler/bsp.c
@@ -574,3 +574,59 @@ void bsp_search_sphere(bsp_t *bsp, v3f_t *center, float radius_min, float radius
_bsp_search_sphere(bsp, &bsp->root, &search, &aabb_min, &aabb_max);
}
+
+
+static void _bsp_walk_leaves(const bsp_t *bsp, const bsp_node_t *node, unsigned depth, const v3f_t *aabb_min, const v3f_t *aabb_max, void (*cb)(const bsp_t *bsp, const list_head_t *occupants, unsigned depth, const v3f_t *bv_min, const v3f_t *bv_max, void *cb_data), void *cb_data)
+{
+ v3f_t oaabb_min, oaabb_max;
+
+ /* if node is a leaf, call cb with the occupants, then return. */
+ if (!node->octrants)
+ return cb(bsp, &node->occupants, depth, aabb_min, aabb_max, cb_data);
+
+ /* node is a parent, recur on each octrant with appropriately adjusted aabb_min:aabb_max values */
+ /* if any of the octrants absolutely overlaps the search sphere, skip the others by returning. */
+#define walk_octrant(_oid, _aabb_min, _aabb_max) \
+ _bsp_walk_leaves(bsp, &node->octrants[_oid], depth + 1, _aabb_min, _aabb_max, cb, cb_data);
+
+ /* OCT_XL_YL_ZL and OCT_XR_YR_ZR AABBs don't require tedious composition */
+ walk_octrant(OCT_XL_YL_ZL, aabb_min, &node->center);
+ walk_octrant(OCT_XR_YR_ZR, &node->center, aabb_max);
+
+ /* the rest are stitched together requiring temp storage and tedium */
+ v3f_set(&oaabb_min, node->center.x, aabb_min->y, aabb_min->z);
+ v3f_set(&oaabb_max, aabb_max->x, node->center.y, node->center.z);
+ walk_octrant(OCT_XR_YL_ZL, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, aabb_min->x, node->center.y, aabb_min->z);
+ v3f_set(&oaabb_max, node->center.x, aabb_max->y, node->center.z);
+ walk_octrant(OCT_XL_YR_ZL, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, node->center.x, node->center.y, aabb_min->z);
+ v3f_set(&oaabb_max, aabb_max->x, aabb_max->y, node->center.z);
+ walk_octrant(OCT_XR_YR_ZL, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, aabb_min->x, aabb_min->y, node->center.z);
+ v3f_set(&oaabb_max, node->center.x, node->center.y, aabb_max->z);
+ walk_octrant(OCT_XL_YL_ZR, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, node->center.x, aabb_min->y, node->center.z);
+ v3f_set(&oaabb_max, aabb_max->x, node->center.y, aabb_max->z);
+ walk_octrant(OCT_XR_YL_ZR, &oaabb_min, &oaabb_max);
+
+ v3f_set(&oaabb_min, aabb_min->x, node->center.y, node->center.z);
+ v3f_set(&oaabb_max, node->center.x, aabb_max->y, aabb_max->z);
+ walk_octrant(OCT_XL_YR_ZR, &oaabb_min, &oaabb_max);
+
+#undef walk_octrant
+}
+
+
+/* traverse the bsp tree calling cb for every leaf node, no discriminating of positions */
+void bsp_walk_leaves(const bsp_t *bsp, void (*cb)(const bsp_t *bsp, const list_head_t *occupants, unsigned depth, const v3f_t *bv_min, const v3f_t *bv_max, void *cb_data), void *cb_data)
+{
+ v3f_t aabb_min = v3f_init(-1.0f, -1.0f, -1.0f);
+ v3f_t aabb_max = v3f_init(1.0f, 1.0f, 1.0f);
+
+ _bsp_walk_leaves(bsp, &bsp->root, 0, &aabb_min, &aabb_max, cb, cb_data);
+}
diff --git a/src/modules/sparkler/bsp.h b/src/modules/sparkler/bsp.h
index f5ce303..3ca0c02 100644
--- a/src/modules/sparkler/bsp.h
+++ b/src/modules/sparkler/bsp.h
@@ -25,4 +25,6 @@ void bsp_delete_occupant(bsp_t *bsp, bsp_occupant_t *occupant);
void bsp_move_occupant(bsp_t *bsp, bsp_occupant_t *occupant, v3f_t *position);
void bsp_search_sphere(bsp_t *bsp, v3f_t *center, float radius_min, float radius_max, void (*cb)(bsp_t *, list_head_t *, void *), void *cb_data);
+void bsp_walk_leaves(const bsp_t *bsp, void (*cb)(const bsp_t *bsp, const list_head_t *occupants, unsigned depth, const v3f_t *bv_min, const v3f_t *bv_max, void *cb_data), void *cb_data);
+
#endif
diff --git a/src/modules/sparkler/burst.c b/src/modules/sparkler/burst.c
index 72cde03..b5ad365 100644
--- a/src/modules/sparkler/burst.c
+++ b/src/modules/sparkler/burst.c
@@ -18,7 +18,7 @@ typedef struct _burst_ctxt_t {
} burst_ctxt_t;
-static int burst_init(particles_t *particles, particle_t *p)
+static int burst_init(particles_t *particles, const particles_conf_t *conf, particle_t *p)
{
burst_ctxt_t *ctxt = p->ctxt;
@@ -43,9 +43,13 @@ static inline void thrust_part(particle_t *burst, particle_t *victim, float dist
typedef struct burst_sphere_t {
- particle_t *center;
+ particles_t *particles;
+ particle_t *center, *last;
+ fb_fragment_t *fragment;
float radius_min;
float radius_max;
+ unsigned trace_matches:1;
+ unsigned trace_affected:1;
} burst_sphere_t;
@@ -64,7 +68,7 @@ static void burst_cb(bsp_t *bsp, list_head_t *occupants, void *_s)
list_for_each_entry(o, occupants, occupants) {
particle_t *p = container_of(o, particle_t, occupant);
float d_sq;
-
+
if (p->props->virtual) {
/* don't move virtual particles (includes ourself) */
continue;
@@ -75,13 +79,22 @@ static void burst_cb(bsp_t *bsp, list_head_t *occupants, void *_s)
if (d_sq > rmin_sq && d_sq < rmax_sq) {
/* displace the part relative to the burst origin */
thrust_part(s->center, p, d_sq);
+
+ if (s->trace_affected) {
+ particles_draw_line(s->particles, &s->last->props->position, &p->props->position, s->fragment);
+ s->last = p;
+ }
}
+ if (s->trace_matches) {
+ particles_draw_line(s->particles, &s->last->props->position, &p->props->position, s->fragment);
+ s->last = p;
+ }
}
}
-static particle_status_t burst_sim(particles_t *particles, particle_t *p)
+static particle_status_t burst_sim(particles_t *particles, const particles_conf_t *conf, particle_t *p, fb_fragment_t *f)
{
burst_ctxt_t *ctxt = p->ctxt;
bsp_t *bsp = particles_bsp(particles); /* XXX see note above about bsp_occupant_t */
@@ -94,7 +107,11 @@ static particle_status_t burst_sim(particles_t *particles, particle_t *p)
/* affect neighbors for the shock-wave */
s.radius_min = (1.0f - ((float)ctxt->longevity / ctxt->lifetime)) * 0.075f;
s.radius_max = s.radius_min + .01f;
- s.center = p;
+ s.center = s.last = p;
+ s.trace_matches = (conf->show_bsp_matches && !conf->show_bsp_matches_affected_only);
+ s.trace_affected = (conf->show_bsp_matches && conf->show_bsp_matches_affected_only);
+ s.particles = particles;
+ s.fragment = f;
bsp_search_sphere(bsp, &p->props->position, s.radius_min, s.radius_max, burst_cb, &s);
return PARTICLE_ALIVE;
diff --git a/src/modules/sparkler/list.h b/src/modules/sparkler/list.h
index 48bca36..04cafd6 100644
--- a/src/modules/sparkler/list.h
+++ b/src/modules/sparkler/list.h
@@ -130,7 +130,7 @@ static inline void list_move_tail(struct list_head *list,
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
-static inline int list_empty(struct list_head *head)
+static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
diff --git a/src/modules/sparkler/particle.c b/src/modules/sparkler/particle.c
index 0e3d2c8..76d0c70 100644
--- a/src/modules/sparkler/particle.c
+++ b/src/modules/sparkler/particle.c
@@ -1,14 +1,14 @@
#include "particle.h"
/* convert a particle to a new type */
-void particle_convert(particles_t *particles, particle_t *p, particle_props_t *props, particle_ops_t *ops)
+void particle_convert(particles_t *particles, const particles_conf_t *conf, particle_t *p, particle_props_t *props, particle_ops_t *ops)
{
- particle_cleanup(particles, p);
+ particle_cleanup(particles, conf, p);
if (props) {
*p->props = *props;
}
if (ops) {
p->ops = ops;
}
- particle_init(particles, p);
+ particle_init(particles, conf, p);
}
diff --git a/src/modules/sparkler/particle.h b/src/modules/sparkler/particle.h
index c63024d..a5999ee 100644
--- a/src/modules/sparkler/particle.h
+++ b/src/modules/sparkler/particle.h
@@ -22,13 +22,14 @@ typedef enum particle_status_t {
typedef struct particle_t particle_t;
typedef struct particles_t particles_t;
+typedef struct particles_conf_t particles_conf_t;
typedef struct particle_ops_t {
unsigned context_size; /* size of the particle context (0 for none) */
- int (*init)(particles_t *, particle_t *); /* initialize the particle, called after allocating context (optional) */
- void (*cleanup)(particles_t *, particle_t *); /* cleanup function, called before freeing context (optional) */
- particle_status_t (*sim)(particles_t *, particle_t *); /* simulate the particle for another cycle (required) */
- void (*draw)(particles_t *, particle_t *, int, int, fb_fragment_t *); /* draw the particle, 3d->2d projection has been done already (optional) */
+ int (*init)(particles_t *, const particles_conf_t *, particle_t *); /* initialize the particle, called after allocating context (optional) */
+ void (*cleanup)(particles_t *, const particles_conf_t *, particle_t *); /* cleanup function, called before freeing context (optional) */
+ particle_status_t (*sim)(particles_t *, const particles_conf_t *, particle_t *, fb_fragment_t *); /* simulate the particle for another cycle (required) */
+ void (*draw)(particles_t *, const particles_conf_t *, particle_t *, int, int, fb_fragment_t *); /* draw the particle, 3d->2d projection has been done already (optional) */
} particle_ops_t;
struct particle_t {
@@ -47,34 +48,38 @@ struct particle_t {
#define INHERIT_PROPS NULL
-static inline int particle_init(particles_t *particles, particle_t *p) {
+static inline int particle_init(particles_t *particles, const particles_conf_t *conf, particle_t *p) {
if (p->ops->init) {
- return p->ops->init(particles, p);
+ return p->ops->init(particles, conf, p);
}
return 1;
}
-static inline void particle_cleanup(particles_t *particles, particle_t *p) {
+static inline void particle_cleanup(particles_t *particles, const particles_conf_t *conf, particle_t *p) {
if (p->ops->cleanup) {
- p->ops->cleanup(particles, p);
+ p->ops->cleanup(particles, conf, p);
}
}
-static inline particle_status_t particle_sim(particles_t *particles, particle_t *p) {
- return p->ops->sim(particles, p);
+/* XXX: fragment is supplied to ops->sim() only for debugging/overlay purposes, if particles_conf_t.show_bsp_matches for
+ * example is true, then sim may draw into fragment, and the callers shouldn't zero the fragment between sim and draw but
+ * instead should zero it before sim. It's kind of janky, not a fan.
+ */
+static inline particle_status_t particle_sim(particles_t *particles, const particles_conf_t *conf, particle_t *p, fb_fragment_t *f) {
+ return p->ops->sim(particles, conf, p, f);
}
-static inline void particle_draw(particles_t *particles, particle_t *p, int x, int y, fb_fragment_t *f) {
+static inline void particle_draw(particles_t *particles, const particles_conf_t *conf, particle_t *p, int x, int y, fb_fragment_t *f) {
if (p->ops->draw) {
- p->ops->draw(particles, p, x, y, f);
+ p->ops->draw(particles, conf, p, x, y, f);
}
}
-void particle_convert(particles_t *particles, particle_t *p, particle_props_t *props, particle_ops_t *ops);
+void particle_convert(particles_t *particles, const particles_conf_t *conf, particle_t *p, particle_props_t *props, particle_ops_t *ops);
#endif
diff --git a/src/modules/sparkler/particles.c b/src/modules/sparkler/particles.c
index b43c57b..d4677b7 100644
--- a/src/modules/sparkler/particles.c
+++ b/src/modules/sparkler/particles.c
@@ -78,7 +78,7 @@ static inline void _particles_free_particle(particles_t *particles, _particle_t
{
assert(p);
- particle_cleanup(particles, &p->public);
+ particle_cleanup(particles, &particles->conf, &p->public);
chunker_free(p);
}
@@ -157,7 +157,7 @@ static inline int _particles_add_particle(particles_t *particles, list_head_t *l
p->public.ctxt = p->context;
}
- if (!particle_init(particles, &p->public)) {
+ if (!particle_init(particles, &particles->conf, &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. */
@@ -237,7 +237,7 @@ static inline void _particles_draw(particles_t *particles, list_head_t *list, fb
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);
+ particle_draw(particles, &particles->conf, &p->public, x, y, fragment);
if (!list_empty(&p->children)) {
_particles_draw(particles, &p->children, fragment);
@@ -246,16 +246,134 @@ static inline void _particles_draw(particles_t *particles, list_head_t *list, fb
}
+/* TODO: maybe polish up and move into fb.c? */
+static void draw_line(fb_fragment_t *fragment, int x1, int y1, int x2, int y2)
+{
+ int x_delta = x2 - x1;
+ int y_delta = y2 - y1;
+ int sdx = x_delta < 0 ? -1 : 1;
+ int sdy = y_delta < 0 ? -1 : 1;
+
+ x_delta = abs(x_delta);
+ y_delta = abs(y_delta);
+
+ if (x_delta >= y_delta) {
+ /* X-major */
+ for (int minor = 0, x = 0; x <= x_delta; x++, x1 += sdx, minor += y_delta) {
+ if (minor >= x_delta) {
+ y1 += sdy;
+ minor -= x_delta;
+ }
+
+ fb_fragment_put_pixel_checked(fragment, x1, y1, 0xffffffff);
+ }
+ } else {
+ /* Y-major */
+ for (int minor = 0, y = 0; y <= y_delta; y++, y1 += sdy, minor += x_delta) {
+ if (minor >= y_delta) {
+ x1 += sdx;
+ minor -= y_delta;
+ }
+
+ fb_fragment_put_pixel_checked(fragment, x1, y1, 0xffffffff);
+ }
+ }
+}
+
+
+static void draw_edge(fb_fragment_t *fragment, const v3f_t *a, const v3f_t *b)
+{
+ float w2 = fragment->frame_width * .5f, h2 = fragment->frame_height * .5f;
+ int x1, y1, x2, y2;
+
+ /* project the 3d coordinates onto the 2d plane */
+ x1 = (a->x / (a->z - ZCONST) * w2) + w2;
+ y1 = (a->y / (a->z - ZCONST) * h2) + h2;
+ x2 = (b->x / (b->z - ZCONST) * w2) + w2;
+ y2 = (b->y / (b->z - ZCONST) * h2) + h2;
+
+ draw_line(fragment, x1, y1, x2, y2);
+}
+
+
+static void draw_bv(fb_fragment_t *fragment, const v3f_t *bv_min, const v3f_t *bv_max)
+{
+ draw_edge(fragment,
+ &(v3f_t){bv_min->x, bv_max->y, bv_min->z},
+ &(v3f_t){bv_max->x, bv_max->y, bv_min->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_min->x, bv_max->y, bv_min->z},
+ &(v3f_t){bv_min->x, bv_max->y, bv_max->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_min->x, bv_max->y, bv_min->z},
+ &(v3f_t){bv_min->x, bv_min->y, bv_min->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_max->x, bv_min->y, bv_min->z},
+ &(v3f_t){bv_max->x, bv_min->y, bv_max->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_max->x, bv_min->y, bv_min->z},
+ &(v3f_t){bv_min->x, bv_min->y, bv_min->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_max->x, bv_min->y, bv_min->z},
+ &(v3f_t){bv_max->x, bv_max->y, bv_min->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_max->x, bv_max->y, bv_max->z},
+ &(v3f_t){bv_min->x, bv_max->y, bv_max->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_max->x, bv_max->y, bv_max->z},
+ &(v3f_t){bv_max->x, bv_max->y, bv_min->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_max->x, bv_max->y, bv_max->z},
+ &(v3f_t){bv_max->x, bv_min->y, bv_max->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_min->x, bv_min->y, bv_max->z},
+ &(v3f_t){bv_min->x, bv_min->y, bv_min->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_min->x, bv_min->y, bv_max->z},
+ &(v3f_t){bv_min->x, bv_max->y, bv_max->z});
+ draw_edge(fragment,
+ &(v3f_t){bv_min->x, bv_min->y, bv_max->z},
+ &(v3f_t){bv_max->x, bv_min->y, bv_max->z});
+}
+
+
+/* something to encapsulate these pointers for passing through as one to draw_leaf() */
+typedef struct draw_leafs_t {
+ particles_t *particles;
+ fb_fragment_t *fragment;
+} draw_leafs_t;
+
+
+/* callback for bsp_walk_leaves() when show_bsp_leafs is enabled */
+static void draw_leaf(const bsp_t *bsp, const list_head_t *occupants, unsigned depth, const v3f_t *bv_min, const v3f_t *bv_max, void *cb_data)
+{
+ draw_leafs_t *draw = cb_data;
+
+ if (list_empty(occupants))
+ return;
+
+ if (depth < draw->particles->conf.show_bsp_leafs_min_depth)
+ return;
+
+ draw_bv(draw->fragment, bv_min, bv_max);
+}
+
+
/* draw all of the particles, currently called in heirarchical order */
void particles_draw(particles_t *particles, fb_fragment_t *fragment)
{
+ draw_leafs_t draw = { .particles = particles, .fragment = fragment };
+
assert(particles);
_particles_draw(particles, &particles->active, fragment);
+
+ if (particles->conf.show_bsp_leafs)
+ bsp_walk_leaves(particles->bsp, draw_leaf, &draw);
}
-static inline particle_status_t _particles_sim(particles_t *particles, list_head_t *list)
+static inline particle_status_t _particles_sim(particles_t *particles, list_head_t *list, fb_fragment_t *fragment)
{
particle_status_t ret = PARTICLE_DEAD, s;
_particle_t *p, *_p;
@@ -264,11 +382,11 @@ static inline particle_status_t _particles_sim(particles_t *particles, list_head
assert(list);
list_for_each_entry_safe(p, _p, list, siblings) {
- if ((s = particle_sim(particles, &p->public)) == PARTICLE_ALIVE) {
+ if ((s = particle_sim(particles, &particles->conf, &p->public, fragment)) == PARTICLE_ALIVE) {
ret = PARTICLE_ALIVE;
if (!list_empty(&p->children) &&
- _particles_sim(particles, &p->children) == PARTICLE_ALIVE) {
+ _particles_sim(particles, &p->children, fragment) == PARTICLE_ALIVE) {
ret = PARTICLE_ALIVE;
}
} else {
@@ -282,11 +400,11 @@ static inline particle_status_t _particles_sim(particles_t *particles, list_head
/* 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)
+particle_status_t particles_sim(particles_t *particles, fb_fragment_t *fragment)
{
assert(particles);
- return _particles_sim(particles, &particles->active);
+ return _particles_sim(particles, &particles->active, fragment);
}
@@ -357,3 +475,21 @@ void particles_age(particles_t *particles)
_particles_age(particles, &particles->active);
}
+
+
+/* draw a line expressed in world-space positions a to b into fragment, this is intended for
+ * instrumentation/overlay debugging type purposes...
+ */
+void particles_draw_line(particles_t *particles, const v3f_t *a, const v3f_t *b, fb_fragment_t *fragment)
+{
+ float w2 = fragment->frame_width * .5f, h2 = fragment->frame_height * .5f;
+ int x1, y1, x2, y2;
+
+ /* project the 3d coordinates onto the 2d plane */
+ x1 = (a->x / (a->z - ZCONST) * w2) + w2;
+ y1 = (a->y / (a->z - ZCONST) * h2) + h2;
+ x2 = (b->x / (b->z - ZCONST) * w2) + w2;
+ y2 = (b->y / (b->z - ZCONST) * h2) + h2;
+
+ draw_line(fragment, x1, y1, x2, y2);
+}
diff --git a/src/modules/sparkler/particles.h b/src/modules/sparkler/particles.h
index b191b6e..9d6e3af 100644
--- a/src/modules/sparkler/particles.h
+++ b/src/modules/sparkler/particles.h
@@ -9,18 +9,22 @@
typedef struct particles_conf_t {
unsigned show_bsp_leafs:1;
unsigned show_bsp_matches:1;
+ unsigned show_bsp_matches_affected_only:1;
+ unsigned show_bsp_leafs_min_depth;
} particles_conf_t;
typedef struct particles_t particles_t;
+typedef struct v3f_t v3f_t;
particles_t * particles_new(const particles_conf_t *conf);
void particles_draw(particles_t *particles, fb_fragment_t *fragment);
-particle_status_t particles_sim(particles_t *particles);
+particle_status_t particles_sim(particles_t *particles, fb_fragment_t *fragment);
void particles_age(particles_t *particles);
void particles_free(particles_t *particles);
int particles_add_particle(particles_t *particles, particle_props_t *props, particle_ops_t *ops);
void particles_spawn_particle(particles_t *particles, particle_t *parent, particle_props_t *props, particle_ops_t *ops);
void particles_add_particles(particles_t *particles, particle_props_t *props, particle_ops_t *ops, int num);
bsp_t * particles_bsp(particles_t *particles);
+void particles_draw_line(particles_t *particles, const v3f_t *a, const v3f_t *b, fb_fragment_t *fragment);
#endif
diff --git a/src/modules/sparkler/rocket.c b/src/modules/sparkler/rocket.c
index b56c324..50e1ff5 100644
--- a/src/modules/sparkler/rocket.c
+++ b/src/modules/sparkler/rocket.c
@@ -28,7 +28,7 @@ typedef struct rocket_ctxt_t {
} rocket_ctxt_t;
-static int rocket_init(particles_t *particles, particle_t *p)
+static int rocket_init(particles_t *particles, const particles_conf_t *conf, particle_t *p)
{
rocket_ctxt_t *ctxt = p->ctxt;
@@ -54,7 +54,7 @@ static int rocket_init(particles_t *particles, particle_t *p)
}
-static particle_status_t rocket_sim(particles_t *particles, particle_t *p)
+static particle_status_t rocket_sim(particles_t *particles, const particles_conf_t *conf, particle_t *p, fb_fragment_t *f)
{
rocket_ctxt_t *ctxt = p->ctxt;
int i, n_sparks;
@@ -120,7 +120,7 @@ static particle_status_t rocket_sim(particles_t *particles, particle_t *p)
}
-static void rocket_draw(particles_t *particles, particle_t *p, int x, int y, fb_fragment_t *f)
+static void rocket_draw(particles_t *particles, const particles_conf_t *conf, particle_t *p, int x, int y, fb_fragment_t *f)
{
rocket_ctxt_t *ctxt = p->ctxt;
@@ -132,7 +132,7 @@ static void rocket_draw(particles_t *particles, particle_t *p, int x, int y, fb_
}
-static void rocket_cleanup(particles_t *particles, particle_t *p)
+static void rocket_cleanup(particles_t *particles, const particles_conf_t *conf, particle_t *p)
{
rockets_cnt--;
}
diff --git a/src/modules/sparkler/simple.c b/src/modules/sparkler/simple.c
index 7c7d415..8db15b1 100644
--- a/src/modules/sparkler/simple.c
+++ b/src/modules/sparkler/simple.c
@@ -23,7 +23,7 @@ typedef struct _simple_ctxt_t {
} simple_ctxt_t;
-static int simple_init(particles_t *particles, particle_t *p)
+static int simple_init(particles_t *particles, const particles_conf_t *conf, particle_t *p)
{
simple_ctxt_t *ctxt = p->ctxt;
@@ -54,7 +54,7 @@ static int simple_init(particles_t *particles, particle_t *p)
}
-static particle_status_t simple_sim(particles_t *particles, particle_t *p)
+static particle_status_t simple_sim(particles_t *particles, const particles_conf_t *conf, particle_t *p, fb_fragment_t *f)
{
simple_ctxt_t *ctxt = p->ctxt;
@@ -95,7 +95,7 @@ static particle_status_t simple_sim(particles_t *particles, particle_t *p)
}
-static void simple_draw(particles_t *particles, particle_t *p, int x, int y, fb_fragment_t *f)
+static void simple_draw(particles_t *particles, const particles_conf_t *conf, particle_t *p, int x, int y, fb_fragment_t *f)
{
simple_ctxt_t *ctxt = p->ctxt;
diff --git a/src/modules/sparkler/spark.c b/src/modules/sparkler/spark.c
index 16268a9..c432bf5 100644
--- a/src/modules/sparkler/spark.c
+++ b/src/modules/sparkler/spark.c
@@ -18,7 +18,7 @@ typedef struct _spark_ctxt_t {
} spark_ctxt_t;
-static int spark_init(particles_t *particles, particle_t *p)
+static int spark_init(particles_t *particles, const particles_conf_t *conf, particle_t *p)
{
spark_ctxt_t *ctxt = p->ctxt;
@@ -32,7 +32,7 @@ static int spark_init(particles_t *particles, particle_t *p)
}
-static particle_status_t spark_sim(particles_t *particles, particle_t *p)
+static particle_status_t spark_sim(particles_t *particles, const particles_conf_t *conf, particle_t *p, fb_fragment_t *f)
{
spark_ctxt_t *ctxt = p->ctxt;
@@ -45,7 +45,7 @@ static particle_status_t spark_sim(particles_t *particles, particle_t *p)
}
-static void spark_draw(particles_t *particles, particle_t *p, int x, int y, fb_fragment_t *f)
+static void spark_draw(particles_t *particles, const particles_conf_t *conf, particle_t *p, int x, int y, fb_fragment_t *f)
{
spark_ctxt_t *ctxt = p->ctxt;
diff --git a/src/modules/sparkler/sparkler.c b/src/modules/sparkler/sparkler.c
index 20a56c7..b673d0c 100644
--- a/src/modules/sparkler/sparkler.c
+++ b/src/modules/sparkler/sparkler.c
@@ -74,7 +74,10 @@ static void sparkler_prepare_frame(void *context, unsigned ticks, unsigned ncpus
*res_fragmenter = sparkler_fragmenter;
ctxt->n_cpus = ncpus;
- particles_sim(ctxt->particles);
+ if (sparkler_conf.show_bsp_matches)
+ fb_fragment_zero(fragment);
+
+ particles_sim(ctxt->particles, fragment);
particles_add_particles(ctxt->particles, NULL, &simple_ops, INIT_PARTS / 4);
particles_age(ctxt->particles);
}
@@ -85,7 +88,9 @@ static void sparkler_render_fragment(void *context, unsigned ticks, unsigned cpu
{
sparkler_context_t *ctxt = context;
- fb_fragment_zero(fragment);
+ if (!sparkler_conf.show_bsp_matches)
+ fb_fragment_zero(fragment);
+
particles_draw(ctxt->particles, fragment);
}
@@ -96,11 +101,13 @@ static int sparkler_setup(const settings_t *settings, setting_desc_t **next_sett
const char *show_bsp_leafs;
const char *show_bsp_matches;
const char *values[] = {
- "on",
"off",
+ "on",
NULL
};
+ /* TODO: return -EINVAL on parse errors? */
+
show_bsp_leafs = settings_get_value(settings, "show_bsp_leafs");
if (!show_bsp_leafs) {
int r;
@@ -117,6 +124,40 @@ static int sparkler_setup(const settings_t *settings, setting_desc_t **next_sett
return 1;
}
+ if (!strcasecmp(show_bsp_leafs, "on")) {
+ const char *show_bsp_leafs_min_depth;
+
+ sparkler_conf.show_bsp_leafs = 1;
+
+ show_bsp_leafs_min_depth = settings_get_value(settings, "show_bsp_leafs_min_depth");
+ if (!show_bsp_leafs_min_depth) {
+ const char *depth_values[] = {
+ "0",
+ "4",
+ "6",
+ "8",
+ "10",
+ NULL
+ };
+ int r;
+
+ r = setting_desc_clone(&(setting_desc_t){
+ .name = "Show BSP Leaf Node Bounding Boxes Minimum Depth",
+ .key = "show_bsp_leafs_min_depth",
+ .preferred = "8",
+ .values = depth_values,
+ }, next_setting);
+ if (r < 0)
+ return r;
+
+ return 1;
+ }
+
+ sscanf(show_bsp_leafs_min_depth, "%u", &sparkler_conf.show_bsp_leafs_min_depth);
+ } else {
+ sparkler_conf.show_bsp_leafs = 0;
+ }
+
show_bsp_matches = settings_get_value(settings, "show_bsp_matches");
if (!show_bsp_matches) {
int r;
@@ -133,17 +174,36 @@ static int sparkler_setup(const settings_t *settings, setting_desc_t **next_sett
return 1;
}
- /* TODO: return -EINVAL on parse errors? */
- if (!strcasecmp(show_bsp_leafs, "on"))
- sparkler_conf.show_bsp_leafs = 1;
- else
- sparkler_conf.show_bsp_leafs = 0;
-
if (!strcasecmp(show_bsp_matches, "on"))
sparkler_conf.show_bsp_matches = 1;
else
sparkler_conf.show_bsp_matches = 0;
+ if (!strcasecmp(show_bsp_matches, "on")) {
+ const char *show_bsp_matches_affected_only;
+
+ show_bsp_matches_affected_only = settings_get_value(settings, "show_bsp_matches_affected_only");
+ if (!show_bsp_matches_affected_only) {
+ int r;
+
+ r = setting_desc_clone(&(setting_desc_t){
+ .name = "Show Only Affected BSP Search Matches",
+ .key = "show_bsp_matches_affected_only",
+ .preferred = "off",
+ .values = values,
+ }, next_setting);
+ if (r < 0)
+ return r;
+
+ return 1;
+ }
+
+ if (!strcasecmp(show_bsp_matches_affected_only, "on"))
+ sparkler_conf.show_bsp_matches_affected_only = 1;
+ else
+ sparkler_conf.show_bsp_matches_affected_only = 0;
+ }
+
return 0;
}
diff --git a/src/modules/sparkler/xplode.c b/src/modules/sparkler/xplode.c
index 8b191cd..4d6ee36 100644
--- a/src/modules/sparkler/xplode.c
+++ b/src/modules/sparkler/xplode.c
@@ -21,7 +21,7 @@ typedef struct _xplode_ctxt_t {
} xplode_ctxt_t;
-static int xplode_init(particles_t *particles, particle_t *p)
+static int xplode_init(particles_t *particles, const particles_conf_t *conf, particle_t *p)
{
xplode_ctxt_t *ctxt = p->ctxt;
@@ -36,7 +36,7 @@ static int xplode_init(particles_t *particles, particle_t *p)
}
-static particle_status_t xplode_sim(particles_t *particles, particle_t *p)
+static particle_status_t xplode_sim(particles_t *particles, const particles_conf_t *conf, particle_t *p, fb_fragment_t *f)
{
xplode_ctxt_t *ctxt = p->ctxt;
@@ -57,7 +57,7 @@ static particle_status_t xplode_sim(particles_t *particles, particle_t *p)
}
-static void xplode_draw(particles_t *particles, particle_t *p, int x, int y, fb_fragment_t *f)
+static void xplode_draw(particles_t *particles, const particles_conf_t *conf, particle_t *p, int x, int y, fb_fragment_t *f)
{
xplode_ctxt_t *ctxt = p->ctxt;
uint32_t color;
© All Rights Reserved