/* * 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 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 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(res->drawable)) { Logger::APP->info("Ray intersects object {}", sd->GetMesh()->name); } else if (LabelDrawable* sd = dynamic_cast(res->drawable)) { Logger::APP->info("Ray intersects label {}", sd->GetTexts().front().GetText()); } } return res; } }