skip dumping empty tracks
[faros-demo] / src / main.cc
1 #include <GL/glew.h>
2 #include <GL/freeglut.h>
3
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <assert.h>
7
8 #include "sdr.h"
9 #include "geom.h"
10 #include "seq.h"
11
12 #define BEAM_SHELLS 40
13 #define BEAM_RMIN 0.01
14 #define BEAM_RMAX 0.125
15 #define BEAM_ENERGY 0.02
16 #define BEAM_LEN 16.0
17 #define BEAM_DEF_SPEED  0.1
18
19 static bool init();
20 static void cleanup();
21
22 static void display();
23 static void light();
24 static void backdrop();
25
26 static void idle();
27 static void reshape(int x, int y);
28 static void keyboard(unsigned char c, int x, int y);
29 static void mbutton(int bn, int state, int x, int y);
30 static void mmotion(int x, int y);
31
32 static float cam_theta = 45, cam_phi, cam_dist = 10;
33 static unsigned int sdr_beam, sdr_sky;
34 static long start_time;
35 static long anim_stop_time;
36 static long tmsec, prev_tmsec;
37
38 static const float sil_color[] = {0.05, 0.02, 0.1, 1.0};
39 static const float beam_color[] = {0.5, 0.4, 0.2, 1.0};
40
41 static float beam_angle, beam_speed;
42
43 int main(int argc, char **argv)
44 {
45         glutInit(&argc, argv);
46         glutInitWindowSize(800, 600);
47         glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
48
49         glutCreateWindow("Faros");
50
51         glutDisplayFunc(display);
52         glutIdleFunc(idle);
53         glutReshapeFunc(reshape);
54         glutKeyboardFunc(keyboard);
55         glutMouseFunc(mbutton);
56         glutMotionFunc(mmotion);
57
58         if(!init()) {
59                 return 1;
60         }
61
62         atexit(cleanup);
63         glutMainLoop();
64
65         return 0;
66 }
67
68 static bool init()
69 {
70         glewInit();
71
72         glEnable(GL_CULL_FACE);
73         glEnable(GL_DEPTH_TEST);
74         glEnable(GL_MULTISAMPLE);
75
76 //      glEnable(GL_LIGHTING);
77         glEnable(GL_LIGHT0);
78
79         glEnable(GL_NORMALIZE);
80
81         if(!init_geom()) {
82                 return false;
83         }
84         if(!(sdr_beam = create_program_load("sdr/beam.v.glsl", "sdr/beam.f.glsl")))
85                 return false;
86
87         if(!(sdr_sky = create_program_load("sdr/sky.v.glsl", "sdr/sky.f.glsl"))) {
88                 return false;
89         }
90
91         if(!init_seq()) {
92                 return false;
93         }
94         add_seq_track("beam-speed", INTERP_SIGMOID, EXTRAP_CLAMP, BEAM_DEF_SPEED);
95         load_seq("seq");
96
97         start_time = glutGet(GLUT_ELAPSED_TIME);
98         prev_tmsec = start_time;
99         return true;
100 }
101
102 static void cleanup()
103 {
104         destroy_seq();
105         destroy_geom();
106         free_program(sdr_beam);
107         free_program(sdr_sky);
108 }
109
110 static void display()
111 {
112         tmsec = (long)glutGet(GLUT_ELAPSED_TIME) - start_time;
113         float dt = (tmsec - prev_tmsec) / 1000.0f;
114         prev_tmsec = tmsec;
115
116         if(anim_stop_time) dt = 0.0f;
117
118         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
119         backdrop();
120
121         glMatrixMode(GL_MODELVIEW);
122         glLoadIdentity();
123
124         glTranslatef(0, -2, -cam_dist);
125         glRotatef(cam_phi, 1, 0, 0);
126         glRotatef(cam_theta, 0, 1, 0);
127
128         glColor3fv(sil_color);
129         ground();
130         faros();
131
132         glPushMatrix();
133
134         beam_speed = get_seq_value("beam-speed", tmsec);
135         beam_angle += beam_speed * 360.0f * dt;
136         glRotatef(beam_angle, 0, 1, 0);
137         light();
138
139         glPopMatrix();
140
141         glutSwapBuffers();
142 }
143
144 static void light()
145 {
146         glPushAttrib(GL_ENABLE_BIT);
147         glDisable(GL_CULL_FACE);
148
149         glPushMatrix();
150
151         glTranslatef(0, 4.65, 0.2);
152         bind_program(sdr_beam);
153         set_uniform_float(sdr_beam, "beam_len", BEAM_LEN);
154
155         glEnable(GL_BLEND);
156         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
157
158         for(int i=0; i<BEAM_SHELLS; i++) {
159                 float t = (float)i / (float)(BEAM_SHELLS - 1);
160                 float rad = BEAM_RMIN + (BEAM_RMAX - BEAM_RMIN) * t;
161                 float alpha = BEAM_ENERGY / (t * t);
162
163                 glColor4f(beam_color[0], beam_color[1], beam_color[2], alpha);
164
165                 glutSolidCylinder(rad, BEAM_LEN, 12, 1);
166         }
167
168         bind_program(0);
169
170         glPopMatrix();
171
172         glPopAttrib();
173 }
174
175 static void backdrop()
176 {
177         glFrontFace(GL_CW);
178         bind_program(sdr_sky);
179         glutSolidSphere(200, 16, 32);
180         bind_program(0);
181         glFrontFace(GL_CCW);
182 }
183
184
185
186 static void idle()
187 {
188         glutPostRedisplay();
189 }
190
191 static void reshape(int x, int y)
192 {
193         glViewport(0, 0, x, y);
194
195         glMatrixMode(GL_PROJECTION);
196         glLoadIdentity();
197
198         gluPerspective(50, (float)x / (float)y, 0.5, 500);
199 }
200
201 #define ANIM_DELTA      0.5
202
203 static void keyboard(unsigned char c, int x, int y)
204 {
205         int idx;
206         static float orig_beam_speed;
207
208         switch(c) {
209         case 27:
210                 exit(0);
211
212         case '\b':
213                 start_time = glutGet(GLUT_ELAPSED_TIME);
214                 prev_tmsec = 0;
215                 anim_stop_time = 0;
216                 beam_angle = 0;
217                 break;
218
219         case ' ':
220                 if(anim_stop_time > 0) {
221                         long msec = glutGet(GLUT_ELAPSED_TIME);
222                         start_time += msec - anim_stop_time;
223                         prev_tmsec = msec - start_time;
224                         anim_stop_time = 0;
225                 } else {
226                         anim_stop_time = glutGet(GLUT_ELAPSED_TIME);
227                 }
228                 break;
229
230         case '=':
231                 beam_speed = get_seq_value("beam-speed", tmsec);
232                 clear_seq_track("beam-speed");
233                 set_seq_value("beam-speed", tmsec, beam_speed + ANIM_DELTA);
234                 break;
235
236         case '-':
237                 beam_speed = get_seq_value("beam-speed", tmsec) - ANIM_DELTA;
238                 if(beam_speed < 0)
239                         beam_speed = 0;
240                 clear_seq_track("beam-speed");
241                 set_seq_value("beam-speed", tmsec, beam_speed);
242                 break;
243
244         case '\r':
245         case '\n':
246                 idx = find_seq_track("beam-speed");
247                 assert(idx >= 0);
248                 if(get_seq_value(idx, tmsec) > 0.0) {
249                         clear_seq_track(idx);
250                         set_seq_value(idx, tmsec, beam_speed);
251                         set_seq_value(idx, tmsec + 3000, 0);
252                         orig_beam_speed = beam_speed;
253                 } else {
254                         clear_seq_track(idx);
255                         set_seq_value(idx, tmsec, 0);
256                         set_seq_value(idx, tmsec + 3000, orig_beam_speed);
257                 }
258                 break;
259
260         case '`':
261                 printf("dumping animation data to: seq_dump\n");
262                 if(!dump_seq("seq_dump")) {
263                         fprintf(stderr, "dump failed\n");
264                 }
265                 break;
266
267         default:
268                 break;
269         }
270 }
271
272 static int prev_x, prev_y;
273 static bool bst[8];
274 static void mbutton(int bn, int state, int x, int y)
275 {
276         int button = bn - GLUT_LEFT_BUTTON;
277         bst[button] = state == GLUT_DOWN;
278
279         prev_x = x;
280         prev_y = y;
281 }
282
283 static void mmotion(int x, int y)
284 {
285         int dx = x - prev_x;
286         int dy = y - prev_y;
287
288         prev_x = x;
289         prev_y = y;
290
291         if (dx == 0 && dy == 0)
292                 return;
293
294         if (bst[0]) {
295                 cam_theta += dx * 0.5;
296                 cam_phi += dy * 0.5;
297
298                 if (cam_phi < -90)
299                         cam_phi = -90;
300
301                 if (cam_phi > 90)
302                         cam_phi = 90;
303         }
304
305         if (bst[2]) {
306                 cam_dist += dy * 0.1;
307
308                 if (cam_dist < 0)
309                         cam_dist = 0;
310         }
311 }