# HG changeset patch # User John Tsiombikas # Date 1347318792 -10800 # Node ID 3871a45a4e4b0f657f624f105586b76941ad6ffe # Parent 5678915dc2c74b266c50b23403f71c6b2b64c625 Almost there diff -r 5678915dc2c7 -r 3871a45a4e4b examples/simple/simple.c --- a/examples/simple/simple.c Mon Sep 10 21:57:49 2012 +0300 +++ b/examples/simple/simple.c Tue Sep 11 02:13:12 2012 +0300 @@ -51,7 +51,12 @@ if(!(ps = psys_create())) { return 1; } - ps->attr.tex = tex; + if(psys_load_attr(&ps->attr, "simple.psys") == -1) { + fprintf(stderr, "failed to load particle system definition\n"); + psys_free(ps); + return 1; + } + /*ps->attr.tex = tex; ps->attr.drag = 2; psys_set_value3(&ps->attr.grav, 0, v3_cons(0, -4, 0)); psys_set_anm_rnd(&ps->attr.life, 0, 2, 0); @@ -62,8 +67,9 @@ psys_set_value3(&ps->attr.part_attr.color, 1000, v3_cons(0.6, 0.3, 1.0)); psys_set_value(&ps->attr.part_attr.alpha, 0, 1); psys_set_value(&ps->attr.part_attr.alpha, 700, 1); - psys_set_value(&ps->attr.part_attr.alpha, 1000, 0); + psys_set_value(&ps->attr.part_attr.alpha, 1000, 0);*/ + assert(glGetError() == GL_NO_ERROR); atexit(cleanup); glutMainLoop(); diff -r 5678915dc2c7 -r 3871a45a4e4b src/pattr.c --- a/src/pattr.c Mon Sep 10 21:57:49 2012 +0300 +++ b/src/pattr.c Tue Sep 11 02:13:12 2012 +0300 @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -31,7 +32,8 @@ static int init_particle_attr(struct psys_particle_attributes *pattr); static void destroy_particle_attr(struct psys_particle_attributes *pattr); -static int get_cfg_opt(const char *line, struct cfgopt *opt); +static struct cfgopt *get_cfg_opt(const char *line); +static void release_cfg_opt(struct cfgopt *opt); static char *stripspace(char *str); static void *tex_cls; @@ -154,93 +156,114 @@ { int lineno = 0; char buf[512]; + struct cfgopt *opt = 0; psys_init_attr(attr); while(fgets(buf, sizeof buf, fp)) { - struct cfgopt opt; lineno++; - if(get_cfg_opt(buf, &opt) == -1) { + if(!(opt = get_cfg_opt(buf))) { + continue; + } + + if(strcmp(opt->name, "texture") == 0) { + if(opt->type != OPT_STR) { + goto err; + } + if(!(attr->tex = load_texture(opt->valstr, tex_cls))) { + fprintf(stderr, "failed to load texture: %s\n", opt->valstr); + goto err; + } + + release_cfg_opt(opt); + continue; + } else if(opt->type == OPT_STR) { + fprintf(stderr, "invalid particle config: '%s'\n", opt->name); goto err; } - if(strcmp(opt.name, "texture")) { - if(opt.type != OPT_STR) { - goto err; - } - if(!(attr->tex = load_texture(opt.valstr, tex_cls))) { - fprintf(stderr, "failed to load texture: %s\n", opt.valstr); - goto err; - } - } else if(opt.type == OPT_STR) { - fprintf(stderr, "invalid particle config: %s\n", opt.name); + if(strcmp(opt->name, "spawn_range") == 0) { + psys_set_value3(&attr->spawn_range, opt->tm, opt->val); + } else if(strcmp(opt->name, "rate") == 0) { + psys_set_value(&attr->rate, opt->tm, opt->val.x); + } else if(strcmp(opt->name, "life") == 0) { + psys_set_anm_rnd(&attr->life, opt->tm, opt->val.x, opt->valrng.x); + } else if(strcmp(opt->name, "size") == 0) { + psys_set_anm_rnd(&attr->size, opt->tm, opt->val.x, opt->valrng.x); + } else if(strcmp(opt->name, "dir") == 0) { + psys_set_anm_rnd3(&attr->dir, opt->tm, opt->val, opt->valrng); + } else if(strcmp(opt->name, "grav") == 0) { + psys_set_value3(&attr->grav, opt->tm, opt->val); + } else if(strcmp(opt->name, "drag") == 0) { + attr->drag = opt->val.x; + } else if(strcmp(opt->name, "pcolor") == 0) { + psys_set_value3(&attr->part_attr.color, opt->tm, opt->val); + } else if(strcmp(opt->name, "palpha") == 0) { + psys_set_value(&attr->part_attr.alpha, opt->tm, opt->val.x); + } else if(strcmp(opt->name, "psize") == 0) { + psys_set_value(&attr->part_attr.size, opt->tm, opt->val.x); + } else { + fprintf(stderr, "unrecognized particle config option: %s\n", opt->name); goto err; } - if(strcmp(opt.name, "spawn_range") == 0) { - psys_set_value3(&attr->spawn_range, opt.tm, opt.val); - } else if(strcmp(opt.name, "rate") == 0) { - psys_set_value(&attr->rate, opt.tm, opt.val.x); - } else if(strcmp(opt.name, "life") == 0) { - psys_set_anm_rnd(&attr->life, opt.tm, opt.val.x, opt.valrng.x); - } else if(strcmp(opt.name, "size") == 0) { - psys_set_anm_rnd(&attr->size, opt.tm, opt.val.x, opt.valrng.x); - } else if(strcmp(opt.name, "dir") == 0) { - psys_set_anm_rnd3(&attr->dir, opt.tm, opt.val, opt.valrng); - } else if(strcmp(opt.name, "grav") == 0) { - psys_set_value3(&attr->grav, opt.tm, opt.val); - } else if(strcmp(opt.name, "drag") == 0) { - attr->drag = opt.val.x; - } else if(strcmp(opt.name, "pcolor") == 0) { - psys_set_value3(&attr->part_attr.color, opt.tm, opt.val); - } else if(strcmp(opt.name, "palpha") == 0) { - psys_set_value(&attr->part_attr.alpha, opt.tm, opt.val.x); - } else if(strcmp(opt.name, "psize") == 0) { - psys_set_value(&attr->part_attr.size, opt.tm, opt.val.x); - } else { - fprintf(stderr, "unrecognized particle config option: %s\n", opt.name); - goto err; - } + release_cfg_opt(opt); } return 0; err: fprintf(stderr, "Line %d: error parsing particle definition\n", lineno); - psys_destroy_attr(attr); + release_cfg_opt(opt); return -1; } -/* strdup on the stack with alloca */ -#define strdup_stack(s) strcpy(alloca(strlen(s) + 1), s) - -static int get_cfg_opt(const char *line, struct cfgopt *opt) +static struct cfgopt *get_cfg_opt(const char *line) { - char *buf; - float tmsec; + char *buf, *tmp; + struct cfgopt *opt; line = stripspace((char*)line); if(line[0] == '#' || !line[0]) { return 0; /* skip empty lines and comments */ } + + if(!(opt = malloc(sizeof *opt))) { + return 0; + } + if(!(opt->valstr = strchr(line, '='))) { - return -1; + release_cfg_opt(opt); + return 0; } *opt->valstr++ = 0; opt->valstr = stripspace(opt->valstr); /* allocate a working buffer on the stack that could fit the current line */ buf = alloca(strlen(line) + 1); + strcpy(buf, line); + buf = stripspace(buf); - if(sscanf(line, "%s(%fs)", buf, &tmsec) == 2) { - opt->tm = (long)(tmsec * 1000.0f); - opt->name = strdup_stack(buf); - } else if(sscanf(line, "%s(%ld)", buf, &opt->tm) == 2) { - opt->name = strdup_stack(buf); + /* parse the keyframe time specifier if it exists */ + if((tmp = strchr(buf, '('))) { + char *endp; + float tval; + + *tmp++ = 0; + opt->name = strdup(buf); + + tval = strtod(tmp + 1, &endp); + if(endp == tmp + 1) { /* nada ... */ + opt->tm = 0; + } else if(*endp == 's') { /* seconds suffix */ + opt->tm = (long)(tval * 1000.0f); + } else { + opt->tm = (long)tval; + } } else { - opt->name = strdup_stack(buf); + opt->name = strdup(buf); opt->tm = 0; } @@ -268,16 +291,26 @@ } else if(sscanf(opt->valstr, "\"%s\"", buf) == 1) { /* just a string... strip the quotes */ + if(buf[strlen(buf) - 1] == '\"') { + buf[strlen(buf) - 1] = 0; + } opt->type = OPT_STR; - opt->valstr = strdup_stack(buf); + opt->valstr = strdup(buf); } else { /* fuck it ... */ - return -1; + release_cfg_opt(opt); + return 0; } - return 0; + return opt; } +static void release_cfg_opt(struct cfgopt *opt) +{ + if(opt) { + free(opt->name); + } +} int psys_save_attr(struct psys_attributes *attr, const char *fname) @@ -308,7 +341,7 @@ str++; } - end = str + strlen(str); + end = str + strlen(str) - 1; while(end >= str && isspace(*end)) { *end-- = 0; } diff -r 5678915dc2c7 -r 3871a45a4e4b src/psys_gl.c --- a/src/psys_gl.c Mon Sep 10 21:57:49 2012 +0300 +++ b/src/psys_gl.c Tue Sep 11 02:13:12 2012 +0300 @@ -1,5 +1,6 @@ #include #include +#include #ifndef __APPLE__ #ifdef WIN32 @@ -85,6 +86,7 @@ if(!(pixels = img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGBA32))) { return 0; } + printf("%s: creating texture %s (%dx%d)\n", __func__, fname, xsz, ysz); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); @@ -92,7 +94,9 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, xsz, ysz, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + assert(glGetError() == GL_NO_ERROR); img_free_pixels(pixels); return tex;