]> git.tdb.fi Git - r2c2.git/blob - source/designer/cameracontroller.cpp
Strip Id tags and copyright notices from files
[r2c2.git] / source / designer / cameracontroller.cpp
1 #include <cmath>
2 #include <msp/input/keys.h>
3 #include "3d/layout.h"
4 #include "cameracontroller.h"
5
6 using namespace std;
7 using namespace Msp;
8 using namespace R2C2;
9
10 CameraController::CameraController(View3D &v, Graphics::EventSource &es):
11         view(v),
12         event_source(es),
13         camera(view.get_camera()),
14         move_x(0),
15         move_y(0),
16         drag_mode(NONE)
17 {
18         event_source.signal_button_press.connect(sigc::mem_fun(this, &CameraController::button_press));
19         event_source.signal_button_release.connect(sigc::mem_fun(this, &CameraController::button_release));
20         event_source.signal_pointer_motion.connect(sigc::mem_fun(this, &CameraController::pointer_motion));
21         event_source.signal_key_press.connect(sigc::mem_fun(this, &CameraController::key_press));
22         event_source.signal_key_release.connect(sigc::mem_fun(this, &CameraController::key_release));
23 }
24
25 void CameraController::top_down()
26 {
27         const GL::Vector3 &look = camera.get_look_direction();
28         float xy_len = sqrt(look.x*look.x+look.y*look.y);
29         set_look_direction(GL::Vector3(look.x*0.01/xy_len, look.y*0.01/xy_len, -0.99995));
30 }
31
32 void CameraController::set_look_direction(const GL::Vector3 &look)
33 {
34         GL::Vector3 focus = get_focus();
35         float dist = get_distance();
36         camera.set_look_direction(look);
37         camera.set_position(GL::Vector3(focus.x-look.x*dist, focus.y-look.y*dist, focus.z-look.z*dist));
38 }
39
40 void CameraController::view_all()
41 {
42         view.view_all();
43 }
44
45 void CameraController::move(float x, float y)
46 {
47         const GL::Vector3 &pos = camera.get_position();
48         const GL::Vector3 &look = camera.get_look_direction();
49         float xy_len = sqrt(look.x*look.x+look.y*look.y);
50         float dx = (look.x*y+look.y*x)/xy_len;
51         float dy = (look.y*y-look.x*x)/xy_len;
52         camera.set_position(GL::Vector3(pos.x+dx, pos.y+dy, pos.z));
53 }
54
55 void CameraController::adjust_distance(float delta)
56 {
57         const GL::Vector3 &pos = camera.get_position();
58         const GL::Vector3 &look = camera.get_look_direction();
59         float dist = get_distance();
60         float low = view.get_layout().get_layout().get_catalogue().get_gauge()*5;
61         if(dist+delta<low)
62                 delta = low-dist;
63         camera.set_position(GL::Vector3(pos.x-look.x*delta, pos.y-look.y*delta, pos.z-look.z*delta));
64         dist += delta;
65         camera.set_depth_clip(dist*0.02, dist*50);
66 }
67
68 void CameraController::rotate(float angle)
69 {
70         GL::Vector3 look = camera.get_look_direction();
71         float c = cos(angle);
72         float s = sin(angle);
73         set_look_direction(GL::Vector3(look.x*c-look.y*s, look.x*s+look.y*c, look.z));
74 }
75
76 void CameraController::pitch(float angle)
77 {
78         GL::Vector3 look = camera.get_look_direction();
79         float xy_len = sqrt(look.x*look.x+look.y*look.y);
80         float c = cos(angle);
81         float s = sin(angle);
82         if(xy_len*c-look.z*s<0.01)
83                 top_down();
84         else if(xy_len*s+look.z*c>-0.01)
85                 set_look_direction(GL::Vector3(look.x*0.99995/xy_len, look.y*0.99995/xy_len, -0.01));
86         else
87         {
88                 float xy_scale = (xy_len*c-look.z*s)/xy_len;
89                 set_look_direction(GL::Vector3(look.x*xy_scale, look.y*xy_scale, xy_len*s+look.z*c));
90         }
91 }
92
93 void CameraController::tick(float dt)
94 {
95         if(move_x || move_y)
96         {
97                 float scale = get_view_scale()*dt;
98                 move(move_x*scale, move_y*scale);
99         }
100 }
101
102 void CameraController::button_press(int x, int y, unsigned btn, unsigned mod)
103 {
104         mod = Input::mod_from_sys(mod);
105         if(btn==2 || btn==3)
106         {
107                 if(mod&Input::MOD_CONTROL)
108                         drag_mode = DISTANCE;
109                 else
110                         drag_mode = ((btn==2)==((mod&Input::MOD_SHIFT)!=0) ? ROTATE : PAN);
111
112                 pointer_x = x;
113                 pointer_y = y;
114         }
115         else if(btn==4)
116         {
117                 adjust_distance(-get_distance()*0.1);
118         }
119         else if(btn==5)
120         {
121                 adjust_distance(get_distance()*0.1);
122         }
123 }
124
125 void CameraController::button_release(int, int, unsigned btn, unsigned)
126 {
127         if(btn==2 || btn==3)
128                 drag_mode = NONE;
129 }
130
131 void CameraController::pointer_motion(int x, int y)
132 {
133         if(drag_mode!=NONE)
134         {
135                 int dx = x-pointer_x;
136                 int dy = y-pointer_y;
137
138                 if(drag_mode==PAN)
139                 {
140                         float scale = get_view_scale()/event_source.get_height();
141                         move(-dx*scale, dy*scale);
142                 }
143                 else if(drag_mode==ROTATE)
144                 {
145                         rotate(-dx*M_PI*2/event_source.get_width());
146                         pitch(-dy*M_PI/event_source.get_height());
147                 }
148                 else if(drag_mode==DISTANCE)
149                         adjust_distance(dy*3*get_distance()/event_source.get_height());
150
151                 pointer_x = x;
152                 pointer_y = y;
153         }
154 }
155
156 void CameraController::key_press(unsigned code, unsigned, wchar_t)
157 {
158         unsigned key = Msp::Input::key_from_sys(code);
159
160         if(key==Msp::Input::KEY_RIGHT)
161                 move_x = 1;
162         else if(key==Msp::Input::KEY_LEFT)
163                 move_x = -1;
164         else if(key==Msp::Input::KEY_UP)
165                 move_y = 1;
166         else if(key==Msp::Input::KEY_DOWN)
167                 move_y = -1;
168         else if(key==Msp::Input::KEY_HOME)
169                 view_all();
170         else if(key==Msp::Input::KEY_INSERT)
171                 top_down();
172 }
173
174 void CameraController::key_release(unsigned code, unsigned)
175 {
176         unsigned key = Msp::Input::key_from_sys(code);
177
178         if(key==Msp::Input::KEY_RIGHT || key==Msp::Input::KEY_LEFT)
179                 move_x = 0;
180         else if(key==Msp::Input::KEY_UP || key==Msp::Input::KEY_DOWN)
181                 move_y = 0;
182 }
183
184 GL::Vector3 CameraController::get_focus() const
185 {
186         const GL::Vector3 &pos = camera.get_position();
187         const GL::Vector3 &look = camera.get_look_direction();
188         float dist = get_distance();
189         return GL::Vector3(pos.x+look.x*dist, pos.y+look.y*dist, pos.z+look.z*dist);
190 }
191
192 float CameraController::get_distance() const
193 {
194         return -camera.get_position().z/camera.get_look_direction().z;
195 }
196
197 float CameraController::get_view_scale() const
198 {
199         float t = tan(camera.get_field_of_view()/2)*2;
200         return get_distance()*t;
201 }