Riyyi
4 years ago
6 changed files with 14 additions and 332 deletions
@ -1,226 +0,0 @@ |
|||||||
#include <algorithm> // std::max, std::min |
|
||||||
#include <memory> // std::make_shared |
|
||||||
|
|
||||||
#include <glm/ext/matrix_clip_space.hpp> // glm::perspective, glm::ortho |
|
||||||
#include <glm/ext/matrix_transform.hpp> // glm::radians, glm::lookAt |
|
||||||
|
|
||||||
#include "inferno/application.h" |
|
||||||
#include "inferno/component/transform.h" |
|
||||||
#include "inferno/input.h" |
|
||||||
#include "inferno/inputcodes.h" |
|
||||||
#include "inferno/render/camera.h" |
|
||||||
#include "inferno/window.h" |
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
Camera::Camera() |
|
||||||
: Camera({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
Camera::Camera(glm::vec3 translate, glm::vec3 rotate) |
|
||||||
{ |
|
||||||
glm::vec3 scale = {1.0f, 1.0f, 1.0f}; |
|
||||||
m_transform = std::make_shared<Transform>(translate, rotate, scale); |
|
||||||
} |
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
OrthographicCamera::OrthographicCamera() |
|
||||||
: Camera({0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}) |
|
||||||
{ |
|
||||||
initialize(); |
|
||||||
} |
|
||||||
|
|
||||||
OrthographicCamera::OrthographicCamera(glm::vec3 translate, glm::vec3 rotate) |
|
||||||
: Camera(translate, rotate) |
|
||||||
{ |
|
||||||
initialize(); |
|
||||||
} |
|
||||||
|
|
||||||
void OrthographicCamera::initialize() |
|
||||||
{ |
|
||||||
m_zoomLevel = 1.0f; |
|
||||||
|
|
||||||
// Set the roatation axis
|
|
||||||
m_rotateAxis = glm::vec3(0.0f, 0.0f, 1.0f); |
|
||||||
|
|
||||||
dbg(Log::Info) << "OrthographicCamera initialized"; |
|
||||||
} |
|
||||||
|
|
||||||
void OrthographicCamera::update(float deltaTime) |
|
||||||
{ |
|
||||||
// Update camera rotation
|
|
||||||
|
|
||||||
float cameraRotateSpeed = ROTATE_SPEED * deltaTime; |
|
||||||
|
|
||||||
glm::vec3 rotate = transform()->rotate(); |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_Q"))) { |
|
||||||
rotate.z += cameraRotateSpeed; |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_E"))) { |
|
||||||
rotate.z -= cameraRotateSpeed; |
|
||||||
} |
|
||||||
|
|
||||||
if (rotate.z > 180.0f) |
|
||||||
rotate.z -= 360.0f; |
|
||||||
else if (rotate.z <= -180.0f) |
|
||||||
rotate.z += 360.0f; |
|
||||||
|
|
||||||
transform()->setRotate(rotate); |
|
||||||
|
|
||||||
// Update camera translation
|
|
||||||
|
|
||||||
float cameraTranslateSpeed = TRANSLATE_SPEED * deltaTime; |
|
||||||
|
|
||||||
glm::vec3 translate = transform()->translate(); |
|
||||||
// WASD movement
|
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_W"))) { |
|
||||||
translate.x += -sin(glm::radians(rotate.z)) * cameraTranslateSpeed; |
|
||||||
translate.y += cos(glm::radians(rotate.z)) * cameraTranslateSpeed; |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_S"))) { |
|
||||||
translate.x -= -sin(glm::radians(rotate.z)) * cameraTranslateSpeed; |
|
||||||
translate.y -= cos(glm::radians(rotate.z)) * cameraTranslateSpeed; |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_A"))) { |
|
||||||
translate.x -= cos(glm::radians(rotate.z)) * cameraTranslateSpeed; |
|
||||||
translate.y -= sin(glm::radians(rotate.z)) * cameraTranslateSpeed; |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_D"))) { |
|
||||||
translate.x += cos(glm::radians(rotate.z)) * cameraTranslateSpeed; |
|
||||||
translate.y += sin(glm::radians(rotate.z)) * cameraTranslateSpeed; |
|
||||||
} |
|
||||||
|
|
||||||
transform()->setTranslate(translate); |
|
||||||
|
|
||||||
// Update camera zoom
|
|
||||||
|
|
||||||
float zoomSpeed = ZOOM_SENSITIVITY * deltaTime; |
|
||||||
|
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_EQUAL"))) { |
|
||||||
m_zoomLevel -= zoomSpeed; |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_MINUS"))) { |
|
||||||
m_zoomLevel += zoomSpeed; |
|
||||||
} |
|
||||||
m_zoomLevel = std::max(m_zoomLevel, 0.25f); |
|
||||||
m_zoomLevel = std::min(m_zoomLevel, 10.0f); |
|
||||||
|
|
||||||
// Update camera matrix
|
|
||||||
|
|
||||||
// Local space -> World space: model matrix
|
|
||||||
// Is done in Object::update()
|
|
||||||
|
|
||||||
// World space -> View space: view matrix
|
|
||||||
transform()->setTransform(glm::translate(glm::mat4(1.0f), translate) * glm::rotate(glm::mat4(1.0f), glm::radians(rotate.z), m_rotateAxis)); |
|
||||||
transform()->setTransform(glm::inverse(transform()->transform())); |
|
||||||
|
|
||||||
// View space -> Clip space: projection matrix
|
|
||||||
float aspectRatio = Application::the().getWindow().getAspect(); |
|
||||||
setProjection(glm::ortho(-aspectRatio * m_zoomLevel, aspectRatio * m_zoomLevel, -m_zoomLevel, m_zoomLevel, -1.0f, 1.0f)); |
|
||||||
|
|
||||||
// Clip space -> Screen space: viewport transform
|
|
||||||
// Is done in the fragment shader using the settings of glViewport
|
|
||||||
} |
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
PerspectiveCamera::PerspectiveCamera() |
|
||||||
: Camera({0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}) |
|
||||||
{ |
|
||||||
initialize(); |
|
||||||
} |
|
||||||
|
|
||||||
PerspectiveCamera::PerspectiveCamera(glm::vec3 translate, glm::vec3 rotate) |
|
||||||
: Camera(translate, rotate) |
|
||||||
{ |
|
||||||
initialize(); |
|
||||||
} |
|
||||||
|
|
||||||
void PerspectiveCamera::initialize() |
|
||||||
{ |
|
||||||
m_fov = 90.0f; |
|
||||||
m_pitch = 0.0f; |
|
||||||
m_yaw = -90.0f; |
|
||||||
|
|
||||||
// Up vector in world space
|
|
||||||
m_up = glm::vec3(0.0f, 1.0f, 0.0f); |
|
||||||
|
|
||||||
dbg(Log::Info) << "PerspectiveCamera initialized"; |
|
||||||
} |
|
||||||
|
|
||||||
void PerspectiveCamera::update(float deltaTime) |
|
||||||
{ |
|
||||||
// Get mouse movement offset compared to last frame
|
|
||||||
float xOffset = Input::getXOffset() * MOUSE_SENSITIVITY; |
|
||||||
float yOffset = Input::getYOffset() * MOUSE_SENSITIVITY; |
|
||||||
m_yaw += xOffset; |
|
||||||
m_pitch += yOffset; |
|
||||||
|
|
||||||
// Prevent gimbal lock
|
|
||||||
if (m_pitch > 89.0f) m_pitch = 89.0f; |
|
||||||
if (m_pitch < -89.0f) m_pitch = -89.0f; |
|
||||||
|
|
||||||
// Update camera rotation, by calculating direction vector via yaw and pitch
|
|
||||||
|
|
||||||
transform()->setRotate( |
|
||||||
cos(glm::radians(m_pitch)) * cos(glm::radians(m_yaw)), |
|
||||||
sin(glm::radians(m_pitch)), |
|
||||||
cos(glm::radians(m_pitch)) * sin(glm::radians(m_yaw))); |
|
||||||
transform()->setRotate(glm::normalize(transform()->rotate())); |
|
||||||
// The direction vector is based on
|
|
||||||
// Camera direction (z): normalize(position - target)
|
|
||||||
// Right axis (x): normalize(cross(up, direction))
|
|
||||||
// Up axis (y): cross(direction, right)
|
|
||||||
|
|
||||||
// Source: https://learnopengl.com/img/getting-started/camera_axes.png
|
|
||||||
|
|
||||||
// Cross = combination of two vectors in 3D space,
|
|
||||||
// where result is always perpendicular to both of the vectors
|
|
||||||
|
|
||||||
// Update camera translation
|
|
||||||
|
|
||||||
float cameraSpeed = TRANSLATE_SPEED * deltaTime; |
|
||||||
// WASD movement
|
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_W"))) { |
|
||||||
transform()->setTranslate(transform()->translate() + cameraSpeed * transform()->rotate()); |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_S"))) { |
|
||||||
transform()->setTranslate(transform()->translate() - cameraSpeed * transform()->rotate()); |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_A"))) { |
|
||||||
transform()->setTranslate(transform()->translate() - |
|
||||||
glm::normalize(glm::cross(transform()->rotate(), m_up)) * cameraSpeed); |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_D"))) { |
|
||||||
transform()->setTranslate(transform()->translate() + |
|
||||||
glm::normalize(glm::cross(transform()->rotate(), m_up)) * cameraSpeed); |
|
||||||
} |
|
||||||
// Up / down movement
|
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_SPACE"))) { |
|
||||||
transform()->setTranslate(transform()->translate().x, transform()->translate().y + cameraSpeed, transform()->translate().z); |
|
||||||
} |
|
||||||
if (Input::isKeyPressed(KeyCode("GLFW_KEY_LEFT_SHIFT"))) { |
|
||||||
transform()->setTranslate(transform()->translate().x, transform()->translate().y - cameraSpeed, transform()->translate().z); |
|
||||||
} |
|
||||||
|
|
||||||
// Update camera matrix
|
|
||||||
|
|
||||||
// Local space -> World space: model matrix
|
|
||||||
// Is done in Object::update()
|
|
||||||
|
|
||||||
// World space -> View space: view matrix
|
|
||||||
transform()->setTransform(glm::lookAt(transform()->translate(), transform()->translate() + transform()->rotate(), m_up)); |
|
||||||
|
|
||||||
// View space -> Clip space: projection matrix
|
|
||||||
float aspect = Application::the().getWindow().getAspect(); |
|
||||||
setProjection(glm::perspective(glm::radians(m_fov), aspect, NEAR_PLANE, FAR_PLANE)); |
|
||||||
|
|
||||||
// Clip space -> Screen space: viewport transform
|
|
||||||
// Is done in the fragment shader using the settings of glViewport
|
|
||||||
|
|
||||||
// Souce: https://learnopengl.com/img/getting-started/coordinate_systems.png
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,87 +0,0 @@ |
|||||||
#ifndef CAMERA_H |
|
||||||
#define CAMERA_H |
|
||||||
|
|
||||||
#define TRANSLATE_SPEED 2.5f |
|
||||||
#define ROTATE_SPEED 90.0f |
|
||||||
#define ZOOM_SENSITIVITY 2.5f |
|
||||||
#define MOUSE_SENSITIVITY 0.25f |
|
||||||
#define NEAR_PLANE 0.1f |
|
||||||
#define FAR_PLANE 100.0f |
|
||||||
|
|
||||||
#include <memory> // std::shared_ptr |
|
||||||
|
|
||||||
#include "glm/ext/matrix_float4x4.hpp" // glm::mat4 |
|
||||||
#include "glm/ext/vector_float3.hpp" // glm:vec3 |
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
class Transform; |
|
||||||
|
|
||||||
class Camera { |
|
||||||
public: |
|
||||||
Camera(); |
|
||||||
Camera(glm::vec3 translate, glm::vec3 rotate); |
|
||||||
virtual ~Camera() {} |
|
||||||
|
|
||||||
virtual void initialize() = 0; |
|
||||||
virtual void update(float deltaTime) = 0; |
|
||||||
// virtual void render() = 0;
|
|
||||||
// virtual void destroy() = 0;
|
|
||||||
|
|
||||||
void setProjection(glm::mat4 projection) { m_projection = projection; } |
|
||||||
|
|
||||||
const glm::mat4& projection() const { return m_projection; } |
|
||||||
const std::shared_ptr<Transform>& transform() const { return m_transform; } |
|
||||||
|
|
||||||
private: |
|
||||||
glm::mat4 m_projection; |
|
||||||
std::shared_ptr<Transform> m_transform; |
|
||||||
}; |
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
class OrthographicCamera final : public Camera { |
|
||||||
public: |
|
||||||
OrthographicCamera(); |
|
||||||
OrthographicCamera(glm::vec3 translate, glm::vec3 rotate); |
|
||||||
virtual ~OrthographicCamera() {} |
|
||||||
|
|
||||||
virtual void initialize() override; |
|
||||||
virtual void update(float deltaTime) override; |
|
||||||
// virtual void render() override;
|
|
||||||
// virtual void destroy() override;
|
|
||||||
|
|
||||||
private: |
|
||||||
float m_zoomLevel; |
|
||||||
glm::vec3 m_rotateAxis; |
|
||||||
}; |
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
class PerspectiveCamera final : public Camera { |
|
||||||
public: |
|
||||||
PerspectiveCamera(); |
|
||||||
PerspectiveCamera(glm::vec3 translate, glm::vec3 rotate); |
|
||||||
virtual ~PerspectiveCamera() {} |
|
||||||
|
|
||||||
virtual void initialize() override; |
|
||||||
virtual void update(float deltaTime) override; |
|
||||||
// virtual void render() override;
|
|
||||||
// virtual void destroy() override;
|
|
||||||
|
|
||||||
private: |
|
||||||
float m_fov; |
|
||||||
float m_pitch; |
|
||||||
float m_yaw; |
|
||||||
glm::vec3 m_up; |
|
||||||
}; |
|
||||||
|
|
||||||
// ----------------------------------------
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
#endif // CAMERA_H
|
|
||||||
|
|
||||||
// @Todo:
|
|
||||||
// - Add sensitivity, fov to settings:camera
|
|
||||||
// - Change ortho view matrix to use glm::lookAt()
|
|
Loading…
Reference in new issue