]> git.tdb.fi Git - r2c2.git/blobdiff - source/designer/designer.cpp
Use a GL::Camera
[r2c2.git] / source / designer / designer.cpp
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));
+}