Implement moving camera

This commit is contained in:
Théophile Bastian 2018-02-14 14:06:35 +01:00
parent 8051f4203f
commit bb530a8302
5 changed files with 150 additions and 22 deletions

View file

@ -56,7 +56,8 @@ int main(int argc, char** argv) {
render.set_idle_func(periodic_update); render.set_idle_func(periodic_update);
render.add_kb_handler(periodic_kb_handler); 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(); render.run();
return 0; return 0;

View file

@ -1,20 +1,66 @@
#include "periodic_updates.hpp" #include "periodic_updates.hpp"
#include <ctime> #include <ctime>
#include <cmath>
#include <chrono> #include <chrono>
#include <GL/glut.h> #include <GL/glut.h>
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 Ball* _ball = nullptr;
static std::chrono::time_point<std::chrono::steady_clock> static std::chrono::time_point<std::chrono::steady_clock>
_last_time, _init_clocks; _last_time, _init_clocks;
static bool is_paused = false; static bool is_paused = false;
static double speed_factor = 1.; 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(); _last_time = std::chrono::steady_clock::now();
_init_clocks = std::chrono::steady_clock::now(); _init_clocks = std::chrono::steady_clock::now();
_ball = ball; _ball = ball;
_render = render;
}
void set_key_mapping(const KeyMappings& mapping) {
_keymap = mapping;
} }
double ellapsed_double( double ellapsed_double(
@ -26,23 +72,38 @@ double ellapsed_double(
} }
void periodic_update() { void periodic_update() {
if(is_paused)
return;
printf("%lf\n", speed_factor);
auto now = std::chrono::steady_clock::now(); 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; _last_time = now;
glutPostRedisplay(); 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) { void periodic_kb_handler(unsigned char key, int, int) {
if(key == ' ') { if(key == ' ')
if(is_paused)
_last_time = std::chrono::steady_clock::now();
is_paused = !is_paused; is_paused = !is_paused;
}
else if(key == '<') { else if(key == '<') {
speed_factor -= .1; speed_factor -= .1;
if(speed_factor <= 0.05) if(speed_factor <= 0.05)
@ -54,4 +115,9 @@ void periodic_kb_handler(unsigned char key, int, int) {
else if(key == '0') { else if(key == '0') {
speed_factor = 1.; speed_factor = 1.;
} }
mvt_keys_update(false, key);
}
void periodic_kb_up_handler(unsigned char key, int, int) {
mvt_keys_update(true, key);
} }

View file

@ -1,8 +1,45 @@
#pragma once #pragma once
#include "Ball.hpp" #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_update();
void periodic_kb_handler(unsigned char key, int, int); void periodic_kb_handler(unsigned char key, int, int);
void periodic_kb_up_handler(unsigned char key, int, int);

View file

@ -12,7 +12,11 @@ GlutRender& GlutRender::get_instance() {
return 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::default_random_engine rand_engine(time(NULL));
std::uniform_real_distribution<double> distribution; std::uniform_real_distribution<double> distribution;
rand_color = std::bind(distribution, rand_engine); rand_color = std::bind(distribution, rand_engine);
@ -30,6 +34,7 @@ void GlutRender::init(int* argc, char** argv,
glutDisplayFunc(display_handle); glutDisplayFunc(display_handle);
glutReshapeFunc(reshape_handle); glutReshapeFunc(reshape_handle);
glutKeyboardFunc(kb_evt_handle); glutKeyboardFunc(kb_evt_handle);
glutKeyboardUpFunc(kb_evt_up_handle);
// ==== Lighting ==== // ==== Lighting ====
GLfloat light0_pos[] = {30., 35., 20., 0.}; 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); 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) { void GlutRender::follow_implicit_position(const ImplicitSurface* surf) {
followed_implicit = 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) { void GlutRender::reshape(int wid, int hei) {
if (hei == 0) if (hei == 0)
hei = 1; hei = 1;
@ -192,16 +206,15 @@ void GlutRender::display() {
// Camera position and orientation // Camera position and orientation
glLoadIdentity(); glLoadIdentity();
Point look_from(0, 2.5, -10);
if(followed_implicit != nullptr) { if(followed_implicit != nullptr) {
const Point& look_at = followed_implicit->getCenter(); const Point& look_at = followed_implicit->getCenter();
gluLookAt(look_from.x, look_from.y, look_from.z, gluLookAt(camera_position.x, camera_position.y, camera_position.z,
look_at.x, look_from.y, look_at.z, look_at.x, camera_position.y, look_at.z,
0, 1, 0); 0, 1, 0);
} }
else { else {
gluLookAt(look_from.x, look_from.y, look_from.z, gluLookAt(camera_position.x, camera_position.y, camera_position.z,
0, 2.5, 0, camera_sight.x, camera_position.y, camera_sight.z,
0, 1, 0); 0, 1, 0);
} }
@ -220,8 +233,9 @@ void GlutRender::display() {
glutSwapBuffers(); glutSwapBuffers();
} }
void GlutRender::on_kb_evt(unsigned char key, int x, int y) { void GlutRender::on_kb_evt(bool up, unsigned char key, int x, int y) {
for(auto& handler: kb_handlers) { std::vector<kb_handler_t>& handlers = up? kb_up_handlers : kb_handlers;
for(auto& handler: handlers) {
handler(key, x, y); handler(key, x, y);
} }
} }
@ -233,5 +247,8 @@ void GlutRender::display_handle() {
get_instance().display(); get_instance().display();
} }
void GlutRender::kb_evt_handle(unsigned char key, int x, int y) { 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);
} }

View file

@ -29,9 +29,12 @@ class GlutRender {
void set_idle_func(void (*func)(void)); void set_idle_func(void (*func)(void));
void add_kb_handler(kb_handler_t handler); 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 follow_implicit_position(const ImplicitSurface* surf);
void set_camera(const Point& location, const Point& sight);
private: private:
struct SurfaceDetails { struct SurfaceDetails {
SurfaceDetails(ImplicitSurface* surf, const Cuboid& box, SurfaceDetails(ImplicitSurface* surf, const Cuboid& box,
@ -56,12 +59,13 @@ class GlutRender {
protected: protected:
void reshape(int wid, int hei); void reshape(int wid, int hei);
void display(); 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 reshape_handle(int wid, int hei);
static void display_handle(); static void display_handle();
static void kb_evt_handle(unsigned char key, int x, int y); 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 private: //attr
std::function<double()> rand_color; std::function<double()> rand_color;
@ -70,6 +74,9 @@ class GlutRender {
std::set<SurfaceDetails> surfaces; std::set<SurfaceDetails> surfaces;
std::vector<kb_handler_t> kb_handlers; std::vector<kb_handler_t> kb_handlers;
std::vector<kb_handler_t> kb_up_handlers;
const ImplicitSurface* followed_implicit; const ImplicitSurface* followed_implicit;
Point camera_position, camera_sight;
}; };