libpsys

changeset 0:1c8eb90a6989

initial commit
author John Tsiombikas <nuclear@mutantstargoat.com>
date Sat, 24 Sep 2011 07:22:07 +0300
parents
children 874a942853ad
files .hgignore Makefile.in README configure src/psys.c src/psys.h src/psys_gl.c src/psys_impl.h
diffstat 8 files changed, 683 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Sat Sep 24 07:22:07 2011 +0300
     1.3 @@ -0,0 +1,6 @@
     1.4 +\.o$
     1.5 +\.d$
     1.6 +\.swp$
     1.7 +^Makefile$
     1.8 +^libpsys\.a$
     1.9 +^libpsys\.so\.
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile.in	Sat Sep 24 07:22:07 2011 +0300
     2.3 @@ -0,0 +1,45 @@
     2.4 +src = $(wildcard src/*.c)
     2.5 +obj = $(src:.c=.o)
     2.6 +lib_a = libpsys.a
     2.7 +lib_so = libpsys.so
     2.8 +
     2.9 +CC = gcc
    2.10 +CFLAGS = -std=c89 -pedantic -Wall -g -fPIC -Isrc `pkg-config --cflags vmath`
    2.11 +LDFLAGS = `pkg-config --libs vmath`
    2.12 +
    2.13 +.PHONY: all
    2.14 +all: $(lib_a) $(lib_so)
    2.15 +
    2.16 +$(lib_a): $(obj)
    2.17 +	$(AR) rcs $@ $^
    2.18 +
    2.19 +$(lib_so): $(obj)
    2.20 +	$(CC) $(CFLAGS) -shared -o $@ $^ $(LDFLAGS)
    2.21 +
    2.22 +.PHONY: install
    2.23 +install: $(lib_a) $(lib_so)
    2.24 +	install -d $(PREFIX)/lib
    2.25 +	install -m 644 $(lib_a) $(lib_so) $(PREFIX)/lib
    2.26 +	install -d $(PREFIX)/include
    2.27 +	install -m 644 src/psys.h $(PREFIX)/include/psys.h
    2.28 +	install -d $(PREFIX)/lib/pkgconfig
    2.29 +	install -m 644 psys.pc $(PREFIX)/lib/pkgconfig/psys.pc
    2.30 +
    2.31 +.PHONY: uninstall
    2.32 +uninstall:
    2.33 +	rm -f $(PREFIX)/lib/$(lib_a)
    2.34 +	rm -f $(PREFIX)/lib/$(lib_so)
    2.35 +	rm -f $(PREFIX)/include/psys.h
    2.36 +	rm -f $(PREFIX)/lib/pkgconfig/psys.pc
    2.37 +
    2.38 +.PHONY: clean
    2.39 +clean:
    2.40 +	rm -f $(obj)
    2.41 +
    2.42 +.PHONY: distclean
    2.43 +distclean:
    2.44 +	rm -f $(obj) $(lib_so) $(lib_a) Makefile psys.pc
    2.45 +
    2.46 +.PHONY: dist
    2.47 +dist: distclean
    2.48 +	cd ..; tar czvf psys.tar.gz psys && mv psys.tar.gz psys/
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/README	Sat Sep 24 07:22:07 2011 +0300
     3.3 @@ -0,0 +1,1 @@
     3.4 +libpsys - 0.1
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/configure	Sat Sep 24 07:22:07 2011 +0300
     4.3 @@ -0,0 +1,71 @@
     4.4 +#!/bin/sh
     4.5 +
     4.6 +PREFIX=/usr/local
     4.7 +OPT=yes
     4.8 +DBG=yes
     4.9 +VERSION=`head -1 README | sed 's/^.*- //'`
    4.10 +
    4.11 +echo "configuring psys $VERSION ..."
    4.12 +
    4.13 +check_vmath()
    4.14 +{
    4.15 +	PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/nekoware/lib/pkgconfig:/usr/freeware/lib/pkgconfig:/opt/lib/pkgconfig
    4.16 +	if [ -z "`pkg-config --cflags vmath`" ]; then
    4.17 +		echo 'libpsys depends on libvmath. You must install libvmath first.'
    4.18 +		exit 1
    4.19 +	fi
    4.20 +}
    4.21 +
    4.22 +for arg; do
    4.23 +	case "$arg" in
    4.24 +	--prefix=*)
    4.25 +		value=`echo $arg | sed 's/--prefix=//'`
    4.26 +		PREFIX=${value:-$PREFIX}
    4.27 +		;;
    4.28 +	
    4.29 +	--enable-opt)
    4.30 +		OPT=yes;;
    4.31 +	--disable-opt)
    4.32 +		OPT=no;;
    4.33 +
    4.34 +	--enable-debug)
    4.35 +		DBG=yes;;
    4.36 +	--disable-debug)
    4.37 +		DBG=no;;
    4.38 +
    4.39 +	--help)
    4.40 +		echo 'usage: ./configure [options]'
    4.41 +		echo 'options:'
    4.42 +		echo '  --prefix=<path>: installation path (default: /usr/local)'
    4.43 +		echo '  --enable-opt: enable speed optimizations (default)'
    4.44 +		echo '  --disable-opt: disable speed optimizations'
    4.45 +		echo '  --enable-debug: include debugging symbols (default)'
    4.46 +		echo '  --disable-debug: do not include debugging symbols'
    4.47 +		echo 'all invalid options are silently ignored'
    4.48 +		exit 0
    4.49 +		;;
    4.50 +	esac
    4.51 +done
    4.52 +
    4.53 +check_vmath
    4.54 +
    4.55 +echo "prefix: $PREFIX"
    4.56 +echo "optimize for speed: $OPT"
    4.57 +echo "include debugging symbols: $DBG"
    4.58 +
    4.59 +echo 'creating makefile ...'
    4.60 +echo "PREFIX = $PREFIX" >Makefile
    4.61 +if [ "$DBG" = 'yes' ]; then
    4.62 +	echo 'dbg = -g' >>Makefile
    4.63 +fi
    4.64 +if [ "$OPT" = 'yes' ]; then
    4.65 +	echo 'opt = -O3' >>Makefile
    4.66 +fi
    4.67 +cat Makefile.in >>Makefile
    4.68 +
    4.69 +echo 'creating pkg-config file ...'
    4.70 +echo "prefix=$PREFIX" >psys.pc
    4.71 +echo "ver=$VERSION" >>psys.pc
    4.72 +cat psys.pc.in >>psys.pc
    4.73 +
    4.74 +echo 'configuration completed, type make (or gmake) to build.'
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/psys.c	Sat Sep 24 07:22:07 2011 +0300
     5.3 @@ -0,0 +1,374 @@
     5.4 +#include <stdlib.h>
     5.5 +#include <math.h>
     5.6 +#include <assert.h>
     5.7 +#include <pthread.h>
     5.8 +#include <vmath.h>
     5.9 +#include "psys_impl.h"
    5.10 +
    5.11 +static int spawn(struct psys_emitter *em, struct psys_particle *p, void *cls);
    5.12 +static void update_particle(struct psys_emitter *em, struct psys_particle *p, float tm, float dt, void *cls);
    5.13 +
    5.14 +static int init_v3track(struct v3track *v3t);
    5.15 +static void destroy_v3track(struct v3track *v3t);
    5.16 +static void set_v3value(struct v3track *v3t, anm_time_t tm, vec3_t v);
    5.17 +static vec3_t get_v3value(struct v3track *v3t, anm_time_t tm);
    5.18 +
    5.19 +/* particle pool */
    5.20 +static struct psys_particle *ppool;
    5.21 +static int ppool_size;
    5.22 +static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER;
    5.23 +
    5.24 +static struct psys_particle *palloc(void);
    5.25 +static void pfree(struct psys_particle *p);
    5.26 +
    5.27 +/* --- constructors and shit --- */
    5.28 +
    5.29 +struct psys_emitter *psys_create(void)
    5.30 +{
    5.31 +	struct psys_emitter *em;
    5.32 +
    5.33 +	if(!(em = malloc(sizeof *em))) {
    5.34 +		return 0;
    5.35 +	}
    5.36 +	if(psys_init(em) == -1) {
    5.37 +		free(em);
    5.38 +		return 0;
    5.39 +	}
    5.40 +	return em;
    5.41 +}
    5.42 +
    5.43 +void psys_free(struct psys_emitter *em)
    5.44 +{
    5.45 +	psys_destroy(em);
    5.46 +	free(em);
    5.47 +}
    5.48 +
    5.49 +int psys_init(struct psys_emitter *em)
    5.50 +{
    5.51 +	memset(em, 0, sizeof *em);
    5.52 +
    5.53 +	if(anm_init_node(&em->prs) == -1) {
    5.54 +		return -1;
    5.55 +	}
    5.56 +	if(anm_init_track(&em->rate) == -1) {
    5.57 +		anm_destroy_node(&em->prs);
    5.58 +		return -1;
    5.59 +	}
    5.60 +	if(init_v3track(&em->dir) == -1) {
    5.61 +		anm_destroy_node(&em->prs);
    5.62 +		anm_destroy_track(&em->rate);
    5.63 +		return -1;
    5.64 +	}
    5.65 +
    5.66 +	em->spawn = spawn;
    5.67 +	em->update = update_particle;
    5.68 +
    5.69 +	em->draw = psys_gl_draw;
    5.70 +	em->draw_start = psys_gl_draw_start;
    5.71 +	em->draw_end = psys_gl_draw_end;
    5.72 +
    5.73 +	return 0;
    5.74 +}
    5.75 +
    5.76 +void psys_destroy(struct psys_emitter *em)
    5.77 +{
    5.78 +	struct psys_particle *part;
    5.79 +
    5.80 +	part = em->plist;
    5.81 +	while(part) {
    5.82 +		struct psys_particle *tmp = part;
    5.83 +		part = part->next;
    5.84 +		pfree(tmp);
    5.85 +	}
    5.86 +
    5.87 +	anm_destroy_node(&em->prs);
    5.88 +	anm_destroy_track(&em->rate);
    5.89 +	destroy_v3track(&em->dir);
    5.90 +}
    5.91 +
    5.92 +void psys_set_pos(struct psys_emitter *em, vec3_t pos, float tm)
    5.93 +{
    5.94 +	anm_set_position(&em->prs, pos, ANM_SEC2TM(tm));
    5.95 +}
    5.96 +
    5.97 +void psys_set_rot(struct psys_emitter *em, quat_t rot, float tm)
    5.98 +{
    5.99 +	anm_set_rotation(&em->prs, rot, ANM_SEC2TM(tm));
   5.100 +}
   5.101 +
   5.102 +void psys_set_pivot(struct psys_emitter *em, vec3_t pivot)
   5.103 +{
   5.104 +	anm_set_pivot(&em->prs, pivot);
   5.105 +}
   5.106 +
   5.107 +void psys_set_rate(struct psys_emitter *em, float rate, float tm)
   5.108 +{
   5.109 +	anm_set_value(&em->rate, ANM_SEC2TM(tm), rate);
   5.110 +}
   5.111 +
   5.112 +void psys_set_dir(struct psys_emitter *em, vec3_t dir, float tm)
   5.113 +{
   5.114 +	set_v3value(&em->dir, ANM_SEC2TM(tm), dir);
   5.115 +}
   5.116 +
   5.117 +
   5.118 +void psys_clear_collision_planes(struct psys_emitter *em)
   5.119 +{
   5.120 +	struct col_plane *plane;
   5.121 +
   5.122 +	plane = em->planes;
   5.123 +	while(plane) {
   5.124 +		struct col_plane *tmp = plane;
   5.125 +		plane = plane->next;
   5.126 +		pfree(tmp);
   5.127 +	}
   5.128 +}
   5.129 +
   5.130 +int psys_add_collision_plane(struct psys_emitter *em, plane_t plane, float elast)
   5.131 +{
   5.132 +	struct col_plane *node;
   5.133 +
   5.134 +	if(!(node = malloc(sizeof *node))) {
   5.135 +		return -1;
   5.136 +	}
   5.137 +	node->p = plane;
   5.138 +	node->elasticity = elast;
   5.139 +	node->next = em->planes;
   5.140 +	em->planes = node;
   5.141 +	return 0;
   5.142 +}
   5.143 +
   5.144 +void psys_add_particle(struct psys_emitter *em, struct psys_particle *p)
   5.145 +{
   5.146 +	p->next = em->plist;
   5.147 +	em->plist = p;
   5.148 +}
   5.149 +
   5.150 +void psys_spawn_func(struct psys_emitter *em, psys_spawn_func_t func, void *cls)
   5.151 +{
   5.152 +	em->spawn = func;
   5.153 +	em->spawn_cls = cls;
   5.154 +}
   5.155 +
   5.156 +void psys_update_func(struct psys_emitter *em, psys_update_func_t func, void *cls)
   5.157 +{
   5.158 +	em->update = func;
   5.159 +	em->upd_cls = cls;
   5.160 +}
   5.161 +
   5.162 +void psys_draw_func(struct psys_emitter *em, psys_draw_func_t draw,
   5.163 +		psys_draw_start_func_t start, psys_draw_end_func_t end, void *cls)
   5.164 +{
   5.165 +	em->draw = draw;
   5.166 +	em->draw_start = start;
   5.167 +	em->draw_end = end;
   5.168 +	em->draw_cls = cls;
   5.169 +}
   5.170 +
   5.171 +/* --- query current state --- */
   5.172 +vec3_t psys_get_pos(struct psys_emitter *em)
   5.173 +{
   5.174 +	return em->cur_pos;
   5.175 +}
   5.176 +
   5.177 +quat_t psys_get_rot(struct psys_emitter *em)
   5.178 +{
   5.179 +	return em->cur_rot;
   5.180 +}
   5.181 +
   5.182 +float psys_get_rate(struct psys_emitter *em)
   5.183 +{
   5.184 +	return em->cur_rate;
   5.185 +}
   5.186 +
   5.187 +float psys_get_life(struct psys_emitter *em)
   5.188 +{
   5.189 +	return em->cur_life;
   5.190 +}
   5.191 +
   5.192 +vec3_t psys_get_dir(struct psys_emitter *em)
   5.193 +{
   5.194 +	return em->cur_dir;
   5.195 +}
   5.196 +
   5.197 +
   5.198 +/* --- update and render --- */
   5.199 +
   5.200 +void psys_update(struct psys_emitter *em, float tm)
   5.201 +{
   5.202 +	float dt, spawn_dt;
   5.203 +	int i, spawn_count;
   5.204 +	struct psys_particle *p, pdummy;
   5.205 +	anm_time_t atm;
   5.206 +
   5.207 +	assert(em->spawn && em->update);
   5.208 +
   5.209 +	atm = ANM_SEC2TM(tm);
   5.210 +
   5.211 +	em->cur_rate = anm_get_value(&em->rate, atm)
   5.212 +	dt = tm - em->last_update;
   5.213 +
   5.214 +	/* how many particles to spawn for this interval ? */
   5.215 +	spawn_count = em->cur_rate * dt;
   5.216 +
   5.217 +#ifndef SUB_UPDATE_POS
   5.218 +	em->pos = anm_get_position(&em->prs, atm);
   5.219 +#endif
   5.220 +	em->cur_dir = get_v3value(&em->dir, atm);
   5.221 +	em->cur_life = anm_get_value(&em->life, atm);
   5.222 +
   5.223 +	spawn_dt = dt / (float)spawn_count;
   5.224 +	for(i=0; i<spawn_count; i++) {
   5.225 +#ifdef SUB_UPDATE_POS
   5.226 +		/* update emitter position for this spawning */
   5.227 +		em->pos = anm_get_position(&em->prs, ANM_SEC2TM(em->last_update + spawn_dt));
   5.228 +#endif
   5.229 +
   5.230 +		if(!(p = palloc())) {
   5.231 +			return;
   5.232 +		}
   5.233 +		if(em->spawn(em, p, em->spawn_cls) == -1) {
   5.234 +			pfree(p);
   5.235 +		}
   5.236 +	}
   5.237 +
   5.238 +	/* update all particles */
   5.239 +	p = em->plist;
   5.240 +	while(p) {
   5.241 +		em->update(em, p, tm, dt, upd_cls);
   5.242 +		p = p->next;
   5.243 +	}
   5.244 +
   5.245 +	/* cleanup dead particles */
   5.246 +	pdummy.next = em->plist;
   5.247 +	p = &pdummy;
   5.248 +	while(p->next) {
   5.249 +		if(p->next->life <= 0) {
   5.250 +			struct psys_particle *tmp = p->next;
   5.251 +			p->next = p->next->next;
   5.252 +			pfree(tmp);
   5.253 +		} else {
   5.254 +			p = p->next;
   5.255 +		}
   5.256 +	}
   5.257 +	em->plist = pdummy.next;
   5.258 +}
   5.259 +
   5.260 +void psys_draw(struct psys_emitter *em)
   5.261 +{
   5.262 +	struct psys_particle *p;
   5.263 +
   5.264 +	if(em->draw_start) {
   5.265 +		em->draw_start(em, em->cls);
   5.266 +	}
   5.267 +
   5.268 +	p = em->plist;
   5.269 +	while(p) {
   5.270 +		em->draw(em, p, em->cls);
   5.271 +		p = p->next;
   5.272 +	}
   5.273 +
   5.274 +	if(em->draw_end) {
   5.275 +		em->draw_end(em, em->cls);
   5.276 +	}
   5.277 +}
   5.278 +
   5.279 +static int spawn(struct psys_emitter *em, struct psys_particle *p, void *cls)
   5.280 +{
   5.281 +	p->pos = em->cur_pos;
   5.282 +	p->vel = em->cur_dir;
   5.283 +	p->size = 1.0;
   5.284 +	p->life = em->cur_life;
   5.285 +
   5.286 +	psys_add_particle(em, p);
   5.287 +	return 0;
   5.288 +}
   5.289 +
   5.290 +static void update_particle(struct psys_emitter *em, struct psys_particle *p, float tm, float dt, void *cls)
   5.291 +{
   5.292 +	vec3_t forces;
   5.293 +
   5.294 +	forces.x = em->cur_grav.x * p->mass - p->vel.x * em->drag;
   5.295 +	forces.y = em->cur_grav.y * p->mass - p->vel.y * em->drag;
   5.296 +	forces.z = em->cur_grav.z * p->mass - p->vel.z * em->drag;
   5.297 +
   5.298 +	p->pos.x += p->vel.x * dt;
   5.299 +	p->pos.y += p->vel.y * dt;
   5.300 +	p->pos.z += p->vel.z * dt;
   5.301 +
   5.302 +
   5.303 +}
   5.304 +
   5.305 +/* --- v3track helper --- */
   5.306 +
   5.307 +int init_v3track(struct v3track *v3t)
   5.308 +{
   5.309 +	if(anm_init_track(&v3t->x) == -1) {
   5.310 +		return -1;
   5.311 +	}
   5.312 +	if(anm_init_track(&v3t->y) == -1) {
   5.313 +		anm_destroy_track(&v3t->x);
   5.314 +		return -1;
   5.315 +	}
   5.316 +	if(anm_init_track(&v3t->z) == -1) {
   5.317 +		anm_destroy_track(&v3t->x);
   5.318 +		anm_destroy_track(&v3t->y);
   5.319 +		return -1;
   5.320 +	}
   5.321 +	return 0;
   5.322 +}
   5.323 +
   5.324 +static void destroy_v3track(struct v3track *v3t)
   5.325 +{
   5.326 +	anm_destroy_track(&v3t->x);
   5.327 +	anm_destroy_track(&v3t->y);
   5.328 +	anm_destroy_track(&v3t->z);
   5.329 +}
   5.330 +
   5.331 +static void set_v3value(struct v3track *v3t, anm_time_t tm, vec3_t v)
   5.332 +{
   5.333 +	anm_set_value(&v3t->x, tm, v.x);
   5.334 +	anm_set_value(&v3t->y, tm, v.y);
   5.335 +	anm_set_value(&v3t->z, tm, v.z);
   5.336 +}
   5.337 +
   5.338 +static vec3_t get_v3value(struct v3track *v3t, anm_time_t tm)
   5.339 +{
   5.340 +	vec3_t v;
   5.341 +	v.x = anm_get_value(&v3t->x, tm);
   5.342 +	v.y = anm_get_value(&v3t->y, tm);
   5.343 +	v.z = anm_get_value(&v3t->z, tm);
   5.344 +	return v;
   5.345 +}
   5.346 +
   5.347 +/* --- particle allocation pool --- */
   5.348 +
   5.349 +static struct psys_particle *palloc(void)
   5.350 +{
   5.351 +	struct psys_particle *p;
   5.352 +
   5.353 +	pthread_mutex_lock(&pool_lock);
   5.354 +	if(ppool) {
   5.355 +		p = ppool;
   5.356 +		ppool = ppool->next;
   5.357 +		ppool_size--;
   5.358 +	} else {
   5.359 +		p = malloc(sizeof *p);
   5.360 +	}
   5.361 +	pthread_mutex_unlock(&pool_lock);
   5.362 +
   5.363 +	if(p) {
   5.364 +		memset(p, 0, sizeof *p);
   5.365 +		reset_pattr(&p->attr);
   5.366 +	}
   5.367 +	return p;
   5.368 +}
   5.369 +
   5.370 +static void pfree(struct psys_particle *p)
   5.371 +{
   5.372 +	pthread_mutex_lock(&pool_lock);
   5.373 +	p->next = ppool;
   5.374 +	ppool = p;
   5.375 +	ppool_size++;
   5.376 +	pthread_mutex_unlock(&pool_lock);
   5.377 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/psys.h	Sat Sep 24 07:22:07 2011 +0300
     6.3 @@ -0,0 +1,61 @@
     6.4 +#ifndef LIBPSYS_H_
     6.5 +#define LIBPSYS_H_
     6.6 +
     6.7 +/* emitter properties:
     6.8 + * - p/r/s (anim)
     6.9 + * - spawn rate (anim)
    6.10 + * - direction (anim)
    6.11 + *
    6.12 + * - collision planes
    6.13 + */
    6.14 +
    6.15 +struct psys_emitter;
    6.16 +struct psys_particle;
    6.17 +
    6.18 +typedef int (*psys_spawn_func_t)(struct psys_emitter*, struct psys_particle*, void*);
    6.19 +typedef void (*psys_update_func_t)(struct psys_emitter*, struct psys_particle*, float, float, void*);
    6.20 +
    6.21 +typedef void (*psys_draw_func_t)(struct psys_emitter*, struct psys_particle*, void*);
    6.22 +typedef void (*psys_draw_start_func_t)(struct psys_emitter*, void*);
    6.23 +typedef void (*psys_draw_end_func_t)(struct psys_emitter*, void*);
    6.24 +
    6.25 +
    6.26 +struct psys_emitter *psys_create(void);
    6.27 +void psys_free(struct psys_emitter *em);
    6.28 +
    6.29 +int psys_init(struct psys_emitter *em);
    6.30 +void psys_destroy(struct psys_emitter *em);
    6.31 +
    6.32 +/* set properties */
    6.33 +
    6.34 +void psys_set_pos(struct psys_emitter *em, vec3_t pos, float tm);
    6.35 +void psys_set_rot(struct psys_emitter *em, quat_t rot, float tm);
    6.36 +void psys_set_pivot(struct psys_emitter *em, vec3_t pivot);
    6.37 +
    6.38 +void psys_set_rate(struct psys_emitter *em, float rate, float tm);
    6.39 +void psys_set_dir(struct psys_emitter *em, vec3_t dir, float tm);
    6.40 +
    6.41 +void psys_clear_collision_planes(struct psys_emitter *em);
    6.42 +int psys_add_collision_plane(struct psys_emitter *em, plane_t plane, float elast);
    6.43 +
    6.44 +void psys_add_particle(struct psys_emitter *em, struct psys_particle *p);
    6.45 +
    6.46 +void psys_spawn_func(struct psys_emitter *em, psys_spawn_func_t func, void *cls);
    6.47 +void psys_update_func(struct psys_emitter *em, psys_update_func_t func, void *cls);
    6.48 +void psys_draw_func(struct psys_emitter *em, psys_draw_func_t draw,
    6.49 +		psys_draw_start_func_t start, psys_draw_end_func_t end, void *cls);
    6.50 +
    6.51 +
    6.52 +/* query emitter state */
    6.53 +vec3_t psys_get_pos(struct psys_emitter *em);
    6.54 +quat_t psys_get_rot(struct psys_emitter *em);
    6.55 +float psys_get_rate(struct psys_emitter *em);
    6.56 +float psys_get_life(struct psys_emitter *em);
    6.57 +vec3_t psys_get_dir(struct psys_emitter *em);
    6.58 +
    6.59 +/* update and render */
    6.60 +
    6.61 +void psys_update(struct psys_emitter *em, float tm);
    6.62 +void psys_draw(struct psys_emitter *em);
    6.63 +
    6.64 +#endif	/* LIBPSYS_H_ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/psys_gl.c	Sat Sep 24 07:22:07 2011 +0300
     7.3 @@ -0,0 +1,57 @@
     7.4 +#ifndef __APPLE__
     7.5 +#include <GL/gl.h>
     7.6 +#else
     7.7 +#include <OpenGL/gl.h>
     7.8 +#endif
     7.9 +
    7.10 +#include "psys_impl.h"
    7.11 +
    7.12 +void psys_gl_draw_start(struct psys_emitter *em, void *cls)
    7.13 +{
    7.14 +	float xform[16];
    7.15 +
    7.16 +	glMatrixMode(GL_MODELVIEW);
    7.17 +	glPushMatrix();
    7.18 +
    7.19 +	glGetFloatv(GL_MODELVIEW_MATRIX, xform);
    7.20 +	xform[3] = xform[7] = xform[11] = xform[12] = xform[13] = xform[14] = 0.0f;
    7.21 +	xform[15] = 1.0f;
    7.22 +
    7.23 +	glLoadMatrixf(xform);
    7.24 +
    7.25 +	glPushAttrib(GL_ENABLE_BIT);
    7.26 +	glDisable(GL_LIGHTING);
    7.27 +
    7.28 +	glDepthMask(0);
    7.29 +
    7.30 +	glBegin(GL_QUADS);
    7.31 +	glColor3f(1, 1, 1);
    7.32 +}
    7.33 +
    7.34 +void psys_gl_draw(struct psys_emitter *em, struct psys_particle *p, void *cls)
    7.35 +{
    7.36 +	float hsz = p->size / 2.0;
    7.37 +
    7.38 +	glTexCoord2f(0, 0);
    7.39 +	glVertex3f(p->pos.x - hsz, p->pos.y - hsz, p->pos.z);
    7.40 +
    7.41 +	glTexCoord2f(1, 0);
    7.42 +	glVertex3f(p->pos.x + hsz, p->pos.y - hsz, p->pos.z);
    7.43 +
    7.44 +	glTexCoord2f(1, 1);
    7.45 +	glVertex3f(p->pos.x + hsz, p->pos.y + hsz, p->pos.z);
    7.46 +
    7.47 +	glTexCoord2f(0, 1);
    7.48 +	glVertex3f(p->pos.x - hsz, p->pos.y + hsz, p->pos.z);
    7.49 +}
    7.50 +
    7.51 +void psys_gl_draw_end(struct psys_emitter *em, void *cls)
    7.52 +{
    7.53 +	glEnd();
    7.54 +
    7.55 +	glDepthMask(1);
    7.56 +	glPopAttrib();
    7.57 +
    7.58 +	glMatrixMode(GL_MODELVIEW);
    7.59 +	glPopMatrix();
    7.60 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/psys_impl.h	Sat Sep 24 07:22:07 2011 +0300
     8.3 @@ -0,0 +1,68 @@
     8.4 +#ifndef PSYS_IMPL_H_
     8.5 +#define PSYS_IMPL_H_
     8.6 +
     8.7 +#include <anim/anim.h>
     8.8 +#include "psys.h"
     8.9 +
    8.10 +struct v3track {
    8.11 +	struct anm_track x, y, z;
    8.12 +};
    8.13 +
    8.14 +struct col_plane {
    8.15 +	plane_t p;
    8.16 +	float elasticity;
    8.17 +	struct col_plane *next;
    8.18 +};
    8.19 +
    8.20 +struct psys_particle;
    8.21 +
    8.22 +struct psys_emitter {
    8.23 +	float last_update;
    8.24 +
    8.25 +	struct anm_node prs;
    8.26 +
    8.27 +	struct anm_track rate;
    8.28 +	struct anm_track life;
    8.29 +	struct v3track dir;
    8.30 +	struct v3track grav;
    8.31 +
    8.32 +	float drag;	/* I don't think this needs to animate */
    8.33 +
    8.34 +	/* list of active particles */
    8.35 +	struct psys_particle *plist;
    8.36 +
    8.37 +	/* list of collision planes */
    8.38 +	struct col_plane *planes;
    8.39 +
    8.40 +	/* custom spawn closure */
    8.41 +	void *spawn_cls;
    8.42 +	psys_spawn_func_t spawn;
    8.43 +
    8.44 +	/* custom particle update closure */
    8.45 +	void *upd_cls;
    8.46 +	psys_update_func_t update;
    8.47 +
    8.48 +	/* custom draw closure */
    8.49 +	void *draw_cls;
    8.50 +	psys_draw_func_t draw;
    8.51 +	psys_draw_start_func_t draw_start;
    8.52 +	psys_draw_end_func_t draw_end;
    8.53 +
    8.54 +	/* calculated on update */
    8.55 +	vec3_t cur_pos;
    8.56 +	qut_t cur_rot;
    8.57 +	float cur_rate, cur_life;
    8.58 +	vec3_t cur_dir;
    8.59 +};
    8.60 +
    8.61 +
    8.62 +struct psys_particle {
    8.63 +	vec3_t pos, vel;
    8.64 +	float life, size, mass;
    8.65 +};
    8.66 +
    8.67 +void psys_gl_draw_start(struct psys_emitter *em, void *cls);
    8.68 +void psys_gl_draw(struct psys_emitter *em, struct psys_particle *p, void *cls);
    8.69 +void psys_gl_draw_end(struct psys_emitter *em, void *cls);
    8.70 +
    8.71 +#endif	/* PSYS_IMPL_H_ */