2 #include <GL/freeglut.h>
14 #define BEAM_SHELLS 40
15 #define BEAM_RMIN 0.01
16 #define BEAM_RMAX 0.125
17 #define BEAM_ENERGY 0.01
19 #define BEAM_DEF_SPEED 0.1
20 #define BEAM_HEIGHT 4.65
24 #define LERP(a, b, t) ((a) + ((b) - (a)) * (t))
33 static void cleanup();
35 static void display();
37 static void paper_light();
38 static void backdrop(float alpha);
42 static void reshape(int x, int y);
43 static void keyboard(unsigned char c, int x, int y);
44 static void keyb_special(int key, int x, int y);
45 static void mbutton(int bn, int state, int x, int y);
46 static void mmotion(int x, int y);
48 int win_width, win_height;
49 static bool freecam = true;
51 static Camera cam = {0, 0, 0, 0, 0, 10};
52 static unsigned int sdr_beam, sdr_sky;
53 static long start_time;
54 static long anim_stop_time;
55 long tmsec, prev_tmsec, anim_time;
58 static const float sil_color[] = {0.05, 0.02, 0.1, 1.0};
59 static const float ink_color[] = {0.05, 0.15, 0.3, 1.0};
60 static const float beam_color[] = {0.5, 0.4, 0.2, 1.0};
61 static const float paper_color[] = {0.9, 0.8, 0.8, 1.0};
63 static float beam_angle, beam_speed;
64 static float beam_len;
65 static float xlogo_alpha, xcircle;
68 static bool show_help, show_ui = true;
70 int main(int argc, char **argv)
72 glutInit(&argc, argv);
73 glutInitWindowSize(800, 600);
74 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
76 glutCreateWindow("Faros (press F1 for controls help)");
78 glutDisplayFunc(display);
80 glutReshapeFunc(reshape);
81 glutKeyboardFunc(keyboard);
82 glutSpecialFunc(keyb_special);
83 glutMouseFunc(mbutton);
84 glutMotionFunc(mmotion);
100 glEnable(GL_CULL_FACE);
101 glEnable(GL_DEPTH_TEST);
102 glEnable(GL_MULTISAMPLE);
104 // glEnable(GL_LIGHTING);
107 glEnable(GL_NORMALIZE);
112 if(!(sdr_beam = create_program_load("sdr/beam.v.glsl", "sdr/beam.f.glsl")))
115 if(!(sdr_sky = create_program_load("sdr/sky.v.glsl", "sdr/sky.f.glsl"))) {
122 add_seq_track("beam-speed", INTERP_SIGMOID, EXTRAP_CLAMP, BEAM_DEF_SPEED);
123 add_seq_track("beam-len", INTERP_SIGMOID, EXTRAP_CLAMP, BEAM_LEN);
124 add_seq_track("cam-dist", INTERP_SIGMOID, EXTRAP_CLAMP, 10);
125 add_seq_track("cam-phi", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
126 add_seq_track("cam-theta", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
127 add_seq_track("cam-x", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
128 add_seq_track("cam-y", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
129 add_seq_track("cam-z", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
130 add_seq_track("xlogo", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
131 add_seq_track("xcircle", INTERP_SIGMOID, EXTRAP_CLAMP, 1);
132 add_seq_track("paper", INTERP_SIGMOID, EXTRAP_CLAMP, 0);
135 freecam = seq_track_empty("cam-theta");
137 glClearColor(paper_color[0], paper_color[1], paper_color[2], 1);
139 start_time = glutGet(GLUT_ELAPSED_TIME);
140 prev_tmsec = start_time;
144 static void cleanup()
148 free_program(sdr_beam);
149 free_program(sdr_sky);
152 static void display()
154 tmsec = (long)glutGet(GLUT_ELAPSED_TIME) - start_time;
155 float dt = (tmsec - prev_tmsec) / 1000.0f;
161 anim_time = anim_stop_time - start_time;
164 paper = get_seq_value("paper", anim_time);
166 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
167 backdrop(1.0f - paper);
169 glMatrixMode(GL_MODELVIEW);
173 cam.dist = get_seq_value("cam-dist", anim_time);
174 cam.phi = get_seq_value("cam-phi", anim_time);
175 cam.theta = get_seq_value("cam-theta", anim_time);
176 cam.x = get_seq_value("cam-x", anim_time);
177 cam.y = get_seq_value("cam-y", anim_time);
178 cam.z = get_seq_value("cam-z", anim_time);
181 glTranslatef(0, -2, -cam.dist);
182 glRotatef(cam.phi, 1, 0, 0);
183 glRotatef(cam.theta, 0, 1, 0);
184 glTranslatef(-cam.x, -cam.y, -cam.z);
187 color[0] = LERP(sil_color[0], ink_color[0], paper);
188 color[1] = LERP(sil_color[1], ink_color[1], paper);
189 color[2] = LERP(sil_color[2], ink_color[2], paper);
195 beam_len = get_seq_value("beam-len", anim_time);
196 beam_speed = get_seq_value("beam-speed", anim_time);
197 beam_angle += beam_speed * 360.0f * dt;
199 xlogo_alpha = get_seq_value("xlogo", anim_time);
200 xcircle = get_seq_value("xcircle", anim_time);
202 if(xlogo_alpha > 0.0) {
204 float beam_angle_rad = beam_angle / 180.0 * M_PI;
205 float xlogo_dist = beam_len;
206 float xlogo_pos[3] = {sin(beam_angle_rad), 0, cos(beam_angle_rad)};
207 glTranslatef(xlogo_pos[0] * xlogo_dist, xlogo_pos[1] * xlogo_dist + BEAM_HEIGHT, xlogo_pos[2] * xlogo_dist);
208 xlogo(XLOGO_RAD, color, paper_color, xlogo_alpha, xcircle);
213 glRotatef(beam_angle, 0, 1, 0);
232 float beam_alpha = 1.0 - paper;
233 if(beam_alpha <= 0.0f) return;
235 glPushAttrib(GL_ENABLE_BIT);
236 glDisable(GL_CULL_FACE);
240 glTranslatef(0, BEAM_HEIGHT, 0.2);
241 bind_program(sdr_beam);
242 set_uniform_float(sdr_beam, "beam_len", beam_len);
245 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
248 for(int i=0; i<BEAM_SHELLS; i++) {
249 float t = (float)i / (float)(BEAM_SHELLS - 1);
250 float rad = BEAM_RMIN + (BEAM_RMAX - BEAM_RMIN) * t;
252 float alpha = BEAM_ENERGY / (t * t);
255 glColor4f(beam_color[0], beam_color[1], beam_color[2], alpha * beam_alpha);
257 glutSolidCylinder(rad, beam_len, 12, 1);
269 static void paper_light()
271 glPushAttrib(GL_ENABLE_BIT);
272 glDisable(GL_CULL_FACE);
275 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
278 glRotatef(beam_angle, 0, 1, 0);
279 glTranslatef(0, BEAM_HEIGHT, 0.3);
281 float rad = BEAM_RMIN + (BEAM_RMAX - BEAM_RMIN) * 0.6f;
282 float maxdist = beam_len - 0.6f;
283 float end_rad = XLOGO_RAD * 0.4;
287 glColor4f(ink_color[0], ink_color[1], ink_color[2], paper);
289 glVertex3f(0, rad, 0);
290 glVertex3f(0, end_rad, maxdist);
291 glVertex3f(0, -rad, 0);
292 glVertex3f(0, -end_rad, maxdist);
299 static void backdrop(float alpha)
301 glPushAttrib(GL_ENABLE_BIT);
303 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
306 bind_program(sdr_sky);
307 set_uniform_float(sdr_sky, "alpha", alpha);
308 glutSolidSphere(200, 16, 32);
317 static const char *help_lines[] = {
319 " LMB drag ....... rotate",
320 " MMB drag ....... pan",
321 " RMB drag/wheel . zoom",
322 " c .............. toggle free/animated camera",
323 " v .............. print current view parameters",
325 " <space> ........ pause time",
326 " <backspace> .... restart time",
327 " +/- ............ change beam rotation speed and set keyframe",
328 " 0 .............. clear beam rotation keyframes",
329 " [/] ............ change beam length and set keyframe",
330 " \\ .............. clear beam length keyframes",
331 " <enter> ........ record automatic beam stop transition",
332 " K .............. set camera keyframe",
333 " <shift>-L ...... clear all camera keyframes",
334 " X/Z ............ toggle X logo/circle and set keyframe",
335 " <shift>-X/Z .... clear logo/circle keyframes",
336 " P .............. toggle paper",
337 " <shift>-P ...... clear paper keyframes",
338 " ~ .............. dump all animation keyframes to seq_dump",
340 " F5 ............. toggle UI",
344 glPushAttrib(GL_ENABLE_BIT);
345 glDisable(GL_DEPTH_TEST);
347 glMatrixMode(GL_MODELVIEW);
350 glMatrixMode(GL_PROJECTION);
353 glOrtho(0, win_width, win_height, 0, -1, 1);
356 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
358 glColor4f(0, 0, 0, 0.5);
360 glVertex2f(0, win_height);
361 glVertex2f(win_width, win_height);
362 glVertex2f(win_width, 0);
368 for(int i=0; help_lines[i]; i++) {
369 glColor3f(0.05, 0.05, 0.05);
370 glRasterPos2i(xpos + 1, ypos + 2);
371 const char *s = help_lines[i];
373 glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++);
375 glColor3f(0.7, 1, 0.6);
376 glRasterPos2i(xpos, ypos);
379 glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++);
386 glMatrixMode(GL_MODELVIEW);
397 static void reshape(int x, int y)
401 glViewport(0, 0, x, y);
403 glMatrixMode(GL_PROJECTION);
406 gluPerspective(50, (float)x / (float)y, 0.5, 500);
409 static void keyboard(unsigned char c, int x, int y)
412 static Camera orig_cam;
413 long anim_time = anim_stopped ? anim_stop_time - start_time : tmsec;
420 start_time = glutGet(GLUT_ELAPSED_TIME);
422 anim_stop_time = anim_stopped ? start_time : 0;
428 long msec = glutGet(GLUT_ELAPSED_TIME);
429 start_time += msec - anim_stop_time;
430 prev_tmsec = msec - start_time;
432 anim_stopped = false;
434 anim_stop_time = glutGet(GLUT_ELAPSED_TIME);
440 beam_speed = get_seq_value("beam-speed", anim_time);
441 set_seq_value("beam-speed", anim_time, beam_speed + 0.1);
445 beam_speed = get_seq_value("beam-speed", anim_time) - 0.1;
446 if(beam_speed < 0) beam_speed = 0;
447 set_seq_value("beam-speed", anim_time, beam_speed);
451 clear_seq_track("beam-speed");
455 beam_len = get_seq_value("beam-len", anim_time) - 0.5;
456 if(beam_len < 0) beam_len = 0;
457 set_seq_value("beam-len", anim_time, beam_len);
461 beam_len = get_seq_value("beam-len", anim_time);
462 set_seq_value("beam-len", anim_time, beam_len + 0.5);
466 clear_seq_track("beam-len");
471 idx = find_seq_track("beam-speed");
473 set_seq_value(idx, anim_time, beam_speed);
474 set_seq_value(idx, anim_time + 2000, 0);
479 printf("camera mode: %s\n", freecam ? "free" : "animated");
488 printf("current view\n");
489 printf(" pos: %f %f %f\n", cam.x, cam.y, cam.z);
490 printf(" theta: %f, phi: %f\n", cam.theta, cam.phi);
491 printf(" dist: %f\n", cam.dist);
495 printf("clearing camera keyframes\n");
496 clear_seq_track("cam-x");
497 clear_seq_track("cam-y");
498 clear_seq_track("cam-z");
499 clear_seq_track("cam-theta");
500 clear_seq_track("cam-phi");
501 clear_seq_track("cam-dist");
505 printf("setting camera keyframe for time: %ld\n", anim_time);
506 set_seq_value("cam-x", anim_time, cam.x);
507 set_seq_value("cam-y", anim_time, cam.y);
508 set_seq_value("cam-z", anim_time, cam.z);
509 set_seq_value("cam-theta", anim_time, cam.theta);
510 set_seq_value("cam-phi", anim_time, cam.phi);
511 set_seq_value("cam-dist", anim_time, cam.dist);
515 set_seq_value("xlogo", anim_time, xlogo_alpha < 0.5 ? 1.0 : 0.0);
519 printf("clearing logo keyframes\n");
520 clear_seq_track("xlogo");
524 set_seq_value("xcircle", anim_time, xcircle < 0.5 ? 1.0 : 0.0);
528 printf("clearing circle keyframes\n");
529 clear_seq_track("xcircle");
534 set_seq_value("paper", anim_time, paper < 0.5 ? 1.0 : 0.0);
538 printf("clearing paper keyframes\n");
539 clear_seq_track("paper");
543 printf("dumping animation data to: seq_dump\n");
544 if(!dump_seq("seq_dump")) {
545 fprintf(stderr, "dump failed\n");
554 static void keyb_special(int key, int x, int y)
558 show_help = !show_help;
570 static int prev_x, prev_y;
572 static void mbutton(int bn, int state, int x, int y)
574 int button = bn - GLUT_LEFT_BUTTON;
575 bool pressed = state == GLUT_DOWN;
576 bst[button] = pressed;
585 if(cam.dist < 0) cam.dist = 0;
598 static void mmotion(int x, int y)
606 if (dx == 0 && dy == 0)
610 cam.theta += dx * 0.5;
621 cam.dist += dy * 0.1;
628 float theta = cam.theta / 180.0f * M_PI;
629 float phi = cam.phi / 180.0f * M_PI;
631 float pan_u[3], pan_v[3];
633 pan_u[0] = cos(theta);
635 pan_u[2] = sin(theta);
637 pan_v[0] = sin(phi) * sin(theta);
639 pan_v[2] = -sin(phi) * cos(theta);
641 float pan_x = -dx * 0.002 * cam.dist;
642 float pan_y = dy * 0.002 * cam.dist;
644 cam.x += pan_u[0] * pan_x + pan_v[0] * pan_y;
645 cam.y += pan_u[1] * pan_x + pan_v[1] * pan_y;
646 cam.z += pan_u[2] * pan_x + pan_v[2] * pan_y;