From 419ab8261dc7530597bfd8cbc39812616fa2064d Mon Sep 17 00:00:00 2001 From: Robert Date: Sun, 6 Sep 2020 13:37:17 +0200 Subject: [PATCH] Camera movement --- src/main.cpp | 85 ++++++++++++++++++++++++++++++++++++------ src/objects/Camera.cpp | 51 +++++++++++++++++++------ src/objects/Camera.hpp | 14 ++++--- 3 files changed, 122 insertions(+), 28 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5c02a97..caf4626 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -20,6 +21,10 @@ int width = 800; int height = 800; +bool trapCursor = true; + +std::function handleMouseCallback; + void LogGlfwError(const char* message) { const char* error; @@ -56,6 +61,63 @@ void FramebufferSizeCallback(GLFWwindow* window, int w, int h) glViewport(0, 0, w, h); } +void CursorPosCallback(GLFWwindow* window, double x, double y) +{ + if (trapCursor) + handleMouseCallback(window, x, y); +} + +void KeyCallback(GLFWwindow* window, int key, int mode, int action, int mods) +{ + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + { + trapCursor = !trapCursor; + glfwSetInputMode(window, GLFW_CURSOR, (trapCursor ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL)); + glfwSetCursorPos(window, width / 2, height / 2); + } +} + +void HandleKeyboard(GLFWwindow* window, Camera& cam, float frametime) +{ + static float movementSpeed = 4.5f; + + // Movement + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + cam.Move(cam.front * movementSpeed * frametime); + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + cam.Move(-cam.front * movementSpeed * frametime); + + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + cam.Move(-cam.right * movementSpeed * frametime); + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + cam.Move(cam.right * movementSpeed * frametime); + + if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) + cam.Move(glm::vec3(0.0f, 1.0f, 0.0f) * movementSpeed * frametime); + if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) + cam.Move(-glm::vec3(0.0f, 1.0f, 0.0f) * movementSpeed * frametime); +} + +void HandleMouse(GLFWwindow* window, Camera* cam, float x, float y) +{ + static const float sensitivity = 0.1f; + + static float pitch = 0.0f; + static float yaw = -90.0f; + + pitch += (height / 2 - y) * sensitivity; + yaw += (x - width / 2) * sensitivity; + + if (pitch > 89.0f) + pitch = 89.0f; + else if (pitch < -89.0f) + pitch = -89.0f; + + cam->SetRotation(glm::vec2(pitch, yaw)); + + glfwSetCursorPos(window, width / 2.0f, height / 2.0f); +} + int main(int argc, char** argv) { // Initialize ImGui @@ -135,18 +197,27 @@ int main(int argc, char** argv) } // A camera - Camera cam(glm::vec3(0.0f, 0.0f, 10.0f), glm::vec3(0.0f, 0.0f, 0.0f)); + Camera cam(glm::vec3(0.0f, 0.0f, 10.0f), glm::vec2(0.0f, -90.0f)); + + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + glfwSetCursorPos(window, width / 2, height / 2); + handleMouseCallback = std::bind(HandleMouse, std::placeholders::_1, &cam, std::placeholders::_2, std::placeholders::_3); + glfwSetCursorPosCallback(window, CursorPosCallback); + glfwSetKeyCallback(window, KeyCallback); - // So that stuff isnt clipping through each other glEnable(GL_DEPTH_TEST); - + float lastTime = glfwGetTime(); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); + float currentTime = glfwGetTime(); + HandleKeyboard(window, cam, currentTime - lastTime); + lastTime = currentTime; + float t = glfwGetTime(); static float PI = glm::pi(); @@ -175,12 +246,6 @@ int main(int argc, char** argv) ImGui::SliderFloat("zFar", &zFar, 10.0f, 100.0f); } - if (ImGui::CollapsingHeader("Orbit")) - { - ImGui::SliderFloat("Speed", &orbitSpeed, 0.0f, 4 * PI, "%.2f rad/s"); - ImGui::SliderFloat("Radius", &orbitRadius, 1.0f, 50.0f, "%.1f u"); - } - ImGui::End(); perspective = glm::perspective(fov, (float)width/(float)height, zNear, zFar); @@ -188,8 +253,6 @@ int main(int argc, char** argv) cubeTexture.Bind(); cubeShader.Use(); cubeShader.SetUniformMat4("projection", &perspective[0][0]); - - cam.SetPosition(orbitRadius * glm::vec3(cos(orbitSpeed * t), 0.0f, sin(orbitSpeed * t))); cam.Use(cubeShader); for (Cube* cube : cubes) diff --git a/src/objects/Camera.cpp b/src/objects/Camera.cpp index f92f089..3c2729d 100644 --- a/src/objects/Camera.cpp +++ b/src/objects/Camera.cpp @@ -2,8 +2,20 @@ #include -Camera::Camera(glm::vec3 position, glm::vec3 target) : - position(position), target(target) +Camera::Camera(glm::vec3 position, glm::vec3 direction) : + position(position), direction(direction) +{ + CalculateCamera(); +} + +Camera::Camera(glm::vec3 position, glm::vec2 pitchYaw) : + position(position), direction( + glm::vec3( + cos(glm::radians(pitchYaw.y)) * cos(glm::radians(pitchYaw.x)), + sin(glm::radians(pitchYaw.x)), + sin(glm::radians(pitchYaw.y)) * cos(glm::radians(pitchYaw.x)) + ) + ) { CalculateCamera(); } @@ -14,18 +26,32 @@ void Camera::SetPosition(glm::vec3 newPos) CalculateCamera(); } -void Camera::SetTarget(glm::vec3 newTarget) -{ - target = newTarget; - CalculateCamera(); -} - void Camera::Move(glm::vec3 movement) { position += movement; CalculateCamera(); } +void Camera::SetRotation(glm::vec2 pitchYaw) +{ + direction = glm::vec3( + cos(glm::radians(pitchYaw.y)) * cos(glm::radians(pitchYaw.x)), + sin(glm::radians(pitchYaw.x)), + sin(glm::radians(pitchYaw.y)) * cos(glm::radians(pitchYaw.x)) + ); + CalculateCamera(); +} + +void Camera::Rotate(glm::vec2 pitchYaw) +{ + direction += glm::vec3( + cos(glm::radians(pitchYaw.y)) * cos(glm::radians(pitchYaw.x)), + sin(glm::radians(pitchYaw.x)), + sin(glm::radians(pitchYaw.y)) * cos(glm::radians(pitchYaw.x)) + ); + CalculateCamera(); +} + void Camera::Use(const Shader& program) { program.SetUniformMat4("view", &viewMatrix[0][0]); @@ -33,9 +59,10 @@ void Camera::Use(const Shader& program) void Camera::CalculateCamera() { - direction = glm::normalize(target - position); - right = glm::normalize(glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), direction)); - up = glm::cross(direction, right); + front = glm::normalize(direction); + right = glm::normalize(glm::cross(front, glm::vec3(0.0f, 1.0f, 0.0f))); + // right = glm::normalize(glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), front)); + up = glm::cross(right, front); - viewMatrix = glm::lookAt(position, target, up); + viewMatrix = glm::lookAt(position, position + front, up); } diff --git a/src/objects/Camera.hpp b/src/objects/Camera.hpp index af1a438..1fffe0a 100644 --- a/src/objects/Camera.hpp +++ b/src/objects/Camera.hpp @@ -8,20 +8,24 @@ class Camera { public: Camera() = default; - Camera(glm::vec3 position, glm::vec3 target); + Camera(glm::vec3 position, glm::vec3 direction); + Camera(glm::vec3 position, glm::vec2 pitchYaw); void SetPosition(glm::vec3 newPos); - void SetTarget(glm::vec3 newTarget); - void Move(glm::vec3 movement); + void SetRotation(glm::vec2 pitchYaw); + void Rotate(glm::vec2 pitchYaw); + void Use(const Shader& program); +public: + glm::vec3 front, up, right; + private: void CalculateCamera(); - glm::vec3 position, target; - glm::vec3 direction, up, right; + glm::vec3 position, direction; glm::mat4 viewMatrix; }; \ No newline at end of file