Ndk: Added CameraComponent (WIP)
Former-commit-id: ae7be5448a1150b7beba10e03916e94df51ea3a0
This commit is contained in:
parent
a494ce5cca
commit
e55b4edd0c
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NDK_COMPONENTS_CAMERACOMPONENT_HPP
|
||||||
|
#define NDK_COMPONENTS_CAMERACOMPONENT_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Math/Frustum.hpp>
|
||||||
|
#include <Nazara/Math/Matrix4.hpp>
|
||||||
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||||
|
#include <NDK/Component.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
class Entity;
|
||||||
|
|
||||||
|
class NDK_API CameraComponent : public Component<CameraComponent>, NzRenderTarget::Listener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CameraComponent();
|
||||||
|
~CameraComponent();
|
||||||
|
|
||||||
|
void EnsureFrustumUpdate() const;
|
||||||
|
void EnsureProjectionMatrixUpdate() const;
|
||||||
|
void EnsureViewMatrixUpdate() const;
|
||||||
|
void EnsureViewportUpdate() const;
|
||||||
|
|
||||||
|
float GetAspectRatio() const;
|
||||||
|
NzVector3f GetEyePosition() const;
|
||||||
|
NzVector3f GetForward() const;
|
||||||
|
float GetFOV() const;
|
||||||
|
const NzFrustumf& GetFrustum() const;
|
||||||
|
unsigned int GetLayer() const;
|
||||||
|
const NzMatrix4f& GetProjectionMatrix() const;
|
||||||
|
const NzRenderTarget* GetTarget() const;
|
||||||
|
const NzRectf& GetTargetRegion() const;
|
||||||
|
const NzMatrix4f& GetViewMatrix() const;
|
||||||
|
const NzRecti& GetViewport() const;
|
||||||
|
float GetZFar() const;
|
||||||
|
float GetZNear() const;
|
||||||
|
|
||||||
|
void SetFOV(float fov);
|
||||||
|
void SetLayer(unsigned int layer);
|
||||||
|
void SetTarget(const NzRenderTarget* renderTarget);
|
||||||
|
void SetTargetRegion(const NzRectf& region);
|
||||||
|
void SetViewport(const NzRecti& viewport);
|
||||||
|
void SetZFar(float zFar);
|
||||||
|
void SetZNear(float zNear);
|
||||||
|
|
||||||
|
static ComponentIndex componentIndex;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void InvalidateFrustum() const;
|
||||||
|
void InvalidateProjectionMatrix() const;
|
||||||
|
void InvalidateViewMatrix() const;
|
||||||
|
void InvalidateViewport() const;
|
||||||
|
|
||||||
|
void OnAttached() override;
|
||||||
|
void OnComponentAttached(BaseComponent& component) override;
|
||||||
|
void OnComponentDetached(BaseComponent& component) override;
|
||||||
|
void OnDetached() override;
|
||||||
|
void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) override;
|
||||||
|
bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) override;
|
||||||
|
|
||||||
|
void UpdateFrustum() const;
|
||||||
|
void UpdateProjectionMatrix() const;
|
||||||
|
void UpdateViewMatrix() const;
|
||||||
|
void UpdateViewport() const;
|
||||||
|
|
||||||
|
mutable NzFrustumf m_frustum;
|
||||||
|
mutable NzMatrix4f m_projectionMatrix;
|
||||||
|
mutable NzMatrix4f m_viewMatrix;
|
||||||
|
NzRectf m_targetRegion;
|
||||||
|
mutable NzRecti m_viewport;
|
||||||
|
const NzRenderTarget* m_target;
|
||||||
|
mutable bool m_frustumUpdated;
|
||||||
|
mutable bool m_projectionMatrixUpdated;
|
||||||
|
mutable bool m_viewMatrixUpdated;
|
||||||
|
mutable bool m_viewportUpdated;
|
||||||
|
mutable float m_aspectRatio;
|
||||||
|
float m_fov;
|
||||||
|
float m_zFar;
|
||||||
|
float m_zNear;
|
||||||
|
unsigned int m_layer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <NDK/Components/CameraComponent.inl>
|
||||||
|
|
||||||
|
#endif // NDK_COMPONENTS_CAMERACOMPONENT_HPP
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
inline CameraComponent::CameraComponent() :
|
||||||
|
m_targetRegion(0.f, 0.f, 1.f, 1.f),
|
||||||
|
m_target(nullptr),
|
||||||
|
m_frustumUpdated(false),
|
||||||
|
m_projectionMatrixUpdated(false),
|
||||||
|
m_viewMatrixUpdated(false),
|
||||||
|
m_viewportUpdated(false),
|
||||||
|
m_aspectRatio(0.f),
|
||||||
|
m_fov(70.f),
|
||||||
|
m_zFar(100.f),
|
||||||
|
m_zNear(1.f),
|
||||||
|
m_layer(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CameraComponent::~CameraComponent()
|
||||||
|
{
|
||||||
|
if (m_target)
|
||||||
|
m_target->RemoveListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::EnsureFrustumUpdate() const
|
||||||
|
{
|
||||||
|
if (!m_frustumUpdated)
|
||||||
|
UpdateFrustum();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::EnsureProjectionMatrixUpdate() const
|
||||||
|
{
|
||||||
|
if (!m_projectionMatrixUpdated)
|
||||||
|
UpdateProjectionMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::EnsureViewMatrixUpdate() const
|
||||||
|
{
|
||||||
|
if (!m_viewMatrixUpdated)
|
||||||
|
UpdateViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::EnsureViewportUpdate() const
|
||||||
|
{
|
||||||
|
if (!m_viewportUpdated)
|
||||||
|
UpdateViewport();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float CameraComponent::GetAspectRatio() const
|
||||||
|
{
|
||||||
|
EnsureViewportUpdate();
|
||||||
|
|
||||||
|
return m_aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float CameraComponent::GetFOV() const
|
||||||
|
{
|
||||||
|
return m_fov;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const NzFrustumf& CameraComponent::GetFrustum() const
|
||||||
|
{
|
||||||
|
EnsureFrustumUpdate();
|
||||||
|
|
||||||
|
return m_frustum;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const NzMatrix4f& CameraComponent::GetProjectionMatrix() const
|
||||||
|
{
|
||||||
|
EnsureProjectionMatrixUpdate();
|
||||||
|
|
||||||
|
return m_projectionMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const NzRenderTarget* CameraComponent::GetTarget() const
|
||||||
|
{
|
||||||
|
return m_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const NzRectf& CameraComponent::GetTargetRegion() const
|
||||||
|
{
|
||||||
|
return m_targetRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const NzMatrix4f& CameraComponent::GetViewMatrix() const
|
||||||
|
{
|
||||||
|
EnsureViewMatrixUpdate();
|
||||||
|
|
||||||
|
return m_viewMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const NzRecti& CameraComponent::GetViewport() const
|
||||||
|
{
|
||||||
|
EnsureViewportUpdate();
|
||||||
|
|
||||||
|
return m_viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float CameraComponent::GetZFar() const
|
||||||
|
{
|
||||||
|
return m_zFar;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float CameraComponent::GetZNear() const
|
||||||
|
{
|
||||||
|
return m_zNear;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::SetFOV(float fov)
|
||||||
|
{
|
||||||
|
NazaraAssert(fov != 0.f, "FOV must be different from zero");
|
||||||
|
|
||||||
|
m_fov = fov;
|
||||||
|
InvalidateProjectionMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::SetTarget(const NzRenderTarget* renderTarget)
|
||||||
|
{
|
||||||
|
if (m_target)
|
||||||
|
m_target->RemoveListener(this);
|
||||||
|
|
||||||
|
m_target = renderTarget;
|
||||||
|
if (m_target)
|
||||||
|
m_target->AddListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::SetTargetRegion(const NzRectf& region)
|
||||||
|
{
|
||||||
|
m_targetRegion = region;
|
||||||
|
InvalidateViewport();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::SetViewport(const NzRecti& viewport)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_target, "Component has no render target");
|
||||||
|
|
||||||
|
// On calcule la région nécessaire pour produire ce viewport avec la taille actuelle de la cible
|
||||||
|
float invWidth = 1.f/m_target->GetWidth();
|
||||||
|
float invHeight = 1.f/m_target->GetHeight();
|
||||||
|
|
||||||
|
SetTargetRegion(NzRectf(invWidth * viewport.x, invHeight * viewport.y, invWidth * viewport.width, invHeight * viewport.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::SetZFar(float zFar)
|
||||||
|
{
|
||||||
|
m_zFar = zFar;
|
||||||
|
InvalidateProjectionMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::SetZNear(float zNear)
|
||||||
|
{
|
||||||
|
NazaraAssert(NzNumberEquals(zNear, 0.f), "zNear cannot be zero");
|
||||||
|
|
||||||
|
m_zNear = zNear;
|
||||||
|
InvalidateProjectionMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::InvalidateFrustum() const
|
||||||
|
{
|
||||||
|
m_frustumUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::InvalidateProjectionMatrix() const
|
||||||
|
{
|
||||||
|
m_frustumUpdated = false;
|
||||||
|
m_projectionMatrixUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::InvalidateViewMatrix() const
|
||||||
|
{
|
||||||
|
m_frustumUpdated = false;
|
||||||
|
m_viewMatrixUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CameraComponent::InvalidateViewport() const
|
||||||
|
{
|
||||||
|
m_frustumUpdated = false;
|
||||||
|
m_projectionMatrixUpdated = false;
|
||||||
|
m_viewportUpdated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Components/CameraComponent.hpp>
|
||||||
|
#include <NDK/Algorithm.hpp>
|
||||||
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
/*void CameraComponent::InvalidateNode()
|
||||||
|
{
|
||||||
|
NzNode::InvalidateNode();
|
||||||
|
|
||||||
|
// Le frustum et la view matrix dépendent des paramètres du node, invalidons-les
|
||||||
|
m_frustumUpdated = false;
|
||||||
|
m_viewMatrixUpdated = false;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void CameraComponent::OnAttached()
|
||||||
|
{
|
||||||
|
InvalidateViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraComponent::OnComponentAttached(BaseComponent& component)
|
||||||
|
{
|
||||||
|
if (IsComponent<NodeComponent>(component))
|
||||||
|
InvalidateViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraComponent::OnComponentDetached(BaseComponent& component)
|
||||||
|
{
|
||||||
|
if (IsComponent<NodeComponent>(component))
|
||||||
|
InvalidateViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraComponent::OnDetached()
|
||||||
|
{
|
||||||
|
InvalidateViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraComponent::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
if (renderTarget == m_target)
|
||||||
|
m_target = nullptr;
|
||||||
|
else
|
||||||
|
NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CameraComponent::OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
if (renderTarget == m_target)
|
||||||
|
{
|
||||||
|
InvalidateViewport();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NazaraInternalError("Not listening to " + NzString::Pointer(renderTarget));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraComponent::UpdateFrustum() const
|
||||||
|
{
|
||||||
|
EnsureProjectionMatrixUpdate();
|
||||||
|
EnsureViewMatrixUpdate();
|
||||||
|
|
||||||
|
m_frustum.Extract(m_viewMatrix, m_projectionMatrix);
|
||||||
|
m_frustumUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraComponent::UpdateProjectionMatrix() const
|
||||||
|
{
|
||||||
|
EnsureViewportUpdate(); // Peut affecter l'aspect ratio
|
||||||
|
|
||||||
|
m_projectionMatrix.MakePerspective(m_fov, m_aspectRatio, m_zNear, m_zFar);
|
||||||
|
m_projectionMatrixUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraComponent::UpdateViewMatrix() const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_entity && m_entity->HasComponent<NodeComponent>(), "CameraComponent requires NodeComponent");
|
||||||
|
|
||||||
|
NodeComponent& nodeComponent = m_entity->GetComponent<NodeComponent>();
|
||||||
|
|
||||||
|
m_viewMatrix.MakeViewMatrix(nodeComponent.GetPosition(nzCoordSys_Global), nodeComponent.GetRotation(nzCoordSys_Global));
|
||||||
|
m_viewMatrixUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraComponent::UpdateViewport() const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_target, "CameraComponent has no target");
|
||||||
|
|
||||||
|
unsigned int targetWidth = m_target->GetWidth();
|
||||||
|
unsigned int targetHeight = std::max(m_target->GetHeight(), 1U); // Pour éviter une division par zéro
|
||||||
|
|
||||||
|
// La zone visée est définie en "pourcentage" (0...1), on calcule les valeurs en pixel
|
||||||
|
NzRectf fViewport(m_targetRegion);
|
||||||
|
fViewport.x *= targetWidth;
|
||||||
|
fViewport.y *= targetHeight;
|
||||||
|
fViewport.width *= targetWidth;
|
||||||
|
fViewport.height *= targetHeight;
|
||||||
|
|
||||||
|
// On calcule le rapport largeur/hauteur, et s'il est différent on invalide
|
||||||
|
float aspectRatio = fViewport.width/fViewport.height;
|
||||||
|
if (!NzNumberEquals(m_aspectRatio, aspectRatio, 0.001f))
|
||||||
|
{
|
||||||
|
m_aspectRatio = aspectRatio;
|
||||||
|
|
||||||
|
InvalidateProjectionMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_viewport.Set(fViewport);
|
||||||
|
m_viewportUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentIndex CameraComponent::componentIndex;
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <Nazara/Utility/Utility.hpp>
|
#include <Nazara/Utility/Utility.hpp>
|
||||||
#include <NDK/Algorithm.hpp>
|
#include <NDK/Algorithm.hpp>
|
||||||
#include <NDK/BaseSystem.hpp>
|
#include <NDK/BaseSystem.hpp>
|
||||||
|
#include <NDK/Components/CameraComponent.hpp>
|
||||||
#include <NDK/Components/CollisionComponent.hpp>
|
#include <NDK/Components/CollisionComponent.hpp>
|
||||||
#include <NDK/Components/ListenerComponent.hpp>
|
#include <NDK/Components/ListenerComponent.hpp>
|
||||||
#include <NDK/Components/NodeComponent.hpp>
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
|
@ -52,6 +53,7 @@ namespace Ndk
|
||||||
BaseSystem::Initialize();
|
BaseSystem::Initialize();
|
||||||
|
|
||||||
// Composants
|
// Composants
|
||||||
|
InitializeComponent<CameraComponent>("NdkCam");
|
||||||
InitializeComponent<CollisionComponent>("NdkColli");
|
InitializeComponent<CollisionComponent>("NdkColli");
|
||||||
InitializeComponent<ListenerComponent>("NdkList");
|
InitializeComponent<ListenerComponent>("NdkList");
|
||||||
InitializeComponent<NodeComponent>("NdkNode");
|
InitializeComponent<NodeComponent>("NdkNode");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue