windows build
[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;
126
127         glClear(GL_COLOR_BUFFER_BIT);
128
129         glLineWidth(5.0);
130
131         anim = fmod(t / 6.0f, LOOPTIME);
132
133         dt = (anim > 1.0f ? 1.0f : anim) / (float)(nverts - 1);
134
135         glColor3f(1, 1, 1);
136         for(i=0; i<nverts-1; i++) {
137                 float t0 = (float)i * dt;
138                 float t1 = (float)(i + 1) * dt;
139                 eval_logo(a, t0);
140                 eval_logo(b, t1);
141                 draw_line(a[0], a[1], b[0], b[1], 0.02);
142         }
143
144         if(anim > 0.0f) {
145                 eval_logo(a, 0);
146                 draw_disc(a[0], a[1], 0.05, 18);
147         }
148         if(anim >= 1.0f) {
149                 eval_logo(b, 1);
150                 draw_disc(b[0], b[1], 0.05, 18);
151         }
152
153         glEnable(GL_BLEND);
154         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
155
156         glColor4f(0.8, 0, 0, 2.0 * (anim - 1.0f) / (LOOPTIME - 1.0f));
157         draw_disc(0, 0, 0.14, 24);
158
159         glDisable(GL_BLEND);
160
161         glutSwapBuffers();
162         assert(glGetError() == GL_NO_ERROR);
163 }
164
165 void idle(void)
166 {
167         glutPostRedisplay();
168 }
169
170 void reshape(int x, int y)
171 {
172         float aspect = (float)x / (float)y;
173         win_width = x;
174         win_height = y;
175
176         glViewport(0, 0, x, y);
177         glMatrixMode(GL_PROJECTION);
178         glLoadIdentity();
179         glScalef(1.0f / aspect, 1.0f, 1.0f);
180 }
181
182 void keyb(unsigned char key, int x, int y)
183 {
184         static int saved_width = 800, saved_height = 600;
185
186         switch(key) {
187         case 27:
188                 exit(0);
189
190         case '-':
191                 nverts -= 8;
192                 printf("nverts: %d\n", nverts);
193                 glutPostRedisplay();
194                 break;
195
196         case '=':
197                 nverts += 8;
198                 printf("nverts: %d\n", nverts);
199                 glutPostRedisplay();
200                 break;
201
202         case 'f':
203                 fullscr = !fullscr;
204                 if(fullscr) {
205                         saved_width = win_width;
206                         saved_height = win_height;
207                         glutFullScreen();
208                 } else {
209                         glutReshapeWindow(saved_width, saved_height);
210                 }
211                 break;
212         }
213 }
214
215 int parse_args(int argc, char **argv)
216 {
217         int i;
218
219         for(i=1; i<argc; i++) {
220                 if(argv[i][0] == '-') {
221                         if(strcmp(argv[i], "-fs") == 0) {
222                                 fullscr = 1;
223                         } else if(strcmp(argv[i], "-noaa") == 0) {
224                                 msaa = 0;
225                         } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) {
226                                 print_usage(argv[0]);
227                                 exit(0);
228                         } else {
229                                 fprintf(stderr, "invalid option: %s\n", argv[i]);
230                                 return -1;
231                         }
232                 } else {
233                         fprintf(stderr, "unexpected argument: %s\n", argv[i]);
234                         return -1;
235                 }
236         }
237         return 0;
238 }
239
240 void print_usage(const char *argv0)
241 {
242         printf("Usage: %s [options]\n", argv0);
243         printf("Options:\n");
244         printf(" -fs: fullscreen\n");
245         printf(" -noaa: disable anti-aliasing\n");
246         printf(" -h,-help: print usage and exit\n");
247 }