Add camera movement with keyboard & mouse

This commit is contained in:
karl 2021-05-08 17:27:16 +02:00
parent 5ffbe94816
commit 82fae245a1
7 changed files with 116 additions and 33 deletions

View File

@ -3,6 +3,7 @@
uniform mat4 projection; uniform mat4 projection;
uniform mat4 view; uniform mat4 view;
uniform vec3 camera_pos;
uniform vec3 quad1, quad2; uniform vec3 quad1, quad2;
@ -22,7 +23,7 @@ void main() {
if(type_pass[0] != 0) { if(type_pass[0] != 0) {
// This is not a generator particle // This is not a generator particle
vec3 old_pos = gl_in[0].gl_Position.xyz; vec3 old_pos = gl_in[0].gl_Position.xyz - camera_pos;
float size = size_pass[0]; float size = size_pass[0];
mat4 view_projection_matrix = projection * view; mat4 view_projection_matrix = projection * view;

View File

@ -107,6 +107,8 @@ void ParticleSystem::set_camera(const Camera &camera) {
quad2 = glm::cross(camera.forward(), quad1); quad2 = glm::cross(camera.forward(), quad1);
quad2 = glm::normalize(quad2); quad2 = glm::normalize(quad2);
camera_pos = camera.get_translation();
} }
void ParticleSystem::render() { void ParticleSystem::render() {
@ -120,6 +122,7 @@ void ParticleSystem::render() {
render_shader.setMat4("view", view_matrix); render_shader.setMat4("view", view_matrix);
render_shader.setVec3("quad1", quad1); render_shader.setVec3("quad1", quad1);
render_shader.setVec3("quad2", quad2); render_shader.setVec3("quad2", quad2);
render_shader.setVec3("camera_pos", camera_pos);
texture->bind_to(0); texture->bind_to(0);

View File

@ -1,9 +1,13 @@
#pragma once #pragma once
#include <GLFW/glfw3.h>
#include <glm/ext/matrix_transform.hpp>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/dual_quaternion.hpp> #include <glm/gtx/dual_quaternion.hpp>
#include "Gedeng/Logger.h"
#include "Input.h"
#include "Spatial.h" #include "Spatial.h"
namespace Gedeng { namespace Gedeng {
@ -28,4 +32,56 @@ class Camera : public Spatial {
glm::mat4 projection; glm::mat4 projection;
}; };
class FPSCamera : public Camera {
public:
FPSCamera(float fov, float width, float height, float near, float far)
: Camera(fov, width, height, near, far), move_speed(glm::vec3(5.0, 5.0, 5.0)), mouse_sensitivity(0.1),
last_mouse_position(Input::get_mouse_position()), pitch(0.0), yaw(0.0) {
}
void update(float delta) {
if (Input::is_key_down(GLFW_KEY_W)) {
translate(glm::vec3(0.0, 0.0, -1.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_S)) {
translate(-glm::vec3(0.0, 0.0, -1.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_D)) {
translate(glm::vec3(1.0, 0.0, 0.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_A)) {
translate(-glm::vec3(1.0, 0.0, 0.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_Q)) {
translate(glm::vec3(0.0, 1.0, 0.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_E)) {
translate(-glm::vec3(0.0, 1.0, 0.0) * move_speed * delta);
}
glm::vec2 mouse_difference = Input::get_mouse_position() - last_mouse_position;
yaw -= mouse_difference.x * mouse_sensitivity;
pitch -= mouse_difference.y * mouse_sensitivity;
if (pitch > 80.0f) pitch = 80.0f;
if (pitch < -80.0f) pitch = -80.0f;
glm::qua rotation = glm::angleAxis(glm::radians((float)yaw), glm::vec3(0.f, 1.f, 0.f));
rotation *= glm::angleAxis(glm::radians((float)pitch), glm::vec3(1.f, 0.f, 0.f));
set_rotation_from_quat(rotation);
last_mouse_position = Input::get_mouse_position();
}
private:
glm::vec3 move_speed;
float mouse_sensitivity;
glm::vec2 last_mouse_position;
float pitch;
float yaw;
};
} // namespace Gedeng } // namespace Gedeng

View File

@ -7,6 +7,8 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include "RenderBackend.h" #include "RenderBackend.h"
#include <glm/fwd.hpp>
#include <glm/glm.hpp>
#include <map> #include <map>
namespace Gedeng { namespace Gedeng {
@ -15,6 +17,10 @@ class Input {
public: public:
static void initialize(GLFWwindow *window) { static void initialize(GLFWwindow *window) {
glfwSetKeyCallback(window, key_callback); glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
is_mouse_active = true;
} }
// FIXME: Ignore warnings produced by these unused variables -- they're required for the callback to work: // FIXME: Ignore warnings produced by these unused variables -- they're required for the callback to work:
@ -25,6 +31,11 @@ class Input {
Input::set_key_down(key, action == GLFW_RELEASE ? false : true); Input::set_key_down(key, action == GLFW_RELEASE ? false : true);
} }
static void mouse_callback(GLFWwindow *window, double xpos, double ypos) {
mouse_position.x = xpos;
mouse_position.y = ypos;
}
static void poll_input() { static void poll_input() {
glfwPollEvents(); glfwPollEvents();
} }
@ -37,7 +48,14 @@ class Input {
return keys_down[key]; return keys_down[key];
} }
static glm::vec2 get_mouse_position() {
return is_mouse_active ? mouse_position : glm::vec2(0.0, 0.0);
}
private:
inline static std::map<int, bool> keys_down; inline static std::map<int, bool> keys_down;
inline static glm::vec2 mouse_position;
inline static bool is_mouse_active;
}; };
} // namespace Gedeng } // namespace Gedeng

View File

@ -57,6 +57,7 @@ class ParticleSystem {
glm::mat4 projection_matrix, view_matrix; glm::mat4 projection_matrix, view_matrix;
glm::vec3 quad1, quad2; glm::vec3 quad1, quad2;
glm::vec3 camera_pos;
float elapsed_time; float elapsed_time;
float next_generation_time; float next_generation_time;

View File

@ -16,7 +16,7 @@ class Spatial {
matrix = glm::translate(matrix, offset); matrix = glm::translate(matrix, offset);
} }
glm::vec3 get_translation() { glm::vec3 get_translation() const {
return glm::vec3(matrix[3]); return glm::vec3(matrix[3]);
} }

View File

@ -9,37 +9,39 @@ class ParticleApp : public Gedeng::Application {
public: public:
ParticleApp(unsigned long ms_per_update, unsigned int window_size_x, unsigned int window_size_y, ParticleApp(unsigned long ms_per_update, unsigned int window_size_x, unsigned int window_size_y,
Gedeng::String window_name) Gedeng::String window_name)
: Application(ms_per_update, window_size_x, window_size_y, window_name), : Application(ms_per_update, window_size_x, window_size_y, window_name), number_of_steps(10.0),
camera(Gedeng::Camera(90, 1920, 1080, 0.1, 1000.0)), number_of_refinement_steps(10.0), bump_depth(0.1),
render_shader(Gedeng::Shader("Shader/bump.vs", "Shader/bump.fs")),
camera(Gedeng::FPSCamera(90, 1920, 1080, 0.1, 1000.0)),
albedo("Resources/Textures/PavingStones/PavingStones070_2K_Color.jpg", Gedeng::Texture::Settings()), albedo("Resources/Textures/PavingStones/PavingStones070_2K_Color.jpg", Gedeng::Texture::Settings()),
bump("Resources/Textures/PavingStones/PavingStones070_2K_Displacement.jpg", Gedeng::Texture::Settings()), bump("Resources/Textures/PavingStones/PavingStones070_2K_Displacement.jpg", Gedeng::Texture::Settings()),
normal("Resources/Textures/PavingStones/PavingStones070_2K_Normal.jpg", Gedeng::Texture::Settings()) { normal("Resources/Textures/PavingStones/PavingStones070_2K_Normal.jpg", Gedeng::Texture::Settings()) {
// Move and rotate the camera so we see the quad well particles.set_position(glm::vec3(0.0f, 0.0f, -10.0f));
// camera.translate(glm::vec3(0.0, 0.0, -1.0));
// camera.rotate(180, glm::vec3(0.0, 1.0, 0.0));
particles.set_position(glm::vec3(0.0f, 0.0f, -5.0f));
particles.set_velocity(glm::vec3(-5, 0, -5), glm::vec3(5, 20, 5)); particles.set_velocity(glm::vec3(-5, 0, -5), glm::vec3(5, 20, 5));
particles.set_gravity(glm::vec3(0, -5, 0)); particles.set_gravity(glm::vec3(0, -5, 0));
particles.set_color(glm::vec3(0.0f, 0.5f, 1.0f)); particles.set_color(glm::vec3(0.0f, 0.5f, 1.0f));
particles.set_lifetime(1.5f, 3.0f); particles.set_lifetime(1.5f, 3.0f);
particles.set_size(0.75f); particles.set_size(0.75f);
particles.set_interval(0.2f); particles.set_interval(0.5f);
particles.set_number_of_particles(30); particles.set_number_of_particles(30);
particles.set_texture(&albedo); particles.set_texture(&albedo);
camera.translate(glm::vec3(0.0, 0.0, 1.0));
// camera.rotate(30, glm::vec3(1.0, 0.0, 0.0));
} }
~ParticleApp() = default; ~ParticleApp() = default;
void fixed_update(double delta) override { void fixed_update(double delta) override {
// camera.rotate(delta * 180, glm::vec3(0.0, 1.0, 0.0)); // camera.rotate(delta * 180, glm::vec3(0.0, 1.0, 0.0));
camera.update(delta);
} }
void dynamic_update(double delta) override { void dynamic_update(double delta) override {
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClearColor(0.85f, 0.9f, 0.94f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* render_shader.use(); render_shader.use();
// Camera // Camera
render_shader.setMat4("projection", camera.get_projection()); render_shader.setMat4("projection", camera.get_projection());
@ -59,22 +61,24 @@ class ParticleApp : public Gedeng::Application {
bump.bind_to(2); bump.bind_to(2);
// Quad which is rendered onto // Quad which is rendered onto
quad_mesh.rotate(delta * 25.0f, glm::normalize(glm::vec3(0.0, 0.0, 1.0)));
quad_mesh.render(render_shader); quad_mesh.render(render_shader);
debug_text.render_text(25.0f, 25.0f, 1.0f, Gedeng::Vector3(1.0, 1.0, 0.0)); */ // Particles
particles.set_camera(camera); particles.set_camera(camera);
particles.update(delta); particles.update(delta);
particles.render(); particles.render();
} }
private: private:
Gedeng::ParticleSystem particles; float number_of_steps;
float number_of_refinement_steps;
float bump_depth;
Gedeng::Shader render_shader;
Gedeng::VertexBuffer vertex_rectangle; Gedeng::VertexBuffer vertex_rectangle;
Gedeng::Camera camera; Gedeng::FPSCamera camera;
Gedeng::Texture albedo; Gedeng::Texture albedo;
Gedeng::Texture bump; Gedeng::Texture bump;
@ -82,7 +86,7 @@ class ParticleApp : public Gedeng::Application {
Gedeng::QuadMesh quad_mesh; Gedeng::QuadMesh quad_mesh;
Gedeng::TextLabel debug_text; Gedeng::ParticleSystem particles;
}; };
Gedeng::Application *Gedeng::create_application() { Gedeng::Application *Gedeng::create_application() {