nice logo
authorJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 30 Aug 2019 00:06:37 +0000 (03:06 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Fri, 30 Aug 2019 00:06:37 +0000 (03:06 +0300)
data/census.curves [new file with mode: 0644]
src/logo.c [new file with mode: 0644]
src/logo.h
src/main.c

diff --git a/data/census.curves b/data/census.curves
new file mode 100644 (file)
index 0000000..3b9efd2
--- /dev/null
@@ -0,0 +1,81 @@
+GCURVES
+curve {
+    type bspline
+    cpcount 76
+    cp 0.770551 -0.12 0 1
+    cp 0.770551 -0.12 0 1
+    cp 0.770551 -0.12 0 1
+    cp 0.464919 -0.423409 0 1
+    cp 0.157055 -0.7461 0 1
+    cp 0.000942409 -0.760054 0 1
+    cp -0.156914 -0.742611 0 1
+    cp -0.460417 -0.424282 0 1
+    cp -0.736884 -0.163513 0 1
+    cp -0.761304 -0.000423729 0 1
+    cp -0.734268 0.167898 0 1
+    cp -0.442102 0.441749 0 1
+    cp -0.17959 0.726937 0 1
+    cp 7.04117e-05 0.762695 0 1
+    cp 0.184963 0.724321 0 1
+    cp 0.403869 0.483612 0 1
+    cp 0.758539 0.124617 0 1
+    cp 0.758539 0.124617 0 1
+    cp 0.758539 0.124617 0 1
+    cp 0.586597 0.120587 0 1
+    cp 0.586597 0.120587 0 1
+    cp 0.586597 0.120587 0 1
+    cp 0.3118 0.392285 0 1
+    cp 0.102777 0.620188 0 1
+    cp 0.000962065 0.630302 0 1
+    cp -0.0947842 0.622211 0 1
+    cp -0.353704 0.344412 0 1
+    cp -0.616669 0.104372 0 1
+    cp -0.630828 -0.000814512 0 1
+    cp -0.611275 -0.11544 0 1
+    cp -0.361121 -0.341995 0 1
+    cp -0.0974812 -0.61912 0 1
+    cp 0.000287853 -0.634628 0 1
+    cp 0.0987312 -0.622491 0 1
+    cp 0.320566 -0.385148 0 1
+    cp 0.578731 -0.12 0 1
+    cp 0.578731 -0.12 0 1
+    cp 0.578731 -0.12 0 1
+    cp 0.410366 -0.12 0 1
+    cp 0.410366 -0.12 0 1
+    cp 0.410366 -0.12 0 1
+    cp 0.221153 -0.305467 0 1
+    cp 0.0576008 -0.481569 0 1
+    cp -0.00106066 -0.497751 0 1
+    cp -0.0603964 -0.477523 0 1
+    cp -0.270768 -0.252317 0 1
+    cp -0.479118 -0.0567789 0 1
+    cp -0.491929 0.000533998 0 1
+    cp -0.479792 0.0558241 0 1
+    cp -0.27414 0.245968 0 1
+    cp -0.0543279 0.476568 0 1
+    cp 0.000287883 0.493425 0 1
+    cp 0.0522066 0.47994 0 1
+    cp 0.195152 0.330252 0 1
+    cp 0.397571 0.12191 0 1
+    cp 0.397571 0.12191 0 1
+    cp 0.397571 0.12191 0 1
+    cp 0.228891 0.12 0 1
+    cp 0.228891 0.12 0 1
+    cp 0.228891 0.12 0 1
+    cp 0.133119 0.210906 0 1
+    cp 0.0366984 0.310024 0 1
+    cp 0.000287898 0.329578 0 1
+    cp -0.032077 0.314069 0 1
+    cp -0.177045 0.161684 0 1
+    cp -0.31055 0.0369445 0 1
+    cp -0.327407 -0.000140294 0 1
+    cp -0.308528 -0.0399222 0 1
+    cp -0.172999 -0.170056 0 1
+    cp -0.0334256 -0.312327 0 1
+    cp 0.000287853 -0.325812 0 1
+    cp 0.0353499 -0.315024 0 1
+    cp 0.108845 -0.236809 0 1
+    cp 0.227761 -0.12 0 1
+    cp 0.227761 -0.12 0 1
+    cp 0.227761 -0.12 0 1
+}
diff --git a/src/logo.c b/src/logo.c
new file mode 100644 (file)
index 0000000..b36473d
--- /dev/null
@@ -0,0 +1,140 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <cgmath/cgmath.h>
+#include "logo.h"
+
+struct cpnode {
+       cgm_vec2 p;
+       struct cpnode *next;
+};
+
+#define CPLERP(res, a, b, t) \
+       do { \
+               (res).x = (a).x + ((b).x - (a).x) * (t); \
+               (res).y = (a).y + ((b).y - (a).y) * (t); \
+       } while(0)
+
+static cgm_vec2 *cp;
+static int numcp;
+
+int init_logo(const char *fname)
+{
+       FILE *fp;
+       char buf[256];
+       struct cpnode *cpn, *cplist = 0, *cptail = 0;
+       int idx;
+
+       if(!(fp = fopen(fname, "rb"))) {
+               fprintf(stderr, "failed to load logo curve: %s\n", fname);
+               return -1;
+       }
+       fgets(buf, sizeof buf, fp);
+       if(memcmp(buf, "GCURVES", 7) != 0) {
+               fprintf(stderr, "invalid logo file: %s\n", fname);
+               fclose(fp);
+               return -1;
+       }
+
+       numcp = 0;
+       while(fgets(buf, sizeof buf, fp)) {
+               char *ptr;
+               cgm_vec2 v;
+
+               ptr = buf;
+               while(*ptr && isspace(*ptr)) ptr++;
+
+               if(sscanf(ptr, "cp %f %f", &v.x, &v.y) == 2) {
+                       if(!(cpn = malloc(sizeof *cpn))) {
+                               continue;
+                       }
+
+                       cpn->p.x = v.x;
+                       cpn->p.y = v.y;
+                       cpn->next = 0;
+
+                       if(cplist) {
+                               cptail->next = cpn;
+                               cptail = cpn;
+                       } else {
+                               cplist = cptail = cpn;
+                       }
+                       numcp++;
+               }
+       }
+       fclose(fp);
+
+       if(numcp < 4) {
+               fprintf(stderr, "invalid logo file, found %d control points\n", numcp);
+               return -1;
+       }
+
+       if(!(cp = malloc(numcp * sizeof *cp))) {
+               fprintf(stderr, "failed to allocate curve of %d control points\n", numcp);
+               while(cplist) {
+                       cpn = cplist;
+                       cplist = cplist->next;
+                       free(cpn);
+               }
+               return -1;
+       }
+
+       idx = 0;
+       while(cplist) {
+               cpn = cplist;
+               cplist = cplist->next;
+               cp[idx++] = cpn->p;
+               free(cpn);
+       }
+
+       return 0;
+}
+
+static void eval_seg(float *res, int a, int b, float t)
+{
+       int prev, next;
+
+       if(numcp == 2) {
+               res[0] = cp[a].x + (cp[b].x - cp[a].x) * t;
+               res[1] = cp[a].y + (cp[b].y - cp[a].y) * t;
+               return;
+       }
+
+       prev = a <= 0 ? a : a - 1;
+       next = b >= numcp - 1 ? b : b + 1;
+
+       res[0] = cgm_bspline(cp[prev].x, cp[a].x, cp[b].x, cp[next].x, t);
+       res[1] = cgm_bspline(cp[prev].y, cp[a].y, cp[b].y, cp[next].y, t);
+}
+
+void eval_logo(float *res, float t)
+{
+       int idx0, idx1;
+       float t0, t1, dt;
+
+       if(!cp || numcp <= 0) {
+               res[0] = res[1] = 0;
+               return;
+       }
+       if(numcp == 1) {
+               res[0] = cp[0].x;
+               res[1] = cp[0].y;
+               return;
+       }
+
+       if(t < 0.0f) t = 0.0f;
+       if(t > 1.0f) t = 1.0f;
+
+       idx0 = (int)floor(t * (numcp - 1));
+       if(idx0 > numcp - 2) idx0 = numcp - 2;
+       idx1 = idx0 + 1;
+
+       dt = 1.0f / (float)(numcp - 1);
+       t0 = (float)idx0 * dt;
+       t1 = (float)idx1 * dt;
+       t = (t - t0) / (t1 - t0);
+
+       eval_seg(res, idx0, idx1, t);
+}
index c483f0c..b285c88 100644 (file)
@@ -1,106 +1,7 @@
 #ifndef LOGO_H_
 #define LOGO_H_
 
-#define LOGO_W 90
-#define LOGO_H 85
-
-static const float logocp[][2] = {
-       {85, 48},
-       {68.5, 64.5},
-       {68.5, 64.5},
-       {52, 81},
-
-       {52, 81},
-       {43, 89},
-       {43, 89},
-       {34, 81},
-
-       {34, 81},
-       {18.5, 66},
-       {18.5, 66},
-       {3, 51},
-
-       {3, 51},
-       {-5, 41.5},
-       {-5, 41.5},
-       {4, 32},
-
-       {4, 32},
-       {19, 17},
-       {19, 17},
-       {33, 3},
-
-       {33, 3},
-       {42, -5},
-       {42, -5},
-       {52, 3},
-
-       {52, 3},
-       {68, 19},
-       {68, 19},
-       {85, 35},
-
-       {85, 35},
-       {75, 35},
-       {85, 35},
-       {75, 35},
-
-       {75, 35},
-       {62, 22},
-       {62, 22},
-       {49, 10},
-
-       {49, 10},
-       {42, 4},
-       {42, 4},
-       {36, 10},
-
-       {36, 10},
-       {23, 22},
-       {23, 22},
-       {11, 35},
-
-       {11, 35},
-       {5, 42},
-       {5, 42},
-       {11, 49},
-
-       {11, 49},
-       {23, 61},
-       {23, 61},
-       {36, 74},
-
-       {36, 74},
-       {42, 79},
-       {42, 79},
-       {49, 74},
-
-       {49, 74},
-       {62, 61},
-       {62, 61},
-       {75, 48},
-
-       {75, 48},
-       {65, 48},
-       {75, 48},
-       {65, 48},
-
-       {65, 48},
-       {55.5, 57.5},
-       {55.5, 57.5},
-       {46, 67},
-
-       {46, 67},
-       {42.5, 70},
-       {42.5, 70},
-       {39, 67},
-
-       {39, 67},
-       {28, 56},
-       {28, 56},
-       {17, 45},
-};
-
-#define LOGOCP_SIZE    (sizeof logocp / sizeof *logocp)
+int init_logo(const char *fname);
+void eval_logo(float *res, float t);
 
 #endif /* LOGO_H_ */
index 06477c1..125c2db 100644 (file)
@@ -1,23 +1,29 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <math.h>
 #include <assert.h>
 #include <GL/glut.h>
 #include "logo.h"
 
-#define BEZ_SEG        16
+#define MSAA
 
 int init(void);
 void display(void);
 void reshape(int x, int y);
 void keyb(unsigned char key, int x, int y);
 
-void draw_bezier(float *cp, int sub);
+int nverts = 256;
 
 int main(int argc, char **argv)
 {
+       unsigned int flags = GLUT_RGB | GLUT_DOUBLE;
+#ifdef MSAA
+       flags |= GLUT_MULTISAMPLE;
+#endif
+
        glutInit(&argc, argv);
        glutInitWindowSize(800, 600);
-       glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+       glutInitDisplayMode(flags);
        glutCreateWindow("census");
 
        glutDisplayFunc(display);
@@ -34,27 +40,77 @@ int main(int argc, char **argv)
 
 int init(void)
 {
-       glEnable(GL_LINE_SMOOTH);
+       if(init_logo("data/census.curves") == -1) {
+               return -1;
+       }
+
+#ifdef MSAA
+       glEnable(GL_MULTISAMPLE);
+#endif
+
        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();
+}
+
 void display(void)
 {
-       int i, nseg;
+       int i;
+       float a[2], b[2], dt = 1.0f / (float)(nverts - 1);
 
        glClear(GL_COLOR_BUFFER_BIT);
 
-       glEnable(GL_BLEND);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glLineWidth(2.0);
+       glLineWidth(5.0);
 
        glColor3f(1, 1, 1);
-       nseg = LOGOCP_SIZE / 4;
-       for(i=0; i<nseg; i++) {
-               draw_bezier((float*)(logocp + i * 4), BEZ_SEG);
+       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);
        }
 
-       glDisable(GL_BLEND);
+       eval_logo(a, 0);
+       eval_logo(b, 1);
+       draw_disc(a[0], a[1], 0.05, 18);
+       draw_disc(b[0], b[1], 0.05, 18);
+
+       glColor3f(0.8, 0, 0);
+       draw_disc(0, 0, 0.14, 24);
 
        glutSwapBuffers();
        assert(glGetError() == GL_NO_ERROR);
@@ -75,46 +131,17 @@ void keyb(unsigned char key, int x, int y)
        switch(key) {
        case 27:
                exit(0);
-       }
-}
-
-#define LERP(a, b, t)  ((a) + ((b) - (a)) * (t))
-
-void draw_bezier(float *cp, int sub)
-{
-       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;
-       }
-
-       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);
+       case '-':
+               nverts -= 8;
+               printf("nverts: %d\n", nverts);
+               glutPostRedisplay();
+               break;
+
+       case '=':
+               nverts += 8;
+               printf("nverts: %d\n", nverts);
+               glutPostRedisplay();
+               break;
        }
-       glEnd();
 }