Add EditorCameraComponent and EditorCameraSystem

This commit is contained in:
SweetId 2023-11-20 14:59:23 +05:30
parent 64171da71a
commit 13a50a87dd
4 changed files with 210 additions and 0 deletions

View File

@ -0,0 +1,39 @@
#pragma once
#include <NazaraEditor/Core/Core.hpp>
#include <Nazara/Platform/WindowEventHandler.hpp>
namespace Nz
{
class NodeComponent;
class WindowEventHandler;
class NAZARAEDITOR_CORE_API EditorCameraComponent
{
public:
EditorCameraComponent();
EditorCameraComponent(const EditorCameraComponent&) = delete;
EditorCameraComponent(EditorCameraComponent&&);
~EditorCameraComponent();
void Update(Time elapsedTime, NodeComponent& node);
inline void SetPosition(const Nz::Vector3f& position) { m_targetPosition = position; }
inline void SetRotation(const Nz::Quaternionf& rotation) { m_targetAngles = rotation.ToEulerAngles(); }
inline const Nz::Vector3f& GetPosition() const { return m_targetPosition; }
inline const Nz::EulerAnglesf& GetOrientation() const { return m_targetAngles; }
private:
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, m_onMouseMoved);
Nz::EulerAnglesf m_targetAngles;
Nz::Vector3f m_targetPosition;
Nz::Vector3f m_currentVelocity;
float m_moveSpeed;
float m_smoothSpeed;
};
}

View File

@ -0,0 +1,37 @@
#pragma once
#include <NazaraEditor/Core/Core.hpp>
#include <entt/entt.hpp>
#include <unordered_set>
namespace Nz
{
class NAZARAEDITOR_CORE_API EditorCameraSystem
{
public:
static constexpr bool AllowConcurrent = false;
static constexpr Int64 ExecutionOrder = 1'001;
EditorCameraSystem(entt::registry& registry);
~EditorCameraSystem();
EditorCameraSystem(const EditorCameraSystem&) = delete;
EditorCameraSystem& operator=(const EditorCameraSystem&) = delete;
EditorCameraSystem(EditorCameraSystem&&) = delete;
EditorCameraSystem& operator=(EditorCameraSystem&&) = delete;
void Update(Time elapsedTime);
private:
void OnCameraDestroy(entt::registry& registry, entt::entity entity);
entt::registry& m_registry;
entt::observer m_cameraConstructObserver;
entt::scoped_connection m_cameraDestroyConnection;
std::unordered_set<entt::entity> m_cameraEntities;
};
}

View File

@ -0,0 +1,95 @@
#include <NazaraEditor/Core/Components/CameraComponent.hpp>
#include <NazaraEditor/Core/Application/BaseApplication.hpp>
namespace
{
// Unity SmoothDamp function
template <typename T>
T SmoothDamp(T current, T target, T& currentVelocity, float smoothTime, Nz::Time deltaTime)
{
if (current.SquaredDistance(target) < 0.0001f)
return target;
// Based on Game Programming Gems 4 Chapter 1.10
smoothTime = std::max(0.0001f, smoothTime);
float omega = 2.f / smoothTime;
float x = omega * deltaTime.AsSeconds();
float exp = 1.f / (1.f + x + 0.48f * x * x + 0.235f * x * x * x);
T change = current - target;
T originalTo = target;
// Clamp maximum speed
float maxChange = smoothTime;
float dist = change.GetLength();
dist = Nz::Clamp(dist, -maxChange, maxChange);
target = current - change.Normalize() * dist;
T temp = (currentVelocity + omega * change) * deltaTime.AsSeconds();
currentVelocity = (currentVelocity - omega * temp) * exp;
T output = target + (change + temp) * exp;
// Prevent overshooting
if (current.SquaredDistance(target) <= current.SquaredDistance(output))
{
output = originalTo;
currentVelocity = (output - originalTo) / deltaTime.AsSeconds();
}
return output;
}
}
namespace Nz
{
EditorCameraComponent::EditorCameraComponent()
: m_moveSpeed(3.f)
, m_smoothSpeed(0.3f)
{
auto& handler = EditorBaseApplication::Instance()->GetWindow()->GetEventHandler();
m_onMouseMoved.Connect(handler.OnMouseMoved, [&](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event)
{
// Gestion de la caméra free-fly (Rotation)
float sensitivity = 0.3f; // Sensibilité de la souris
// On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris
m_targetAngles.yaw = m_targetAngles.yaw - event.deltaX * sensitivity;
m_targetAngles.yaw.Normalize();
// Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles
m_targetAngles.pitch = Nz::Clamp(m_targetAngles.pitch - event.deltaY * sensitivity, -89.f, 89.f);
});
}
EditorCameraComponent::~EditorCameraComponent()
{
m_onMouseMoved.Disconnect();
}
void EditorCameraComponent::Update(Time elapsedTime, NodeComponent& node)
{
// todo use action mapping
Nz::Vector3f delta;
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::W))
delta += Nz::Vector3f::Forward();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::S))
delta += Nz::Vector3f::Backward();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::A))
delta += Nz::Vector3f::Left();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D))
delta += Nz::Vector3f::Right();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Q))
delta += Nz::Vector3f::Up();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::E))
delta += Nz::Vector3f::Down();
auto currentRotation = m_targetAngles.ToQuaternion();
m_targetPosition += (currentRotation * delta) * elapsedTime.AsSeconds() * m_moveSpeed;
auto currentPosition = SmoothDamp(node.GetPosition(), m_targetPosition, m_currentVelocity, m_smoothSpeed, elapsedTime);
node.SetPosition(currentPosition);
node.SetRotation(currentRotation);
}
}

View File

@ -0,0 +1,39 @@
#include <NazaraEditor/Core/Systems/CameraSystem.hpp>
#include <NazaraEditor/Core/Components/CameraComponent.hpp>
#include <Nazara/Utility/Components/NodeComponent.hpp>
namespace Nz
{
EditorCameraSystem::EditorCameraSystem(entt::registry& registry)
: m_registry(registry)
, m_cameraConstructObserver(registry, entt::collector.group<EditorCameraComponent, NodeComponent>())
{
m_cameraDestroyConnection = registry.on_destroy<EditorCameraComponent>().connect<&EditorCameraSystem::OnCameraDestroy>(this);
}
EditorCameraSystem::~EditorCameraSystem()
{
m_cameraConstructObserver.disconnect();
}
void EditorCameraSystem::Update(Time elapsedTime)
{
m_cameraConstructObserver.each([&](entt::entity entity) {
m_cameraEntities.insert(entity);
});
for (auto entity : m_cameraEntities)
{
EditorCameraComponent& camera = m_registry.get<EditorCameraComponent>(entity);
NodeComponent& transform = m_registry.get<NodeComponent>(entity);
camera.Update(elapsedTime, transform);
}
}
void EditorCameraSystem::OnCameraDestroy(entt::registry& registry, entt::entity entity)
{
m_cameraEntities.erase(entity);
}
}