static void camOrbit(int dx, int dy) { const double radius = 200; double dist; Vec3 v = cam_position; Quaternion o = cam_orientation; Quaternion q, q2; /* We invert the transformation because we are transforming the camera * and not the scene. */ q = quat_conjugate(quat_trackball(dx, dy, radius)); /* The quaternion q gives us an intrinsic transformation, close to unity. * To make it extrinsic, we compute q2 = o * q * ~o */ q2 = quat_multiply(o, quat_multiply(q, quat_conjugate(o))); q2 = quat_normalize(q2); /* As round-off errors accumulate, the distance between the camera and the * target would normally fluctuate. We take steps to prevent that here. */ dist = vec3_length(v); v = quat_transform(q2, v); v = vec3_normalize(v); v = vec3_scale(v, dist); cam_position = v; cam_orientation = quat_multiply(q2, cam_orientation); }
Vec3 kepler_position_at_E(KeplerOrbit *orbit, double E) { double e = orbit->Ecc; double a = orbit->SMa, b = a * sqrt(1 - e*e); Vec3 plane_pos; plane_pos.x = a * (cos(E) - e); plane_pos.y = b * sin(E); plane_pos.z = 0; return quat_transform(orbit->plane_orientation, plane_pos); }
Vec3 kepler_position_at_true_anomaly(KeplerOrbit *orbit, double theta) { double e = orbit->Ecc; double p = orbit->SMa * (1-e*e); Vec3 plane_pos; plane_pos.x = p / (1 + e*cos(theta)) * cos(theta); plane_pos.y = p / (1 + e*cos(theta)) * sin(theta); plane_pos.z = 0; return quat_transform(orbit->plane_orientation, plane_pos); }
bool handle_input(ALLEGRO_EVENT_QUEUE *ev_queue, Camera *cam) { ALLEGRO_EVENT ev; ALLEGRO_MOUSE_STATE state; while (al_get_next_event(ev_queue, &ev)) { switch (ev.type) { case ALLEGRO_EVENT_DISPLAY_CLOSE: return false; break; case ALLEGRO_EVENT_MOUSE_BUTTON_UP: //al_show_mouse_cursor(dpy); //al_ungrab_mouse(); break; case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: //al_hide_mouse_cursor(dpy); //al_grab_mouse(dpy); break; case ALLEGRO_EVENT_MOUSE_AXES: if (ev.mouse.dz != 0) cam_dolly(cam, ev.mouse.dz); al_get_mouse_state(&state); /* The y coordinate needs to be inverted because OpenGL has * the origin in the lower-left and Allegro the upper-left */ if (state.buttons & 1) cam_orbit(cam, ev.mouse.dx, -ev.mouse.dy); else if (state.buttons & 2) cam_rotate(cam, ev.mouse.dx, -ev.mouse.dy); break; case ALLEGRO_EVENT_KEY_CHAR: if (ev.keyboard.unichar == 'w') { wireframe = !wireframe; if (wireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_CULL_FACE); } else { glPolygonMode(GL_FRONT, GL_FILL); glEnable(GL_CULL_FACE); } } else if (ev.keyboard.unichar == 'c') { Vec3 upv = quat_transform(cam->orientation, (Vec3){0, 1, 0}); cam_lookat(cam, cam->position, cam->target, upv); } break; case ALLEGRO_EVENT_DISPLAY_RESIZE: cam->width = ev.display.width; cam->height = ev.display.height; glmLoadIdentity(glmProjectionMatrix); cam_projection_matrix(cam, glmProjectionMatrix); glViewport(cam->left, cam->bottom, cam->width, cam->height); default: break; } } return true; }