From bb530a830274feff58c17c059972cb49c8b12305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Bastian?= Date: Wed, 14 Feb 2018 14:06:35 +0100 Subject: [PATCH] Implement moving camera --- main_bounce.cpp | 3 +- periodic_updates.cpp | 86 ++++++++++++++++++++++++++++++++++++++----- periodic_updates.hpp | 39 +++++++++++++++++++- render/GlutRender.cpp | 35 +++++++++++++----- render/GlutRender.hpp | 9 ++++- 5 files changed, 150 insertions(+), 22 deletions(-) diff --git a/main_bounce.cpp b/main_bounce.cpp index 42ab831..6fdad8e 100644 --- a/main_bounce.cpp +++ b/main_bounce.cpp @@ -56,7 +56,8 @@ int main(int argc, char** argv) { render.set_idle_func(periodic_update); render.add_kb_handler(periodic_kb_handler); - init_periodic_static(&ball); + render.add_kb_up_handler(periodic_kb_up_handler); + init_periodic_static(&ball, &render); render.run(); return 0; diff --git a/periodic_updates.cpp b/periodic_updates.cpp index 38f35f1..e395581 100644 --- a/periodic_updates.cpp +++ b/periodic_updates.cpp @@ -1,20 +1,66 @@ #include "periodic_updates.hpp" #include +#include #include #include +struct Movement { + Movement() : + fwd(false), + bck(false), + left(false), + right(false), + turn_l(false), + turn_r(false), + sight_angle(0.) + {} + + bool + fwd, + bck, + left, + right, + turn_l, + turn_r; + + double sight_angle; + + void tick() { + sight_angle += (turn_l - turn_r) * .05; + } + + Point movement() { + Point front_dir = Point(-sin(sight_angle), 0, -cos(sight_angle)), + left_dir = Point(-cos(sight_angle), 0, sin(sight_angle)); + return (fwd - bck) * front_dir + + (left - right) * left_dir; + } + Point sight() { + return Point(-sin(sight_angle), 0., -cos(sight_angle)); + } +}; + static Ball* _ball = nullptr; static std::chrono::time_point _last_time, _init_clocks; static bool is_paused = false; static double speed_factor = 1.; +static KeyMappings _keymap = KeyMappings::qwerty(); +static Movement _movement; +static Point _position(0., 2.5, -10.); +static GlutRender* _render = nullptr; -void init_periodic_static(Ball* ball) { +void init_periodic_static(Ball* ball, GlutRender* render) { _last_time = std::chrono::steady_clock::now(); _init_clocks = std::chrono::steady_clock::now(); _ball = ball; + _render = render; +} + +void set_key_mapping(const KeyMappings& mapping) { + _keymap = mapping; } double ellapsed_double( @@ -26,23 +72,38 @@ double ellapsed_double( } void periodic_update() { - if(is_paused) - return; - - printf("%lf\n", speed_factor); auto now = std::chrono::steady_clock::now(); - _ball->update_pos(speed_factor * ellapsed_double(_last_time, now)); + + if(!is_paused) + _ball->update_pos(speed_factor * ellapsed_double(_last_time, now)); + + _movement.tick(); + _position += _movement.movement(); + + _render->set_camera(_position, _position + _movement.sight()); _last_time = now; glutPostRedisplay(); } +void mvt_keys_update(bool up, unsigned key) { + if(key == _keymap.mv_fwd) + _movement.fwd = !up; + else if(key == _keymap.mv_bck) + _movement.bck = !up; + else if(key == _keymap.mv_left) + _movement.left = !up; + else if(key == _keymap.mv_right) + _movement.right = !up; + else if(key == _keymap.turn_left) + _movement.turn_l = !up; + else if(key == _keymap.turn_right) + _movement.turn_r = !up; +} + void periodic_kb_handler(unsigned char key, int, int) { - if(key == ' ') { - if(is_paused) - _last_time = std::chrono::steady_clock::now(); + if(key == ' ') is_paused = !is_paused; - } else if(key == '<') { speed_factor -= .1; if(speed_factor <= 0.05) @@ -54,4 +115,9 @@ void periodic_kb_handler(unsigned char key, int, int) { else if(key == '0') { speed_factor = 1.; } + mvt_keys_update(false, key); +} + +void periodic_kb_up_handler(unsigned char key, int, int) { + mvt_keys_update(true, key); } diff --git a/periodic_updates.hpp b/periodic_updates.hpp index fd1d0b4..beadef0 100644 --- a/periodic_updates.hpp +++ b/periodic_updates.hpp @@ -1,8 +1,45 @@ #pragma once #include "Ball.hpp" +#include "render/GlutRender.hpp" -void init_periodic_static(Ball* ball); +struct KeyMappings { + static KeyMappings qwerty() { + return KeyMappings('w', 's', 'a', 'd', 'q', 'e'); + } + static KeyMappings azerty() { + return KeyMappings('z', 's', 'q', 'd', 'a', 'e'); + } + + KeyMappings( + unsigned char mv_fwd, + unsigned char mv_bck, + unsigned char mv_left, + unsigned char mv_right, + unsigned char turn_left, + unsigned char turn_right) + : + mv_fwd(mv_fwd), + mv_bck(mv_bck), + mv_left(mv_left), + mv_right(mv_right), + turn_left(turn_left), + turn_right(turn_right) + {} + + + unsigned char + mv_fwd, + mv_bck, + mv_left, + mv_right, + turn_left, + turn_right; +}; + +void init_periodic_static(Ball* ball, GlutRender* render); +void set_key_mapping(const KeyMappings& mapping); void periodic_update(); void periodic_kb_handler(unsigned char key, int, int); +void periodic_kb_up_handler(unsigned char key, int, int); diff --git a/render/GlutRender.cpp b/render/GlutRender.cpp index 5f367e9..c00cc57 100644 --- a/render/GlutRender.cpp +++ b/render/GlutRender.cpp @@ -12,7 +12,11 @@ GlutRender& GlutRender::get_instance() { return instance; } -GlutRender::GlutRender() : followed_implicit(nullptr) { +GlutRender::GlutRender() + : followed_implicit(nullptr), + camera_position(0., 2.5, -10.), + camera_sight(0, 2.5, 0) +{ std::default_random_engine rand_engine(time(NULL)); std::uniform_real_distribution distribution; rand_color = std::bind(distribution, rand_engine); @@ -30,6 +34,7 @@ void GlutRender::init(int* argc, char** argv, glutDisplayFunc(display_handle); glutReshapeFunc(reshape_handle); glutKeyboardFunc(kb_evt_handle); + glutKeyboardUpFunc(kb_evt_up_handle); // ==== Lighting ==== GLfloat light0_pos[] = {30., 35., 20., 0.}; @@ -97,10 +102,19 @@ void GlutRender::add_kb_handler(GlutRender::kb_handler_t handler) { kb_handlers.push_back(handler); } +void GlutRender::add_kb_up_handler(GlutRender::kb_handler_t handler) { + kb_up_handlers.push_back(handler); +} + void GlutRender::follow_implicit_position(const ImplicitSurface* surf) { followed_implicit = surf; } +void GlutRender::set_camera(const Point& location, const Point& sight) { + camera_position = location; + camera_sight = sight; +} + void GlutRender::reshape(int wid, int hei) { if (hei == 0) hei = 1; @@ -192,16 +206,15 @@ void GlutRender::display() { // Camera position and orientation glLoadIdentity(); - Point look_from(0, 2.5, -10); if(followed_implicit != nullptr) { const Point& look_at = followed_implicit->getCenter(); - gluLookAt(look_from.x, look_from.y, look_from.z, - look_at.x, look_from.y, look_at.z, + gluLookAt(camera_position.x, camera_position.y, camera_position.z, + look_at.x, camera_position.y, look_at.z, 0, 1, 0); } else { - gluLookAt(look_from.x, look_from.y, look_from.z, - 0, 2.5, 0, + gluLookAt(camera_position.x, camera_position.y, camera_position.z, + camera_sight.x, camera_position.y, camera_sight.z, 0, 1, 0); } @@ -220,8 +233,9 @@ void GlutRender::display() { glutSwapBuffers(); } -void GlutRender::on_kb_evt(unsigned char key, int x, int y) { - for(auto& handler: kb_handlers) { +void GlutRender::on_kb_evt(bool up, unsigned char key, int x, int y) { + std::vector& handlers = up? kb_up_handlers : kb_handlers; + for(auto& handler: handlers) { handler(key, x, y); } } @@ -233,5 +247,8 @@ void GlutRender::display_handle() { get_instance().display(); } void GlutRender::kb_evt_handle(unsigned char key, int x, int y) { - get_instance().on_kb_evt(key, x, y); + get_instance().on_kb_evt(false, key, x, y); +} +void GlutRender::kb_evt_up_handle(unsigned char key, int x, int y) { + get_instance().on_kb_evt(true, key, x, y); } diff --git a/render/GlutRender.hpp b/render/GlutRender.hpp index cff2998..cc76fa9 100644 --- a/render/GlutRender.hpp +++ b/render/GlutRender.hpp @@ -29,9 +29,12 @@ class GlutRender { void set_idle_func(void (*func)(void)); void add_kb_handler(kb_handler_t handler); + void add_kb_up_handler(kb_handler_t handler); void follow_implicit_position(const ImplicitSurface* surf); + void set_camera(const Point& location, const Point& sight); + private: struct SurfaceDetails { SurfaceDetails(ImplicitSurface* surf, const Cuboid& box, @@ -56,12 +59,13 @@ class GlutRender { protected: void reshape(int wid, int hei); void display(); - void on_kb_evt(unsigned char key, int x, int y); + void on_kb_evt(bool up, unsigned char key, int x, int y); static void reshape_handle(int wid, int hei); static void display_handle(); static void kb_evt_handle(unsigned char key, int x, int y); + static void kb_evt_up_handle(unsigned char key, int x, int y); private: //attr std::function rand_color; @@ -70,6 +74,9 @@ class GlutRender { std::set surfaces; std::vector kb_handlers; + std::vector kb_up_handlers; const ImplicitSurface* followed_implicit; + + Point camera_position, camera_sight; };