Adds optimization to octtree navigation
This commit is contained in:
@@ -42,7 +42,6 @@ int main()
|
||||
{
|
||||
EngineContext engine_ctx {};
|
||||
|
||||
/*
|
||||
EditorGuiContext editor_ctx { engine_ctx.getWindow() };
|
||||
|
||||
// We start by hooking into the imgui rendering.
|
||||
@@ -90,7 +89,6 @@ int main()
|
||||
}
|
||||
|
||||
engine_ctx.waitIdle();
|
||||
*/
|
||||
}
|
||||
catch ( const vk::LayerNotPresentError& e )
|
||||
{
|
||||
|
||||
@@ -87,8 +87,8 @@ namespace fgl::engine
|
||||
}
|
||||
|
||||
obj.getTransform().translation = WorldCoordinate(
|
||||
-10.0f + ( static_cast< float >( x ) * offset ),
|
||||
-10.0f + ( static_cast< float >( y ) * offset ),
|
||||
10.0f + ( static_cast< float >( x ) * offset ),
|
||||
10.0f + ( static_cast< float >( y ) * offset ),
|
||||
0.0f );
|
||||
|
||||
m_game_objects_root.addGameObject( std::move( obj ) );
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#pragma once
|
||||
|
||||
//clang-format: off
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <tracy/TracyVulkan.hpp>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
//clang-format: on
|
||||
|
||||
#include "descriptors/Descriptor.hpp"
|
||||
@@ -58,6 +58,7 @@ namespace fgl::engine
|
||||
constexpr descriptors::AttachmentDescriptor metallic_descriptor { 3, 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 {
|
||||
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.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::DescriptorSetLayoutBindingFlagsCreateInfo flags_info {};
|
||||
flags_info.setBindingFlags( flags );
|
||||
flags_info.setBindingFlags( m_flags );
|
||||
|
||||
vk::DescriptorSetLayoutCreateInfo info {};
|
||||
info.setFlags( vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool );
|
||||
info.setBindings( bindings );
|
||||
info.setBindings( m_bindings );
|
||||
info.setPNext( &flags_info );
|
||||
|
||||
return Device::getInstance()->createDescriptorSetLayout( info );
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace fgl::engine::descriptors
|
||||
|
||||
class DescriptorSetLayout
|
||||
{
|
||||
std::vector< vk::DescriptorSetLayoutBinding > bindings {};
|
||||
std::vector< vk::DescriptorBindingFlags > flags {};
|
||||
std::vector< vk::DescriptorSetLayoutBinding > m_bindings {};
|
||||
std::vector< vk::DescriptorBindingFlags > m_flags {};
|
||||
|
||||
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... } )
|
||||
{}
|
||||
|
||||
[[nodiscard]] std::size_t count() const { return bindings.size(); }
|
||||
[[nodiscard]] std::size_t count() const { return m_bindings.size(); }
|
||||
|
||||
std::unique_ptr< DescriptorSet > create();
|
||||
[[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 )
|
||||
{
|
||||
#if ENABLE_IMGUI
|
||||
if ( ImGui::CollapsingHeader( "OctTree debug settings" ) )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
if ( ImGui::Button( "Optimize Octree Travel" ) )
|
||||
{
|
||||
info.game_objects.optimizePath();
|
||||
}
|
||||
|
||||
if ( time.has_value() )
|
||||
{
|
||||
ImGui::Text( "Time spent reorganizing: %.2ldus", time.value().count() );
|
||||
ImGui::Text( "Moved %ld objects", number_moved );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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 ) };
|
||||
//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 ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
|
||||
@@ -464,6 +473,8 @@ namespace fgl::engine
|
||||
|
||||
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 ) };
|
||||
|
||||
FOR_EACH_OCTTREE_NODE
|
||||
@@ -532,8 +543,16 @@ namespace fgl::engine
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_skip != nullptr )
|
||||
{
|
||||
m_skip->getAllLeafs( out_leafs );
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& nodes { std::get< OctTreeNodeArray >( m_node_data ) };
|
||||
|
||||
// If we have a node to skip to, Skip to it.
|
||||
|
||||
FOR_EACH_OCTTREE_NODE
|
||||
{
|
||||
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()
|
||||
{
|
||||
ZoneScoped;
|
||||
std::size_t counter { 0 };
|
||||
if ( std::holds_alternative< NodeDataT >( m_node_data ) )
|
||||
{
|
||||
|
||||
@@ -52,6 +52,11 @@ namespace fgl::engine
|
||||
|
||||
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:
|
||||
|
||||
OctTreeNode() = delete;
|
||||
@@ -106,6 +111,7 @@ namespace fgl::engine
|
||||
|
||||
//! Rebuilds the tree checking if nodes have moved.
|
||||
std::size_t reorganize();
|
||||
OctTreeNode* optimizePath();
|
||||
|
||||
//! Returns true if the fixed bounding box is larger then the inital bounding box
|
||||
bool isBoundsExpanded() const;
|
||||
|
||||
Reference in New Issue
Block a user