fadeout
[censuslogo] / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <assert.h>
6 #include <GL/glut.h>
7 #include "logo.h"
8
9 #ifndef GL_MULTISAMPLE
10 #define GL_MULTISAMPLE  0x809d
11 #endif
12
13 #define MSAA
14
15 int init(void);
16 void display(void);
17 void idle(void);
18 void reshape(int x, int y);
19 void keyb(unsigned char key, int x, int y);
20 int parse_args(int argc, char **argv);
21 void print_usage(const char *argv0);
22
23 int win_width, win_height;
24 int nverts = 256;
25 long start_time;
26 int msaa = 1;
27 int fullscr = 0;
28
29
30 int main(int argc, char **argv)
31 {
32         unsigned int flags = GLUT_RGB | GLUT_DOUBLE;
33
34         glutInit(&argc, argv);
35         if(parse_args(argc, argv) == -1) {
36                 return 1;
37         }
38
39 #ifdef MSAA
40         if(msaa) {
41                 flags |= GLUT_MULTISAMPLE;
42         }
43 #endif
44
45         glutInitWindowSize(1280, 800);
46         glutInitDisplayMode(flags);
47         glutCreateWindow("census");
48
49         if(fullscr) {
50                 glutFullScreen();
51         }
52
53         glutDisplayFunc(display);
54         glutIdleFunc(idle);
55         glutReshapeFunc(reshape);
56         glutKeyboardFunc(keyb);
57
58         if(init() == -1) {
59                 return 1;
60         }
61
62         glutMainLoop();
63         return 0;
64 }
65
66 int init(void)
67 {
68         if(init_logo("data/census.curves") == -1) {
69                 return -1;
70         }
71
72 #ifdef MSAA
73         if(msaa) {
74                 glEnable(GL_MULTISAMPLE);
75         }
76 #endif
77
78         start_time = glutGet(GLUT_ELAPSED_TIME);
79         return 0;
80 }
81
82 static void draw_disc(float x, float y, float rad, int sub)
83 {
84         int i;
85         glBegin(GL_TRIANGLE_FAN);
86         glVertex2f(x, y);
87         for(i=0; i<sub; i++) {
88                 float t = (float)i / (float)(sub - 1);
89                 float theta = t * M_PI * 2.0;
90                 glVertex2f(cos(theta) * rad + x, sin(theta) * rad + y);
91         }
92         glEnd();
93 }
94
95 static void draw_line(float x0, float y0, float x1, float y1, float rad)
96 {
97         float dx, dy, rx, ry, len;
98
99         dx = x1 - x0;
100         dy = y1 - y0;
101         len = sqrt(dx * dx + dy * dy);
102
103         rx = rad * dy / len;
104         ry = -rad * dx / len;
105
106         draw_disc(x0, y0, rad, 8);
107         draw_disc(x1, y1, rad, 8);
108
109         glBegin(GL_QUADS);
110         glVertex2f(x0 + rx, y0 + ry);
111         glVertex2f(x1 + rx, y1 + ry);
112         glVertex2f(x1 - rx, y1 - ry);
113         glVertex2f(x0 - rx, y0 - ry);
114         glEnd();
115 }
116
117 #define LOOPTIME        1.3f
118
119 void display(void)
120 {
121         int i;
122         long msec = glutGet(GLUT_ELAPSED_TIME) - start_time;
123         float t = (float)msec / 1000.0f;
124         float a[2], b[2], dt;
125         float anim, alpha;
126
127         glClear(GL_COLOR_BUFFER_BIT);
128
129         glLineWidth(5.0);
130
131         anim = fmod(t / 6.0f, LOOPTIME);
132         alpha = 1.0f - ((anim - (LOOPTIME - 0.2)) / 0.2f);
133         if(alpha < 0.0f) alpha = 0.0f;
134         if(alpha > 1.0f) alpha = 1.0f;
135
136         dt = (anim > 1.0f ? 1.0f : anim) / (float)(nverts - 1);
137
138         glColor4f(1, 1, 1, alpha);
139         for(i=0; i<nverts-1; i++) {
140                 float t0 = (float)i * dt;
141                 float t1 = (float)(i + 1) * dt;
142                 eval_logo(a, t0);
143                 eval_logo(b, t1);
144                 draw_line(a[0], a[1], b[0], b[1], 0.02);
145         }
146
147         if(anim > 0.0f) {
148                 eval_logo(a, 0);
149                 draw_disc(a[0], a[1], 0.05, 18);
150         }
151         if(anim >= 1.0f) {
152                 eval_logo(b, 1);
153                 draw_disc(b[0], b[1], 0.05, 18);
154         }
155
156         glEnable(GL_BLEND);
157         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
158
159         glColor4f(0.8, 0, 0, 2.0 * (anim - 1.0f) / (LOOPTIME - 1.0f));
160         draw_disc(0, 0, 0.14, 24);
161
162         if(alpha < 1.0f) {
163                 glBegin(GL_QUADS);
164                 glColor4f(0, 0, 0, 1.0f - alpha);
165                 glVertex2f(-1, -1);
166                 glVertex2f(1, -1);
167                 glVertex2f(1, 1);
168                 glVertex2f(-1, 1);
169                 glEnd();
170         }
171
172         glDisable(GL_BLEND);
173
174         glutSwapBuffers();
175         assert(glGetError() == GL_NO_ERROR);
176 }
177
178 void idle(void)
179 {
180         glutPostRedisplay();
181 }
182
183 void reshape(int x, int y)
184 {
185         float aspect = (float)x / (float)y;
186         win_width = x;
187         win_height = y;
188
189         glViewport(0, 0, x, y);
190         glMatrixMode(GL_PROJECTION);
191         glLoadIdentity();
192         glScalef(1.0f / aspect, 1.0f, 1.0f);
193 }
194
195 void keyb(unsigned char key, int x, int y)
196 {
197         static int saved_width = 800, saved_height = 600;
198
199         switch(key) {
200         case 27:
201                 exit(0);
202
203         case '-':
204                 nverts -= 8;
205                 printf("nverts: %d\n", nverts);
206                 glutPostRedisplay();
207                 break;
208
209         case '=':
210                 nverts += 8;
211                 printf("nverts: %d\n", nverts);
212                 glutPostRedisplay();
213                 break;
214
215         case 'f':
216                 fullscr = !fullscr;
217                 if(fullscr) {
218                         saved_width = win_width;
219                         saved_height = win_height;
220                         glutFullScreen();
221                 } else {
222                         glutReshapeWindow(saved_width, saved_height);
223                 }
224                 break;
225         }
226 }
227
228 int parse_args(int argc, char **argv)
229 {
230         int i;
231
232         for(i=1; i<argc; i++) {
233                 if(argv[i][0] == '-') {
234                         if(strcmp(argv[i], "-fs") == 0) {
235                                 fullscr = 1;
236                         } else if(strcmp(argv[i], "-noaa") == 0) {
237                                 msaa = 0;
238                         } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
239                                 print_usage(argv[0]);
240                                 exit(0);
241                         } else {
242                                 fprintf(stderr, "invalid option: %s\n", argv[i]);
243                                 return -1;
244                         }
245                 } else {
246                         fprintf(stderr, "unexpected argument: %s\n", argv[i]);
247                         return -1;
248                 }
249         }
250         return 0;
251 }
252
253 void print_usage(const char *argv0)
254 {
255         printf("Usage: %s [options]\n", argv0);
256         printf("Options:\n");
257         printf(" -fs: fullscreen\n");
258         printf(" -noaa: disable anti-aliasing\n");
259         printf(" -h,-help: print usage and exit\n");
260 }