]> git.tdb.fi Git - r2c2.git/commitdiff
Use a GL::Camera
authorMikko Rasa <tdb@tdb.fi>
Wed, 24 Feb 2010 21:56:28 +0000 (21:56 +0000)
committerMikko Rasa <tdb@tdb.fi>
Wed, 24 Feb 2010 21:56:28 +0000 (21:56 +0000)
Move camera controls to a separate class

source/designer/cameracontroller.cpp [new file with mode: 0644]
source/designer/cameracontroller.h [new file with mode: 0644]
source/designer/designer.cpp
source/designer/designer.h

diff --git a/source/designer/cameracontroller.cpp b/source/designer/cameracontroller.cpp
new file mode 100644 (file)
index 0000000..fb16bb8
--- /dev/null
@@ -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 <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;
+}
diff --git a/source/designer/cameracontroller.h b/source/designer/cameracontroller.h
new file mode 100644 (file)
index 0000000..63ba2c1
--- /dev/null
@@ -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 <msp/gbase/window.h>
+#include <msp/gl/camera.h>
+
+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
index 02563f808edef83585cb8c2055ac3717cebdaf97..f79ef7a9ae8daa4bfdb94a901ba3b6d170412b9c 100644 (file)
@@ -9,6 +9,7 @@ Distributed under the GPL
 #include <cmath>
 #include <GL/gl.h>
 #include <msp/gl/blend.h>
+#include <msp/gl/framebuffer.h>
 #include <msp/gl/matrix.h>
 #include <msp/gl/misc.h>
 #include <msp/gl/projection.h>
@@ -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<float>(x)*2/window.get_width()-1;
-       float yf = static_cast<float>(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<Track3D *> &tracks = layout_3d->get_tracks();
+       for(list<Track3D *>::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));
+}
index 37a4a1e6524456c88ce90dbc74c408a2489abc96..a72316e128044aea2e182190a59008f60712950c 100644 (file)
@@ -11,6 +11,7 @@ Distributed under the GPL
 #include <string>
 #include <msp/core/application.h>
 #include <msp/gbase/simplewindow.h>
+#include <msp/gl/camera.h>
 #include <msp/gl/font.h>
 #include <msp/gl/light.h>
 #include <msp/gl/lighting.h>
@@ -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