Implement moving camera
This commit is contained in:
parent
8051f4203f
commit
bb530a8302
5 changed files with 150 additions and 22 deletions
|
@ -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;
|
||||
|
|
|
@ -1,20 +1,66 @@
|
|||
#include "periodic_updates.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#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 std::chrono::time_point<std::chrono::steady_clock>
|
||||
_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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<double> 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<kb_handler_t>& 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);
|
||||
}
|
||||
|
|
|
@ -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<double()> rand_color;
|
||||
|
@ -70,6 +74,9 @@ class GlutRender {
|
|||
std::set<SurfaceDetails> surfaces;
|
||||
|
||||
std::vector<kb_handler_t> kb_handlers;
|
||||
std::vector<kb_handler_t> kb_up_handlers;
|
||||
|
||||
const ImplicitSurface* followed_implicit;
|
||||
|
||||
Point camera_position, camera_sight;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue