fixed more animation bugs, added rudimentary UI
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 7 Oct 2018 13:38:01 +0000 (16:38 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 7 Oct 2018 13:38:01 +0000 (16:38 +0300)
src/geom.cc
src/geom.h
src/main.cc
src/seq.cc
src/seq.h
src/ui.cc [new file with mode: 0644]
src/ui.h [new file with mode: 0644]

index 62e36d3..770b438 100644 (file)
@@ -1,20 +1,52 @@
+#include <math.h>
 #include <GL/glew.h>
 #include <GL/freeglut.h>
 #include "geom.h"
 #include "sdr.h"
 
 static unsigned int sdr_curve_top;
+static unsigned int tex_xcircle;
+
+static const unsigned char tex_xcircle_pixels[] = {
+       0, 64, 255, 255, 255, 255, 64, 0,
+       0, 64, 255, 255, 255, 255, 64, 0,
+       0, 64, 255, 255, 255, 255, 64, 0,
+       0, 64, 255, 255, 255, 255, 64, 0,
+       0, 64, 255, 255, 255, 255, 64, 0,
+       0, 64, 255, 255, 255, 255, 64, 0,
+       0, 64, 255, 255, 255, 255, 64, 0,
+       0, 64, 255, 255, 255, 255, 64, 0,
+
+       0, 64, 255, 255, 255, 255, 64, 0,
+       0, 0, 255, 255, 255, 255, 0, 0,
+       0, 0, 128, 255, 255, 128, 0, 0,
+       0, 0, 0, 64, 64, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0
+};
+
 
 bool init_geom()
 {
        if(!(sdr_curve_top = create_program_load("sdr/curve_top.v.glsl", "sdr/curve_top.f.glsl"))) {
                return false;
        }
+
+       glGenTextures(1, &tex_xcircle);
+       glBindTexture(GL_TEXTURE_2D, tex_xcircle);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 8, 16, 0,
+                       GL_LUMINANCE, GL_UNSIGNED_BYTE, tex_xcircle_pixels);
        return true;
 }
 
 void destroy_geom()
 {
+       glDeleteTextures(1, &tex_xcircle);
        free_program(sdr_curve_top);
 }
 
@@ -112,7 +144,7 @@ void ground()
        glPopMatrix();
 }
 
-void xlogo()
+void xlogo(float sz, float alpha, float xcircle)
 {
        static const float xlogo_varr[] = {
                -0.500, 0.407, -0.113, -0.109, 0.059, -0.006, -0.251, 0.407,
@@ -124,23 +156,57 @@ void xlogo()
        /* billboarding */
        float mv[16];
        glGetFloatv(GL_MODELVIEW_MATRIX, mv);
-       mv[0] = mv[5] = mv[10] = 1.0f;
+       mv[0] = mv[5] = mv[10] = sz;
        mv[1] = mv[2] = mv[4] = mv[6] = mv[8] = mv[9] = 0.0f;
 
        glPushMatrix();
        glLoadMatrixf(mv);
+       glTranslatef(0, 0.15, 0);
 
        glPushAttrib(GL_ENABLE_BIT);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
        glBegin(GL_QUADS);
+       glColor4f(0, 0, 0, alpha);
        const float *vptr = xlogo_varr;
        for(int i=0; i<(int)(sizeof xlogo_varr / sizeof *xlogo_varr) / 2; i++) {
                glVertex2fv(vptr);
                vptr += 2;
        }
        glEnd();
+       glTranslatef(0, -0.15, 0);
+       glDisable(GL_BLEND);
+
+       glEnable(GL_TEXTURE_2D);
+       glBindTexture(GL_TEXTURE_2D, tex_xcircle);
+
+       glDisable(GL_CULL_FACE);
+       glEnable(GL_ALPHA_TEST);
+       float aref = 1.0f - xcircle;
+       glAlphaFunc(GL_GREATER, aref > 0.0f ? aref : 0.0f);
+
+       glScalef(1.4, 1, 1);
+
+#define XLOGO_CIRCLE_SEG       64
+       // circle thingy
+       glBegin(GL_QUAD_STRIP);
+       for(int i=0; i<XLOGO_CIRCLE_SEG; i++) {
+               float t = (float)i / (float)(XLOGO_CIRCLE_SEG - 1);
+               float tcol = fmod(t + 0.075f, 1.0f);
+
+               float theta = t * M_PI * 2.0f;
+               float rad = 0.4f;
+               float width = 0.05f * tcol;
+               float z = -cos(theta) * 0.1;
+
+               glColor4f(0.9, 0.9, 0.9, tcol);
+               glTexCoord2f(0, 1.0f - tcol);
+               glVertex3f(sin(theta) * (rad + width), cos(theta) * (rad + width), z);
+               glTexCoord2f(1, 1.0f - tcol);
+               glVertex3f(sin(theta) * (rad - width), cos(theta) * (rad - width), z);
+       }
+       glEnd();
 
        glPopAttrib();
        glPopMatrix();
index 14ba125..fb8e60a 100644 (file)
@@ -6,6 +6,6 @@ void destroy_geom();
 
 void faros();
 void ground();
-void xlogo();
+void xlogo(float sz, float alpha, float xcircle);
 
 #endif /* GEOM_H_ */
index fee5283..02f631e 100644 (file)
@@ -9,6 +9,7 @@
 #include "sdr.h"
 #include "geom.h"
 #include "seq.h"
+#include "ui.h"
 
 #define BEAM_SHELLS 40
 #define BEAM_RMIN 0.01
@@ -38,14 +39,15 @@ static void keyb_special(int key, int x, int y);
 static void mbutton(int bn, int state, int x, int y);
 static void mmotion(int x, int y);
 
-static int win_width, win_height;
+int win_width, win_height;
 static bool freecam = true;
 
 static Camera cam = {0, 0, 0, 0, 0, 10};
 static unsigned int sdr_beam, sdr_sky;
 static long start_time;
 static long anim_stop_time;
-static long tmsec, prev_tmsec;
+long tmsec, prev_tmsec, anim_time;
+bool anim_stopped;
 
 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};
@@ -54,7 +56,7 @@ static float beam_angle, beam_speed;
 static float beam_len;
 static float xlogo_alpha;
 
-static bool show_help;
+static bool show_help, show_ui = true;
 
 int main(int argc, char **argv)
 {
@@ -117,8 +119,11 @@ static bool init()
        add_seq_track("cam-y", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
        add_seq_track("cam-z", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
        add_seq_track("xlogo", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
+       add_seq_track("xcircle", INTERP_SIGMOID, EXTRAP_CLAMP, 1);
        load_seq("seq");
 
+       freecam = seq_track_empty("cam-theta");
+
        start_time = glutGet(GLUT_ELAPSED_TIME);
        prev_tmsec = start_time;
        return true;
@@ -138,7 +143,11 @@ static void display()
        float dt = (tmsec - prev_tmsec) / 1000.0f;
        prev_tmsec = tmsec;
 
-       if(anim_stop_time) dt = 0.0f;
+       anim_time = tmsec;
+       if(anim_stopped) {
+               dt = 0.0f;
+               anim_time = anim_stop_time - start_time;
+       }
 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        backdrop();
@@ -147,12 +156,12 @@ static void display()
        glLoadIdentity();
 
        if(!freecam) {
-               cam.dist = get_seq_value("cam-dist", tmsec);
-               cam.phi = get_seq_value("cam-phi", tmsec);
-               cam.theta = get_seq_value("cam-theta", tmsec);
-               cam.x = get_seq_value("cam-x", tmsec);
-               cam.y = get_seq_value("cam-y", tmsec);
-               cam.z = get_seq_value("cam-z", tmsec);
+               cam.dist = get_seq_value("cam-dist", anim_time);
+               cam.phi = get_seq_value("cam-phi", anim_time);
+               cam.theta = get_seq_value("cam-theta", anim_time);
+               cam.x = get_seq_value("cam-x", anim_time);
+               cam.y = get_seq_value("cam-y", anim_time);
+               cam.z = get_seq_value("cam-z", anim_time);
        }
 
        glTranslatef(0, -2, -cam.dist);
@@ -164,19 +173,20 @@ static void display()
        ground();
        faros();
 
-       beam_len = get_seq_value("beam-len", tmsec);
-       beam_speed = get_seq_value("beam-speed", tmsec);
+       beam_len = get_seq_value("beam-len", anim_time);
+       beam_speed = get_seq_value("beam-speed", anim_time);
        beam_angle += beam_speed * 360.0f * dt;
 
-       xlogo_alpha = get_seq_value("xlogo", tmsec);
+       xlogo_alpha = get_seq_value("xlogo", anim_time);
+       float xcircle = get_seq_value("xcircle", anim_time);
+
        if(xlogo_alpha > 0.0) {
                glPushMatrix();
                float beam_angle_rad = beam_angle / 180.0 * M_PI;
                float xlogo_dist = beam_len;
                float xlogo_pos[3] = {sin(beam_angle_rad), 0, cos(beam_angle_rad)};
-               glTranslatef(xlogo_pos[0] * xlogo_dist, xlogo_pos[1] * xlogo_dist + 5, xlogo_pos[2] * xlogo_dist);
-               glColor4f(0, 0, 0, xlogo_alpha);
-               xlogo();
+               glTranslatef(xlogo_pos[0] * xlogo_dist, xlogo_pos[1] * xlogo_dist + 4.7, xlogo_pos[2] * xlogo_dist);
+               xlogo(0.5, xlogo_alpha, xcircle);
                glPopMatrix();
        }
 
@@ -185,6 +195,10 @@ static void display()
        light();
        glPopMatrix();
 
+       if(show_ui) {
+               ui();
+       }
+
        if(show_help) {
                help();
        }
@@ -241,7 +255,7 @@ static void help()
 {
        static const char *help_lines[] = {
                "Camera control",
-               "   LMB ............ rotate",
+               "   LMB drag ....... rotate",
                "   MMB drag ....... pan",
                "   RMB drag/wheel . zoom",
                "   c .............. toggle free/animated camera",
@@ -333,7 +347,7 @@ static void keyboard(unsigned char c, int x, int y)
        int idx;
        static float orig_beam_speed;
        static Camera orig_cam;
-       long anim_time = anim_stop_time ? anim_stop_time - start_time : tmsec;
+       long anim_time = anim_stopped ? anim_stop_time - start_time : tmsec;
 
        switch(c) {
        case 27:
@@ -342,18 +356,20 @@ static void keyboard(unsigned char c, int x, int y)
        case '\b':
                start_time = glutGet(GLUT_ELAPSED_TIME);
                prev_tmsec = 0;
-               anim_stop_time = 0;
+               anim_stop_time = anim_stopped ? start_time : 0;
                beam_angle = 0;
                break;
 
        case ' ':
-               if(anim_stop_time > 0) {
+               if(anim_stopped) {
                        long msec = glutGet(GLUT_ELAPSED_TIME);
                        start_time += msec - anim_stop_time;
                        prev_tmsec = msec - start_time;
                        anim_stop_time = 0;
+                       anim_stopped = false;
                } else {
                        anim_stop_time = glutGet(GLUT_ELAPSED_TIME);
+                       anim_stopped = true;
                }
                break;
 
@@ -468,6 +484,10 @@ static void keyb_special(int key, int x, int y)
                show_help = !show_help;
                break;
 
+       case GLUT_KEY_F5:
+               show_ui = !show_ui;
+               break;
+
        default:
                break;
        }
index 592abd5..36ce88c 100644 (file)
@@ -78,16 +78,31 @@ void clear_seq_track(const char *name)
        }
 }
 
+bool seq_track_empty(int idx)
+{
+       return tracks[idx].track->empty();
+}
+
+bool seq_track_empty(const char *name)
+{
+       int idx = find_seq_track(name);
+       if(idx >= 0) {
+               return tracks[idx].track->empty();
+       }
+       return true;
+}
+
 void set_seq_value(int idx, long tm, float val)
 {
        tracks[idx].track->set_value(tm, val);
+       printf("track(%d): set keyframe %ld -> %f\n", idx, 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_value(tm, val);
+               set_seq_value(idx, tm, val);
        }
 }
 
@@ -199,16 +214,16 @@ bool dump_seq(const char *fname)
                int nkeys = tracks[i].track->get_num_keys();
                if(!nkeys) continue;
 
-               fprintf(fp, "  track {\n");
-               fprintf(fp, "    name = \"%s\"\n", tracks[i].name);
+               fprintf(fp, "\ttrack {\n");
+               fprintf(fp, "\t\tname = \"%s\"\n", tracks[i].name);
                for(int j=0; j<nkeys; j++) {
                        TrackKey key = (*tracks[i].track)[j];
-                       fprintf(fp, "    key {\n");
-                       fprintf(fp, "      time = %ld\n", key.time);
-                       fprintf(fp, "      value = %g\n", key.value);
-                       fprintf(fp, "    }\n");
+                       fprintf(fp, "\t\tkey {\n");
+                       fprintf(fp, "\t\t\ttime = %ld\n", key.time);
+                       fprintf(fp, "\t\t\tvalue = %g\n", key.value);
+                       fprintf(fp, "\t\t}\n");
                }
-               fprintf(fp, "  }\n\n");
+               fprintf(fp, "\t}\n\n");
        }
        fprintf(fp, "}\n");
        fclose(fp);
index e1d8392..619c191 100644 (file)
--- a/src/seq.h
+++ b/src/seq.h
@@ -13,6 +13,9 @@ Track *get_seq_track(int idx);
 void clear_seq_track(int idx);
 void clear_seq_track(const char *name);
 
+bool seq_track_empty(int idx);
+bool seq_track_empty(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);
diff --git a/src/ui.cc b/src/ui.cc
new file mode 100644 (file)
index 0000000..6c77970
--- /dev/null
+++ b/src/ui.cc
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <alloca.h>
+#include <GL/glut.h>
+#include "ui.h"
+
+extern int win_width, win_height;
+
+extern bool anim_stopped;
+extern long anim_time;
+
+
+bool init_ui()
+{
+       return true;
+}
+
+void destroy_ui()
+{
+}
+
+void ui()
+{
+       glPushAttrib(GL_ENABLE_BIT);
+       glDisable(GL_DEPTH_TEST);
+
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glLoadIdentity();
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadIdentity();
+       glOrtho(0, win_width, win_height, 0, -1, 1);
+
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+       if(anim_stopped) {
+               glBegin(GL_QUADS);
+               glColor3f(1, 1, 1);
+               glVertex2f(10, 10);
+               glVertex2f(10, 50);
+               glVertex2f(22, 50);
+               glVertex2f(22, 10);
+               glVertex2f(30, 10);
+               glVertex2f(30, 50);
+               glVertex2f(42, 50);
+               glVertex2f(42, 10);
+               glEnd();
+       }
+
+       glColor3f(1, 0.9, 0.5);
+       gl_printf(win_width - 100, 20, "%4ld.%03ld", anim_time / 1000, anim_time % 1000);
+
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+
+       glPopAttrib();
+}
+
+void gl_printf(int x, int y, const char *fmt, ...)
+{
+       va_list ap;
+       int buf_size, curx, cury;
+       char *buf, tmp;
+
+       va_start(ap, fmt);
+       buf_size = vsnprintf(&tmp, 0, fmt, ap);
+       va_end(ap);
+
+       if(buf_size == -1) {
+               buf_size = 512;
+       }
+
+       buf = (char*)alloca(buf_size + 1);
+       va_start(ap, fmt);
+       vsnprintf(buf, buf_size + 1, fmt, ap);
+       va_end(ap);
+
+       static const float tabstop = 4;
+       static const float line_spacing = 18;
+
+       curx = x;
+       cury = y;
+       glRasterPos2i(x, y);
+
+       while(*buf) {
+               char c = *buf++;
+
+               switch(c) {
+               case '\r':
+                       if(*buf == '\n') ++buf;
+               case '\n':
+                       cury += line_spacing;
+                       curx = x;
+                       glRasterPos2i(curx, cury);
+                       break;
+
+               case '\t':
+                       curx = (curx / tabstop) * tabstop + tabstop;
+                       glRasterPos2i(curx, cury);
+                       break;
+
+               default:
+                       glutBitmapCharacter(GLUT_BITMAP_9_BY_15, c);
+               }
+       }
+}
diff --git a/src/ui.h b/src/ui.h
new file mode 100644 (file)
index 0000000..c2b519d
--- /dev/null
+++ b/src/ui.h
@@ -0,0 +1,11 @@
+#ifndef UI_H_
+#define UI_H_
+
+bool init_ui();
+void destroy_ui();
+
+void ui();
+
+void gl_printf(int x, int y, const char *fmt, ...);
+
+#endif /* UI_H_ */