fadeout
[censuslogo] / src / main.c
index 06477c1..23b9878 100644 (file)
@@ -1,26 +1,57 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <math.h>
 #include <assert.h>
 #include <GL/glut.h>
 #include "logo.h"
 
-#define BEZ_SEG        16
+#ifndef GL_MULTISAMPLE
+#define GL_MULTISAMPLE 0x809d
+#endif
+
+#define MSAA
 
 int init(void);
 void display(void);
+void idle(void);
 void reshape(int x, int y);
 void keyb(unsigned char key, int x, int y);
+int parse_args(int argc, char **argv);
+void print_usage(const char *argv0);
+
+int win_width, win_height;
+int nverts = 256;
+long start_time;
+int msaa = 1;
+int fullscr = 0;
 
-void draw_bezier(float *cp, int sub);
 
 int main(int argc, char **argv)
 {
+       unsigned int flags = GLUT_RGB | GLUT_DOUBLE;
+
        glutInit(&argc, argv);
-       glutInitWindowSize(800, 600);
-       glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+       if(parse_args(argc, argv) == -1) {
+               return 1;
+       }
+
+#ifdef MSAA
+       if(msaa) {
+               flags |= GLUT_MULTISAMPLE;
+       }
+#endif
+
+       glutInitWindowSize(1280, 800);
+       glutInitDisplayMode(flags);
        glutCreateWindow("census");
 
+       if(fullscr) {
+               glutFullScreen();
+       }
+
        glutDisplayFunc(display);
+       glutIdleFunc(idle);
        glutReshapeFunc(reshape);
        glutKeyboardFunc(keyb);
 
@@ -34,24 +65,108 @@ int main(int argc, char **argv)
 
 int init(void)
 {
-       glEnable(GL_LINE_SMOOTH);
+       if(init_logo("data/census.curves") == -1) {
+               return -1;
+       }
+
+#ifdef MSAA
+       if(msaa) {
+               glEnable(GL_MULTISAMPLE);
+       }
+#endif
+
+       start_time = glutGet(GLUT_ELAPSED_TIME);
        return 0;
 }
 
+static void draw_disc(float x, float y, float rad, int sub)
+{
+       int i;
+       glBegin(GL_TRIANGLE_FAN);
+       glVertex2f(x, y);
+       for(i=0; i<sub; i++) {
+               float t = (float)i / (float)(sub - 1);
+               float theta = t * M_PI * 2.0;
+               glVertex2f(cos(theta) * rad + x, sin(theta) * rad + y);
+       }
+       glEnd();
+}
+
+static void draw_line(float x0, float y0, float x1, float y1, float rad)
+{
+       float dx, dy, rx, ry, len;
+
+       dx = x1 - x0;
+       dy = y1 - y0;
+       len = sqrt(dx * dx + dy * dy);
+
+       rx = rad * dy / len;
+       ry = -rad * dx / len;
+
+       draw_disc(x0, y0, rad, 8);
+       draw_disc(x1, y1, rad, 8);
+
+       glBegin(GL_QUADS);
+       glVertex2f(x0 + rx, y0 + ry);
+       glVertex2f(x1 + rx, y1 + ry);
+       glVertex2f(x1 - rx, y1 - ry);
+       glVertex2f(x0 - rx, y0 - ry);
+       glEnd();
+}
+
+#define LOOPTIME       1.3f
+
 void display(void)
 {
-       int i, nseg;
+       int i;
+       long msec = glutGet(GLUT_ELAPSED_TIME) - start_time;
+       float t = (float)msec / 1000.0f;
+       float a[2], b[2], dt;
+       float anim, alpha;
 
        glClear(GL_COLOR_BUFFER_BIT);
 
+       glLineWidth(5.0);
+
+       anim = fmod(t / 6.0f, LOOPTIME);
+       alpha = 1.0f - ((anim - (LOOPTIME - 0.2)) / 0.2f);
+       if(alpha < 0.0f) alpha = 0.0f;
+       if(alpha > 1.0f) alpha = 1.0f;
+
+       dt = (anim > 1.0f ? 1.0f : anim) / (float)(nverts - 1);
+
+       glColor4f(1, 1, 1, alpha);
+       for(i=0; i<nverts-1; i++) {
+               float t0 = (float)i * dt;
+               float t1 = (float)(i + 1) * dt;
+               eval_logo(a, t0);
+               eval_logo(b, t1);
+               draw_line(a[0], a[1], b[0], b[1], 0.02);
+       }
+
+       if(anim > 0.0f) {
+               eval_logo(a, 0);
+               draw_disc(a[0], a[1], 0.05, 18);
+       }
+       if(anim >= 1.0f) {
+               eval_logo(b, 1);
+               draw_disc(b[0], b[1], 0.05, 18);
+       }
+
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glLineWidth(2.0);
 
-       glColor3f(1, 1, 1);
-       nseg = LOGOCP_SIZE / 4;
-       for(i=0; i<nseg; i++) {
-               draw_bezier((float*)(logocp + i * 4), BEZ_SEG);
+       glColor4f(0.8, 0, 0, 2.0 * (anim - 1.0f) / (LOOPTIME - 1.0f));
+       draw_disc(0, 0, 0.14, 24);
+
+       if(alpha < 1.0f) {
+               glBegin(GL_QUADS);
+               glColor4f(0, 0, 0, 1.0f - alpha);
+               glVertex2f(-1, -1);
+               glVertex2f(1, -1);
+               glVertex2f(1, 1);
+               glVertex2f(-1, 1);
+               glEnd();
        }
 
        glDisable(GL_BLEND);
@@ -60,9 +175,16 @@ void display(void)
        assert(glGetError() == GL_NO_ERROR);
 }
 
+void idle(void)
+{
+       glutPostRedisplay();
+}
+
 void reshape(int x, int y)
 {
        float aspect = (float)x / (float)y;
+       win_width = x;
+       win_height = y;
 
        glViewport(0, 0, x, y);
        glMatrixMode(GL_PROJECTION);
@@ -72,49 +194,67 @@ void reshape(int x, int y)
 
 void keyb(unsigned char key, int x, int y)
 {
+       static int saved_width = 800, saved_height = 600;
+
        switch(key) {
        case 27:
                exit(0);
+
+       case '-':
+               nverts -= 8;
+               printf("nverts: %d\n", nverts);
+               glutPostRedisplay();
+               break;
+
+       case '=':
+               nverts += 8;
+               printf("nverts: %d\n", nverts);
+               glutPostRedisplay();
+               break;
+
+       case 'f':
+               fullscr = !fullscr;
+               if(fullscr) {
+                       saved_width = win_width;
+                       saved_height = win_height;
+                       glutFullScreen();
+               } else {
+                       glutReshapeWindow(saved_width, saved_height);
+               }
+               break;
        }
 }
 
-#define LERP(a, b, t)  ((a) + ((b) - (a)) * (t))
-
-void draw_bezier(float *cp, int sub)
+int parse_args(int argc, char **argv)
 {
        int i;
-       float cx[4], cy[4], mx[3], my[3], mmx[2], mmy[2], x, y;
 
-       if(sub < 1) sub = 1;
-
-       for(i=0; i<4; i++) {
-               cx[i] = cp[i * 2] / LOGO_W - 0.5f;
-               cy[i] = 0.5f - cp[i * 2 + 1] / LOGO_H;
+       for(i=1; i<argc; i++) {
+               if(argv[i][0] == '-') {
+                       if(strcmp(argv[i], "-fs") == 0) {
+                               fullscr = 1;
+                       } else if(strcmp(argv[i], "-noaa") == 0) {
+                               msaa = 0;
+                       } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
+                               print_usage(argv[0]);
+                               exit(0);
+                       } else {
+                               fprintf(stderr, "invalid option: %s\n", argv[i]);
+                               return -1;
+                       }
+               } else {
+                       fprintf(stderr, "unexpected argument: %s\n", argv[i]);
+                       return -1;
+               }
        }
+       return 0;
+}
 
-       glBegin(GL_LINE_STRIP);
-       for(i=0; i<BEZ_SEG; i++) {
-               float t = (float)i / (float)(BEZ_SEG - 1);
-
-               mx[0] = LERP(cx[0], cx[1], t);
-               my[0] = LERP(cy[0], cy[1], t);
-
-               mx[1] = LERP(cx[1], cx[2], t);
-               my[1] = LERP(cy[1], cy[2], t);
-
-               mx[2] = LERP(cx[2], cx[3], t);
-               my[2] = LERP(cy[2], cy[3], t);
-
-               mmx[0] = LERP(mx[0], mx[1], t);
-               mmy[0] = LERP(my[0], my[1], t);
-
-               mmx[1] = LERP(mx[1], mx[2], t);
-               mmy[1] = LERP(my[1], my[2], t);
-
-               x = LERP(mmx[0], mmx[1], t);
-               y = LERP(mmy[0], mmy[1], t);
-
-               glVertex2f(x, y);
-       }
-       glEnd();
+void print_usage(const char *argv0)
+{
+       printf("Usage: %s [options]\n", argv0);
+       printf("Options:\n");
+       printf(" -fs: fullscreen\n");
+       printf(" -noaa: disable anti-aliasing\n");
+       printf(" -h,-help: print usage and exit\n");
 }