From d60954c471d6f446523bad8c4c4860aa2138da1e Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Thu, 4 Oct 2018 16:56:48 +0300 Subject: [PATCH] reorganized everything new animation system with keyframes --- src/geom.cc | 117 ++++++++++++++++++++++++++++++ src/geom.h | 11 +++ src/main.cc | 225 +++++++++++++++++++++------------------------------------- src/seq.cc | 103 +++++++++++++++++++++++++++ src/seq.h | 23 ++++++ src/track.cc | 146 +++++++++++++++++++++++++++++++++++++ src/track.h | 45 ++++++++++++ 7 files changed, 525 insertions(+), 145 deletions(-) create mode 100644 src/geom.cc create mode 100644 src/geom.h create mode 100644 src/seq.cc create mode 100644 src/seq.h create mode 100644 src/track.cc create mode 100644 src/track.h diff --git a/src/geom.cc b/src/geom.cc new file mode 100644 index 0000000..804c18f --- /dev/null +++ b/src/geom.cc @@ -0,0 +1,117 @@ +#include +#include +#include "geom.h" +#include "sdr.h" + +static unsigned int sdr_curve_top; + +bool init_geom() +{ + if(!(sdr_curve_top = create_program_load("sdr/curve_top.v.glsl", "sdr/curve_top.f.glsl"))) { + return false; + } + return true; +} + +void destroy_geom() +{ + free_program(sdr_curve_top); +} + +void faros() +{ + // kormos + glPushMatrix(); + glScalef(1.1, 3, 1.1); + glTranslatef(0, 0.5, 0); + glutSolidCube(1.0); + glPopMatrix(); + + glShadeModel(GL_FLAT); + + // base + glPushMatrix(); + glRotatef(90, 1, 0, 0); + glTranslatef(0, -0.15, 0); + glutSolidCylinder(2, 0.3, 16, 1); + glPopMatrix(); + + // middle cylinder + glPushMatrix(); + glTranslatef(0, 3, 0); + glRotatef(22.5, 0, 1, 0); + glRotatef(-90, 1, 0, 0); + glutSolidCylinder(0.5, 1.0, 8, 1); + glPopMatrix(); + + // trim middle cylinder (mporntoura) + glPushMatrix(); + glTranslatef(0, 3.9, 0); + glRotatef(22.5, 0, 1, 0); + glRotatef(-90, 1, 0, 0); + glutSolidCylinder(0.55, 0.02, 8, 1); + glPopMatrix(); + + // top smaller cylinder + glPushMatrix(); + glTranslatef(0, 4, 0); + glRotatef(22.5, 0, 1, 0); + glRotatef(-90, 1, 0, 0); + glutSolidCylinder(0.28, 0.5, 8, 1); + glPopMatrix(); + + // top wire even smaller cylinder + glPushMatrix(); + glTranslatef(0, 4.5, 0); + glRotatef(22.5, 0, 1, 0); + glRotatef(-90, 1, 0, 0); + glutWireCylinder(0.18, 0.3, 9, 3); + glPopMatrix(); + + glShadeModel(GL_SMOOTH); + + // top troulos + glPushMatrix(); + glTranslatef(0, 4.8, 0); + glRotatef(22.5, 0, 1, 0); + glRotatef(-90, 1, 0, 0); + glutSolidCone(0.18, 0.2, 9, 1); + glPopMatrix(); + + // tsamploukano + glPushMatrix(); + glTranslatef(-0.28, 4, 0); + glScalef(1, 13, 1); + glutSolidSphere(0.1, 16, 16); + glPopMatrix(); + + //pyramid on top of kormos + bind_program(sdr_curve_top); + + glPushMatrix(); + glTranslatef(0, 3, 0); + glRotatef(45, 0, 1, 0); + glRotatef(-90, 1, 0, 0); + glScalef(1, 1, 0.45); + glutSolidCylinder(1, 1, 4, 16); + glPopMatrix(); + + bind_program(0); +} + + +void ground() +{ + glPushMatrix(); + + glTranslatef(0, -1.25, 0); + glScalef(1, 0.1, 1); + + glutSolidSphere(10, 32, 32); + + glPopMatrix(); +} + +void xlogo() +{ +} diff --git a/src/geom.h b/src/geom.h new file mode 100644 index 0000000..14ba125 --- /dev/null +++ b/src/geom.h @@ -0,0 +1,11 @@ +#ifndef GEOM_H_ +#define GEOM_H_ + +bool init_geom(); +void destroy_geom(); + +void faros(); +void ground(); +void xlogo(); + +#endif /* GEOM_H_ */ diff --git a/src/main.cc b/src/main.cc index a2164a4..245c87f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -3,30 +3,26 @@ #include #include +#include #include "sdr.h" - -#define CURVE_VS "sdr/curve_top.v.glsl" -#define CURVE_FS "sdr/curve_top.f.glsl" -#define BEAM_VS "sdr/beam.v.glsl" -#define BEAM_FS "sdr/beam.f.glsl" +#include "geom.h" +#include "seq.h" #define BEAM_SHELLS 40 #define BEAM_RMIN 0.01 #define BEAM_RMAX 0.125 #define BEAM_ENERGY 0.02 #define BEAM_LEN 16.0 +#define BEAM_DEF_SPEED 0.1 static bool init(); static void cleanup(); -static void faros(); +static void display(); static void light(); -static void ground(); static void backdrop(); -static void xlogo(); -static void display(); static void idle(); static void reshape(int x, int y); static void keyboard(unsigned char c, int x, int y); @@ -34,15 +30,16 @@ static void mbutton(int bn, int state, int x, int y); static void mmotion(int x, int y); static float cam_theta = 45, cam_phi, cam_dist = 10; -static unsigned int sdr_curve_top, sdr_beam, sdr_sky; +static unsigned int sdr_beam, sdr_sky; static long start_time; -static float anim_speed = 1.0; static long anim_stop_time; -static long tmsec; +static long tmsec, prev_tmsec; static const float sil_color[] = {0.05, 0.02, 0.1, 1.0}; static const float beam_color[] = {0.5, 0.4, 0.2, 1.0}; +static float beam_angle, beam_speed; + int main(int argc, char **argv) { glutInit(&argc, argv); @@ -81,105 +78,67 @@ static bool init() glEnable(GL_NORMALIZE); - if(!(sdr_curve_top = create_program_load(CURVE_VS, CURVE_FS))) + if(!init_geom()) { return false; - - if(!(sdr_beam = create_program_load(BEAM_VS, BEAM_FS))) + } + if(!(sdr_beam = create_program_load("sdr/beam.v.glsl", "sdr/beam.f.glsl"))) return false; if(!(sdr_sky = create_program_load("sdr/sky.v.glsl", "sdr/sky.f.glsl"))) { return false; } + if(!init_seq()) { + return false; + } + add_seq_track("beam-speed", INTERP_SIGMOID, EXTRAP_CLAMP, BEAM_DEF_SPEED); + load_seq("seq"); + start_time = glutGet(GLUT_ELAPSED_TIME); + prev_tmsec = start_time; return true; } static void cleanup() { + destroy_seq(); + destroy_geom(); + free_program(sdr_beam); + free_program(sdr_sky); } -static void faros() +static void display() { - glColor3fv(sil_color); + tmsec = (long)glutGet(GLUT_ELAPSED_TIME) - start_time; + float dt = (tmsec - prev_tmsec) / 1000.0f; + prev_tmsec = tmsec; - // kormos - glPushMatrix(); - glScalef(1.1, 3, 1.1); - glTranslatef(0, 0.5, 0); - glutSolidCube(1.0); - glPopMatrix(); - - glShadeModel(GL_FLAT); - - // base - glPushMatrix(); - glRotatef(90, 1, 0, 0); - glTranslatef(0, -0.15, 0); - glutSolidCylinder(2, 0.3, 16, 1); - glPopMatrix(); - - // middle cylinder - glPushMatrix(); - glTranslatef(0, 3, 0); - glRotatef(22.5, 0, 1, 0); - glRotatef(-90, 1, 0, 0); - glutSolidCylinder(0.5, 1.0, 8, 1); - glPopMatrix(); - - // trim middle cylinder (mporntoura) - glPushMatrix(); - glTranslatef(0, 3.9, 0); - glRotatef(22.5, 0, 1, 0); - glRotatef(-90, 1, 0, 0); - glutSolidCylinder(0.55, 0.02, 8, 1); - glPopMatrix(); + if(anim_stop_time) dt = 0.0f; - // top smaller cylinder - glPushMatrix(); - glTranslatef(0, 4, 0); - glRotatef(22.5, 0, 1, 0); - glRotatef(-90, 1, 0, 0); - glutSolidCylinder(0.28, 0.5, 8, 1); - glPopMatrix(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + backdrop(); - // top wire even smaller cylinder - glPushMatrix(); - glTranslatef(0, 4.5, 0); - glRotatef(22.5, 0, 1, 0); - glRotatef(-90, 1, 0, 0); - glutWireCylinder(0.18, 0.3, 9, 3); - glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); - glShadeModel(GL_SMOOTH); + glTranslatef(0, -2, -cam_dist); + glRotatef(cam_phi, 1, 0, 0); + glRotatef(cam_theta, 0, 1, 0); - // top troulos - glPushMatrix(); - glTranslatef(0, 4.8, 0); - glRotatef(22.5, 0, 1, 0); - glRotatef(-90, 1, 0, 0); - glutSolidCone(0.18, 0.2, 9, 1); - glPopMatrix(); + glColor3fv(sil_color); + ground(); + faros(); - // tsamploukano glPushMatrix(); - glTranslatef(-0.28, 4, 0); - glScalef(1, 13, 1); - glutSolidSphere(0.1, 16, 16); - glPopMatrix(); - //pyramid on top of kormos - bind_program(sdr_curve_top); + beam_speed = get_seq_value("beam-speed", tmsec); + beam_angle += beam_speed * 360.0f * dt; + glRotatef(beam_angle, 0, 1, 0); + light(); - glPushMatrix(); - glTranslatef(0, 3, 0); - glRotatef(45, 0, 1, 0); - glRotatef(-90, 1, 0, 0); - glScalef(1, 1, 0.45); - glutSolidCylinder(1, 1, 4, 16); glPopMatrix(); - bind_program(0); + glutSwapBuffers(); } static void light() @@ -213,19 +172,6 @@ static void light() glPopAttrib(); } -static void ground() -{ - glPushMatrix(); - - glTranslatef(0, -1.25, 0); - glScalef(1, 0.1, 1); - - glColor3fv(sil_color); - glutSolidSphere(10, 32, 32); - - glPopMatrix(); -} - static void backdrop() { glFrontFace(GL_CW); @@ -235,40 +181,7 @@ static void backdrop() glFrontFace(GL_CCW); } -static void display() -{ - if(anim_stop_time > 0) { - tmsec = anim_stop_time - start_time; - } else { - tmsec = (long)glutGet(GLUT_ELAPSED_TIME) - start_time; - } - float tsec = (float)tmsec / 1000.0; - float tanim = tsec * anim_speed; - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - backdrop(); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glTranslatef(0, -2, -cam_dist); - glRotatef(cam_phi, 1, 0, 0); - glRotatef(cam_theta, 0, 1, 0); - - ground(); - faros(); - - glPushMatrix(); - - float beam_angle = tanim * 0.1 * 360; - glRotatef(beam_angle, 0, 1, 0); - light(); - - glPopMatrix(); - - glutSwapBuffers(); -} static void idle() { @@ -285,25 +198,29 @@ static void reshape(int x, int y) gluPerspective(50, (float)x / (float)y, 0.5, 500); } -static long calc_timeshift(float prev_speed, float speed) -{ - long delta = tmsec * speed - tmsec * prev_speed; - return delta / speed; -} - #define ANIM_DELTA 0.5 static void keyboard(unsigned char c, int x, int y) { - float prev_anim_speed; + int idx; + static float orig_beam_speed; switch(c) { case 27: exit(0); + case '\b': + start_time = glutGet(GLUT_ELAPSED_TIME); + prev_tmsec = 0; + anim_stop_time = 0; + beam_angle = 0; + break; + case ' ': if(anim_stop_time > 0) { - start_time += glutGet(GLUT_ELAPSED_TIME) - anim_stop_time; + long msec = glutGet(GLUT_ELAPSED_TIME); + start_time += msec - anim_stop_time; + prev_tmsec = msec - start_time; anim_stop_time = 0; } else { anim_stop_time = glutGet(GLUT_ELAPSED_TIME); @@ -311,17 +228,35 @@ static void keyboard(unsigned char c, int x, int y) break; case '=': - start_time += calc_timeshift(anim_speed, anim_speed + ANIM_DELTA); - anim_speed += ANIM_DELTA; + beam_speed = get_seq_value("beam-speed", tmsec); + clear_seq_track("beam-speed"); + set_seq_value("beam-speed", tmsec, beam_speed + ANIM_DELTA); break; case '-': - prev_anim_speed = anim_speed; - anim_speed -= ANIM_DELTA; - if(anim_speed < 0) - anim_speed = 0; - start_time += calc_timeshift(prev_anim_speed, anim_speed); + beam_speed = get_seq_value("beam-speed", tmsec) - ANIM_DELTA; + if(beam_speed < 0) + beam_speed = 0; + clear_seq_track("beam-speed"); + set_seq_value("beam-speed", tmsec, beam_speed); break; + + case '\r': + case '\n': + idx = find_seq_track("beam-speed"); + assert(idx >= 0); + if(get_seq_value(idx, tmsec) > 0.0) { + clear_seq_track(idx); + set_seq_value(idx, tmsec, beam_speed); + set_seq_value(idx, tmsec + 3000, 0); + orig_beam_speed = beam_speed; + } else { + clear_seq_track(idx); + set_seq_value(idx, tmsec, 0); + set_seq_value(idx, tmsec + 3000, orig_beam_speed); + } + break; + default: break; } diff --git a/src/seq.cc b/src/seq.cc new file mode 100644 index 0000000..29036a5 --- /dev/null +++ b/src/seq.cc @@ -0,0 +1,103 @@ +#include +#include +#include "seq.h" +#include "track.h" + +struct SeqTrack { + char *name; + Track *track; +}; + +static std::vector tracks; + +bool init_seq() +{ + return true; +} + +void destroy_seq() +{ + int ntrk = tracks.size(); + for(int i=0; i= 0) return idx; + + SeqTrack st; + st.name = new char[strlen(name) + 1]; + strcpy(st.name, name); + st.track = new Track; + st.track->defval = defval; + st.track->interp = inmode; + st.track->extrap = exmode; + tracks.push_back(st); + return tracks.size() - 1; +} + +int find_seq_track(const char *name) +{ + int ntrk = tracks.size(); + for(int i=0; iclear(); +} + +void clear_seq_track(const char *name) +{ + int idx = find_seq_track(name); + if(idx >= 0) { + tracks[idx].track->clear(); + } +} + +void set_seq_value(int idx, long tm, float val) +{ + tracks[idx].track->set_key(tm, val); +} + +void set_seq_value(const char *name, long tm, float val) +{ + int idx = find_seq_track(name); + if(idx >= 0) { + tracks[idx].track->set_key(tm, val); + } +} + +float get_seq_value(int idx, long tm) +{ + return (*tracks[idx].track)(tm); +} + +float get_seq_value(const char *name, long tm) +{ + int idx = find_seq_track(name); + if(idx < 0) { + return 0.0f; + } + return (*tracks[idx].track)(tm); +} + +bool load_seq(const char *fname) +{ + return false; /* TODO */ +} diff --git a/src/seq.h b/src/seq.h new file mode 100644 index 0000000..aebd836 --- /dev/null +++ b/src/seq.h @@ -0,0 +1,23 @@ +#ifndef ANIM_H_ +#define ANIM_H_ + +#include "track.h" + +bool init_seq(); +void destroy_seq(); + +int add_seq_track(const char *name, InterpMode inmode, ExtrapMode exmode, float defval); +int find_seq_track(const char *name); +Track *get_seq_track(int idx); + +void clear_seq_track(int idx); +void clear_seq_track(const char *name); + +void set_seq_value(int idx, long tm, float val); +void set_seq_value(const char *name, long tm, float val); +float get_seq_value(int idx, long tm); +float get_seq_value(const char *name, long tm); + +bool load_seq(const char *fname); + +#endif /* ANIM_H_ */ diff --git a/src/track.cc b/src/track.cc new file mode 100644 index 0000000..bc775ba --- /dev/null +++ b/src/track.cc @@ -0,0 +1,146 @@ +#include +#include +#include "track.h" + +static long remap_time(ExtrapMode mode, long t, long t0, long t1); +static float smoothstep(float a, float b, float x); + +Track::Track() +{ + interp = INTERP_SIGMOID; + extrap = EXTRAP_CLAMP; + keys_sorted = true; + defval = 0.0f; +} + +void Track::clear() +{ + keys.clear(); +} + +void Track::set_key(long tm, float val) +{ + int idx = find_key(tm); + if(idx >= 0) { + keys[idx].value = val; + return; + } + + TrackKey key = {tm, val}; + keys.push_back(key); + keys_sorted = false; +} + +float Track::get_key(long tm) const +{ + int idx = find_key(tm); + if(idx == -1) return 0.0f; + return keys[idx].value; +} + +int Track::find_key(long tm) const +{ + int sz = (int)keys.size(); + for(int i=0; ikeys.begin(), track->keys.end(), keycmp); + keys_sorted = true; + } + + long tstart = keys[0].time; + long tend = keys[nkeys - 1].time; + + tm = remap_time(extrap, tm, tstart, tend); + + int idx0 = get_interval(tm); + assert(idx0 >= 0 && idx0 < nkeys); + int idx1 = idx0 + 1; + + if(idx0 == nkeys - 1) { + return keys[idx0].value; + } + + float dt = (float)(keys[idx1].time - keys[idx0].time); + float t = (float)(tm - keys[idx0].time) / dt; + + switch(interp) { + case INTERP_STEP: + return keys[idx0].value; + + case INTERP_SIGMOID: + t = smoothstep(0, 1, t); + case INTERP_LINEAR: + return keys[idx0].value + (keys[idx1].value - keys[idx0].value) * t; + + default: + break; + } + return 0.0f; +} + +int Track::get_interval(long tm) const +{ + int nkeys = (int)keys.size(); + + for(int i=0; i= t1 ? t1 : t); + + case EXTRAP_REPEAT: + if(interval > 0) { + long x = (t - t0) % interval; + if(x < 0) x += interval; + return x + t0; + } + return t0; + + default: + break; + } + + assert(!"unreachable"); + return t; +} + +static float smoothstep(float a, float b, float x) +{ + if(x < a) return 0.0f; + if(x >= b) return 1.0f; + + x = (x - a) / (b - a); + return x * x * (3.0f - 2.0f * x); +} diff --git a/src/track.h b/src/track.h new file mode 100644 index 0000000..b80562e --- /dev/null +++ b/src/track.h @@ -0,0 +1,45 @@ +#ifndef TRACK_H_ +#define TRACK_H_ + +#include + +enum InterpMode { + INTERP_STEP, + INTERP_LINEAR, + INTERP_SIGMOID +}; + +enum ExtrapMode { + EXTRAP_CLAMP, + EXTRAP_REPEAT +}; + +struct TrackKey { + long time; + float value; +}; + +class Track { +private: + std::vector keys; + mutable bool keys_sorted; + + int get_interval(long tm) const; + +public: + InterpMode interp; + ExtrapMode extrap; + float defval; + + Track(); + + void clear(); + + void set_key(long tm, float val); + float get_key(long tm) const; + int find_key(long tm) const; + + float operator ()(long tm) const; +}; + +#endif /* TRACK_H_ */ -- 1.7.10.4