3 This file is part of the MSP Märklin suite
4 Copyright © 2010 Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
9 #include <msp/input/keys.h>
10 #include "cameracontroller.h"
15 using namespace Marklin;
17 CameraController::CameraController(Designer &d, Graphics::EventSource &es, GL::Camera &c):
25 event_source.signal_button_press.connect(sigc::mem_fun(this, &CameraController::button_press));
26 event_source.signal_button_release.connect(sigc::mem_fun(this, &CameraController::button_release));
27 event_source.signal_pointer_motion.connect(sigc::mem_fun(this, &CameraController::pointer_motion));
28 event_source.signal_key_press.connect(sigc::mem_fun(this, &CameraController::key_press));
29 event_source.signal_key_release.connect(sigc::mem_fun(this, &CameraController::key_release));
32 void CameraController::top_down()
34 const GL::Vector3 &look = camera.get_look_direction();
35 float xy_len = sqrt(look.x*look.x+look.y*look.y);
36 set_look_direction(GL::Vector3(look.x*0.01/xy_len, look.y*0.01/xy_len, -0.99995));
39 void CameraController::set_look_direction(const GL::Vector3 &look)
41 GL::Vector3 focus = get_focus();
42 float dist = get_distance();
43 camera.set_look_direction(look);
44 camera.set_position(GL::Vector3(focus.x-look.x*dist, focus.y-look.y*dist, focus.z-look.z*dist));
47 void CameraController::view_all()
52 const Layout3D::TrackMap &tracks = designer.get_layout_3d().get_tracks();
53 for(Layout3D::TrackMap::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
57 i->second->get_bounds(0, tmin, tmax);
58 minp.x = min(minp.x, tmin.x);
59 minp.y = min(minp.y, tmin.y);
60 maxp.x = max(maxp.x, tmax.x);
61 maxp.y = max(maxp.y, tmax.y);
64 float t = tan(camera.get_field_of_view()/2)*2;
65 float size = max((maxp.y-minp.y+0.1), (maxp.x-minp.x+0.1)/camera.get_aspect());
66 float dist = size/t+size*0.25;
67 GL::Vector3 center((minp.x+maxp.x)/2, (minp.y+maxp.y)/2, 0);
68 const GL::Vector3 &look = camera.get_look_direction();
69 camera.set_position(GL::Vector3(center.x-look.x*dist, center.y-look.y*dist, center.z-look.z*dist));
72 void CameraController::move(float x, float y)
74 const GL::Vector3 &pos = camera.get_position();
75 const GL::Vector3 &look = camera.get_look_direction();
76 float xy_len = sqrt(look.x*look.x+look.y*look.y);
77 float dx = (look.x*y+look.y*x)/xy_len;
78 float dy = (look.y*y-look.x*x)/xy_len;
79 camera.set_position(GL::Vector3(pos.x+dx, pos.y+dy, pos.z));
82 void CameraController::adjust_distance(float delta)
84 const GL::Vector3 &pos = camera.get_position();
85 const GL::Vector3 &look = camera.get_look_direction();
86 camera.set_position(GL::Vector3(pos.x-look.x*delta, pos.y-look.y*delta, pos.z-look.z*delta));
89 void CameraController::rotate(float angle)
91 GL::Vector3 look = camera.get_look_direction();
94 set_look_direction(GL::Vector3(look.x*c-look.y*s, look.x*s+look.y*c, look.z));
97 void CameraController::pitch(float angle)
99 GL::Vector3 look = camera.get_look_direction();
100 float xy_len = sqrt(look.x*look.x+look.y*look.y);
101 float c = cos(angle);
102 float s = sin(angle);
103 if(xy_len*c-look.z*s<0.01)
105 else if(xy_len*s+look.z*c>-0.01)
106 set_look_direction(GL::Vector3(look.x*0.99995/xy_len, look.y*0.99995/xy_len, -0.01));
109 float xy_scale = (xy_len*c-look.z*s)/xy_len;
110 set_look_direction(GL::Vector3(look.x*xy_scale, look.y*xy_scale, xy_len*s+look.z*c));
114 void CameraController::tick(float dt)
118 float scale = get_view_scale()*dt;
119 move(move_x*scale, move_y*scale);
123 void CameraController::button_press(int x, int y, unsigned btn, unsigned mod)
125 mod = Input::mod_from_sys(mod);
128 if(mod&Input::MOD_CONTROL)
129 drag_mode = DISTANCE;
131 drag_mode = ((btn==2)==((mod&Input::MOD_SHIFT)!=0) ? ROTATE : PAN);
138 adjust_distance(-get_distance()*0.1);
142 adjust_distance(get_distance()*0.1);
146 void CameraController::button_release(int, int, unsigned btn, unsigned)
152 void CameraController::pointer_motion(int x, int y)
156 int dx = x-pointer_x;
157 int dy = y-pointer_y;
161 float scale = get_view_scale()/event_source.get_height();
162 move(-dx*scale, dy*scale);
164 else if(drag_mode==ROTATE)
166 rotate(-dx*M_PI*2/event_source.get_width());
167 pitch(-dy*M_PI/event_source.get_height());
169 else if(drag_mode==DISTANCE)
170 adjust_distance(dy*3*get_distance()/event_source.get_height());
177 void CameraController::key_press(unsigned code, unsigned, wchar_t)
179 unsigned key = Msp::Input::key_from_sys(code);
181 if(key==Msp::Input::KEY_RIGHT)
183 else if(key==Msp::Input::KEY_LEFT)
185 else if(key==Msp::Input::KEY_UP)
187 else if(key==Msp::Input::KEY_DOWN)
189 else if(key==Msp::Input::KEY_HOME)
191 else if(key==Msp::Input::KEY_INSERT)
195 void CameraController::key_release(unsigned code, unsigned)
197 unsigned key = Msp::Input::key_from_sys(code);
199 if(key==Msp::Input::KEY_RIGHT || key==Msp::Input::KEY_LEFT)
201 else if(key==Msp::Input::KEY_UP || key==Msp::Input::KEY_DOWN)
205 GL::Vector3 CameraController::get_focus() const
207 const GL::Vector3 &pos = camera.get_position();
208 const GL::Vector3 &look = camera.get_look_direction();
209 float dist = get_distance();
210 return GL::Vector3(pos.x+look.x*dist, pos.y+look.y*dist, pos.z+look.z*dist);
213 float CameraController::get_distance() const
215 return -camera.get_position().z/camera.get_look_direction().z;
218 float CameraController::get_view_scale() const
220 float t = tan(camera.get_field_of_view()/2)*2;
221 return get_distance()*t;