Riyyi
4 years ago
4 changed files with 245 additions and 0 deletions
@ -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
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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
|
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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…
Reference in new issue