]> git.tdb.fi Git - r2c2.git/commitdiff
Better visualization for placing a train
authorMikko Rasa <tdb@tdb.fi>
Thu, 8 Aug 2013 16:13:39 +0000 (19:13 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 8 Aug 2013 16:13:39 +0000 (19:13 +0300)
Still far from perfect, but it's a start.

data/ghost.technique [new file with mode: 0644]
source/3d/view.cpp
source/3d/view.h
source/engineer/controlpanel.cpp
source/engineer/controlpanel.h
source/engineer/placementghost.cpp [new file with mode: 0644]
source/engineer/placementghost.h [new file with mode: 0644]

diff --git a/data/ghost.technique b/data/ghost.technique
new file mode 100644 (file)
index 0000000..c019ab0
--- /dev/null
@@ -0,0 +1,7 @@
+pass "translucent"
+{
+       material
+       {
+               diffuse 1.0 1.0 1.0 0.3;
+       };
+};
index 8943abce36e7e2c0307fca0b4f9bea6ce24ab11f..5779616f6ce88ea2b82da9982298e169fca79777 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/gl/blend.h>
 #include <msp/gl/tests.h>
 #include "layout.h"
 #include "track.h"
@@ -16,11 +17,17 @@ View3D::View3D(Layout3D &l, unsigned w, unsigned h):
 {
        pipeline.set_camera(&camera);
        pipeline.add_renderable_for_pass(layout.get_scene(), 0);
+       pipeline.add_renderable_for_pass(layout.get_scene(), "translucent");
 
        GL::Pipeline::Pass *pass = &pipeline.add_pass(0);
        pass->set_lighting(&layout.get_lighting());
        pass->set_depth_test(&GL::DepthTest::lequal());
 
+       pass = &pipeline.add_pass("translucent");
+       pass->set_lighting(&layout.get_lighting());
+       pass->set_depth_test(&GL::DepthTest::lequal());
+       pass->set_blend(&GL::Blend::alpha());
+
        camera.set_up_direction(GL::Vector3(0, 0, 1));
        // Y+, 60° down
        camera.set_look_direction(GL::Vector3(0, 0.5, -0.866));
@@ -29,6 +36,18 @@ View3D::View3D(Layout3D &l, unsigned w, unsigned h):
        view_all();
 }
 
+Ray View3D::create_ray(int x, int y)
+{
+       return create_ray(x*2.0f/width-1.0f, y*2.0f/height-1.0f);
+}
+
+Ray View3D::create_ray(float x, float y)
+{
+       const GL::Vector3 &start = camera.get_position();
+       GL::Vector4 ray = camera.unproject(GL::Vector4(x, y, 0, 0));
+       return Ray(start, Vector(ray));
+}
+
 void View3D::view_all(bool tight)
 {
        const set<Track *> &tracks = layout.get_layout().get_all<Track>();
index ffe608e88cfe2a63113ea1f333e3dea86c68dc78..a1bdaf50cc605e7ae45ae7be4de270c9a53d1f1f 100644 (file)
@@ -24,6 +24,9 @@ public:
        Msp::GL::Camera &get_camera() { return camera; }
        Msp::GL::Pipeline &get_pipeline() { return pipeline; }
 
+       Ray create_ray(int, int);
+       Ray create_ray(float, float);
+
        void view_all(bool = false);
 
        void render();
index e81d25c366d9b671b7193a312b84e3853232aed7..050b37623fb98c472294c75078ea325f39e98312 100644 (file)
@@ -6,6 +6,7 @@
 #include "libr2c2/vehicle.h"
 #include "controlpanel.h"
 #include "engineer.h"
+#include "placementghost.h"
 #include "trainview.h"
 
 using namespace std;
@@ -58,14 +59,13 @@ void ControlPanel::train_function_changed(unsigned func, bool value)
 
 void ControlPanel::place_clicked()
 {
-       pick_conn = engineer.signal_pick_done.connect(sigc::mem_fun(this, &ControlPanel::place_pick_done));
-       engineer.pick(true);
-}
+       signal_grab_pointer.emit();
+       placing = true;
 
-void ControlPanel::place_pick_done(Track *track, unsigned ep)
-{
-       pick_conn.disconnect();
-       train.place(TrackIter(track, ep).block_iter());
+       Layout3D &layout3d = engineer.get_layout_3d();
+       unsigned n_vehs = train.get_n_vehicles();
+       for(unsigned i=0; i<n_vehs; ++i)
+               ghosts.push_back(new PlacementGhost(layout3d, train.get_vehicle(i).get_type()));
 }
 
 void ControlPanel::take_clicked()
@@ -83,3 +83,45 @@ void ControlPanel::view_clicked()
        root->add(*dlg);
        dlg->autosize();
 }
+
+void ControlPanel::button_press(int x, int y, unsigned btn)
+{
+       Panel::button_press(x, y, btn);
+
+       if(placing)
+       {
+               signal_ungrab_pointer.emit();
+               placing = false;
+
+               for(vector<PlacementGhost *>::iterator i=ghosts.begin(); i!=ghosts.end(); ++i)
+                       delete *i;
+               ghosts.clear();
+
+               if(btn==1 && place_location)
+                       train.place(place_location);
+       }
+}
+
+void ControlPanel::pointer_motion(int x, int y)
+{
+       Panel::pointer_motion(x, y);
+
+       if(placing)
+       {
+               int rx = x;
+               int ry = y;
+               map_coords_to_ancestor(rx, ry, *find_ancestor<GLtk::Root>());
+               Ray ray = engineer.get_main_view().create_ray(rx, ry);
+               Track *track = engineer.get_layout().pick<Track>(ray);
+               if(track)
+               {
+                       place_location = TrackIter(track, 0).block_iter();
+                       if(place_location)
+                       {
+                               ghosts.back()->place(place_location.track_iter());
+                               for(unsigned i=ghosts.size()-1; i--; )
+                                       ghosts[i]->place_before(*ghosts[i+1]);
+                       }
+               }
+       }
+}
index c99ca17f61f86c084f70b7d9803a65e8a05774fd..23ca8bcfc57bd67dee3803f9600dcdf5f42d845d 100644 (file)
@@ -4,9 +4,11 @@
 #include <map>
 #include <msp/gltk/panel.h>
 #include <msp/gltk/toggle.h>
+#include "libr2c2/blockiter.h"
 #include "libr2c2/train.h"
 
 class Engineer;
+class PlacementGhost;
 
 class ControlPanel: public Msp::GLtk::Panel
 {
@@ -17,6 +19,10 @@ private:
        std::map<unsigned, Msp::GLtk::Toggle *> tgl_funcs;
        sigc::connection pick_conn;
 
+       bool placing;
+       std::vector<PlacementGhost *> ghosts;
+       R2C2::BlockIter place_location;
+
 public:
        ControlPanel(Engineer &, R2C2::Train &);
 
@@ -27,6 +33,9 @@ private:
        void place_pick_done(R2C2::Track *, unsigned);
        void take_clicked();
        void view_clicked();
+
+       virtual void button_press(int, int, unsigned);
+       virtual void pointer_motion(int, int);
 };
 
 #endif
diff --git a/source/engineer/placementghost.cpp b/source/engineer/placementghost.cpp
new file mode 100644 (file)
index 0000000..e59da68
--- /dev/null
@@ -0,0 +1,59 @@
+#include <msp/gl/box.h>
+#include <msp/gl/meshbuilder.h>
+#include <msp/gl/renderer.h>
+#include <msp/gl/technique.h>
+#include "libr2c2/vehicletype.h"
+#include "placementghost.h"
+
+using namespace Msp;
+using namespace R2C2;
+
+PlacementGhost::PlacementGhost(Layout3D &a, const VehicleType &t):
+       layout(a),
+       type(t),
+       placement(type),
+       mesh(new GL::Mesh((GL::VERTEX3, GL::NORMAL3))),
+       object(new GL::Object(mesh, &layout.get_catalogue().get<GL::Technique>("ghost.technique")))
+{
+       GL::MeshBuilder bld(*mesh);
+       float l = type.get_length();
+       float w = type.get_width();
+       float h = type.get_height();
+       GL::BoxBuilder(GL::Vector3(-l/2, -w/2, 0), GL::Vector3(l, w, h)).build(bld);
+
+       layout.get_scene().add(*this);
+}
+
+PlacementGhost::~PlacementGhost()
+{
+       layout.get_scene().remove(*this);
+
+       delete object;
+       delete mesh;
+}
+
+void PlacementGhost::place(const TrackOffsetIter &track)
+{
+       placement.place(track, VehiclePlacement::BACK_BUFFER);
+}
+
+void PlacementGhost::place_before(const PlacementGhost &other)
+{
+       placement.place_before(other.placement);
+}
+
+void PlacementGhost::render(GL::Renderer &renderer, const GL::Tag &tag) const
+{
+       if(!object->get_technique()->has_pass(tag))
+               return;
+
+       GL::Renderer::Push push(renderer);
+
+       OrientedPoint point = placement.get_point();
+       GL::Matrix matrix;
+       matrix.translate(point.position);
+       matrix.rotate(point.rotation, 0, 0, 1);
+       renderer.matrix_stack() *= matrix;
+
+       object->render(renderer, tag);
+}
diff --git a/source/engineer/placementghost.h b/source/engineer/placementghost.h
new file mode 100644 (file)
index 0000000..3ae2639
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef PLACEMENTGHOST_H_
+#define PLACEMENTGHOST_H_
+
+#include <msp/gl/mesh.h>
+#include <msp/gl/object.h>
+#include <msp/gl/renderable.h>
+#include "libr2c2/vehicleplacement.h"
+#include "3d/layout.h"
+
+class PlacementGhost: public Msp::GL::Renderable
+{
+private:
+       R2C2::Layout3D &layout;
+       const R2C2::VehicleType &type;
+       R2C2::VehiclePlacement placement;
+       Msp::GL::Mesh *mesh;
+       Msp::GL::Object *object;
+
+public:
+       PlacementGhost(R2C2::Layout3D &, const R2C2::VehicleType &);
+       virtual ~PlacementGhost();
+
+       void place(const R2C2::TrackOffsetIter &);
+       void place_before(const PlacementGhost &);
+
+       virtual void render(Msp::GL::Renderer &, const Msp::GL::Tag &) const;
+};
+
+#endif