You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
2.9 KiB
104 lines
2.9 KiB
/* |
|
* Copyright (C) 2022,2024 Riyyi |
|
* |
|
* SPDX-License-Identifier: MIT |
|
*/ |
|
|
|
#include <utility> // std::pair |
|
|
|
#include "glm/ext/matrix_clip_space.hpp" // glm::perspective, glm::ortho |
|
#include "glm/ext/matrix_transform.hpp" // glm::radians, glm::lookAt |
|
#include "ruc/format/log.h" |
|
#include "ruc/meta/assert.h" |
|
|
|
#include "inferno/application.h" |
|
#include "inferno/component/cameracomponent.h" |
|
#include "inferno/component/transformcomponent.h" |
|
#include "inferno/io/input.h" |
|
#include "inferno/system/camerasystem.h" |
|
#include "inferno/window.h" |
|
|
|
namespace Inferno { |
|
|
|
CameraSystem::CameraSystem(s) |
|
{ |
|
ruc::info("CameraSystem initialized"); |
|
} |
|
|
|
CameraSystem::~CameraSystem() |
|
{ |
|
} |
|
|
|
void CameraSystem::update() |
|
{ |
|
auto view = m_registry->view<TransformComponent, CameraComponent>(); |
|
|
|
for (auto [entity, transform, camera] : view.each()) { |
|
|
|
if (camera.type == CameraType::Orthographic) { |
|
updateOrthographic(transform, camera); |
|
} |
|
else if (camera.type == CameraType::Perspective) { |
|
updatePerspective(transform, camera); |
|
} |
|
} |
|
} |
|
|
|
std::pair<glm::mat4, glm::mat4> CameraSystem::projectionView() |
|
{ |
|
auto view = m_registry->view<TransformComponent, CameraComponent>(); |
|
|
|
for (auto [entity, transform, camera] : view.each()) { |
|
return { camera.projection, transform.transform }; |
|
} |
|
|
|
VERIFY_NOT_REACHED(); |
|
|
|
return {}; |
|
} |
|
|
|
void CameraSystem::updateOrthographic(TransformComponent& transform, CameraComponent& camera) |
|
{ |
|
// Update camera matrix |
|
|
|
// Local space -> World space: model matrix |
|
// Is done in Object::update() |
|
|
|
// World space -> View space: view matrix |
|
transform.transform = { |
|
glm::translate(glm::mat4(1.0f), transform.translate) * glm::rotate(glm::mat4(1.0f), glm::radians(transform.rotate.z), camera.rotateAxis) |
|
}; |
|
transform.transform = { glm::inverse(transform.transform) }; |
|
|
|
// View space -> Clip space: projection matrix |
|
float aspectRatio = Application::the().window().getAspect(); |
|
camera.projection = { |
|
glm::ortho(-aspectRatio * camera.zoomLevel, aspectRatio * camera.zoomLevel, |
|
-camera.zoomLevel, camera.zoomLevel, -1.0f, 1.0f) |
|
}; |
|
|
|
// Clip space -> Screen space: viewport transform |
|
// Is done in the fragment shader using the settings of glViewport |
|
} |
|
|
|
void CameraSystem::updatePerspective(TransformComponent& transform, CameraComponent& camera) |
|
{ |
|
// 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, camera.up) }; |
|
|
|
// View space -> Clip space: projection matrix |
|
float aspect = Application::the().window().getAspect(); |
|
camera.projection = { glm::perspective(glm::radians(camera.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 |
|
} |
|
|
|
} // namespace Inferno
|
|
|