From: Mikko Rasa Date: Wed, 24 Feb 2010 21:56:28 +0000 (+0000) Subject: Use a GL::Camera X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=e07c0d862a4d43b2585c93e79d25380d00675309;p=r2c2.git Use a GL::Camera Move camera controls to a separate class --- diff --git a/source/designer/cameracontroller.cpp b/source/designer/cameracontroller.cpp new file mode 100644 index 0000000..fb16bb8 --- /dev/null +++ b/source/designer/cameracontroller.cpp @@ -0,0 +1,99 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2010 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#include +#include +#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; +} diff --git a/source/designer/cameracontroller.h b/source/designer/cameracontroller.h new file mode 100644 index 0000000..63ba2c1 --- /dev/null +++ b/source/designer/cameracontroller.h @@ -0,0 +1,34 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2010 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#ifndef CAMERACONTROLLER_H_ +#define CAMERACONTROLLER_H_ + +#include +#include + +class CameraController +{ +private: + Msp::Graphics::Window &window; + Msp::GL::Camera &camera; + int move_x; + int move_y; + int zoom; + int rotate; + int pitch; + +public: + CameraController(Msp::Graphics::Window &, Msp::GL::Camera &); + + void tick(float); +private: + void key_press(unsigned, unsigned, wchar_t); + void key_release(unsigned, unsigned); +}; + +#endif diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp index 02563f8..f79ef7a 100644 --- a/source/designer/designer.cpp +++ b/source/designer/designer.cpp @@ -9,6 +9,7 @@ Distributed under the GPL #include #include #include +#include #include #include #include @@ -46,15 +47,8 @@ Designer::Designer(int argc, char **argv): manipulator(*this, selection), measure(*this), input(0), - cam_yaw(M_PI/2), - cam_pitch(-M_PI/4), - cam_pos(0, -0.5, 0.5), - shift(false), - move_x(0), - move_y(0), - zoom(0), - rotate(0), - pitch(0) + camera_ctl(window, camera), + shift(false) { window.set_title("Railway Designer"); window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Designer::exit), 0)); @@ -98,6 +92,7 @@ Designer::Designer(int argc, char **argv): GL::enable(GL_CULL_FACE); pipeline = new GL::Pipeline(window.get_width(), window.get_height(), false); + pipeline->set_camera(&camera); pipeline->add_renderable(layout_3d->get_scene()); if(base_object) pipeline->add_renderable(*base_object); @@ -108,6 +103,9 @@ Designer::Designer(int argc, char **argv): GL::PipelinePass *pass = &pipeline->add_pass(GL::Tag()); pass->lighting = &lighting; + camera.set_up_direction(GL::Vector3(0, 0, 1)); + view_all(); + // Setup UI DataFile::load(ui_res, "marklin.res"); root = new GLtk::Root(ui_res, window); @@ -175,29 +173,14 @@ void Designer::add_selection_to_route() } } -void Designer::map_pointer_coords(int x, int y, float &gx, float &gy) +Point Designer::map_pointer_coords(int x, int y) { - float cos_pitch = cos(cam_pitch); - float sin_pitch = sin(cam_pitch); - float cos_yaw = cos(cam_yaw); - float sin_yaw = sin(cam_yaw); - - float rx = sin_yaw*0.55228; - float ry = -cos_yaw*0.55228; - - float ux = cos_yaw*-sin_pitch*0.41421; - float uy = sin_yaw*-sin_pitch*0.41421; - float uz = cos_pitch*0.41421; - - float xf = static_cast(x)*2/window.get_width()-1; - float yf = static_cast(y)*2/window.get_height()-1; + float xf = x*2.0/window.get_width()-1.0; + float yf = y*2.0/window.get_height()-1.0; + GL::Vector4 vec = camera.unproject(GL::Vector4(xf, yf, 0, 0)); + const GL::Vector3 &pos = camera.get_position(); - float vx = cos_yaw*cos_pitch + xf*rx + yf*ux; - float vy = sin_yaw*cos_pitch + xf*ry + yf*uy; - float vz = sin_pitch + yf*uz; - - gx = cam_pos.x-vx*cam_pos.z/vz; - gy = cam_pos.y-vy*cam_pos.z/vz; + return Point(pos.x-vec.x*pos.z/vec.z, pos.y-vec.y*pos.z/vec.z); } void Designer::tick() @@ -207,50 +190,7 @@ void Designer::tick() last_tick = t; window.get_display().tick(); - - if(move_y) - { - cam_pos.x += cos(cam_yaw)*dt*move_y; - cam_pos.y += sin(cam_yaw)*dt*move_y; - } - if(move_x) - { - cam_pos.x += sin(cam_yaw)*dt*move_x; - cam_pos.y += -cos(cam_yaw)*dt*move_x; - } - if(zoom) - { - cam_pos.x += cos(cam_yaw)*cos(cam_pitch)*dt*zoom; - cam_pos.y += sin(cam_yaw)*cos(cam_pitch)*dt*zoom; - cam_pos.z += sin(cam_pitch)*dt*zoom; - } - if(rotate) - { - float vx = cos(cam_yaw)*cos(cam_pitch); - float vy = sin(cam_yaw)*cos(cam_pitch); - float vz = sin(cam_pitch); - - float gx = cam_pos.x-vx*cam_pos.z/vz; - float gy = cam_pos.y-vy*cam_pos.z/vz; - float d = sqrt(vx*vx+vy*vy)*cam_pos.z/vz; - - cam_yaw += M_PI*dt*rotate; - if(cam_yaw>M_PI*2) - cam_yaw -= M_PI*2; - else if(cam_yaw<0) - cam_yaw += M_PI*2; - - cam_pos.x = gx+cos(cam_yaw)*d; - cam_pos.y = gy+sin(cam_yaw)*d; - } - if(pitch) - { - cam_pitch += M_PI/2*dt*pitch; - if(cam_pitch>M_PI/12) - cam_pitch = M_PI/12; - else if(cam_pitch<-M_PI/2) - cam_pitch = -M_PI/2; - } + camera_ctl.tick(dt); if(tooltip_timeout && t>tooltip_timeout) { @@ -416,26 +356,6 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t) } else if(key==Msp::Input::KEY_A) add_selection_to_route(); - else 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 Designer::key_release(unsigned code, unsigned) @@ -447,24 +367,13 @@ void Designer::key_release(unsigned code, unsigned) if(key==Msp::Input::KEY_SHIFT_L || key==Msp::Input::KEY_SHIFT_R) shift = false; - else 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; } void Designer::button_press(int x, int y, unsigned btn, unsigned) { y = window.get_height()-y-1; - float gx, gy; - map_pointer_coords(x, y, gx, gy); + Point ground = map_pointer_coords(x, y); if(mode==CATALOGUE) { @@ -474,7 +383,7 @@ void Designer::button_press(int x, int y, unsigned btn, unsigned) if(ctrack) { Track *track = ctrack->get_track().copy(); - track->set_position(Point(gx, gy, 0)); + track->set_position(ground); layout->add_track(*track); selection.clear(); @@ -500,9 +409,9 @@ void Designer::button_press(int x, int y, unsigned btn, unsigned) } } else if(mode==MANIPULATE) - manipulator.button_press(x, y, gx, gy, btn); + manipulator.button_press(x, y, ground.x, ground.y, btn); else if(mode==MEASURE) - measure.button_press(x, y, gx, gy, btn); + measure.button_press(x, y, ground.x, ground.y, btn); } void Designer::pointer_motion(int x, int y) @@ -519,44 +428,38 @@ void Designer::pointer_motion(int x, int y) if(mode!=INPUT) { - float gx, gy; - map_pointer_coords(x, y, gx, gy); - manipulator.pointer_motion(x, y, gx, gy); - measure.pointer_motion(x, y, gx, gy); + Point ground = map_pointer_coords(x, y); + manipulator.pointer_motion(x, y, ground.x, ground.y); + measure.pointer_motion(x, y, ground.x, ground.y); } } -void Designer::project_3d() -{ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-0.055228, 0.055228, -0.041421, 0.041421, 0.1, 10); - glMatrixMode(GL_MODELVIEW); -} - void Designer::apply_camera() { - glLoadIdentity(); if(mode==CATALOGUE) - glTranslatef(0, 0, -1); - else { - glRotatef(-cam_pitch*180/M_PI-90, 1, 0, 0); - glRotatef(90-cam_yaw*180/M_PI, 0, 0, 1); - glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z); + GL::matrix_mode(GL::PROJECTION); + GL::load_identity(); + GL::frustum_centered(0.11046, 0.082843, 0.1, 10); + GL::matrix_mode(GL::MODELVIEW); + GL::load_identity(); + GL::translate(0, 0, -1); } + else + camera.apply(); } void Designer::render() { - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + GL::clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT); GL::enable(GL::DEPTH_TEST); GL::Texture::unbind(); - project_3d(); - apply_camera(); if(mode==CATALOGUE) + { + apply_camera(); cat_layout_3d->get_scene().render(); + } else { pipeline->render_all(); @@ -606,7 +509,6 @@ Track3D *Designer::pick_track(int x, int y) float yy = (float(y)/window.get_height()-0.5)*0.82843; float size = 4.0/window.get_height()*0.82843; - project_3d(); apply_camera(); return l->pick_track(xx, yy, size); @@ -709,3 +611,28 @@ void Designer::input_dismiss() input = 0; mode = SELECT; } + +void Designer::view_all() +{ + Point minp; + Point maxp; + + const list &tracks = layout_3d->get_tracks(); + for(list::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + Point tmin; + Point tmax; + (*i)->get_bounds(0, tmin, tmax); + minp.x = min(minp.x, tmin.x); + minp.y = min(minp.y, tmin.y); + maxp.x = max(maxp.x, tmax.x); + maxp.y = max(maxp.y, tmax.y); + } + + float t = tan(camera.get_field_of_view()/2)*2; + float size = max((maxp.y-minp.y+0.1), (maxp.x-minp.x+0.1)/camera.get_aspect()); + float cam_dist = size/t+size*0.25; + Point center((minp.x+maxp.x)/2, (minp.y+maxp.y)/2); + camera.set_position(GL::Vector3(center.x, center.y-cam_dist*0.5, cam_dist*0.866)); + camera.set_look_direction(GL::Vector3(0, 0.5, -0.866)); +} diff --git a/source/designer/designer.h b/source/designer/designer.h index 37a4a1e..a72316e 100644 --- a/source/designer/designer.h +++ b/source/designer/designer.h @@ -11,6 +11,7 @@ Distributed under the GPL #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ Distributed under the GPL #include "libmarklin/layout.h" #include "3d/layout.h" #include "3d/track.h" +#include "cameracontroller.h" #include "manipulator.h" #include "measure.h" #include "selection.h" @@ -59,6 +61,7 @@ private: Msp::GL::Object *base_object; Marklin::Route *cur_route; Msp::GL::Pipeline *pipeline; + Msp::GL::Camera camera; Msp::GL::Lighting lighting; Msp::GL::Light light; @@ -67,17 +70,9 @@ private: Manipulator manipulator; Measure measure; Input *input; - - float cam_yaw; - float cam_pitch; - Marklin::Point cam_pos; + CameraController camera_ctl; bool shift; - int move_x; - int move_y; - int zoom; - int rotate; - int pitch; int pointer_x; int pointer_y; @@ -101,14 +96,13 @@ public: Marklin::Route *get_current_route() const { return cur_route; } void add_selection_to_route(); - void map_pointer_coords(int, int, float &, float &); + Marklin::Point map_pointer_coords(int, int); private: void tick(); void key_press(unsigned, unsigned, wchar_t); void key_release(unsigned, unsigned); void button_press(int, int, unsigned, unsigned); void pointer_motion(int, int); - void project_3d(); void apply_camera(); void render(); Marklin::Track3D *pick_track(int, int); @@ -123,6 +117,7 @@ private: void turnout_id_accept(); void sensor_id_accept(); void input_dismiss(); + void view_all(); }; #endif