implement ray casting events
This commit is contained in:
68
openVulkanoCpp/Scene/Camera.cpp
Normal file
68
openVulkanoCpp/Scene/Camera.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "Camera.hpp"
|
||||
#include "Scene/Scene.hpp"
|
||||
#include "Scene/SimpleDrawable.hpp"
|
||||
#include "Scene/Geometry.hpp"
|
||||
#include "Scene/Shader/Shader.hpp"
|
||||
#include "Scene/TextDrawable.hpp"
|
||||
#include "Scene/Prefabs/LabelDrawable.hpp"
|
||||
#include "Scene/Ray.hpp"
|
||||
#include "Scene/TextDrawable.hpp"
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
|
||||
std::optional<DrawableRayHit> PerspectiveCamera::CastRay(const Math::Vector2i& xy) const
|
||||
{
|
||||
using namespace Math::Utils;
|
||||
|
||||
auto scene = GetScene();
|
||||
|
||||
// nds
|
||||
float ndsX = (2.f * xy.x) / m_width - 1.0f;
|
||||
float ndsY = (2.f * xy.y) / m_height - 1.0f;
|
||||
|
||||
Math::Vector4f rayClip = { ndsX, ndsY, 0, 1.f };
|
||||
|
||||
Math::Vector4f rayEye = inverse(m_projection) * rayClip;
|
||||
rayEye.z = -1;
|
||||
rayEye.a = 0;
|
||||
|
||||
Math::Vector3f rayWorld = normalize(inverse(m_view) * rayEye);
|
||||
|
||||
std::optional<DrawableRayHit> res;
|
||||
for (Drawable* d: scene->rayHittableDrawables)
|
||||
{
|
||||
const auto& m = d->GetNodes()[0]->GetWorldMatrix();
|
||||
const Math::Vector3f rayLocalDir = normalize(inverse(m) * Math::Vector4f(rayWorld, 0));
|
||||
const Math::Vector4f rayLocalPos = inverse(m) * m_camPosition;
|
||||
const Ray ray(rayLocalPos, rayLocalDir);
|
||||
if (auto hit = d->Intersect(ray))
|
||||
{
|
||||
// choose the closest one
|
||||
if (!res || (hit->distance < res->distance))
|
||||
{
|
||||
res = hit;
|
||||
res->drawable = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res)
|
||||
{
|
||||
if (SimpleDrawable* sd = dynamic_cast<SimpleDrawable*>(res->drawable))
|
||||
{
|
||||
Logger::APP->info("Ray intersects object {}", sd->GetMesh()->name);
|
||||
}
|
||||
else if (LabelDrawable* sd = dynamic_cast<LabelDrawable*>(res->drawable))
|
||||
{
|
||||
Logger::APP->info("Ray intersects label {}", sd->GetTexts().front().GetText());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user