diff --git a/openVulkanoCpp/Scene/Drawable.hpp b/openVulkanoCpp/Scene/Drawable.hpp index 5f58614..2c24b0d 100644 --- a/openVulkanoCpp/Scene/Drawable.hpp +++ b/openVulkanoCpp/Scene/Drawable.hpp @@ -7,6 +7,7 @@ #pragma once #include "Base/ICloseable.hpp" +#include "Scene/IRayIntersectable.hpp" #include "DrawEncoder.hpp" #include #include @@ -26,13 +27,14 @@ namespace OpenVulkano::Scene BACKGROUND = 0, MAIN, TRANSPARENT, POST }; - class Drawable : public ICloseable + class Drawable : public ICloseable, public IRayIntersectable { std::vector m_nodes; Scene* m_scene = nullptr; Shader* m_shader = nullptr; const DrawEncoder m_encoder; const DrawPhase m_drawPhase; + bool m_isHittable = false; public: explicit Drawable(const DrawEncoder& encoder, @@ -45,6 +47,12 @@ namespace OpenVulkano::Scene void SetShader(Shader* shader) { m_shader = shader; } + std::optional Intersect(const Ray& ray) const override { return {}; } + + void SetIsHittable(bool hittable) { m_isHittable = hittable; } + + bool IsHittable() const { return m_isHittable; } + [[nodiscard]] Scene* GetScene() const { return m_scene; } [[nodiscard]] const auto& GetNodes() const { return m_nodes; } diff --git a/openVulkanoCpp/Scene/IRayIntersectable.hpp b/openVulkanoCpp/Scene/IRayIntersectable.hpp new file mode 100644 index 0000000..0deaf91 --- /dev/null +++ b/openVulkanoCpp/Scene/IRayIntersectable.hpp @@ -0,0 +1,18 @@ +/* + * 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/. + */ + +#pragma once + +#include "Scene/Ray.hpp" + +namespace OpenVulkano::Scene +{ + class IRayIntersectable + { + public: + virtual std::optional Intersect(const Ray& ray) const = 0; + }; +} diff --git a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp index 4ca1aff..e1ddfef 100644 --- a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp +++ b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp @@ -80,6 +80,11 @@ namespace OpenVulkano::Scene m_billboardSettings = settings; } + std::optional LabelDrawable::Intersect(const Ray& ray) const + { + return ray.IntersectAABB(m_bbox); + } + void LabelDrawable::RecalculateBbox(const Math::AABB& other) { if (m_bbox.IsEmpty()) diff --git a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp index c8269fb..ce29ae7 100644 --- a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp +++ b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp @@ -61,6 +61,7 @@ namespace OpenVulkano::Scene Math::Vector3f& GetPosition() { return m_position; } bool IsBillboard() const { return m_isBillboard; } const Math::AABB& GetBoundingBox() const { return m_bbox; } + std::optional Intersect(const Ray& ray) const override; private: void RecalculateBbox(const Math::AABB& other); void SetupShaders(); diff --git a/openVulkanoCpp/Scene/SimpleDrawable.cpp b/openVulkanoCpp/Scene/SimpleDrawable.cpp index 0920971..cc2de23 100644 --- a/openVulkanoCpp/Scene/SimpleDrawable.cpp +++ b/openVulkanoCpp/Scene/SimpleDrawable.cpp @@ -5,6 +5,9 @@ */ #include "SimpleDrawable.hpp" +#include "Scene/Geometry.hpp" +#include "Scene/Shader/Shader.hpp" +#include "Base/Logger.hpp" #include namespace OpenVulkano::Scene @@ -26,4 +29,61 @@ namespace OpenVulkano::Scene m_uniBuffer = drawable->m_uniBuffer; SetShader(drawable->GetShader()); } + + std::optional SimpleDrawable::Intersect(const Ray& ray) const + { + if (!m_mesh || !GetShader()) + { + return {}; + } + if (m_mesh->aabb.IsEmpty()) + { + m_mesh->CalculateAABB(); + } + if (ray.IntersectAABB(m_mesh->aabb)) + { + if (GetShader()->topology == Topology::TRIANGLE_LIST) + { + if (m_mesh->indexCount != 0) + { + for (int i = 0; i < m_mesh->indexCount / 3; i++) + { + if (m_mesh->indexType == VertexIndexType::UINT16) + { + uint16_t* indices = m_mesh->GetIndices16(); + if (auto hit = ray.IntersectTriangle(m_mesh->vertices[indices[i * 3]].position, + m_mesh->vertices[indices[i * 3 + 1]].position, + m_mesh->vertices[indices[i * 3 + 2]].position)) + { + return hit; + } + } + else + { + uint32_t* indices = m_mesh->GetIndices32(); + if (auto hit = ray.IntersectTriangle(m_mesh->vertices[indices[i * 3]].position, + m_mesh->vertices[indices[i * 3 + 1]].position, + m_mesh->vertices[indices[i * 3 + 2]].position)) + { + return hit; + } + } + } + } + else + { + for (int i = 0; i < m_mesh->vertexCount / 3; i++) + { + if (auto hit = ray.IntersectTriangle(m_mesh->vertices[i * 3].position, + m_mesh->vertices[i * 3 + 1].position, + m_mesh->vertices[i * 3 + 2].position)) + { + return hit; + } + } + } + } + } + return {}; + } } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/SimpleDrawable.hpp b/openVulkanoCpp/Scene/SimpleDrawable.hpp index 231a87b..f78139b 100644 --- a/openVulkanoCpp/Scene/SimpleDrawable.hpp +++ b/openVulkanoCpp/Scene/SimpleDrawable.hpp @@ -44,6 +44,8 @@ namespace OpenVulkano::Scene void Init(SimpleDrawable* drawable); + std::optional Intersect(const Ray& ray) const override; + [[nodiscard]] Geometry* GetMesh() const { return m_mesh; } [[nodiscard]] Material* GetMaterial() const { return m_material; }