From 88b6ff63b7a090ee8b33f7f0fd4da7de799bb030 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Tue, 14 Mar 2023 18:07:03 +0100 Subject: [PATCH] Graphics/AbstractViewer: Add Project & Unproject methods --- include/Nazara/Graphics/AbstractViewer.hpp | 4 +++ src/Nazara/Graphics/AbstractViewer.cpp | 39 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Graphics/AbstractViewer.hpp b/include/Nazara/Graphics/AbstractViewer.hpp index c03431c37..57dbfa4ef 100644 --- a/include/Nazara/Graphics/AbstractViewer.hpp +++ b/include/Nazara/Graphics/AbstractViewer.hpp @@ -29,6 +29,10 @@ namespace Nz virtual ViewerInstance& GetViewerInstance() = 0; virtual const ViewerInstance& GetViewerInstance() const = 0; virtual const Recti& GetViewport() const = 0; + + Vector3f Project(const Vector3f& worldPos); + + Vector3f Unproject(const Vector3f& screenPos); }; } diff --git a/src/Nazara/Graphics/AbstractViewer.cpp b/src/Nazara/Graphics/AbstractViewer.cpp index baa6e4aae..1788793c5 100644 --- a/src/Nazara/Graphics/AbstractViewer.cpp +++ b/src/Nazara/Graphics/AbstractViewer.cpp @@ -3,9 +3,46 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include #include namespace Nz { - AbstractViewer::~AbstractViewer() = default; + AbstractViewer::~AbstractViewer() = default; + + Vector3f AbstractViewer::Project(const Vector3f& worldPos) + { + const Matrix4f& viewProj = GetViewerInstance().GetViewProjMatrix(); + Vector2f screenSize = Vector2f(GetRenderTarget().GetSize()); + + Vector4f clipspace = viewProj * Vector4f(worldPos, 1.f); + clipspace.x = clipspace.x / clipspace.w; + clipspace.y = clipspace.y / clipspace.w; + clipspace.z = clipspace.z / clipspace.w; + + Vector3f screenSpace; + screenSpace.x = (clipspace.x * 0.5f + 0.5f) * screenSize.x; + screenSpace.y = (clipspace.y * 0.5f + 0.5f) * screenSize.y; + screenSpace.z = clipspace.z; + + return screenSpace; + } + + Vector3f AbstractViewer::Unproject(const Vector3f& screenPos) + { + const Matrix4f& inverseViewProj = GetViewerInstance().GetInvViewProjMatrix(); + Vector2f screenSize = Vector2f(GetRenderTarget().GetSize()); + + // Screen space => clip space + Vector4f clipSpace; + clipSpace.x = screenPos.x / screenSize.x * 2.f - 1.f; + clipSpace.y = screenPos.y / screenSize.y * 2.f - 1.f; + clipSpace.z = screenPos.z; + clipSpace.w = 1.f; + + // Clip space => projection space => view space => world space + Vector4f unproj = inverseViewProj * clipSpace; + return Vector3f(unproj.x, unproj.y, unproj.z) / unproj.w; + } }