Graphics/AbstractViewer: Add Project & Unproject methods

This commit is contained in:
SirLynix 2023-03-14 18:07:03 +01:00
parent a414afec24
commit 88b6ff63b7
2 changed files with 42 additions and 1 deletions

View File

@ -29,6 +29,10 @@ namespace Nz
virtual ViewerInstance& GetViewerInstance() = 0; virtual ViewerInstance& GetViewerInstance() = 0;
virtual const ViewerInstance& GetViewerInstance() const = 0; virtual const ViewerInstance& GetViewerInstance() const = 0;
virtual const Recti& GetViewport() const = 0; virtual const Recti& GetViewport() const = 0;
Vector3f Project(const Vector3f& worldPos);
Vector3f Unproject(const Vector3f& screenPos);
}; };
} }

View File

@ -3,9 +3,46 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/AbstractViewer.hpp> #include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/ViewerInstance.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Graphics/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
namespace Nz 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;
}
} }