+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <cmath>
+#include <msp/input/keys.h>
+#include "cameracontroller.h"
+
+using namespace std;
+using namespace Msp;
+
+CameraController::CameraController(Graphics::Window &w, GL::Camera &c):
+ window(w),
+ camera(c),
+ move_x(0),
+ move_y(0),
+ zoom(0),
+ rotate(0),
+ pitch(0)
+{
+ window.signal_key_press.connect(sigc::mem_fun(this, &CameraController::key_press));
+ window.signal_key_release.connect(sigc::mem_fun(this, &CameraController::key_release));
+}
+
+void CameraController::tick(float dt)
+{
+ if(!move_x && !move_y && !zoom && !rotate && !pitch)
+ return;
+
+ GL::Vector3 pos = camera.get_position();
+ GL::Vector3 look = camera.get_look_direction();
+ float xy_len = sqrt(look.x*look.x+look.y*look.y);
+ GL::Vector3 look_xy(look.x/xy_len, look.y/xy_len, 0);
+ GL::Vector3 ground(pos.x-look.x*pos.z/look.z, pos.y-look.y*pos.z/look.z, 0);
+
+ if(rotate || pitch)
+ {
+ float speed = -3*dt*xy_len*pos.z/look.z;
+ pos.x += (look_xy.y*rotate - look_xy.x*look.z*pitch)*speed;
+ pos.y += (-look_xy.x*rotate - look_xy.y*look.z*pitch)*speed;
+ pos.z += xy_len*pitch*speed;
+ camera.set_position(pos);
+ camera.look_at(ground);
+ }
+
+ if(move_x || move_y || zoom)
+ {
+ float zoom_speed = -zoom*pos.z/look.z;
+ pos.x += (look_xy.x*move_y + look_xy.y*move_x + look.x*zoom_speed)*dt;
+ pos.y += (look_xy.y*move_y - look_xy.x*move_x + look.y*zoom_speed)*dt;
+ pos.z += look.z*dt*zoom_speed;
+ camera.set_position(pos);
+ }
+}
+
+void CameraController::key_press(unsigned code, unsigned, wchar_t)
+{
+ unsigned key = Msp::Input::key_from_sys(code);
+
+ if(key==Msp::Input::KEY_RIGHT)
+ rotate = -1;
+ else if(key==Msp::Input::KEY_LEFT)
+ rotate = 1;
+ else if(key==Msp::Input::KEY_UP)
+ move_y = 1;
+ else if(key==Msp::Input::KEY_DOWN)
+ move_y = -1;
+ else if(key==Msp::Input::KEY_INSERT)
+ zoom = -1;
+ else if(key==Msp::Input::KEY_PGUP)
+ zoom = 1;
+ else if(key==Msp::Input::KEY_HOME)
+ pitch = 1;
+ else if(key==Msp::Input::KEY_END)
+ pitch = -1;
+ else if(key==Msp::Input::KEY_DELETE)
+ move_x = -1;
+ else if(key==Msp::Input::KEY_PGDN)
+ move_x = 1;
+}
+
+void CameraController::key_release(unsigned code, unsigned)
+{
+ unsigned key = Msp::Input::key_from_sys(code);
+
+ if(key==Msp::Input::KEY_RIGHT || key==Msp::Input::KEY_LEFT)
+ rotate = 0;
+ else if(key==Msp::Input::KEY_UP || key==Msp::Input::KEY_DOWN)
+ move_y = 0;
+ else if(key==Msp::Input::KEY_INSERT || key==Msp::Input::KEY_PGUP)
+ zoom = 0;
+ else if(key==Msp::Input::KEY_HOME || key==Msp::Input::KEY_END)
+ pitch = 0;
+ else if(key==Msp::Input::KEY_DELETE || key==Msp::Input::KEY_PGDN)
+ move_x = 0;
+}