X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fdesigner%2Fcameracontroller.cpp;h=4706ceefeeec2c742b97e4ce8cd0bc12fe571922;hb=495c54e187ddbb7514c983e1829a69d82ccad5f3;hp=fb16bb862911f00988c0c88809fd99b481f103db;hpb=e07c0d862a4d43b2585c93e79d25380d00675309;p=r2c2.git diff --git a/source/designer/cameracontroller.cpp b/source/designer/cameracontroller.cpp index fb16bb8..4706cee 100644 --- a/source/designer/cameracontroller.cpp +++ b/source/designer/cameracontroller.cpp @@ -1,58 +1,162 @@ /* $Id$ -This file is part of the MSP Märklin suite -Copyright © 2010 Mikkosoft Productions, Mikko Rasa +This file is part of R²C² +Copyright © 2010-2011 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ #include #include +#include "3d/layout.h" #include "cameracontroller.h" using namespace std; using namespace Msp; +using namespace R2C2; -CameraController::CameraController(Graphics::Window &w, GL::Camera &c): - window(w), - camera(c), +CameraController::CameraController(View3D &v, Graphics::EventSource &es): + view(v), + event_source(es), + camera(view.get_camera()), move_x(0), move_y(0), - zoom(0), - rotate(0), - pitch(0) + drag_mode(NONE) { - window.signal_key_press.connect(sigc::mem_fun(this, &CameraController::key_press)); - window.signal_key_release.connect(sigc::mem_fun(this, &CameraController::key_release)); + event_source.signal_button_press.connect(sigc::mem_fun(this, &CameraController::button_press)); + event_source.signal_button_release.connect(sigc::mem_fun(this, &CameraController::button_release)); + event_source.signal_pointer_motion.connect(sigc::mem_fun(this, &CameraController::pointer_motion)); + event_source.signal_key_press.connect(sigc::mem_fun(this, &CameraController::key_press)); + event_source.signal_key_release.connect(sigc::mem_fun(this, &CameraController::key_release)); } -void CameraController::tick(float dt) +void CameraController::top_down() +{ + const GL::Vector3 &look = camera.get_look_direction(); + float xy_len = sqrt(look.x*look.x+look.y*look.y); + set_look_direction(GL::Vector3(look.x*0.01/xy_len, look.y*0.01/xy_len, -0.99995)); +} + +void CameraController::set_look_direction(const GL::Vector3 &look) +{ + GL::Vector3 focus = get_focus(); + float dist = get_distance(); + camera.set_look_direction(look); + camera.set_position(GL::Vector3(focus.x-look.x*dist, focus.y-look.y*dist, focus.z-look.z*dist)); +} + +void CameraController::view_all() +{ + view.view_all(); +} + +void CameraController::move(float x, float y) +{ + const GL::Vector3 &pos = camera.get_position(); + const GL::Vector3 &look = camera.get_look_direction(); + float xy_len = sqrt(look.x*look.x+look.y*look.y); + float dx = (look.x*y+look.y*x)/xy_len; + float dy = (look.y*y-look.x*x)/xy_len; + camera.set_position(GL::Vector3(pos.x+dx, pos.y+dy, pos.z)); +} + +void CameraController::adjust_distance(float delta) { - if(!move_x && !move_y && !zoom && !rotate && !pitch) - return; + const GL::Vector3 &pos = camera.get_position(); + const GL::Vector3 &look = camera.get_look_direction(); + float dist = get_distance(); + float low = view.get_layout().get_layout().get_catalogue().get_gauge()*5; + if(dist+delta-0.01) + set_look_direction(GL::Vector3(look.x*0.99995/xy_len, look.y*0.99995/xy_len, -0.01)); + else + { + float xy_scale = (xy_len*c-look.z*s)/xy_len; + set_look_direction(GL::Vector3(look.x*xy_scale, look.y*xy_scale, xy_len*s+look.z*c)); + } +} + +void CameraController::tick(float dt) +{ + if(move_x || move_y) + { + float scale = get_view_scale()*dt; + move(move_x*scale, move_y*scale); + } +} - if(rotate || pitch) +void CameraController::button_press(int x, int y, unsigned btn, unsigned mod) +{ + mod = Input::mod_from_sys(mod); + if(btn==2 || btn==3) + { + if(mod&Input::MOD_CONTROL) + drag_mode = DISTANCE; + else + drag_mode = ((btn==2)==((mod&Input::MOD_SHIFT)!=0) ? ROTATE : PAN); + + pointer_x = x; + pointer_y = y; + } + else if(btn==4) { - 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); + adjust_distance(-get_distance()*0.1); } + else if(btn==5) + { + adjust_distance(get_distance()*0.1); + } +} - if(move_x || move_y || zoom) +void CameraController::button_release(int, int, unsigned btn, unsigned) +{ + if(btn==2 || btn==3) + drag_mode = NONE; +} + +void CameraController::pointer_motion(int x, int y) +{ + if(drag_mode!=NONE) { - 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); + int dx = x-pointer_x; + int dy = y-pointer_y; + + if(drag_mode==PAN) + { + float scale = get_view_scale()/event_source.get_height(); + move(-dx*scale, dy*scale); + } + else if(drag_mode==ROTATE) + { + rotate(-dx*M_PI*2/event_source.get_width()); + pitch(-dy*M_PI/event_source.get_height()); + } + else if(drag_mode==DISTANCE) + adjust_distance(dy*3*get_distance()/event_source.get_height()); + + pointer_x = x; + pointer_y = y; } } @@ -61,25 +165,17 @@ 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; + move_x = 1; else if(key==Msp::Input::KEY_LEFT) - rotate = 1; + move_x = -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; + view_all(); + else if(key==Msp::Input::KEY_INSERT) + top_down(); } void CameraController::key_release(unsigned code, unsigned) @@ -87,13 +183,26 @@ 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; + move_x = 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; +} + +GL::Vector3 CameraController::get_focus() const +{ + const GL::Vector3 &pos = camera.get_position(); + const GL::Vector3 &look = camera.get_look_direction(); + float dist = get_distance(); + return GL::Vector3(pos.x+look.x*dist, pos.y+look.y*dist, pos.z+look.z*dist); +} + +float CameraController::get_distance() const +{ + return -camera.get_position().z/camera.get_look_direction().z; +} + +float CameraController::get_view_scale() const +{ + float t = tan(camera.get_field_of_view()/2)*2; + return get_distance()*t; }