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