summaryrefslogtreecommitdiff
path: root/src/modules/sparkler/particle.h
blob: 6a5bf73f2b2d191b083db079676c2050ecad6fcc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#ifndef _PARTICLE_H
#define _PARTICLE_H

#include "til_fb.h"

#include "bsp.h"
#include "v3f.h"

typedef struct particle_props_t {
	v3f_t		position;	/* position in 3d space */
	v3f_t		direction;	/* trajectory in 3d space */
	float		velocity;	/* linear velocity */
	float		mass;		/* mass of particle */
	float		drag;		/* drag of particle */
	int		of_use:1;	/* are these properties of use/meaningful? */
	int		virtual:1;	/* is this a virtual particle? (not to be moved or otherwise acted upon) */
} particle_props_t;

typedef enum particle_status_t {
	PARTICLE_ALIVE,
	PARTICLE_DEAD
} 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 *, 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 *, til_fb_fragment_t *);			/* simulate the particle for another cycle (required) */
	void			(*draw)(particles_t *, const particles_conf_t *, particle_t *, int, int, til_fb_fragment_t *);	/* draw the particle, 3d->2d projection has been done already (optional) */
} particle_ops_t;

struct particle_t {
	bsp_occupant_t		occupant;	/* occupant node in the bsp tree */
	particle_props_t	*props;
	particle_ops_t		*ops;
	void			*ctxt;
};


//#define rand_within_range(_min, _max) ((rand() % (_max - _min)) + _min)
// the style of random number generator used by c libraries has less entropy in the lower bits meaning one shouldn't just use modulo, while this is slower, the results do seem a little different.
#define rand_within_range(_min, _max) (int)(((float)_min) + ((float)rand() / (float)RAND_MAX) * (_max - _min))

#define INHERIT_OPS	NULL
#define INHERIT_PROPS	NULL


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, conf, p);
	}

	return 1;
}


static inline void particle_cleanup(particles_t *particles, const particles_conf_t *conf, particle_t *p) {
	if (p->ops->cleanup) {
		p->ops->cleanup(particles, conf, 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, til_fb_fragment_t *f) {
	return p->ops->sim(particles, conf, p, f);
}


static inline void particle_draw(particles_t *particles, const particles_conf_t *conf, particle_t *p, int x, int y, til_fb_fragment_t *f) {
	if (p->ops->draw) {
		p->ops->draw(particles, conf, p, x, y, f);
	}
}


void particle_convert(particles_t *particles, const particles_conf_t *conf, particle_t *p, particle_props_t *props, particle_ops_t *ops);

#endif
© All Rights Reserved