From ecac8b143152200476c48724a2032b85b25401fa Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 7 Oct 2018 07:52:20 +0300 Subject: [PATCH] xlogo, more animation controls, help screen with F1. --- src/geom.cc | 20 ++++ src/main.cc | 316 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 301 insertions(+), 35 deletions(-) diff --git a/src/geom.cc b/src/geom.cc index 804c18f..a0d99cf 100644 --- a/src/geom.cc +++ b/src/geom.cc @@ -114,4 +114,24 @@ void ground() void xlogo() { + static const float xlogo_varr[] = { + -0.500, 0.407, -0.113, -0.109, 0.059, -0.006, -0.251, 0.407, + -0.113, -0.109, -0.499, -0.593, -0.410, -0.593, 0.059, -0.006, + -0.058, -0.182, 0.251, -0.593, 0.500, -0.593, 0.114, -0.079, + -0.058, -0.182, 0.114, -0.079, 0.500, 0.407, 0.411, 0.407 + }; + + glPushAttrib(GL_ENABLE_BIT); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glBegin(GL_QUADS); + const float *vptr = xlogo_varr; + for(int i=0; i<(int)(sizeof xlogo_varr / sizeof *xlogo_varr) / 2; i++) { + glVertex2fv(vptr); + vptr += 2; + } + glEnd(); + + glPopAttrib(); } diff --git a/src/main.cc b/src/main.cc index fcf4995..ce85a59 100644 --- a/src/main.cc +++ b/src/main.cc @@ -3,6 +3,7 @@ #include #include +#include #include #include "sdr.h" @@ -12,24 +13,35 @@ #define BEAM_SHELLS 40 #define BEAM_RMIN 0.01 #define BEAM_RMAX 0.125 -#define BEAM_ENERGY 0.02 +#define BEAM_ENERGY 0.01 #define BEAM_LEN 16.0 #define BEAM_DEF_SPEED 0.1 +struct Camera { + float x, y, z; + float theta, phi; + float dist; +}; + static bool init(); static void cleanup(); static void display(); static void light(); static void backdrop(); +static void help(); static void idle(); static void reshape(int x, int y); static void keyboard(unsigned char c, int x, int y); +static void keyb_special(int key, int x, int y); static void mbutton(int bn, int state, int x, int y); static void mmotion(int x, int y); -static float cam_theta = 45, cam_phi, cam_dist = 10; +static int win_width, win_height; +static bool freecam = true; + +static Camera cam = {0, 0, 0, 0, 0, 10}; static unsigned int sdr_beam, sdr_sky; static long start_time; static long anim_stop_time; @@ -39,6 +51,10 @@ static const float sil_color[] = {0.05, 0.02, 0.1, 1.0}; static const float beam_color[] = {0.5, 0.4, 0.2, 1.0}; static float beam_angle, beam_speed; +static float beam_len; +static float xlogo_alpha; + +static bool show_help; int main(int argc, char **argv) { @@ -46,12 +62,13 @@ int main(int argc, char **argv) glutInitWindowSize(800, 600); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); - glutCreateWindow("Faros"); + glutCreateWindow("Faros (press F1 for controls help)"); glutDisplayFunc(display); glutIdleFunc(idle); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); + glutSpecialFunc(keyb_special); glutMouseFunc(mbutton); glutMotionFunc(mmotion); @@ -92,6 +109,14 @@ static bool init() return false; } add_seq_track("beam-speed", INTERP_SIGMOID, EXTRAP_CLAMP, BEAM_DEF_SPEED); + add_seq_track("beam-len", INTERP_SIGMOID, EXTRAP_CLAMP, BEAM_LEN); + add_seq_track("cam-dist", INTERP_SIGMOID, EXTRAP_CLAMP, 10); + add_seq_track("cam-phi", INTERP_SIGMOID, EXTRAP_CLAMP, 0); + add_seq_track("cam-theta", INTERP_SIGMOID, EXTRAP_CLAMP, 0); + add_seq_track("cam-x", INTERP_SIGMOID, EXTRAP_CLAMP, 0); + add_seq_track("cam-y", INTERP_SIGMOID, EXTRAP_CLAMP, 0); + add_seq_track("cam-z", INTERP_SIGMOID, EXTRAP_CLAMP, 0); + add_seq_track("xlogo", INTERP_SIGMOID, EXTRAP_CLAMP, 0); load_seq("seq"); start_time = glutGet(GLUT_ELAPSED_TIME); @@ -121,23 +146,49 @@ static void display() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glTranslatef(0, -2, -cam_dist); - glRotatef(cam_phi, 1, 0, 0); - glRotatef(cam_theta, 0, 1, 0); + if(!freecam) { + cam.dist = get_seq_value("cam-dist", tmsec); + cam.phi = get_seq_value("cam-phi", tmsec); + cam.theta = get_seq_value("cam-theta", tmsec); + cam.x = get_seq_value("cam-x", tmsec); + cam.y = get_seq_value("cam-y", tmsec); + cam.z = get_seq_value("cam-z", tmsec); + } + + glTranslatef(0, -2, -cam.dist); + glRotatef(cam.phi, 1, 0, 0); + glRotatef(cam.theta, 0, 1, 0); + glTranslatef(-cam.x, -cam.y, -cam.z); glColor3fv(sil_color); ground(); faros(); - glPushMatrix(); - + beam_len = get_seq_value("beam-len", tmsec); beam_speed = get_seq_value("beam-speed", tmsec); beam_angle += beam_speed * 360.0f * dt; + + xlogo_alpha = get_seq_value("xlogo", tmsec); + if(xlogo_alpha > 0.0) { + glPushMatrix(); + float beam_angle_rad = beam_angle / 180.0 * M_PI; + float xlogo_dist = beam_len; + float xlogo_pos[3] = {sin(beam_angle_rad), 0, cos(beam_angle_rad)}; + glTranslatef(xlogo_pos[0] * xlogo_dist, xlogo_pos[1] * xlogo_dist + 5, xlogo_pos[2] * xlogo_dist); + glColor4f(0, 0, 0, xlogo_alpha); + xlogo(); + glPopMatrix(); + } + + glPushMatrix(); glRotatef(beam_angle, 0, 1, 0); light(); - glPopMatrix(); + if(show_help) { + help(); + } + glutSwapBuffers(); } @@ -150,21 +201,26 @@ static void light() glTranslatef(0, 4.65, 0.2); bind_program(sdr_beam); - set_uniform_float(sdr_beam, "beam_len", BEAM_LEN); + set_uniform_float(sdr_beam, "beam_len", beam_len); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDepthMask(0); for(int i=0; i ........ pause time", + " .... restart time", + " +/- ............ change beam rotation speed and set keyframe", + " 0 .............. clear beam rotation keyframes", + " [/] ............ change beam length and set keyframe", + " \\ .............. clear beam length keyframes", + " ........ record automatic beam start/stop transition", + " K .............. set camera keyframe", + " -L ...... clear all camera keyframes", + " X .............. toggle X logo and set keyframe", + " -X ...... clear logo keyframes", + " ~ .............. dump all animation keyframes to seq_dump", + 0 + }; + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, win_width, win_height, 0, -1, 1); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBegin(GL_QUADS); + glColor4f(0, 0, 0, 0.5); + glVertex2f(0, 0); + glVertex2f(0, win_height); + glVertex2f(win_width, win_height); + glVertex2f(win_width, 0); + glEnd(); + glDisable(GL_BLEND); + + int xpos = 20; + int ypos = 30; + for(int i=0; help_lines[i]; i++) { + glColor3f(0.05, 0.05, 0.05); + glRasterPos2i(xpos + 1, ypos + 2); + const char *s = help_lines[i]; + while(*s) { + glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++); + } + glColor3f(0.7, 1, 0.6); + glRasterPos2i(xpos, ypos); + s = help_lines[i]; + while(*s) { + glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++); + } + + ypos += 25; + } + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glPopAttrib(); +} static void idle() { @@ -190,6 +318,8 @@ static void idle() static void reshape(int x, int y) { + win_width = x; + win_height = y; glViewport(0, 0, x, y); glMatrixMode(GL_PROJECTION); @@ -198,12 +328,12 @@ static void reshape(int x, int y) gluPerspective(50, (float)x / (float)y, 0.5, 500); } -#define ANIM_DELTA 0.5 - static void keyboard(unsigned char c, int x, int y) { int idx; static float orig_beam_speed; + static Camera orig_cam; + long anim_time = anim_stop_time ? anim_stop_time - start_time : tmsec; switch(c) { case 27: @@ -228,35 +358,97 @@ static void keyboard(unsigned char c, int x, int y) break; case '=': - beam_speed = get_seq_value("beam-speed", tmsec); - clear_seq_track("beam-speed"); - set_seq_value("beam-speed", tmsec, beam_speed + ANIM_DELTA); + beam_speed = get_seq_value("beam-speed", anim_time); + set_seq_value("beam-speed", anim_time, beam_speed + 0.1); break; case '-': - beam_speed = get_seq_value("beam-speed", tmsec) - ANIM_DELTA; - if(beam_speed < 0) - beam_speed = 0; + beam_speed = get_seq_value("beam-speed", anim_time) - 0.1; + if(beam_speed < 0) beam_speed = 0; + set_seq_value("beam-speed", anim_time, beam_speed); + break; + + case '0': clear_seq_track("beam-speed"); - set_seq_value("beam-speed", tmsec, beam_speed); + break; + + case '[': + beam_len = get_seq_value("beam-len", anim_time) - 0.5; + if(beam_len < 0) beam_len = 0; + set_seq_value("beam-len", anim_time, beam_len); + break; + + case ']': + beam_len = get_seq_value("beam-len", anim_time); + set_seq_value("beam-len", anim_time, beam_len + 0.5); + break; + + case '\\': + clear_seq_track("beam-len"); break; case '\r': case '\n': idx = find_seq_track("beam-speed"); assert(idx >= 0); - if(get_seq_value(idx, tmsec) > 0.0) { + if(get_seq_value(idx, anim_time) > 0.0) { clear_seq_track(idx); - set_seq_value(idx, tmsec, beam_speed); - set_seq_value(idx, tmsec + 3000, 0); + set_seq_value(idx, anim_time, beam_speed); + set_seq_value(idx, anim_time + 3000, 0); orig_beam_speed = beam_speed; } else { clear_seq_track(idx); - set_seq_value(idx, tmsec, 0); - set_seq_value(idx, tmsec + 3000, orig_beam_speed); + set_seq_value(idx, anim_time, 0); + set_seq_value(idx, anim_time + 3000, orig_beam_speed); } break; + case 'c': + freecam = !freecam; + printf("camera mode: %s\n", freecam ? "free" : "animated"); + if(!freecam) { + orig_cam = cam; + } else { + cam = orig_cam; + } + break; + + case 'v': + printf("current view\n"); + printf(" pos: %f %f %f\n", cam.x, cam.y, cam.z); + printf(" theta: %f, phi: %f\n", cam.theta, cam.phi); + printf(" dist: %f\n", cam.dist); + break; + + case 'L': + printf("clearing camera keyframes\n"); + clear_seq_track("cam-x"); + clear_seq_track("cam-y"); + clear_seq_track("cam-z"); + clear_seq_track("cam-theta"); + clear_seq_track("cam-phi"); + clear_seq_track("cam-dist"); + break; + + case 'k': + printf("setting camera keyframe for time: %ld\n", anim_time); + set_seq_value("cam-x", anim_time, cam.x); + set_seq_value("cam-y", anim_time, cam.y); + set_seq_value("cam-z", anim_time, cam.z); + set_seq_value("cam-theta", anim_time, cam.theta); + set_seq_value("cam-phi", anim_time, cam.phi); + set_seq_value("cam-dist", anim_time, cam.dist); + break; + + case 'x': + set_seq_value("xlogo", anim_time, xlogo_alpha < 0.5 ? 1.0 : 0.0); + break; + + case 'X': + printf("clearing logo keyframes\n"); + clear_seq_track("xlogo"); + break; + case '`': printf("dumping animation data to: seq_dump\n"); if(!dump_seq("seq_dump")) { @@ -269,15 +461,44 @@ static void keyboard(unsigned char c, int x, int y) } } +static void keyb_special(int key, int x, int y) +{ + switch(key) { + case GLUT_KEY_F1: + show_help = !show_help; + break; + + default: + break; + } +} + static int prev_x, prev_y; static bool bst[8]; static void mbutton(int bn, int state, int x, int y) { int button = bn - GLUT_LEFT_BUTTON; - bst[button] = state == GLUT_DOWN; + bool pressed = state == GLUT_DOWN; + bst[button] = pressed; prev_x = x; prev_y = y; + + if(pressed) { + switch(bn) { + case 3: + cam.dist -= 0.5; + if(cam.dist < 0) cam.dist = 0; + break; + + case 4: + cam.dist += 0.5; + break; + + default: + break; + } + } } static void mmotion(int x, int y) @@ -292,20 +513,45 @@ static void mmotion(int x, int y) return; if (bst[0]) { - cam_theta += dx * 0.5; - cam_phi += dy * 0.5; + cam.theta += dx * 0.5; + cam.phi += dy * 0.5; + + cam.theta = fmod(cam.theta, 360.0f); + if(cam.theta < 0.0f) cam.theta += 360.0f; - if (cam_phi < -90) - cam_phi = -90; + if (cam.phi < -90) + cam.phi = -90; - if (cam_phi > 90) - cam_phi = 90; + if (cam.phi > 90) + cam.phi = 90; } if (bst[2]) { - cam_dist += dy * 0.1; + cam.dist += dy * 0.1; + + if (cam.dist < 0) + cam.dist = 0; + } + + if(bst[1]) { + float theta = cam.theta / 180.0f * M_PI; + float phi = cam.phi / 180.0f * M_PI; + + float pan_u[3], pan_v[3]; + + pan_u[0] = cos(theta); + pan_u[1] = 0; + pan_u[2] = sin(theta); + + pan_v[0] = sin(phi) * sin(theta); + pan_v[1] = cos(phi); + pan_v[2] = -sin(phi) * cos(theta); + + float pan_x = -dx * 0.002 * cam.dist; + float pan_y = dy * 0.002 * cam.dist; - if (cam_dist < 0) - cam_dist = 0; + cam.x += pan_u[0] * pan_x + pan_v[0] * pan_y; + cam.y += pan_u[1] * pan_x + pan_v[1] * pan_y; + cam.z += pan_u[2] * pan_x + pan_v[2] * pan_y; } } -- 1.7.10.4