Optimization
This commit is contained in:
@@ -505,7 +505,7 @@ namespace fgl::engine
|
||||
|
||||
model->syncBuffers( command_buffer );
|
||||
|
||||
constexpr int val { 4 };
|
||||
constexpr int val { 32 };
|
||||
|
||||
constexpr float x_offset { -( static_cast< float >( val ) * 30.0f ) / 2.0f };
|
||||
constexpr float y_offset { -( static_cast< float >( val ) * 20.0f ) / 2.0f };
|
||||
|
||||
@@ -83,6 +83,8 @@ namespace fgl::engine
|
||||
DescriptorSet& gbuffer_descriptor_set;
|
||||
|
||||
const Frustum< CoordinateSpace::World >& camera_frustum;
|
||||
|
||||
std::vector< std::vector< GameObject >* > in_view_leafs {};
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
@@ -81,6 +81,15 @@ namespace fgl::engine
|
||||
template < typename T >
|
||||
bool intersects( const T& t ) const;
|
||||
|
||||
template < typename T, std::size_t TSize >
|
||||
inline bool intersects( const std::array< T, TSize >& t ) const
|
||||
{
|
||||
for ( std::size_t i = 0; i < TSize; ++i )
|
||||
if ( intersects( t[ i ] ) ) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
Coordinate< CType > intersection( const T& t ) const;
|
||||
|
||||
|
||||
@@ -17,9 +17,10 @@ namespace fgl::engine
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
std::vector< Coordinate< CType > > AxisAlignedBoundingBox< CType >::points() const
|
||||
std::array< Coordinate< CType >, interface::BoundingBox::POINT_COUNT > AxisAlignedBoundingBox< CType >::points()
|
||||
const
|
||||
{
|
||||
std::vector< Coordinate< CType > > points;
|
||||
std::array< Coordinate< CType >, POINT_COUNT > points {};
|
||||
|
||||
// xp == x positive (Highest x point)
|
||||
// xn == x negative (Lowest x point)
|
||||
@@ -40,7 +41,6 @@ namespace fgl::engine
|
||||
const glm::vec3 xn_yp_zn { xn, yp, zn }; // (- + -)
|
||||
const glm::vec3 xp_yp_zn { xp, yp, zn }; // (+ + -)
|
||||
|
||||
points.resize( 8 );
|
||||
points[ 0 ] = Coordinate< CType >( xp_yp_zp );
|
||||
points[ 1 ] = Coordinate< CType >( xn_yp_zp );
|
||||
points[ 2 ] = Coordinate< CType >( xn_yp_zn );
|
||||
@@ -62,29 +62,30 @@ namespace fgl::engine
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
std::vector< LineSegment< CType > > AxisAlignedBoundingBox< CType >::lines() const
|
||||
std::array< LineSegment< CType >, interface::BoundingBox::LINE_COUNT > AxisAlignedBoundingBox< CType >::lines()
|
||||
const
|
||||
{
|
||||
const auto points { this->points() };
|
||||
|
||||
std::vector< LineSegment< CType > > lines;
|
||||
std::array< LineSegment< CType >, LINE_COUNT > lines {};
|
||||
|
||||
//Top
|
||||
lines.emplace_back( points[ 0 ], points[ 1 ] );
|
||||
lines.emplace_back( points[ 1 ], points[ 2 ] );
|
||||
lines.emplace_back( points[ 2 ], points[ 3 ] );
|
||||
lines.emplace_back( points[ 3 ], points[ 0 ] );
|
||||
lines[ 0 ] = LineSegment< CType >( points[ 0 ], points[ 1 ] );
|
||||
lines[ 1 ] = LineSegment< CType >( points[ 1 ], points[ 2 ] );
|
||||
lines[ 2 ] = LineSegment< CType >( points[ 2 ], points[ 3 ] );
|
||||
lines[ 3 ] = LineSegment< CType >( points[ 3 ], points[ 0 ] );
|
||||
|
||||
//Bottom
|
||||
lines.emplace_back( points[ 4 ], points[ 5 ] );
|
||||
lines.emplace_back( points[ 5 ], points[ 6 ] );
|
||||
lines.emplace_back( points[ 6 ], points[ 7 ] );
|
||||
lines.emplace_back( points[ 7 ], points[ 4 ] );
|
||||
lines[ 4 ] = LineSegment< CType >( points[ 4 ], points[ 5 ] );
|
||||
lines[ 5 ] = LineSegment< CType >( points[ 5 ], points[ 6 ] );
|
||||
lines[ 6 ] = LineSegment< CType >( points[ 6 ], points[ 7 ] );
|
||||
lines[ 7 ] = LineSegment< CType >( points[ 7 ], points[ 4 ] );
|
||||
|
||||
//Sides
|
||||
lines.emplace_back( points[ 0 ], points[ 4 ] );
|
||||
lines.emplace_back( points[ 1 ], points[ 5 ] );
|
||||
lines.emplace_back( points[ 2 ], points[ 6 ] );
|
||||
lines.emplace_back( points[ 3 ], points[ 7 ] );
|
||||
lines[ 8 ] = LineSegment< CType >( points[ 0 ], points[ 4 ] );
|
||||
lines[ 9 ] = LineSegment< CType >( points[ 1 ], points[ 5 ] );
|
||||
lines[ 10 ] = LineSegment< CType >( points[ 2 ], points[ 6 ] );
|
||||
lines[ 11 ] = LineSegment< CType >( points[ 3 ], points[ 7 ] );
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ namespace fgl::engine
|
||||
|
||||
virtual Scale scale() const;
|
||||
|
||||
std::vector< Coordinate< CType > > points() const;
|
||||
std::vector< LineSegment< CType > > lines() const;
|
||||
std::array< Coordinate< CType >, POINT_COUNT > points() const;
|
||||
std::array< LineSegment< CType >, LINE_COUNT > lines() const;
|
||||
|
||||
constexpr NormalVector right() const { return NormalVector::bypass( constants::WORLD_RIGHT ); }
|
||||
|
||||
|
||||
@@ -12,10 +12,14 @@ namespace fgl::engine::interface
|
||||
class NormalVector;
|
||||
|
||||
//! Dummy class to allow for inheriting to pass 'is_bounding_box[
|
||||
class BoundingBox
|
||||
struct BoundingBox
|
||||
{
|
||||
public:
|
||||
|
||||
constexpr static std::size_t POINT_COUNT { 8 };
|
||||
constexpr static std::size_t LINE_COUNT { ( POINT_COUNT / 2 ) * 3 };
|
||||
// Each point has 3 lines (Divide by 2 since we only need 1 line per direction)
|
||||
|
||||
virtual ~BoundingBox() {};
|
||||
};
|
||||
|
||||
|
||||
@@ -84,11 +84,11 @@ namespace fgl::engine
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
std::vector< Coordinate< CType > > OrientedBoundingBox< CType >::points() const
|
||||
std::array< Coordinate< CType >, interface::BoundingBox::POINT_COUNT > OrientedBoundingBox< CType >::points() const
|
||||
{
|
||||
assert( middle.vec() != constants::DEFAULT_VEC3 );
|
||||
assert( scale != glm::vec3( 0.0f ) );
|
||||
std::vector< Coordinate< CType > > points;
|
||||
std::array< Coordinate< CType >, POINT_COUNT > points {};
|
||||
|
||||
// xp == x positive (Highest x point)
|
||||
// xn == x negative (Lowest x point)
|
||||
@@ -129,7 +129,6 @@ namespace fgl::engine
|
||||
* 6 =========== 7
|
||||
*/
|
||||
|
||||
points.resize( 8 );
|
||||
points[ 0 ] = Coordinate< CType >( xp_yp_zp );
|
||||
points[ 1 ] = Coordinate< CType >( xn_yp_zp );
|
||||
points[ 2 ] = Coordinate< CType >( xn_yp_zn );
|
||||
@@ -170,41 +169,72 @@ namespace fgl::engine
|
||||
|
||||
ZoneScoped;
|
||||
const auto& other_points { other.points() };
|
||||
std::vector< Coordinate< CType > > points { this->points() };
|
||||
points.insert( points.end(), other_points.begin(), other_points.end() );
|
||||
const auto points { this->points() };
|
||||
std::array< Coordinate< CType >, interface::BoundingBox::POINT_COUNT * 2 > combined_points {};
|
||||
std::copy( other_points.begin(), other_points.end(), combined_points.begin() );
|
||||
std::copy( points.begin(), points.end(), combined_points.begin() + POINT_COUNT );
|
||||
|
||||
//TODO: There might be a way to do this without needing to do yet another point calculation.
|
||||
return generateBoundingFromPoints< CType >( points );
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
std::vector< LineSegment< CType > > OrientedBoundingBox< CType >::lines() const
|
||||
std::array< LineSegment< CType >, interface::BoundingBox::LINE_COUNT > OrientedBoundingBox< CType >::lines() const
|
||||
{
|
||||
const auto points { this->points() };
|
||||
|
||||
std::vector< LineSegment< CType > > lines;
|
||||
std::array< LineSegment< CType >, LINE_COUNT > lines;
|
||||
|
||||
//Top
|
||||
lines.emplace_back( points[ 0 ], points[ 1 ] );
|
||||
lines.emplace_back( points[ 1 ], points[ 2 ] );
|
||||
lines.emplace_back( points[ 2 ], points[ 3 ] );
|
||||
lines.emplace_back( points[ 3 ], points[ 0 ] );
|
||||
lines[ 0 ] = LineSegment< CType >( points[ 0 ], points[ 1 ] );
|
||||
lines[ 1 ] = LineSegment< CType >( points[ 1 ], points[ 2 ] );
|
||||
lines[ 2 ] = LineSegment< CType >( points[ 2 ], points[ 3 ] );
|
||||
lines[ 3 ] = LineSegment< CType >( points[ 3 ], points[ 0 ] );
|
||||
|
||||
//Bottom
|
||||
lines.emplace_back( points[ 4 ], points[ 5 ] );
|
||||
lines.emplace_back( points[ 5 ], points[ 6 ] );
|
||||
lines.emplace_back( points[ 6 ], points[ 7 ] );
|
||||
lines.emplace_back( points[ 7 ], points[ 4 ] );
|
||||
lines[ 4 ] = LineSegment< CType >( points[ 4 ], points[ 5 ] );
|
||||
lines[ 5 ] = LineSegment< CType >( points[ 5 ], points[ 6 ] );
|
||||
lines[ 6 ] = LineSegment< CType >( points[ 6 ], points[ 7 ] );
|
||||
lines[ 7 ] = LineSegment< CType >( points[ 7 ], points[ 4 ] );
|
||||
|
||||
//Sides
|
||||
lines.emplace_back( points[ 0 ], points[ 4 ] );
|
||||
lines.emplace_back( points[ 1 ], points[ 5 ] );
|
||||
lines.emplace_back( points[ 2 ], points[ 6 ] );
|
||||
lines.emplace_back( points[ 3 ], points[ 7 ] );
|
||||
lines[ 8 ] = LineSegment< CType >( points[ 0 ], points[ 4 ] );
|
||||
lines[ 9 ] = LineSegment< CType >( points[ 1 ], points[ 5 ] );
|
||||
lines[ 10 ] = LineSegment< CType >( points[ 2 ], points[ 6 ] );
|
||||
lines[ 11 ] = LineSegment< CType >( points[ 3 ], points[ 7 ] );
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType, std::size_t TCount >
|
||||
OrientedBoundingBox< CType > generateBoundingFromPoints( const std::array< Coordinate< CType >, TCount >& points )
|
||||
{
|
||||
ZoneScoped;
|
||||
assert( points.size() > 0 );
|
||||
|
||||
// neg (min)
|
||||
glm::vec3 top_left_front { points[ 0 ].vec() };
|
||||
// pos (max)
|
||||
glm::vec3 bottom_right_back { points[ 0 ].vec() };
|
||||
|
||||
for ( const auto& pos : points )
|
||||
{
|
||||
top_left_front.x = std::min( pos.vec().x, top_left_front.x );
|
||||
top_left_front.y = std::min( pos.vec().y, top_left_front.y );
|
||||
top_left_front.z = std::min( pos.vec().z, top_left_front.z );
|
||||
|
||||
bottom_right_back.x = std::max( pos.vec().x, bottom_right_back.x );
|
||||
bottom_right_back.y = std::max( pos.vec().y, bottom_right_back.y );
|
||||
bottom_right_back.z = std::max( pos.vec().z, bottom_right_back.z );
|
||||
}
|
||||
|
||||
//Calculate midpoint
|
||||
const glm::vec3 midpoint { ( top_left_front + bottom_right_back ) / glm::vec3( 2.0f ) };
|
||||
const glm::vec3 scale { bottom_right_back - midpoint };
|
||||
|
||||
return { Coordinate< CType >( midpoint ), scale };
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
OrientedBoundingBox< CType > generateBoundingFromPoints( const std::vector< Coordinate< CType > >& points )
|
||||
{
|
||||
@@ -234,6 +264,10 @@ namespace fgl::engine
|
||||
return { Coordinate< CType >( midpoint ), scale };
|
||||
}
|
||||
|
||||
template OrientedBoundingBox< CoordinateSpace::Model > generateBoundingFromPoints( const std::vector< Coordinate<
|
||||
CoordinateSpace::Model > >&
|
||||
points );
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > generateBoundingFromVerts( const std::vector< Vertex >& verts )
|
||||
{
|
||||
// neg (min)
|
||||
|
||||
@@ -56,8 +56,8 @@ namespace fgl::engine
|
||||
|
||||
consteval static std::array< std::uint32_t, indicies_count > triangleIndicies();
|
||||
|
||||
std::vector< Coordinate< CType > > points() const;
|
||||
std::vector< LineSegment< CType > > lines() const;
|
||||
std::array< Coordinate< CType >, POINT_COUNT > points() const;
|
||||
std::array< LineSegment< CType >, LINE_COUNT > lines() const;
|
||||
|
||||
NormalVector forward() const { return rotation.forward(); }
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace fgl::engine
|
||||
template < CoordinateSpace CType >
|
||||
class LineSegment final : public LineBase
|
||||
{
|
||||
Coordinate< CType > start;
|
||||
Coordinate< CType > end;
|
||||
Coordinate< CType > start { -constants::DEFAULT_VEC3 };
|
||||
Coordinate< CType > end { constants::DEFAULT_VEC3 };
|
||||
|
||||
glm::vec3 getVec3Position() const override { return getPosition().vec(); }
|
||||
|
||||
@@ -25,11 +25,7 @@ namespace fgl::engine
|
||||
|
||||
public:
|
||||
|
||||
NormalVector getDirection() const { return NormalVector( end - start ); }
|
||||
|
||||
Coordinate< CType > getPosition() const { return start; }
|
||||
|
||||
Coordinate< CType > getEnd() const { return end; }
|
||||
LineSegment() = default;
|
||||
|
||||
explicit LineSegment( const Coordinate< CType > i_start, const Coordinate< CType > i_end ) noexcept :
|
||||
start( i_start ),
|
||||
@@ -38,6 +34,12 @@ namespace fgl::engine
|
||||
|
||||
explicit LineSegment( const glm::vec3 i_start, glm::vec3 i_end ) : start( i_start ), end( i_end ) {}
|
||||
|
||||
NormalVector getDirection() const { return NormalVector( end - start ); }
|
||||
|
||||
Coordinate< CType > getPosition() const { return start; }
|
||||
|
||||
Coordinate< CType > getEnd() const { return end; }
|
||||
|
||||
inline LineSegment flip() const { return LineSegment( end, start ); }
|
||||
|
||||
template < typename T >
|
||||
|
||||
@@ -51,16 +51,20 @@ namespace fgl::engine
|
||||
throw std::runtime_error( "Failed to allocate command buffers" );
|
||||
|
||||
#if TRACY_ENABLE
|
||||
m_tracy_ctx.resize( SwapChain::MAX_FRAMES_IN_FLIGHT );
|
||||
VkPhysicalDevice phy_dev { Device::getInstance().phyDevice() };
|
||||
VkDevice dev { Device::getInstance().device() };
|
||||
|
||||
for ( int i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
|
||||
{
|
||||
VkPhysicalDevice phy_dev { Device::getInstance().phyDevice() };
|
||||
VkDevice dev { Device::getInstance().device() };
|
||||
m_tracy_ctx = TracyVkContext( phy_dev, dev, Device::getInstance().graphicsQueue(), m_command_buffer[ 0 ] );
|
||||
|
||||
m_tracy_ctx[ i ] =
|
||||
TracyVkContext( phy_dev, dev, Device::getInstance().graphicsQueue(), m_command_buffer[ i ] );
|
||||
}
|
||||
/*
|
||||
m_tracy_ctx = TracyVkContextCalibrated(
|
||||
phy_dev,
|
||||
dev,
|
||||
Device::getInstance().graphicsQueue(),
|
||||
m_command_buffer[ 0 ],
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.vkGetPhysicalDeviceCalibrateableTimeDomainsEXT,
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.vkGetCalibratedTimestampsEXT );
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace fgl::engine
|
||||
|
||||
std::vector< vk::CommandBuffer > m_command_buffer {};
|
||||
|
||||
std::vector< TracyVkCtx > m_tracy_ctx {};
|
||||
std::optional< TracyVkCtx > m_tracy_ctx { std::nullopt };
|
||||
|
||||
void createCommandBuffers();
|
||||
void freeCommandBuffers();
|
||||
@@ -63,7 +63,8 @@ namespace fgl::engine
|
||||
TracyVkCtx getCurrentTracyCTX() const
|
||||
{
|
||||
#if TRACY_ENABLE
|
||||
return m_tracy_ctx[ current_frame_idx ];
|
||||
assert( m_tracy_ctx.has_value() );
|
||||
return m_tracy_ctx.value();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
|
||||
@@ -13,15 +13,27 @@
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
static bool enable_culling { true };
|
||||
|
||||
void CullingSystem::pass( FrameInfo& info )
|
||||
{
|
||||
ZoneScopedN( "Culling pass" );
|
||||
|
||||
const auto frustum { info.camera_frustum };
|
||||
|
||||
for ( auto* leaf : info.game_objects.getAllLeafsInFrustum( frustum ) )
|
||||
ImGui::Checkbox( "Enable culling", &enable_culling );
|
||||
|
||||
if ( !enable_culling )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto leafs { info.game_objects.getAllLeafsInFrustum( frustum ) };
|
||||
|
||||
for ( auto* leaf : leafs )
|
||||
{
|
||||
assert( leaf );
|
||||
|
||||
for ( auto& obj : *leaf )
|
||||
{
|
||||
//Has model?
|
||||
@@ -43,6 +55,8 @@ namespace fgl::engine
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info.in_view_leafs = std::move( leafs );
|
||||
}
|
||||
|
||||
void CullingSystem::runner()
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "concepts.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
struct FrameInfo;
|
||||
@@ -34,4 +36,7 @@ namespace fgl::engine
|
||||
void wait();
|
||||
};
|
||||
|
||||
static_assert( is_system< CullingSystem > );
|
||||
static_assert( is_threaded_system< CullingSystem > );
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
@@ -113,9 +113,7 @@ namespace fgl::engine
|
||||
std::uint64_t object_counter { 0 };
|
||||
std::uint64_t primitive_counter { 0 };
|
||||
|
||||
const auto in_view_leafs { info.game_objects.getAllLeafsInFrustum( info.camera_frustum ) };
|
||||
|
||||
for ( auto* node : in_view_leafs )
|
||||
for ( auto* node : info.in_view_leafs )
|
||||
{
|
||||
ZoneScopedN( "Process leaf" );
|
||||
for ( const auto& obj : *node )
|
||||
|
||||
33
src/engine/systems/concepts.hpp
Normal file
33
src/engine/systems/concepts.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Created by kj16609 on 3/11/24.
|
||||
//
|
||||
|
||||
#ifndef GAME_CONCEPTS_HPP
|
||||
#define GAME_CONCEPTS_HPP
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
struct FrameInfo;
|
||||
|
||||
template < typename T >
|
||||
concept is_system = requires( T t, FrameInfo info ) {
|
||||
{
|
||||
t.pass( info )
|
||||
};
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
concept is_threaded_system = requires( T t, FrameInfo info ) {
|
||||
requires is_system< T >;
|
||||
{
|
||||
t.startPass( info )
|
||||
};
|
||||
{
|
||||
t.wait()
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
#endif //GAME_CONCEPTS_HPP
|
||||
@@ -30,12 +30,13 @@ namespace fgl::engine
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector< NodeLeaf* > OctTreeNode::getAllLeafsInFrustum( const Frustum< CoordinateSpace::World >& frustum )
|
||||
void OctTreeNode::
|
||||
getAllLeafsInFrustum( const Frustum< CoordinateSpace::World >& frustum, std::vector< NodeLeaf* >& out_leafs )
|
||||
{
|
||||
std::vector< NodeLeaf* > leafs {};
|
||||
|
||||
//Check if we are inside of the frustum.
|
||||
if ( !isInFrustum( frustum ) ) return leafs;
|
||||
if ( !isInFrustum( frustum ) ) return;
|
||||
|
||||
auto& leafs { out_leafs };
|
||||
|
||||
switch ( m_node_data.index() )
|
||||
{
|
||||
@@ -45,62 +46,35 @@ namespace fgl::engine
|
||||
NodeArray& node_array { std::get< NodeArray >( m_node_data ) };
|
||||
//Search deeper
|
||||
|
||||
#ifndef NDEBUG
|
||||
for ( int x = 0; x < 2; ++x )
|
||||
for ( int y = 0; y < 2; ++y )
|
||||
for ( int z = 0; z < 2; ++z ) assert( node_array[ x ][ y ][ z ] );
|
||||
#endif
|
||||
node_array[ LEFT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
node_array[ LEFT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
|
||||
{
|
||||
const auto ret { node_array[ LEFT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum ) };
|
||||
leafs = std::move( ret );
|
||||
}
|
||||
{
|
||||
const auto ret { node_array[ LEFT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum ) };
|
||||
leafs.insert( leafs.end(), ret.begin(), ret.end() );
|
||||
}
|
||||
{
|
||||
const auto ret { node_array[ LEFT ][ BACK ][ TOP ]->getAllLeafsInFrustum( frustum ) };
|
||||
leafs.insert( leafs.end(), ret.begin(), ret.end() );
|
||||
}
|
||||
{
|
||||
const auto ret { node_array[ LEFT ][ BACK ][ BOTTOM ]->getAllLeafsInFrustum( frustum ) };
|
||||
leafs.insert( leafs.end(), ret.begin(), ret.end() );
|
||||
}
|
||||
node_array[ LEFT ][ BACK ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
node_array[ LEFT ][ BACK ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
|
||||
{
|
||||
const auto ret { node_array[ RIGHT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum ) };
|
||||
leafs.insert( leafs.end(), ret.begin(), ret.end() );
|
||||
}
|
||||
{
|
||||
const auto ret { node_array[ RIGHT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum ) };
|
||||
leafs.insert( leafs.end(), ret.begin(), ret.end() );
|
||||
}
|
||||
{
|
||||
const auto ret { node_array[ RIGHT ][ BACK ][ TOP ]->getAllLeafsInFrustum( frustum ) };
|
||||
leafs.insert( leafs.end(), ret.begin(), ret.end() );
|
||||
}
|
||||
{
|
||||
const auto ret { node_array[ RIGHT ][ BACK ][ BOTTOM ]->getAllLeafsInFrustum( frustum ) };
|
||||
leafs.insert( leafs.end(), ret.begin(), ret.end() );
|
||||
}
|
||||
return leafs;
|
||||
node_array[ RIGHT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
node_array[ RIGHT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
|
||||
node_array[ RIGHT ][ BACK ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
node_array[ RIGHT ][ BACK ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs );
|
||||
return;
|
||||
}
|
||||
case 1: // NodeLeaf
|
||||
{
|
||||
assert( std::holds_alternative< NodeLeaf >( m_node_data ) );
|
||||
leafs.reserve( 4096 );
|
||||
leafs.emplace_back( &std::get< NodeLeaf >( m_node_data ) );
|
||||
NodeLeaf& leaf { std::get< NodeLeaf >( m_node_data ) };
|
||||
leafs.reserve( LEAF_RESERVE_SIZE );
|
||||
leafs.emplace_back( &leaf );
|
||||
|
||||
//debug::world::drawBoundingBox( m_bounds );
|
||||
|
||||
return leafs;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error( "OctTreeNode::Index out of bounds" );
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
return leafs;
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
OctTreeNode::OctTreeNode( const WorldCoordinate center, float span, OctTreeNode* parent ) :
|
||||
@@ -115,6 +89,7 @@ namespace fgl::engine
|
||||
|
||||
void OctTreeNode::split( int depth )
|
||||
{
|
||||
ZoneScoped;
|
||||
if ( std::holds_alternative< NodeArray >( m_node_data ) ) return;
|
||||
auto& game_objects { std::get< NodeLeaf >( m_node_data ) };
|
||||
|
||||
@@ -212,7 +187,7 @@ namespace fgl::engine
|
||||
}
|
||||
}
|
||||
|
||||
bool OctTreeNode::isInFrustum( const Frustum< CoordinateSpace::World >& frustum )
|
||||
bool OctTreeNode::isInFrustum( const Frustum< CoordinateSpace::World >& frustum ) const
|
||||
{
|
||||
#if ENABLE_IMGUI
|
||||
if ( isEmpty() ) return false;
|
||||
@@ -308,11 +283,9 @@ namespace fgl::engine
|
||||
return m_parent->getRoot();
|
||||
}
|
||||
|
||||
std::vector< NodeLeaf* > OctTreeNode::getAllLeafs()
|
||||
void OctTreeNode::getAllLeafs( std::vector< NodeLeaf* >& objects )
|
||||
{
|
||||
ZoneScoped;
|
||||
std::vector< NodeLeaf* > objects {};
|
||||
|
||||
if ( std::holds_alternative< NodeLeaf >( m_node_data ) )
|
||||
{
|
||||
auto& leaf { std::get< NodeLeaf >( m_node_data ) };
|
||||
@@ -335,8 +308,6 @@ namespace fgl::engine
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
bool OctTreeNode::recalculateBoundingBoxes()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <bitset>
|
||||
#include <functional>
|
||||
|
||||
#include "engine/GameObject.hpp"
|
||||
#include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp"
|
||||
@@ -28,6 +29,34 @@ namespace fgl::engine
|
||||
class OctTreeNode;
|
||||
class GameObject;
|
||||
|
||||
template < typename T >
|
||||
class OctTreeAllocator : public std::allocator< T >
|
||||
{
|
||||
std::vector< std::vector< std::byte > > blocks;
|
||||
using BlockIDX = int;
|
||||
|
||||
//! Map for each pointer to their respective blocks
|
||||
std::unordered_map< T*, BlockIDX > m_block_map;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
using unique_alloc_ptr = std::unique_ptr< T, std::function< void( T* ) > >;
|
||||
|
||||
template < typename T, typename... Ts >
|
||||
unique_alloc_ptr< T > make_unique_from_allocator( OctTreeAllocator< T >& allocator, Ts... args )
|
||||
{
|
||||
T* ptr = allocator.allocate( 1 );
|
||||
allocator.construct( ptr, args... );
|
||||
|
||||
auto deleter = [ &allocator ]( const auto* ptr_i ) -> void
|
||||
{
|
||||
allocator.destroy( ptr_i );
|
||||
allocator.deallocate( ptr_i, 1 );
|
||||
};
|
||||
|
||||
return std::unique_ptr< T, decltype( deleter ) >( ptr, deleter );
|
||||
}
|
||||
|
||||
using NodeArray = std::array< std::array< std::array< std::unique_ptr< OctTreeNode >, 2 >, 2 >, 2 >;
|
||||
using NodeLeaf = std::vector< GameObject >;
|
||||
|
||||
@@ -44,7 +73,10 @@ namespace fgl::engine
|
||||
//! Real bounds of the node
|
||||
AxisAlignedBoundingCube< CoordinateSpace::World > m_bounds;
|
||||
|
||||
std::variant< NodeArray, NodeLeaf > m_node_data;
|
||||
using NodeDataT = NodeArray;
|
||||
using LeafDataT = NodeLeaf;
|
||||
|
||||
std::variant< NodeDataT, LeafDataT > m_node_data;
|
||||
|
||||
OctTreeNode* m_parent;
|
||||
|
||||
@@ -77,7 +109,7 @@ namespace fgl::engine
|
||||
|
||||
GameObject extract( const GameObject::ID id );
|
||||
|
||||
bool isInFrustum( const Frustum< CoordinateSpace::World >& frustum );
|
||||
bool isInFrustum( const Frustum< CoordinateSpace::World >& frustum ) const;
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
@@ -86,13 +118,34 @@ namespace fgl::engine
|
||||
|
||||
auto getGameObjectItter( const GameObject::ID id );
|
||||
|
||||
void getAllLeafs( std::vector< NodeLeaf* >& out_leafs );
|
||||
void getAllLeafsInFrustum(
|
||||
const Frustum< CoordinateSpace::World >& frustum, std::vector< NodeLeaf* >& out_leafs );
|
||||
|
||||
public:
|
||||
|
||||
bool recalculateBoundingBoxes();
|
||||
|
||||
std::vector< NodeLeaf* > getAllLeafs();
|
||||
constexpr static std::size_t LEAF_RESERVE_SIZE { 1024 };
|
||||
|
||||
std::vector< NodeLeaf* > getAllLeafsInFrustum( const Frustum< CoordinateSpace::World >& frustum );
|
||||
[[nodiscard]] inline std::vector< NodeLeaf* > getAllLeafs()
|
||||
{
|
||||
ZoneScoped;
|
||||
std::vector< NodeLeaf* > leafs;
|
||||
leafs.reserve( LEAF_RESERVE_SIZE );
|
||||
this->getAllLeafs( leafs );
|
||||
return leafs;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::vector< NodeLeaf* > getAllLeafsInFrustum( const Frustum< CoordinateSpace::World >&
|
||||
frustum )
|
||||
{
|
||||
ZoneScoped;
|
||||
std::vector< NodeLeaf* > leafs;
|
||||
leafs.reserve( LEAF_RESERVE_SIZE );
|
||||
this->getAllLeafsInFrustum( frustum, leafs );
|
||||
return leafs;
|
||||
}
|
||||
|
||||
//! Adds a game object, Will split the node if the auto split threshold is reached
|
||||
OctTreeNode* addGameObject( GameObject&& obj );
|
||||
|
||||
Reference in New Issue
Block a user