Browse Source

Add transform and camera system

master
Riyyi 3 years ago
parent
commit
716c6569c0
  1. 125
      inferno/src/inferno/systems/camera.cpp
  2. 42
      inferno/src/inferno/systems/camera.h
  3. 50
      inferno/src/inferno/systems/transform.cpp
  4. 28
      inferno/src/inferno/systems/transform.h

125
inferno/src/inferno/systems/camera.cpp

@ -0,0 +1,125 @@
#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/assertions.h"
#include "inferno/input.h"
#include "inferno/inputcodes.h"
#include "inferno/log.h"
#include "inferno/scene/entity.h"
#include "inferno/systems/camera.h"
#include "inferno/window.h"
namespace Inferno {
CameraSystem* CameraSystem::s_instance = nullptr;
void CameraSystem::initialize()
{
ASSERT(!s_instance, "CameraSystem already exists!");
s_instance = this;
dbg(Log::Info) << "CameraSystem initialized";
}
void CameraSystem::update()
{
auto orthoView = m_registry->view<TransformComponent, OrthographicCameraComponment>();
for(auto&& [entity, transform, orthographic] : orthoView.each()) {
updateOrthographic(transform, orthographic);
}
auto perspectiveView = m_registry->view<TransformComponent, PerspectiveCameraComponent>();
for(auto&& [entity, transform, perspective] : perspectiveView.each()) {
updatePerspective(transform, perspective);
}
}
void CameraSystem::destroy()
{
delete s_instance;
s_instance = nullptr;
}
void CameraSystem::updateOrthographic(TransformComponent& transform, OrthographicCameraComponment& orthographic)
{
}
void CameraSystem::updatePerspective(TransformComponent& transform, PerspectiveCameraComponent& perspective)
{
// Get mouse movement offset compared to last frame
float xOffset = Input::getXOffset() * MOUSE_SENSITIVITY;
float yOffset = Input::getYOffset() * MOUSE_SENSITIVITY;
perspective.yaw += xOffset;
perspective.pitch += yOffset;
// Prevent gimbal lock
if (perspective.pitch > 89.0f) perspective.pitch = 89.0f;
if (perspective.pitch < -89.0f) perspective.pitch = -89.0f;
// Update camera rotation, by calculating direction vector via yaw and pitch
transform.rotate = {
cos(glm::radians(perspective.pitch)) * cos(glm::radians(perspective.yaw)),
sin(glm::radians(perspective.pitch)),
cos(glm::radians(perspective.pitch)) * sin(glm::radians(perspective.yaw))
};
transform.rotate = 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 * (1.0f / 60.0f);
// WASD movement
if (Input::isKeyPressed(KeyCode("GLFW_KEY_W"))) {
transform.translate = { transform.translate + cameraSpeed * transform.rotate };
}
if (Input::isKeyPressed(KeyCode("GLFW_KEY_S"))) {
transform.translate = { transform.translate - cameraSpeed * transform.rotate };
}
if (Input::isKeyPressed(KeyCode("GLFW_KEY_A"))) {
transform.translate = { transform.translate -
glm::normalize(glm::cross(transform.rotate, perspective.up)) * cameraSpeed };
}
if (Input::isKeyPressed(KeyCode("GLFW_KEY_D"))) {
transform.translate = { transform.translate +
glm::normalize(glm::cross(transform.rotate, perspective.up)) * cameraSpeed };
}
// Up / down movement
if (Input::isKeyPressed(KeyCode("GLFW_KEY_SPACE"))) {
transform.translate = { transform.translate.x, transform.translate.y + cameraSpeed, transform.translate.z };
}
if (Input::isKeyPressed(KeyCode("GLFW_KEY_LEFT_SHIFT"))) {
transform.translate = { 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.transform = { glm::lookAt(transform.translate, transform.translate + transform.rotate, perspective.up) };
// View space -> Clip space: projection matrix
float aspect = Application::the().getWindow().getAspect();
perspective.projection = { glm::perspective(glm::radians(perspective.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
}
}

42
inferno/src/inferno/systems/camera.h

@ -0,0 +1,42 @@
#ifndef CAMERA_SYSTEM_H
#define CAMERA_SYSTEM_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 "entt/entity/registry.hpp" // entt::entity, entt::registry
#include "inferno/scene/components.h"
namespace Inferno {
class Entity;
class CameraSystem {
public:
void initialize();
void update();
void destroy();
void setRegistry(const std::shared_ptr<entt::registry>& registry) { m_registry = registry; };
static inline CameraSystem& the() { return *s_instance; }
private:
void updateOrthographic(TransformComponent& transform, OrthographicCameraComponment& orthographic);
void updatePerspective(TransformComponent& transform, PerspectiveCameraComponent& perspective);
std::shared_ptr<entt::registry> m_registry;
static CameraSystem* s_instance;
};
}
#endif // CAMERA_SYSTEM_H

50
inferno/src/inferno/systems/transform.cpp

@ -0,0 +1,50 @@
#include <glm/ext/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::radians
#include "inferno/assertions.h"
#include "inferno/log.h"
#include "inferno/scene/components.h"
#include "inferno/systems/transform.h"
namespace Inferno {
TransformSystem* TransformSystem::s_instance = nullptr;
void TransformSystem::initialize()
{
ASSERT(!s_instance, "TransformSystem already exists!");
s_instance = this;
dbg(Log::Info) << "TransformSystem initialized";
}
void TransformSystem::update()
{
auto view = m_registry->view<TransformComponent>();
for (auto entity : view) {
auto& component = view.get<TransformComponent>(entity);
// Identity matrix
component.transform = glm::mat4(1.0f);
// Translate
component.transform = glm::translate(component.transform, component.translate);
// Rotate
component.transform = glm::rotate(component.transform, glm::radians(component.rotate.x), {1.0, 0.0, 0.0});
component.transform = glm::rotate(component.transform, glm::radians(component.rotate.y), {0.0, 1.0, 0.0});
component.transform = glm::rotate(component.transform, glm::radians(component.rotate.z), {0.0, 0.0, 1.0});
// Scale
component.transform = glm::scale(component.transform, component.scale);
}
}
void TransformSystem::destroy()
{
delete s_instance;
s_instance = nullptr;
}
}

28
inferno/src/inferno/systems/transform.h

@ -0,0 +1,28 @@
#ifndef TRANSFORM_SYSTEM_H
#define TRANSFORM_SYSTEM_H
#include <memory> //std::shared_ptr
#include "entt/entity/registry.hpp" // entt::entity, entt::registry
namespace Inferno {
class TransformSystem {
public:
void initialize();
void update();
void destroy();
void setRegistry(const std::shared_ptr<entt::registry>& registry) { m_registry = registry; };
static inline TransformSystem& the() { return *s_instance; }
private:
std::shared_ptr<entt::registry> m_registry;
static TransformSystem* s_instance;
};
}
#endif // TRANSFORM_SYSTEM_H
Loading…
Cancel
Save