Inferno Game Engine
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

/*
* 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