From e873d40ccc9818e28969b9573967e48bc6763d1c Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 18 Mar 2015 20:26:59 +0100 Subject: [PATCH] (View) Added Map[Pixel|World]To[World|Pixel] method Former-commit-id: 39295c71d040d472117cb30c266169476f563e9d --- include/Nazara/Graphics/View.hpp | 11 ++++ src/Nazara/Graphics/View.cpp | 86 ++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/include/Nazara/Graphics/View.hpp b/include/Nazara/Graphics/View.hpp index 41cab8fe8..b10b30cc0 100644 --- a/include/Nazara/Graphics/View.hpp +++ b/include/Nazara/Graphics/View.hpp @@ -35,15 +35,20 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget NzVector3f GetGlobalForward() const; NzVector3f GetGlobalRight() const; NzVector3f GetGlobalUp() const; + const NzMatrix4f& GetInvViewProjMatrix() const; const NzMatrix4f& GetProjectionMatrix() const; const NzVector2f& GetSize() const; const NzRenderTarget* GetTarget() const; const NzRectf& GetTargetRegion() const; const NzMatrix4f& GetViewMatrix() const; + const NzMatrix4f& GetViewProjMatrix() const; const NzRecti& GetViewport() const; float GetZFar() const; float GetZNear() const; + NzVector2i MapWorldToPixel(const NzVector2f& coords); + NzVector2f MapPixelToWorld(const NzVector2i& pixel); + void SetSize(const NzVector2f& size); void SetSize(float width, float height); void SetTarget(const NzRenderTarget* renderTarget); @@ -61,20 +66,26 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) override; void UpdateFrustum() const; + void UpdateInvViewProjMatrix() const; void UpdateProjectionMatrix() const; void UpdateViewMatrix() const; + void UpdateViewProjMatrix() const; void UpdateViewport() const; mutable NzFrustumf m_frustum; + mutable NzMatrix4f m_invViewProjMatrix; mutable NzMatrix4f m_projectionMatrix; mutable NzMatrix4f m_viewMatrix; + mutable NzMatrix4f m_viewProjMatrix; NzRectf m_targetRegion; mutable NzRecti m_viewport; NzVector2f m_size; const NzRenderTarget* m_target; mutable bool m_frustumUpdated; + mutable bool m_invViewProjMatrixUpdated; mutable bool m_projectionMatrixUpdated; mutable bool m_viewMatrixUpdated; + mutable bool m_viewProjMatrixUpdated; mutable bool m_viewportUpdated; float m_zFar; float m_zNear; diff --git a/src/Nazara/Graphics/View.cpp b/src/Nazara/Graphics/View.cpp index 07d7a2a97..9662b3cc0 100644 --- a/src/Nazara/Graphics/View.cpp +++ b/src/Nazara/Graphics/View.cpp @@ -13,8 +13,10 @@ m_targetRegion(0.f, 0.f, 1.f, 1.f), m_size(0.f), m_target(nullptr), m_frustumUpdated(false), +m_invViewProjMatrixUpdated(false), m_projectionMatrixUpdated(false), m_viewMatrixUpdated(false), +m_viewProjMatrixUpdated(false), m_viewportUpdated(false), m_zFar(1.f), m_zNear(-1.f) @@ -95,6 +97,14 @@ NzVector3f NzView::GetGlobalUp() const return -NzVector3f::UnitY(); } +const NzMatrix4f& NzView::GetInvViewProjMatrix() const +{ + if (!m_invViewProjMatrixUpdated) + UpdateInvViewProjMatrix(); + + return m_invViewProjMatrix; +} + const NzMatrix4f& NzView::GetProjectionMatrix() const { if (!m_projectionMatrixUpdated) @@ -121,6 +131,14 @@ const NzMatrix4f& NzView::GetViewMatrix() const return m_viewMatrix; } +const NzMatrix4f& NzView::GetViewProjMatrix() const +{ + if (!m_viewProjMatrixUpdated) + UpdateViewProjMatrix(); + + return m_viewProjMatrix; +} + const NzRecti& NzView::GetViewport() const { #if NAZARA_GRAPHICS_SAFE @@ -147,6 +165,44 @@ float NzView::GetZNear() const return m_zNear; } +NzVector2i NzView::MapWorldToPixel(const NzVector2f& coords) +{ + if (!m_viewProjMatrixUpdated) + UpdateViewProjMatrix(); + + if (!m_viewportUpdated) + UpdateViewport(); + + // Conversion du viewport en flottant + NzRectf viewport(m_viewport); + + NzVector2f normalized = m_viewProjMatrix.Transform(coords); + + NzVector2i pixel; + pixel.x = static_cast(( normalized.x + 1.f) * viewport.width / 2.f + viewport.x); + pixel.y = static_cast((-normalized.y + 1.f) * viewport.width / 2.f + viewport.y); + + return pixel; +} + +NzVector2f NzView::MapPixelToWorld(const NzVector2i& pixel) +{ + if (!m_invViewProjMatrixUpdated) + UpdateInvViewProjMatrix(); + + if (!m_viewportUpdated) + UpdateViewport(); + + // Conversion du viewport en flottant + NzRectf viewport(m_viewport); + + NzVector2f normalized; + normalized.x = -1.f + 2.f * (pixel.x - viewport.x) / viewport.width; + normalized.y = 1.f - 2.f * (pixel.y - viewport.y) / viewport.height; + + return m_invViewProjMatrix.Transform(normalized); +} + void NzView::SetSize(const NzVector2f& size) { SetSize(size.x, size.y); @@ -178,7 +234,9 @@ void NzView::SetTargetRegion(const NzRectf& region) m_targetRegion = region; m_frustumUpdated = false; + m_invViewProjMatrixUpdated = false; m_projectionMatrixUpdated = false; + m_viewProjMatrixUpdated = false; m_viewportUpdated = false; } @@ -204,7 +262,9 @@ void NzView::SetZFar(float zFar) m_zFar = zFar; m_frustumUpdated = false; + m_invViewProjMatrixUpdated = false; m_projectionMatrixUpdated = false; + m_viewProjMatrixUpdated = false; } void NzView::SetZNear(float zNear) @@ -212,7 +272,9 @@ void NzView::SetZNear(float zNear) m_zNear = zNear; m_frustumUpdated = false; + m_invViewProjMatrixUpdated = false; m_projectionMatrixUpdated = false; + m_viewProjMatrixUpdated = false; } void NzView::ApplyView() const @@ -246,7 +308,9 @@ void NzView::InvalidateNode() // Le frustum et la view matrix dépendent des paramètres du node, invalidons-les m_frustumUpdated = false; + m_invViewProjMatrixUpdated = false; m_viewMatrixUpdated = false; + m_viewProjMatrixUpdated = false; } void NzView::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) @@ -287,6 +351,15 @@ void NzView::UpdateFrustum() const m_frustumUpdated = true; } +void NzView::UpdateInvViewProjMatrix() const +{ + if (!m_viewProjMatrixUpdated) + UpdateViewProjMatrix(); + + m_viewProjMatrix.GetInverseAffine(&m_invViewProjMatrix); + m_invViewProjMatrixUpdated = true; +} + void NzView::UpdateProjectionMatrix() const { if (m_size.x <= 0.f || m_size.y <= 0.f) // Si la taille est nulle, on prendra la taille du viewport @@ -311,6 +384,19 @@ void NzView::UpdateViewMatrix() const m_viewMatrixUpdated = true; } +void NzView::UpdateViewProjMatrix() const +{ + if (!m_projectionMatrixUpdated) + UpdateProjectionMatrix(); + + if (!m_viewMatrixUpdated) + UpdateViewMatrix(); + + // La matrice de projection orthogonale est affine + m_viewProjMatrix = NzMatrix4f::ConcatenateAffine(m_viewMatrix, m_projectionMatrix); + m_viewProjMatrixUpdated = true; +} + void NzView::UpdateViewport() const { unsigned int width = m_target->GetWidth();