Fixes up some bounding box stuff

This commit is contained in:
2024-10-12 08:05:55 -04:00
parent 59fda55356
commit 282a60e4b2
14 changed files with 232 additions and 64 deletions

View File

@@ -5,6 +5,7 @@
#include "engine/debug/profiling/counters.hpp"
#include "engine/math/literals/size.hpp"
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/tree/octtree/OctTreeNode.hpp"
#include "safe_include.hpp"
namespace fgl::engine::gui
@@ -110,6 +111,8 @@ namespace fgl::engine::gui
drawMemoryStats();
}
imGuiOctTreeSettings( info );
ImGui::End();
}

View File

@@ -27,11 +27,11 @@ namespace fgl::engine
EngineContext::EngineContext() :
m_ubo_buffer_pool( 512_KiB, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible ),
m_matrix_info_pool(
2_MiB,
256_MiB,
vk::BufferUsageFlagBits::eVertexBuffer,
vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible ),
m_draw_parameter_pool(
1_MiB,
128_MiB,
vk::BufferUsageFlagBits::eIndirectBuffer,
vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible ),
m_delta_time( 0.0 )

View File

@@ -4,12 +4,12 @@
#include "TransferManager.hpp"
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/memory/buffers/BufferSuballocation.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
#include "engine/assets/image/Image.hpp"
#include "engine/assets/image/ImageHandle.hpp"
#include "engine/math/literals/size.hpp"
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/memory/buffers/BufferSuballocation.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
#include "engine/texture/Texture.hpp"
namespace fgl::engine::memory
@@ -21,8 +21,14 @@ namespace fgl::engine::memory
if ( queue.size() > 0 ) log::info( "[TransferManager]: Queue size: {}", queue.size() );
std::size_t counter { 0 };
constexpr std::size_t counter_max { 256 };
while ( queue.size() > 0 )
{
++counter;
if ( counter > counter_max ) break;
TransferData data { std::move( queue.front() ) };
queue.pop();

View File

@@ -17,6 +17,11 @@ namespace fgl::engine::debug
drawLine( line.getStart(), line.getEnd(), color );
}
void drawBoundingBox( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box )
{
drawBoundingBox( bounding_box, glm::vec3( 1.0f ) );
}
void drawBoundingBox( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box, const glm::vec3 color )
{
for ( const auto& line : bounding_box.lines() )
@@ -27,11 +32,14 @@ namespace fgl::engine::debug
void drawBoundingBox( const OrientedBoundingBox< CoordinateSpace::World >& bounding_box )
{
constexpr glm::vec3 bounding_box_color { 1.0f, 0.0f, 0.0f };
drawBoundingBox( bounding_box, glm::vec3( 1.0f ) );
}
void drawBoundingBox( const OrientedBoundingBox< CoordinateSpace::World >& bounding_box, const glm::vec3 color )
{
for ( const auto& line : bounding_box.lines() )
{
drawLine( line.getStart(), line.getEnd(), bounding_box_color );
drawLine( line.getStart(), line.getEnd(), color );
}
}

View File

@@ -15,7 +15,11 @@ namespace fgl::engine::debug
void drawLine( const LineSegment< CoordinateSpace::World >& line, glm::vec3 color = { 1.0f, 1.0f, 1.0f } );
void drawBoundingBox( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box );
void drawBoundingBox( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box, glm::vec3 color );
void drawBoundingBox( const OrientedBoundingBox< CoordinateSpace::World >& bounding_box );
void drawBoundingBox( const OrientedBoundingBox< CoordinateSpace::World >& bounding_box, glm::vec3 color );
void drawFrustum( const Frustum& frustum );
void drawAxisHelper();

View File

@@ -111,6 +111,31 @@ namespace fgl::engine
return *this;
}
template < CoordinateSpace CType >
AxisAlignedBoundingBox< CType >& AxisAlignedBoundingBox< CType >::combine( const OrientedBoundingBox< CType >&
other )
{
const auto other_trf { other.topRightForward() };
const auto other_blb { other.bottomLeftBack() };
const Coordinate< CType > new_top_right_forward {
std::max( this->m_top_right_forward.x, other_trf.x ),
std::max( this->m_top_right_forward.y, other_trf.y ),
std::max( this->m_top_right_forward.z, other_trf.z ),
};
const Coordinate< CType > new_bottom_left_back {
std::min( this->m_bottom_left_back.x, other_blb.x ),
std::min( this->m_bottom_left_back.y, other_blb.y ),
std::min( this->m_bottom_left_back.z, other_blb.z ),
};
this->m_top_right_forward = new_top_right_forward;
this->m_bottom_left_back = new_bottom_left_back;
return *this;
}
template < CoordinateSpace CType >
AxisAlignedBoundingBox< CType >::AxisAlignedBoundingBox( const OrientedBoundingBox< CType >& oobb ) :
m_top_right_forward( constants::DEFAULT_VEC3 ),

View File

@@ -46,6 +46,8 @@ namespace fgl::engine
explicit AxisAlignedBoundingBox( const OrientedBoundingBox< CType >& oobb );
AxisAlignedBoundingBox& combine( const AxisAlignedBoundingBox& other );
AxisAlignedBoundingBox& combine( const OrientedBoundingBox< CType >& other );
//AxisAlignedBoundingBox& combine( const OrientedBoundingBox< CType >& other );
bool operator==( const AxisAlignedBoundingBox< CType >& other ) const

View File

@@ -33,6 +33,11 @@ namespace fgl::engine
constexpr NormalVector up() const { return NormalVector( constants::WORLD_Z ); }
constexpr NormalVector forward() const { return NormalVector( constants::WORLD_Y ); }
operator AxisAlignedBoundingBox< CType >() const
{
return static_cast< AxisAlignedBoundingBox< CType > >( *this );
}
};
} // namespace fgl::engine

View File

@@ -200,7 +200,7 @@ namespace fgl::engine
}
template < CoordinateSpace CType >
AxisAlignedBoundingBox< CType > OrientedBoundingBox< CType >::alignToWorld()
AxisAlignedBoundingBox< CType > OrientedBoundingBox< CType >::alignToWorld() const
{
const auto points { this->points() };
glm::vec3 max { std::numeric_limits< glm::vec3::type >::infinity() };

View File

@@ -110,7 +110,7 @@ namespace fgl::engine
OrientedBoundingBox combine( const OrientedBoundingBox& other ) const;
AxisAlignedBoundingBox< CType > alignToWorld();
AxisAlignedBoundingBox< CType > alignToWorld() const;
};
template < CoordinateSpace CType, MatrixType MType >

View File

@@ -96,11 +96,25 @@ namespace fgl::engine
template < CoordinateSpace CType >
Coordinate< CType > midpoint( const Coordinate< CType > left, const Coordinate< CType > right )
{
glm::vec3 left_vec { left.vec() };
glm::vec3 right_vec { right.vec() };
left_vec *= 0.5f;
right_vec *= 0.5f;
return Coordinate< CType >( left_vec + right_vec );
/*
const auto x { ( left.vec().x + right.vec().x ) / 2.0f };
const auto y { ( left.vec().y + right.vec().y ) / 2.0f };
const auto z { ( left.vec().z + right.vec().z ) / 2.0f };
assert( !std::isinf( x ) );
assert( !std::isinf( y ) );
assert( !std::isinf( z ) );
return Coordinate< CType >( x, y, z );
*/
}
} // namespace fgl::engine

View File

@@ -84,7 +84,7 @@ namespace fgl::engine
std::make_pair( matrix_info.albedo_id, primitive.m_index_buffer.getOffset() )
};
debug::drawBoundingBox( matrix * primitive.m_bounding_box );
//debug::drawBoundingBox( matrix * primitive.m_bounding_box );
assert( primitive.m_index_buffer.size() > 0 );

View File

@@ -8,7 +8,11 @@
#include <engine/FrameInfo.hpp>
#include <glm/gtx/string_cast.hpp>
#include <imgui.h>
#include "engine/assets/model/Model.hpp"
#include "engine/clock.hpp"
#include "engine/debug/drawers.hpp"
#include "engine/primitives/Frustum.hpp"
namespace fgl::engine
@@ -18,18 +22,19 @@ namespace fgl::engine
static bool draw_leaf_fit_bounds { false };
static bool draw_leaf_real_bounds { false };
static bool draw_inview_bounds { false };
static bool draw_branches { false };
static std::size_t number_moved { 0 };
static std::optional< std::chrono::microseconds > time { std::nullopt };
void imGuiOctTreeSettings( FrameInfo& info )
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 );
ImGui::Checkbox( "Draw leaf real bounding boxes", &draw_leaf_real_bounds );
ImGui::Checkbox( "Draw ALL in view bounding boxes", &draw_inview_bounds );
ImGui::Checkbox( "Draw branches", &draw_branches );
if ( ImGui::Button( "Reorganize Octtree" ) )
{
@@ -40,30 +45,39 @@ namespace fgl::engine
time = std::chrono::duration_cast< std::chrono::microseconds >( time_diff );
}
if ( ImGui::Button( "Recalculate Bounds" ) )
{
const auto start { fgl::clock::now() };
info.game_objects.recalculateBounds();
const auto end { fgl::clock::now() };
const auto time_diff { end - start };
time = std::chrono::duration_cast< std::chrono::microseconds >( time_diff );
}
if ( time.has_value() )
{
ImGui::Text( "Time spent reorganizing: %.2ldus", time.value().count() );
ImGui::Text( "Moved %ld objects", number_moved );
}
}
#endif*/
#endif
}
void OctTreeNode::getAllLeafsInFrustum( const Frustum& frustum, std::vector< OctTreeNodeLeaf* >& out_leafs )
{
ZoneScoped;
//Check if we are inside of the frustum.
if ( !isInFrustum( frustum ) ) return;
auto& leafs { out_leafs };
leafs.reserve( 256 );
switch ( m_node_data.index() )
{
case 0: // NodeArray
{
//Check if we are inside the frustum.
if ( !isInFrustum( frustum ) ) return;
assert( std::holds_alternative< OctTreeNodeArray >( m_node_data ) );
OctTreeNodeArray& node_array { std::get< OctTreeNodeArray >( m_node_data ) };
const OctTreeNodeArray& node_array { std::get< OctTreeNodeArray >( m_node_data ) };
//Search deeper
node_array[ LEFT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs );
@@ -81,8 +95,13 @@ namespace fgl::engine
}
case 1: // NodeLeaf
{
assert( std::holds_alternative< OctTreeNodeLeaf >( m_node_data ) );
OctTreeNodeLeaf& leaf { std::get< OctTreeNodeLeaf >( m_node_data ) };
if ( leaf.size() == 0 ) return;
//Check if we are inside the frustum.
if ( !isInFrustum( frustum ) ) return;
assert( std::holds_alternative< OctTreeNodeLeaf >( m_node_data ) );
leafs.emplace_back( &leaf );
//debug::world::drawBoundingBox( m_bounds );
@@ -104,18 +123,22 @@ namespace fgl::engine
OctTreeNode& OctTreeNode::operator[]( const WorldCoordinate coord )
{
assert( std::holds_alternative< OctTreeNodeArray >( m_node_data ) );
const auto test_dim { glm::greaterThanEqual( coord.vec(), this->m_bounds.getPosition().vec() ) };
const auto bounds_center { this->m_bounds.getPosition().vec() };
const auto test_dim { glm::greaterThanEqual( coord.vec(), bounds_center ) };
auto& node_array { std::get< OctTreeNodeArray >( m_node_data ) };
const auto& node { node_array[ test_dim.x ][ test_dim.y ][ test_dim.z ] };
const auto& node { node_array[ test_dim.x ? 1 : 0 ][ test_dim.y ? 1 : 0 ][ test_dim.z ? 1 : 0 ] };
assert( node );
assert( node->canContain( coord ) );
return *node.get();
}
OctTreeNode::OctTreeNode( const WorldCoordinate center, float span, OctTreeNode* parent ) :
m_fit_bounding_box( center, glm::vec3( span, span, span ) ),
m_bounds( center, span ),
OctTreeNode::OctTreeNode( const WorldCoordinate center, const float span, OctTreeNode* parent ) :
m_fit_bounding_box( center, glm::vec3( glm::abs( span ) ) ),
m_bounds( center, glm::abs( span ) ),
m_node_data( OctTreeNodeLeaf() ),
m_parent( parent )
{
@@ -123,11 +146,11 @@ namespace fgl::engine
std::get< OctTreeNodeLeaf >( m_node_data ).reserve( MAX_NODES_IN_LEAF );
}
void OctTreeNode::split( int depth )
void OctTreeNode::split( const int depth )
{
ZoneScoped;
if ( std::holds_alternative< OctTreeNodeArray >( m_node_data ) ) return;
auto& game_objects { std::get< OctTreeNodeLeaf >( m_node_data ) };
auto game_objects { std::get< OctTreeNodeLeaf >( std::move( m_node_data ) ) };
//Figure out the half span
const float half_span { m_bounds.span() / 2.0f };
@@ -139,11 +162,17 @@ namespace fgl::engine
const float left_x { center.x - half_span };
const float right_x { center.x + half_span };
const float forward_y { center.y - half_span };
const float backward_y { center.y + half_span };
const float forward_y { center.y + half_span };
const float backward_y { center.y - half_span };
const float top_z { center.z - half_span };
const float bottom_z { center.z + half_span };
const float top_z { center.z + half_span };
const float bottom_z { center.z - half_span };
assert( !std::isinf( left_x ) && !std::isinf( right_x ) );
assert( !std::isinf( forward_y ) && !std::isinf( backward_y ) );
assert( !std::isinf( top_z ) && !std::isinf( bottom_z ) );
log::debug( "Splitting node at {}", m_bounds.span() );
new_nodes[ LEFT ][ FORWARD ][ TOP ] =
std::make_unique< OctTreeNode >( WorldCoordinate( left_x, forward_y, top_z ), half_span, this );
@@ -195,7 +224,8 @@ namespace fgl::engine
OctTreeNode* OctTreeNode::addGameObject( GameObject&& obj )
{
assert( this->canContain( obj ) );
if ( std::holds_alternative< OctTreeNodeLeaf >( m_node_data ) )
if ( std::holds_alternative< OctTreeNodeLeaf >( m_node_data ) ) // This node is a leaf
{
auto& objects { std::get< OctTreeNodeLeaf >( m_node_data ) };
assert( objects.capacity() == MAX_NODES_IN_LEAF );
@@ -203,15 +233,21 @@ namespace fgl::engine
if ( objects.size() + 1 > MAX_NODES_IN_LEAF )
{
split();
return this->addGameObject( std::move( obj ) );
auto* node { this->addGameObject( std::move( obj ) ) };
return node;
}
log::debug( "Added game object" );
objects.emplace_back( std::move( obj ) );
return this;
}
else if ( std::holds_alternative< OctTreeNodeArray >( m_node_data ) )
{
auto* node { ( *this )[ obj.getPosition() ].addGameObject( std::forward< GameObject >( obj ) ) };
return node;
}
return ( *this )[ obj.getPosition() ].addGameObject( std::forward< GameObject >( obj ) );
FGL_UNREACHABLE();
}
bool OctTreeNode::isInFrustum( const Frustum& frustum ) const
@@ -219,10 +255,22 @@ namespace fgl::engine
#if ENABLE_IMGUI
if ( !isEmpty() && frustum.intersects( m_fit_bounding_box ) )
{
if ( ( draw_inview_bounds || std::holds_alternative< OctTreeNodeLeaf >( this->m_node_data ) ) && m_parent )
if ( ( draw_inview_bounds || ( std::holds_alternative< OctTreeNodeLeaf >( this->m_node_data ) )
|| draw_branches )
&& m_parent ) [[unlikely]]
{
// if ( draw_leaf_fit_bounds ) debug::world::drawBoundingBox( m_fit_bounding_box );
// if ( draw_leaf_real_bounds ) debug::world::drawBoundingBox( m_bounds );
if ( draw_leaf_fit_bounds ) [[unlikely]]
debug::drawBoundingBox( m_fit_bounding_box );
/*
debug::drawBoundingBox(
m_fit_bounding_box,
glm::vec3(
m_fit_bounding_box.getPosition().x > 0.0f ? 1.0f : 0.0f,
m_fit_bounding_box.getPosition().y > 0.0f ? 1.0f : 0.0f,
m_fit_bounding_box.getPosition().z > 0.0f ? 1.0f : 0.0f ) );
*/
if ( draw_leaf_real_bounds ) [[unlikely]]
debug::drawBoundingBox( m_bounds );
}
return true;
@@ -235,6 +283,49 @@ namespace fgl::engine
#endif
}
void OctTreeNode::recalculateBounds()
{
m_fit_bounding_box = m_bounds;
if ( std::holds_alternative< NodeDataT >( m_node_data ) )
{
// We aren't a leaf. So we need to use the bounding box of the children below us
const auto& nodes { std::get< NodeDataT >( m_node_data ) };
for ( std::size_t x = 0; x < 2; ++x )
{
for ( std::size_t y = 0; y < 2; ++y )
{
for ( std::size_t z = 0; z < 2; ++z )
{
nodes[ x ][ y ][ z ]->recalculateBounds();
m_fit_bounding_box = m_fit_bounding_box.combine( nodes[ x ][ y ][ z ]->m_fit_bounding_box );
}
}
}
}
else if ( std::holds_alternative< LeafDataT >( m_node_data ) )
{
const auto& data { std::get< LeafDataT >( m_node_data ) };
for ( const auto& game_object : data )
{
auto model_components { game_object.getComponents< ModelComponent >() };
for ( const auto& model : model_components )
{
const OrientedBoundingBox model_bounding_box { ( *model )->getBoundingBox() };
const OrientedBoundingBox< CoordinateSpace::World > world_bounding_box { model->m_transform.mat()
* model_bounding_box };
m_fit_bounding_box = m_fit_bounding_box.combine( world_bounding_box.alignToWorld() );
}
}
}
}
OctTreeNode* OctTreeNode::findID( const GameObject::GameObjectID id )
{
ZoneScoped;
@@ -286,9 +377,14 @@ namespace fgl::engine
game_objects.begin(), game_objects.end(), [ id ]( const GameObject& obj ) { return id == obj.getId(); } );
}
bool OctTreeNode::canContain( const GameObject& obj )
bool OctTreeNode::canContain( const GameObject& obj ) const
{
return m_bounds.contains( obj.getTransform().translation );
return canContain( obj.getTransform().translation );
}
bool OctTreeNode::canContain( const WorldCoordinate& obj ) const
{
return m_bounds.contains( obj );
}
GameObject OctTreeNode::extract( const GameObject::GameObjectID id )
@@ -422,6 +518,25 @@ namespace fgl::engine
std::size_t OctTreeNode::reorganize()
{
std::size_t counter { 0 };
if ( std::holds_alternative< NodeDataT >( m_node_data ) )
{
const auto& nodes { std::get< NodeDataT >( m_node_data ) };
for ( std::size_t x = 0; x < 2; ++x )
{
for ( std::size_t y = 0; y < 2; ++y )
{
for ( std::size_t z = 0; z < 2; ++z )
{
if ( x == 0 && y == 0 && z == 0 ) continue;
const auto& node { nodes[ x ][ y ][ z ] };
counter += node->reorganize();
}
}
}
return counter;
}
if ( std::holds_alternative< LeafDataT >( m_node_data ) )
{
//Check if any of the nodes in this group need to be moved.
@@ -441,25 +556,6 @@ namespace fgl::engine
}
return counter;
}
else if ( std::holds_alternative< NodeDataT >( m_node_data ) )
{
const auto& nodes { std::get< NodeDataT >( m_node_data ) };
for ( std::size_t x = 0; x < 2; ++x )
{
for ( std::size_t y = 0; y < 2; ++y )
{
for ( std::size_t z = 0; z < 2; ++z )
{
if ( x == 0 && y == 0 && z == 0 ) continue;
const auto& node { nodes[ x ][ y ][ z ] };
counter += node->reorganize();
}
}
}
return counter;
}
FGL_UNREACHABLE();
}

View File

@@ -14,17 +14,19 @@
namespace fgl::engine
{
constexpr std::size_t MAX_NODES_IN_LEAF { 32 };
constexpr std::size_t STARTING_DEPTH { 4 };
constexpr std::size_t STARTING_DEPTH { 1 };
constexpr float ROOT_SPAN { std::numeric_limits< float >::max() };
struct Frustum;
constexpr std::uint8_t TOP { 0 };
constexpr std::uint8_t BOTTOM { 1 };
constexpr std::uint8_t LEFT { 0 };
constexpr std::uint8_t TOP { 1 };
constexpr std::uint8_t BOTTOM { 0 };
constexpr std::uint8_t RIGHT { 1 };
constexpr std::uint8_t FORWARD { 0 };
constexpr std::uint8_t BACK { 1 };
constexpr std::uint8_t LEFT { 0 };
constexpr std::uint8_t FORWARD { 1 };
constexpr std::uint8_t BACK { 0 };
class OctTreeNode;
class GameObject;
@@ -37,7 +39,7 @@ namespace fgl::engine
struct FrameInfo;
void imGuiOctTreeSettings( FrameInfo& info );
void imGuiOctTreeSettings( const FrameInfo& info );
class OctTreeNode
{
@@ -79,7 +81,8 @@ namespace fgl::engine
OctTreeNode* getRoot();
//! returns true if this node should contain the given object
bool canContain( const GameObject& obj );
bool canContain( const GameObject& obj ) const;
bool canContain( const WorldCoordinate& obj ) const;
GameObject extract( GameObject::GameObjectID id );
@@ -107,6 +110,8 @@ namespace fgl::engine
//! Rebuilds the tree checking if nodes have moved.
std::size_t reorganize();
void recalculateBounds();
constexpr static std::size_t LEAF_RESERVE_SIZE { 1024 };
[[nodiscard]] std::vector< OctTreeNodeLeaf* > getAllLeafs()