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