Adds optimization to octtree navigation
This commit is contained in:
@@ -42,7 +42,6 @@ int main()
|
|||||||
{
|
{
|
||||||
EngineContext engine_ctx {};
|
EngineContext engine_ctx {};
|
||||||
|
|
||||||
/*
|
|
||||||
EditorGuiContext editor_ctx { engine_ctx.getWindow() };
|
EditorGuiContext editor_ctx { engine_ctx.getWindow() };
|
||||||
|
|
||||||
// We start by hooking into the imgui rendering.
|
// We start by hooking into the imgui rendering.
|
||||||
@@ -90,7 +89,6 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
engine_ctx.waitIdle();
|
engine_ctx.waitIdle();
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
catch ( const vk::LayerNotPresentError& e )
|
catch ( const vk::LayerNotPresentError& e )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ namespace fgl::engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj.getTransform().translation = WorldCoordinate(
|
obj.getTransform().translation = WorldCoordinate(
|
||||||
-10.0f + ( static_cast< float >( x ) * offset ),
|
10.0f + ( static_cast< float >( x ) * offset ),
|
||||||
-10.0f + ( static_cast< float >( y ) * offset ),
|
10.0f + ( static_cast< float >( y ) * offset ),
|
||||||
0.0f );
|
0.0f );
|
||||||
|
|
||||||
m_game_objects_root.addGameObject( std::move( obj ) );
|
m_game_objects_root.addGameObject( std::move( obj ) );
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//clang-format: off
|
//clang-format: off
|
||||||
#include <vulkan/vulkan.hpp>
|
|
||||||
#include <tracy/TracyVulkan.hpp>
|
#include <tracy/TracyVulkan.hpp>
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
//clang-format: on
|
//clang-format: on
|
||||||
|
|
||||||
#include "descriptors/Descriptor.hpp"
|
#include "descriptors/Descriptor.hpp"
|
||||||
@@ -58,6 +58,7 @@ namespace fgl::engine
|
|||||||
constexpr descriptors::AttachmentDescriptor metallic_descriptor { 3, FRAG_STAGE };
|
constexpr descriptors::AttachmentDescriptor metallic_descriptor { 3, FRAG_STAGE };
|
||||||
constexpr descriptors::AttachmentDescriptor emissive_descriptor { 4, FRAG_STAGE };
|
constexpr descriptors::AttachmentDescriptor emissive_descriptor { 4, FRAG_STAGE };
|
||||||
|
|
||||||
|
//TODO: Move this from being static, It being here prevents safe cleanup
|
||||||
inline static descriptors::DescriptorSetLayout gbuffer_set {
|
inline static descriptors::DescriptorSetLayout gbuffer_set {
|
||||||
0, color_descriptor, position_descriptor, normal_descriptor, metallic_descriptor, emissive_descriptor
|
0, color_descriptor, position_descriptor, normal_descriptor, metallic_descriptor, emissive_descriptor
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ namespace fgl::engine::descriptors
|
|||||||
binding.stageFlags = descriptor.m_stage_flags;
|
binding.stageFlags = descriptor.m_stage_flags;
|
||||||
binding.pImmutableSamplers = VK_NULL_HANDLE;
|
binding.pImmutableSamplers = VK_NULL_HANDLE;
|
||||||
|
|
||||||
bindings.emplace_back( binding );
|
m_bindings.emplace_back( binding );
|
||||||
|
|
||||||
flags.emplace_back( descriptor.m_binding_flags );
|
m_flags.emplace_back( descriptor.m_binding_flags );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,11 +47,11 @@ namespace fgl::engine::descriptors
|
|||||||
vk::raii::DescriptorSetLayout DescriptorSetLayout::createLayout() const
|
vk::raii::DescriptorSetLayout DescriptorSetLayout::createLayout() const
|
||||||
{
|
{
|
||||||
vk::DescriptorSetLayoutBindingFlagsCreateInfo flags_info {};
|
vk::DescriptorSetLayoutBindingFlagsCreateInfo flags_info {};
|
||||||
flags_info.setBindingFlags( flags );
|
flags_info.setBindingFlags( m_flags );
|
||||||
|
|
||||||
vk::DescriptorSetLayoutCreateInfo info {};
|
vk::DescriptorSetLayoutCreateInfo info {};
|
||||||
info.setFlags( vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool );
|
info.setFlags( vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool );
|
||||||
info.setBindings( bindings );
|
info.setBindings( m_bindings );
|
||||||
info.setPNext( &flags_info );
|
info.setPNext( &flags_info );
|
||||||
|
|
||||||
return Device::getInstance()->createDescriptorSetLayout( info );
|
return Device::getInstance()->createDescriptorSetLayout( info );
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ namespace fgl::engine::descriptors
|
|||||||
|
|
||||||
class DescriptorSetLayout
|
class DescriptorSetLayout
|
||||||
{
|
{
|
||||||
std::vector< vk::DescriptorSetLayoutBinding > bindings {};
|
std::vector< vk::DescriptorSetLayoutBinding > m_bindings {};
|
||||||
std::vector< vk::DescriptorBindingFlags > flags {};
|
std::vector< vk::DescriptorBindingFlags > m_flags {};
|
||||||
|
|
||||||
std::optional< vk::raii::DescriptorSetLayout > m_layout { std::nullopt };
|
std::optional< vk::raii::DescriptorSetLayout > m_layout { std::nullopt };
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ namespace fgl::engine::descriptors
|
|||||||
DescriptorSetLayout( set_idx, std::vector< std::reference_wrapper< const Descriptor > > { descriptors... } )
|
DescriptorSetLayout( set_idx, std::vector< std::reference_wrapper< const Descriptor > > { descriptors... } )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
[[nodiscard]] std::size_t count() const { return bindings.size(); }
|
[[nodiscard]] std::size_t count() const { return m_bindings.size(); }
|
||||||
|
|
||||||
std::unique_ptr< DescriptorSet > create();
|
std::unique_ptr< DescriptorSet > create();
|
||||||
[[nodiscard]] vk::raii::DescriptorSetLayout createLayout() const;
|
[[nodiscard]] vk::raii::DescriptorSetLayout createLayout() const;
|
||||||
|
|||||||
9
src/engine/tree/bvh/BVHTree.cpp
Normal file
9
src/engine/tree/bvh/BVHTree.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//
|
||||||
|
// Created by kj16609 on 1/24/25.
|
||||||
|
//
|
||||||
|
#include "BVHTree.hpp"
|
||||||
|
|
||||||
|
namespace fgl::engine
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
43
src/engine/tree/bvh/BVHTree.hpp
Normal file
43
src/engine/tree/bvh/BVHTree.hpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// Created by kj16609 on 1/24/25.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "glm/vec3.hpp"
|
||||||
|
|
||||||
|
namespace fgl::engine
|
||||||
|
{
|
||||||
|
using BVHIndex = std::uint32_t;
|
||||||
|
|
||||||
|
class BVHTree
|
||||||
|
{
|
||||||
|
struct GameObjectInfo
|
||||||
|
{};
|
||||||
|
|
||||||
|
struct BVHNode
|
||||||
|
{
|
||||||
|
using FlagType = std::uint8_t;
|
||||||
|
|
||||||
|
enum Masks : FlagType
|
||||||
|
{
|
||||||
|
Flag_None = 0,
|
||||||
|
//! This node was visible during the last test
|
||||||
|
Flag_Previously_Visible = 1 << 0,
|
||||||
|
//! This node was not visible during the last test
|
||||||
|
Flag_Previously_Invisible = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
FlagType m_flags { Masks::Flag_None };
|
||||||
|
glm::vec3 m_centerpoint;
|
||||||
|
|
||||||
|
//! Index to try next if we hit this index.
|
||||||
|
BVHIndex m_hit;
|
||||||
|
//! Index t otry if we fail this index.
|
||||||
|
BVHIndex m_miss;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
} // namespace fgl::engine
|
||||||
@@ -34,7 +34,6 @@ namespace fgl::engine
|
|||||||
|
|
||||||
void imGuiOctTreeSettings( const FrameInfo& info )
|
void imGuiOctTreeSettings( const FrameInfo& info )
|
||||||
{
|
{
|
||||||
#if ENABLE_IMGUI
|
|
||||||
if ( ImGui::CollapsingHeader( "OctTree debug settings" ) )
|
if ( ImGui::CollapsingHeader( "OctTree debug settings" ) )
|
||||||
{
|
{
|
||||||
ImGui::Checkbox( "Draw leaf fitted bounding boxes", &draw_leaf_fit_bounds );
|
ImGui::Checkbox( "Draw leaf fitted bounding boxes", &draw_leaf_fit_bounds );
|
||||||
@@ -61,13 +60,17 @@ namespace fgl::engine
|
|||||||
time = std::chrono::duration_cast< std::chrono::microseconds >( time_diff );
|
time = std::chrono::duration_cast< std::chrono::microseconds >( time_diff );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ImGui::Button( "Optimize Octree Travel" ) )
|
||||||
|
{
|
||||||
|
info.game_objects.optimizePath();
|
||||||
|
}
|
||||||
|
|
||||||
if ( time.has_value() )
|
if ( time.has_value() )
|
||||||
{
|
{
|
||||||
ImGui::Text( "Time spent reorganizing: %.2ldus", time.value().count() );
|
ImGui::Text( "Time spent reorganizing: %.2ldus", time.value().count() );
|
||||||
ImGui::Text( "Moved %ld objects", number_moved );
|
ImGui::Text( "Moved %ld objects", number_moved );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctTreeNode::getAllLeafsInFrustum( const Frustum& frustum, std::vector< OctTreeNodeLeaf* >& out_leafs )
|
void OctTreeNode::getAllLeafsInFrustum( const Frustum& frustum, std::vector< OctTreeNodeLeaf* >& out_leafs )
|
||||||
@@ -87,6 +90,12 @@ namespace fgl::engine
|
|||||||
const OctTreeNodeArray& node_array { std::get< OctTreeNodeArray >( m_node_data ) };
|
const OctTreeNodeArray& node_array { std::get< OctTreeNodeArray >( m_node_data ) };
|
||||||
//Search deeper
|
//Search deeper
|
||||||
|
|
||||||
|
if ( m_skip != nullptr )
|
||||||
|
{
|
||||||
|
m_skip->getAllLeafsInFrustum( frustum, out_leafs );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
node_array[ LEFT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs );
|
node_array[ LEFT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||||
node_array[ LEFT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs );
|
node_array[ LEFT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||||
|
|
||||||
@@ -464,6 +473,8 @@ namespace fgl::engine
|
|||||||
|
|
||||||
if ( std::holds_alternative< OctTreeNodeArray >( this->m_node_data ) )
|
if ( std::holds_alternative< OctTreeNodeArray >( this->m_node_data ) )
|
||||||
{
|
{
|
||||||
|
if ( m_skip != nullptr ) return m_skip->findID( id );
|
||||||
|
|
||||||
const auto& node_array { std::get< OctTreeNodeArray >( this->m_node_data ) };
|
const auto& node_array { std::get< OctTreeNodeArray >( this->m_node_data ) };
|
||||||
|
|
||||||
FOR_EACH_OCTTREE_NODE
|
FOR_EACH_OCTTREE_NODE
|
||||||
@@ -532,8 +543,16 @@ namespace fgl::engine
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if ( m_skip != nullptr )
|
||||||
|
{
|
||||||
|
m_skip->getAllLeafs( out_leafs );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto& nodes { std::get< OctTreeNodeArray >( m_node_data ) };
|
const auto& nodes { std::get< OctTreeNodeArray >( m_node_data ) };
|
||||||
|
|
||||||
|
// If we have a node to skip to, Skip to it.
|
||||||
|
|
||||||
FOR_EACH_OCTTREE_NODE
|
FOR_EACH_OCTTREE_NODE
|
||||||
{
|
{
|
||||||
auto ret { nodes[ x ][ y ][ z ]->getAllLeafs() };
|
auto ret { nodes[ x ][ y ][ z ]->getAllLeafs() };
|
||||||
@@ -542,8 +561,56 @@ namespace fgl::engine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OctTreeNode* OctTreeNode::optimizePath()
|
||||||
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
|
// The node returned here will be the optimal node to jump to. If we return nullptr then that means this node has multiple paths it can take.
|
||||||
|
|
||||||
|
if ( std::holds_alternative< NodeDataT >( m_node_data ) )
|
||||||
|
{
|
||||||
|
const auto& nodes { std::get< NodeDataT >( m_node_data ) };
|
||||||
|
|
||||||
|
OctTreeNode* optimal { nullptr };
|
||||||
|
|
||||||
|
FOR_EACH_OCTTREE_NODE
|
||||||
|
{
|
||||||
|
// Why did I skip the 0,0,0 node previously?
|
||||||
|
// if ( x == 0 && y == 0 && z == 0 ) continue;
|
||||||
|
const auto& node { nodes[ x ][ y ][ z ] };
|
||||||
|
|
||||||
|
if ( auto* optimal_ret = node->optimizePath(); optimal_ret != nullptr )
|
||||||
|
{
|
||||||
|
// If the node returns nullptr, Then it means that this node shouldn't jump to any node directly.
|
||||||
|
if ( optimal != nullptr )
|
||||||
|
{
|
||||||
|
m_skip = nullptr;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
optimal = optimal_ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_skip = optimal;
|
||||||
|
return optimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( std::holds_alternative< LeafDataT >( m_node_data ) )
|
||||||
|
{
|
||||||
|
const auto& leaf_data { std::get< LeafDataT >( m_node_data ) };
|
||||||
|
|
||||||
|
if ( leaf_data.empty() ) return nullptr;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FGL_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t OctTreeNode::reorganize()
|
std::size_t OctTreeNode::reorganize()
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
std::size_t counter { 0 };
|
std::size_t counter { 0 };
|
||||||
if ( std::holds_alternative< NodeDataT >( m_node_data ) )
|
if ( std::holds_alternative< NodeDataT >( m_node_data ) )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ namespace fgl::engine
|
|||||||
|
|
||||||
OctTreeNode* m_parent;
|
OctTreeNode* m_parent;
|
||||||
|
|
||||||
|
//! Node to skip too when attempting to parse this node.
|
||||||
|
//! This is done in order to prevent navigating through an empty set of nodes.
|
||||||
|
//! This is only set if there is only one leaf filled with data.
|
||||||
|
OctTreeNode* m_skip { nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
OctTreeNode() = delete;
|
OctTreeNode() = delete;
|
||||||
@@ -106,6 +111,7 @@ namespace fgl::engine
|
|||||||
|
|
||||||
//! Rebuilds the tree checking if nodes have moved.
|
//! Rebuilds the tree checking if nodes have moved.
|
||||||
std::size_t reorganize();
|
std::size_t reorganize();
|
||||||
|
OctTreeNode* optimizePath();
|
||||||
|
|
||||||
//! Returns true if the fixed bounding box is larger then the inital bounding box
|
//! Returns true if the fixed bounding box is larger then the inital bounding box
|
||||||
bool isBoundsExpanded() const;
|
bool isBoundsExpanded() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user