From af34567ae71e1a285f8065f787fa00a4feb482de Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 27 May 2018 21:45:06 +0200 Subject: [PATCH] Graphics/AbstractViewer: Add Project/Unproject methods --- ChangeLog.md | 3 +- include/Nazara/Graphics/AbstractViewer.hpp | 3 ++ src/Nazara/Graphics/AbstractViewer.cpp | 36 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 75e1a5ced..98b92b55b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,7 +20,7 @@ Miscellaneous: Nazara Engine: - VertexMapper:GetComponentPtr no longer throw an error if component is disabled or incompatible with template type, instead a null pointer is returned. -- Bitset swap operation is now correctly marked as noexcept` +- Bitset swap operation is now correctly marked as noexcept - Mesh loaders now takes MeshParams vertexDeclaration into account - ⚠️ Replaced RenderTarget::Get[Height|Width] by RenderTarget::GetSize - ⚠️ Removed Window::Get[Height|Width] methods @@ -104,6 +104,7 @@ Nazara Engine: - Added LuaState::CallWithHandler methods, allowing to setup a error handler function - Added LuaState::Traceback method - Added ModelLibrary, ModelManager and ModelSaver +- Added AbstractViewer::Project and AbstractViewer::Unproject methods Nazara Development Kit: - Added ImageWidget (#139) diff --git a/include/Nazara/Graphics/AbstractViewer.hpp b/include/Nazara/Graphics/AbstractViewer.hpp index 2821fdbec..c682deeb2 100644 --- a/include/Nazara/Graphics/AbstractViewer.hpp +++ b/include/Nazara/Graphics/AbstractViewer.hpp @@ -40,6 +40,9 @@ namespace Nz virtual float GetZFar() const = 0; virtual float GetZNear() const = 0; + Nz::Vector3f Project(const Nz::Vector3f& worldPosition) const; + Nz::Vector3f Unproject(const Nz::Vector3f& screenPos) const; + AbstractViewer& operator=(const AbstractViewer&) = default; AbstractViewer& operator=(AbstractViewer&&) noexcept = default; }; diff --git a/src/Nazara/Graphics/AbstractViewer.cpp b/src/Nazara/Graphics/AbstractViewer.cpp index e83737baa..ed9176e76 100644 --- a/src/Nazara/Graphics/AbstractViewer.cpp +++ b/src/Nazara/Graphics/AbstractViewer.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz @@ -16,4 +17,39 @@ namespace Nz */ AbstractViewer::~AbstractViewer() = default; + + Vector3f AbstractViewer::Project(const Nz::Vector3f& worldPosition) const + { + Vector4f pos4D(worldPosition, 1.f); + pos4D = GetViewMatrix() * pos4D; + pos4D = GetProjectionMatrix() * pos4D; + pos4D /= pos4D.w; + + Rectf viewport = Rectf(GetViewport()); + + Nz::Vector3f screenPosition(pos4D.x * 0.5f + 0.5f, -pos4D.y * 0.5f + 0.5f, pos4D.z * 0.5f + 0.5f); + screenPosition.x = screenPosition.x * viewport.width + viewport.x; + screenPosition.y = screenPosition.y * viewport.height + viewport.y; + + return screenPosition; + } + + Vector3f AbstractViewer::Unproject(const Nz::Vector3f& screenPos) const + { + Rectf viewport = Rectf(GetViewport()); + + Nz::Vector4f normalizedPosition; + normalizedPosition.x = (screenPos.x - viewport.x) / viewport.width * 2.f - 1.f; + normalizedPosition.y = (screenPos.y - viewport.y) / viewport.height * 2.f - 1.f; + normalizedPosition.z = screenPos.z * 2.f - 1.f; + normalizedPosition.w = 1.f; + + Nz::Matrix4f invMatrix = GetViewMatrix() * GetProjectionMatrix(); + invMatrix.Inverse(); + + Nz::Vector4f worldPos = invMatrix * normalizedPosition; + worldPos /= worldPos.w; + + return Nz::Vector3f(worldPos.x, worldPos.y, worldPos.z); + } }