Browse Source

Add camera class

master
Riyyi 4 years ago
parent
commit
ab9a94358a
  1. 211
      inferno/src/inferno/render/camera.cpp
  2. 87
      inferno/src/inferno/render/camera.h

211
inferno/src/inferno/render/camera.cpp

@ -0,0 +1,211 @@
#include <memory> // std::make_shared
#include <glm/ext/matrix_clip_space.hpp> // glm::perspective, glm::ortho
#include <glm/ext/matrix_transform.hpp> // glm::radians
#include <glm/gtx/transform.hpp> // glm::lookAt, glm::perspective
#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()
{
// Set the roatation axis
m_rotate = 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 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_rotate));
transform()->setTransform(glm::inverse(transform()->transform()));
// View space -> Clip space: projection matrix
float aspectRatio = Application::get().getWindow().getAspect();
setProjection(glm::ortho(-aspectRatio, aspectRatio, -1.0f, 1.0f, -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() * SENSITIVITY;
float yOffset = Input::getYOffset() * 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::get().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
}
}

87
inferno/src/inferno/render/camera.h

@ -0,0 +1,87 @@
#ifndef CAMERA_H
#define CAMERA_H
#include "inferno/log.h" // @@@@@@@@@@
#define TRANSLATE_SPEED 2.5f
#define ROTATE_SPEED 90.0f
#define 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() { dbg(Log::Danger) << "KILLED 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() { dbg(Log::Danger) << "KILLED ORTHOGRAPHICCAMERA"; }
virtual void initialize() override;
virtual void update(float deltaTime) override;
// virtual void render() override;
// virtual void destroy() override;
private:
glm::vec3 m_rotate;
};
// ----------------------------------------
class PerspectiveCamera final : public Camera {
public:
PerspectiveCamera();
PerspectiveCamera(glm::vec3 translate, glm::vec3 rotate);
virtual ~PerspectiveCamera() { dbg(Log::Danger) << "KILLED 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
// - Add zoom to ortho camera
// - Change ortho view matrix to use glm::lookAt()
Loading…
Cancel
Save