# HG changeset patch # User John Tsiombikas # Date 1361290637 -7200 # Node ID 7056437a361b30298da2e3deb7646a7fc6164f0a # Parent f0a47f46ee45d6e0346c80b393e1fdaaa4f597e8 added demosys diff -r f0a47f46ee45 -r 7056437a361b Makefile --- a/Makefile Mon Feb 18 06:53:44 2013 +0200 +++ b/Makefile Tue Feb 19 18:17:17 2013 +0200 @@ -1,11 +1,12 @@ csrc = $(wildcard src/*.c) \ - $(wildcard libs/metasurf/*.c) + $(wildcard libs/metasurf/*.c) \ + $(wildcard libs/dsys2/*.c) ccsrc = $(wildcard src/*.cc) obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) dep = $(obj:.o=.d) bin = udg -CFLAGS = -pedantic -Wall -g -O3 -Ilibs/metasurf +CFLAGS = -pedantic -Wall -g -O3 -Ilibs/metasurf -Ilibs/dsys2 CXXFLAGS = -std=c++11 $(CFLAGS) LDFLAGS = $(libgl) -limago -lvmath diff -r f0a47f46ee45 -r 7056437a361b libs/dsys2/dsys.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/dsys2/dsys.c Tue Feb 19 18:17:17 2013 +0200 @@ -0,0 +1,515 @@ +#include +#include +#include +#include +#include +#include +#include "dsys.h" +#include "dsys_impl.h" + +static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname); +static char *strip_ws(char *buf); +static void dbg_print_events(struct dsys_event *ev); + +static void proc_event(struct dsys_event *ev, demotime_t tm); +static void link_callback(struct dsys_event *ev, void *cls); +static void free_event(struct dsys_event *ev); + +static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev); +static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2); + + +struct dsys_demo *dsys_open(const char *fname) +{ + FILE *fp; + struct dsys_demo *demo; + + if(!(fp = fopen(fname, "r"))) { + fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno)); + return 0; + } + + if(!(demo = malloc(sizeof *demo))) { + perror("failed to allocate memory"); + fclose(fp); + return 0; + } + memset(demo, 0, sizeof *demo); + + demo->src_tm = demo->start_tm = -1; + + if(read_script(demo, fp, fname) == -1) { + free(demo); + fclose(fp); + return 0; + } + + fclose(fp); + return demo; +} + +struct dsys_demo *dsys_open_stream(FILE *fp) +{ + struct dsys_demo *demo; + + if(!(demo = malloc(sizeof *demo))) { + perror("failed to allocate memory"); + return 0; + } + memset(demo, 0, sizeof *demo); + + demo->src_tm = demo->start_tm = -1; + + if(read_script(demo, fp, 0) == -1) { + free(demo); + return 0; + } + + return demo; +} + +void dsys_close(struct dsys_demo *demo) +{ + while(demo->evlist) { + struct dsys_event *ev = demo->evlist; + demo->evlist = demo->evlist->next; + free_event(ev); + } + + free(demo); +} + + +#define SEP " \t\n\r" + +static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname) +{ + int nline = 0; + char buf[512], *line, *tok, *endp; + unsigned int t0, t1; + struct dsys_event *ev; + + if(!fname) { + fname = ""; + } + + demo->duration = dsys_msec_to_dtime(0); + + while(fgets(buf, sizeof buf, fp)) { + nline++; + + line = strip_ws(buf); + + if(!line || !*line) { + continue; + } + + if(!(tok = strtok(line, SEP)) || (t0 = strtol(tok, &endp, 10), endp == tok)) { + fprintf(stderr, "%s line: %d, error: expected timestamp t0\n", fname, nline); + return -1; + } + + if(!(tok = strtok(0, SEP))) { + fprintf(stderr, "%s line: %d, error: expected second timestamp or event name\n", fname, nline); + return -1; + } + + t1 = strtol(tok, &endp, 10); + if(endp == tok) { + t1 = t0; + } else { + if(!(tok = strtok(0, SEP))) { + fprintf(stderr, "%s line: %d, error: expected event name\n", fname, nline); + return -1; + } + } + + if(!(ev = malloc(sizeof *ev))) { + perror("read_script: failed to allocate memory for an event\n"); + return -1; + } + memset(ev, 0, sizeof *ev); + ev->t0 = dsys_msec_to_dtime(t0); + ev->t1 = dsys_msec_to_dtime(t1); + + if(!(ev->name = malloc(strlen(tok) + 1))) { + free(ev); + fprintf(stderr, "read_script: failed to allocate memory for the event name: %s\n", tok); + return -1; + } + strcpy(ev->name, tok); + + ev->eval = t0 == t1 ? dsys_eval_step : dsys_eval_lerp; + + ev->next = demo->evlist; + ev->prev = 0; + if(demo->evlist) { + demo->evlist->prev = ev; + } + demo->evlist = ev; + demo->num_ev++; + + if(ev->t1 > demo->duration) { + demo->duration = ev->t1; + } + } + + demo->evlist = sort_evlist(demo->evlist, demo->num_ev); + + /*dbg_print_events(demo->evlist);*/ + + return 0; +} + +static char *strip_ws(char *buf) +{ + char *ptr; + + while(isspace(*buf)) { + buf++; + } + + ptr = buf; + while(*ptr) { + if(*ptr == '\n' || *ptr == '\r' || *ptr == '#') { + *ptr = 0; + break; + } + ptr++; + } + + return buf; +} + +static void dbg_print_events(struct dsys_event *ev) +{ + int i; + + for(i=0; ev; i++) { + printf("%02d - %s (%f -> %f) [%s]\n", i, ev->eval == dsys_eval_step ? "step" : "lerp", + ev->t0, ev->t1, ev->name); + ev = ev->next; + } +} + +void dsys_update(struct dsys_demo *demo, demotime_t tm) +{ + struct dsys_event *ev; + + demo->src_tm = tm; + + if(demo->start_tm == -1) { + dsys_start(demo); + } + + if(!demo->running) { + return; /* nothing changes */ + } + + demo->tm = tm - demo->start_tm - demo->stoppage_tm; + + if(demo->tm < 0) { + demo->tm = 0; + } + if(demo->tm > demo->duration) { + demo->tm = demo->duration; + } + + while(demo->active && demo->active->t1 <= demo->tm) { + proc_event(demo->active, demo->tm); + demo->active = demo->active->next; + } + + ev = demo->active; + while(ev && ev->t0 <= demo->tm) { + proc_event(ev, demo->tm); + ev = ev->next; + } + demo->nextev = ev; + + + if(demo->tm >= demo->duration) { + dsys_stop(demo); + } +} + +static void proc_event(struct dsys_event *ev, demotime_t tm) +{ + float val = ev->eval(ev, tm); + + if(ev->val != val) { + struct callback *cb = ev->cblist; + + ev->val = val; + + while(cb) { + cb->func(ev, cb->cls); + cb = cb->next; + } + } +} + +void dsys_start(struct dsys_demo *demo) +{ + if(demo->running) { + return; + } + + if(demo->start_tm == -1) { + demo->start_tm = demo->src_tm; + demo->nextev = demo->active = demo->evlist; + } else { + demo->stoppage_tm += demo->src_tm - demo->stop_tm; + } + + demo->running = 1; +} + +void dsys_stop(struct dsys_demo *demo) +{ + if(!demo->running) { + return; + } + + demo->stop_tm = demo->src_tm; + demo->running = 0; +} + +int dsys_is_running(struct dsys_demo *demo) +{ + return demo->running; +} + + +demotime_t dsys_duration(struct dsys_demo *demo) +{ + return demo->duration; +} + +demotime_t dsys_time(struct dsys_demo *demo) +{ + return demo->tm; +} + +float dsys_progress(struct dsys_demo *demo) +{ + return demo->tm / demo->duration; +} + +/* seek without continuity */ +void dsys_seek(struct dsys_demo *demo, demotime_t tm) +{ + struct dsys_event *ev; + + if(tm < 0) { + tm = 0; + } + if(tm > demo->duration) { + tm = demo->duration; + } + + if(tm < demo->tm) { + /* on backwards seek, invalidate the sliding window */ + demo->nextev = demo->active = demo->evlist; + } + + demo->start_tm = demo->src_tm - tm; + demo->stoppage_tm = 0; + demo->stop_tm = demo->src_tm; + demo->tm = tm; + + /* recalculate events */ + ev = demo->evlist; + while(ev) { + proc_event(ev, tm); + ev = ev->next; + } +} + +void dsys_seek_norm(struct dsys_demo *demo, float t) +{ + dsys_seek(demo, t * demo->duration); +} + +/* seek by accelerating time */ +void dsys_warp(struct dsys_demo *demo, demotime_t tm) +{ + fprintf(stderr, "dsys_warp not implemented yet\n"); +} + +void dsys_warp_norm(struct dsys_demo *demo, float t) +{ + dsys_warp(demo, t * demo->duration); +} + + +/* events */ +struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name) +{ + struct dsys_event *iter = demo->evlist; + + while(iter) { + if(strcmp(iter->name, name) == 0) { + return iter; + } + iter = iter->next; + } + return 0; +} + +enum dsys_evtype dsys_event_type(struct dsys_event *ev) +{ + return ev->type; +} + +float dsys_event_value(struct dsys_event *ev) +{ + return ev->val; +} + +int dsys_event_callback(struct dsys_event *ev, void (*func)(struct dsys_event*, void*), void *cls) +{ + struct callback *cb; + + if(!(cb = malloc(sizeof *cb))) { + perror("failed to allocate memory"); + return -1; + } + cb->func = func; + cb->cls = cls; + cb->next = ev->cblist; + ev->cblist = cb; + return 0; +} + +int dsys_event_link(struct dsys_event *ev, float *link) +{ + return dsys_event_callback(ev, link_callback, link); +} + +static void link_callback(struct dsys_event *ev, void *cls) +{ + *(float*)cls = ev->val; +} + + +/* time conversion */ +demotime_t dsys_sec_to_dtime(float sec) +{ + return sec; +} + +demotime_t dsys_msec_to_dtime(unsigned long msec) +{ + return (demotime_t)msec / 1000.0; +} + +float dsys_dtime_to_sec(demotime_t tm) +{ + return tm; +} + +unsigned long dsys_dtime_to_msec(demotime_t tm) +{ + return (unsigned long)(tm * 1000.0); +} + + +float dsys_eval_step(struct dsys_event *ev, demotime_t t) +{ + return t >= ev->t1 ? 1.0 : 0.0; +} + +#define CLAMP(x, low, high) ((x) < (low) ? (low) : ((x) > (high) ? (high) : (x))) + +float dsys_eval_lerp(struct dsys_event *ev, demotime_t t) +{ + float res = (t - ev->t0) / (ev->t1 - ev->t0); + return CLAMP(res, 0.0, 1.0); +} + +float dsys_eval_sigmoid(struct dsys_event *ev, demotime_t t) +{ + t = dsys_eval_lerp(ev, t); + return 1.0 - (cos(t * M_PI) * 0.5 + 0.5); +} + +static void free_event(struct dsys_event *ev) +{ + while(ev->cblist) { + struct callback *cb = ev->cblist; + ev->cblist = ev->cblist->next; + free(cb); + } +} + +static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev) +{ + int i, num_left, num_right; + struct dsys_event *left, *right, *node = list; + + if(num_ev < 2) { + return list; + } + + num_left = num_ev / 2; + num_right = num_ev - num_left; + + for(i=0; inext; + } + + if(node->prev) { + node->prev->next = 0; + node->prev = 0; + } + + left = sort_evlist(list, num_left); + right = sort_evlist(node, num_right); + + return merge_evlists(left, right); +} + +static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2) +{ + struct dsys_event *head, *tail, *node; + + if(!list1) { + return list2; + } + if(!list2) { + return list1; + } + + head = tail = 0; + + while(list1 && list2) { + if(list1->t0 < list2->t0) { + node = list1; + list1 = list1->next; + } else { + node = list2; + list2 = list2->next; + } + + node->next = 0; + node->prev = tail; + + if(!head) { + head = node; + } else { + tail->next = node; + } + tail = node; + } + + if(list1) { + tail->next = list1; + list1->prev = tail; + } else if(list2) { + tail->next = list2; + list2->prev = tail; + } + + return head; +} diff -r f0a47f46ee45 -r 7056437a361b libs/dsys2/dsys.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/dsys2/dsys.h Tue Feb 19 18:17:17 2013 +0200 @@ -0,0 +1,71 @@ +#ifndef DSYS2_H_ +#define DSYS2_H_ + +#include + +struct dsys_demo; +struct dsys_event; + +typedef float demotime_t; + +enum dsys_evtype { + DSYS_SINGLE, + DSYS_PERIODIC +}; + +#ifdef __cplusplus +extern "C" { +#endif + +struct dsys_demo *dsys_open(const char *fname); +struct dsys_demo *dsys_open_stream(FILE *fp); +void dsys_close(struct dsys_demo *demo); + +void dsys_update(struct dsys_demo *demo, demotime_t tm); + + +void dsys_start(struct dsys_demo *demo); +void dsys_stop(struct dsys_demo *demo); +int dsys_is_running(struct dsys_demo *demo); + + +demotime_t dsys_duration(struct dsys_demo *demo); +demotime_t dsys_time(struct dsys_demo *demo); +float dsys_progress(struct dsys_demo *demo); + +/* seek without continuity */ +void dsys_seek(struct dsys_demo *demo, demotime_t tm); +void dsys_seek_norm(struct dsys_demo *demo, float t); + +/* seek by accelerating time */ +void dsys_warp(struct dsys_demo *demo, demotime_t tm); +void dsys_warp_norm(struct dsys_demo *demo, float t); + + +/* events */ +struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name); + +enum dsys_evtype dsys_event_type(struct dsys_event *ev); +float dsys_event_value(struct dsys_event *ev); + +int dsys_event_callback(struct dsys_event *ev, void (*func)(struct dsys_event*, void*), void *cls); +int dsys_event_link(struct dsys_event *ev, float *link); + +/* event evaluators */ +float dsys_eval_step(struct dsys_event *ev, demotime_t t); +float dsys_eval_lerp(struct dsys_event *ev, demotime_t t); +float dsys_eval_sigmoid(struct dsys_event *ev, demotime_t t); + +/* time conversion */ +demotime_t dsys_sec_to_dtime(float sec); +demotime_t dsys_msec_to_dtime(unsigned long msec); + +float dsys_dtime_to_sec(demotime_t tm); +unsigned long dsys_dtime_to_msec(demotime_t tm); + +#ifdef __cplusplus +} +#endif + + +#endif /* DSYS2_H_ */ diff -r f0a47f46ee45 -r 7056437a361b libs/dsys2/dsys_impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/dsys2/dsys_impl.h Tue Feb 19 18:17:17 2013 +0200 @@ -0,0 +1,40 @@ +#ifndef DSYS_IMPL_H_ +#define DSYS_IMPL_H_ + +#include "dsys.h" + +struct dsys_demo { + demotime_t tm, src_tm, start_tm, stop_tm, duration; + demotime_t stoppage_tm; + + struct dsys_event *evlist; + int num_ev; + + struct dsys_event *nextev, *active; + + int running; +}; + +struct callback { + void (*func)(struct dsys_event*, void*); + void *cls; + + struct callback *next; +}; + + +struct dsys_event { + enum dsys_evtype type; + + char *name; + demotime_t t0, t1; + float val; + + float (*eval)(struct dsys_event*, demotime_t); + + struct callback *cblist; + + struct dsys_event *next, *prev; +}; + +#endif /* DSYS_IMPL_H_ */ diff -r f0a47f46ee45 -r 7056437a361b src/mballs.cc --- a/src/mballs.cc Mon Feb 18 06:53:44 2013 +0200 +++ b/src/mballs.cc Tue Feb 19 18:17:17 2013 +0200 @@ -3,6 +3,7 @@ #include "mballs.h" #include "metasurf.h" #include "vmath/vmath.h" +#include "dsys.h" struct MetaBall { Vector3 pos; @@ -14,7 +15,7 @@ #define VOL_SZ 2 #define MBALL_GRID_SZ 50 -static void update(); +static void update(float sec); static float calc_field(float x, float y, float z); static float eval(float x, float y, float z); static void vertex(float x, float y, float z); @@ -43,7 +44,7 @@ for(int i=0; i<10; i++) { MetaBall mb; mb.orbit = 0.25 * rand() / (float)RAND_MAX + 0.35; - mb.energy = 0.2 * rand() / (float)RAND_MAX + 0.15; + mb.energy = 0.1 * rand() / (float)RAND_MAX + 0.15; mb.phase_offs = rand() / (float)RAND_MAX * M_PI * 2.0; balls.push_back(mb); } @@ -51,9 +52,9 @@ return true; } -void mball_render() +void mball_render(float sec) { - update(); + update(sec); const float blue[] = {0.4, 0.45, 1.0, 1}; const float dark_red[] = {0.6, 0.2, 0.1, 1}; @@ -114,11 +115,8 @@ } -static void update() +static void update(float sec) { - unsigned int msec = glutGet(GLUT_ELAPSED_TIME); - float sec = msec / 1000.0; - for(size_t i=0; i