Cleans up intersection testing

This commit is contained in:
2024-10-28 06:55:59 -04:00
parent e55fe643c7
commit 78bee55482
24 changed files with 459 additions and 293 deletions

View File

@@ -4,12 +4,9 @@
#pragma once
namespace fgl::engine
{
struct CameraInfo
{
glm::mat4 projection { 1.0f };
@@ -17,5 +14,4 @@ namespace fgl::engine
glm::mat4 inverse_view { 1.0f };
};
} // namespace fgl::engine

View File

@@ -0,0 +1,11 @@
//
// Created by kj16609 on 10/28/24.
//
#include "intersections/frustum/intersections.hpp"
#include "intersections/line/intersections.hpp"
namespace fgl::engine
{
using namespace intersections;
}

View File

@@ -0,0 +1,8 @@
This folder structure follows the following pattern
```cpp
bool intersects( Frustum frustum, OrientedBoundingBox& oob );
```
would be placed in `frustum/obb`

View File

@@ -0,0 +1,29 @@
//
// Created by kj16609 on 10/28/24.
//
#include "engine/math/intersections/helpers.hpp"
#include "engine/primitives/Frustum.hpp"
#include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp"
namespace fgl::engine::intersections
{
bool intersects( const Frustum& frustum, const AxisAlignedBoundingCube< CS::World >& aabc )
{
const auto box_points { aabc.points() };
if ( frustum.containsAnyPoint( box_points ) ) return true;
const auto frustum_points { frustum.points() };
if ( canPlotLine( frustum, frustum_points, box_points ) ) return false;
// Now to test every axis from the bounding box
if ( testAxis( aabc.right(), frustum_points, box_points ) ) return false;
if ( testAxis( aabc.forward(), frustum_points, box_points ) ) return false;
if ( testAxis( aabc.up(), frustum_points, box_points ) ) return false;
return true;
}
} // namespace fgl::engine::intersections

View File

@@ -0,0 +1,30 @@
//
// Created by kj16609 on 10/28/24.
//
#include "engine/math/intersections/helpers.hpp"
#include "engine/primitives/Frustum.hpp"
#include "engine/primitives/boxes/AxisAlignedBoundingBox.hpp"
namespace fgl::engine::intersections
{
bool intersects( const Frustum& frustum, const AxisAlignedBoundingBox< CS::World >& aabb )
{
const auto box_points { aabb.points() };
if ( frustum.containsAnyPoint( box_points ) ) return true;
const auto frustum_points { frustum.points() };
if ( canPlotLine( frustum, frustum_points, box_points ) ) return false;
// Now to test every axis from the bounding box
if ( testAxis( aabb.right(), frustum_points, box_points ) ) return false;
if ( testAxis( aabb.forward(), frustum_points, box_points ) ) return false;
if ( testAxis( aabb.up(), frustum_points, box_points ) ) return false;
return true;
}
} // namespace fgl::engine::intersections

View File

@@ -0,0 +1,15 @@
//
// Created by kj16609 on 10/28/24.
//
#pragma once
#include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp"
namespace fgl::engine::intersections
{
bool intersects( const Frustum& frustum, const AxisAlignedBoundingBox< CS::World >& aabb );
bool intersects( const Frustum& frustum, const AxisAlignedBoundingCube< CS::World >& aabc );
bool intersects( const Frustum& frustum, const OrientedBoundingBox< CS::World >& obb );
} // namespace fgl::engine::intersections

View File

@@ -0,0 +1,30 @@
//
// Created by kj16609 on 10/28/24.
//
#include "engine/math/intersections/helpers.hpp"
#include "engine/primitives/Frustum.hpp"
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
namespace fgl::engine::intersections
{
bool intersects( const Frustum& frustum, const OrientedBoundingBox< CS::World >& obb )
{
const auto box_points { obb.points() };
if ( frustum.containsAnyPoint( box_points ) ) return true;
const auto frustum_points { frustum.points() };
if ( canPlotLine( frustum, frustum_points, box_points ) ) return false;
// Now to test every axis from the bounding box
if ( testAxis( obb.right(), frustum_points, box_points ) ) return false;
if ( testAxis( obb.forward(), frustum_points, box_points ) ) return false;
if ( testAxis( obb.up(), frustum_points, box_points ) ) return false;
return true;
}
} // namespace fgl::engine::intersections

View File

@@ -0,0 +1,66 @@
//
// Created by kj16609 on 10/28/24.
//
#pragma once
#include "engine/FGL_DEFINES.hpp"
#include "engine/primitives/Frustum.hpp"
#include "engine/primitives/vectors/NormalVector.hpp"
namespace fgl::engine
{
//! Returns the max and min of a point along an axis
std::pair< float, float > minMaxDot( const NormalVector axis, const auto points )
{
assert( points.size() > 2 );
float min { std::numeric_limits< float >::infinity() };
float max { -std::numeric_limits< float >::infinity() };
for ( std::size_t i = 0; i < points.size(); ++i )
{
const auto value { glm::dot( points[ i ].vec(), axis.vec() ) };
min = std::min( min, value );
max = std::max( max, value );
}
return std::make_pair( min, max );
}
//! Returns true if we can draw a line between the two point sets.
template < typename TL, typename TR >
//TODO: Concept this to only allow for arrays/vectors
bool testAxis( const NormalVector axis, const TL& left_points, const TR& right_points )
{
const auto [ min_left, max_left ] = minMaxDot( axis, left_points );
const auto [ min_right, max_right ] = minMaxDot( axis, right_points );
//If there is an overlap then we are unable to draw a line between the two.
return max_left < min_right || max_right < min_left;
}
// Hyperplane Separation Theorem
// Since the bounding box is oriented we need to test all points from it and 3 axis from the frustum and 3 axis from the box.
// If we find 1 line that seperates then we fail the test and can early exit
// This test might be more optimal to do then a pointInside check since it will early fail rather then early pass.
// We can also make this more optimal by discarding overlapping points. For example, Testing the right axis vector on the Frustum means we can discard the 'low' points. Since the 'high' points would be identical.
// Though this will likely be a micro-optimizaton in the long run anyways. But less tests means we might be able to almost half the points being tested.
//! Can plot line between frustum and a given set of points
template < CoordinateSpace CType, std::uint64_t FrustumPointCount, std::uint64_t BoundingBoxPointCount >
FGL_FLATTEN_HOT bool canPlotLine(
const Frustum& frustum,
const std::array< Coordinate< CType >, FrustumPointCount >& frustum_points,
const std::array< Coordinate< CType >, BoundingBoxPointCount >& bounding_points )
{
return (
testAxis( frustum.right.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.left.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.near.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.far.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.top.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.bottom.getDirection(), frustum_points, bounding_points ) );
}
} // namespace fgl::engine

View File

@@ -0,0 +1,129 @@
//
// Created by kj16609 on 10/28/24.
//
#include "engine/primitives/Frustum.hpp"
#include <vector>
#include "engine/primitives/lines/LineSegment.hpp"
#include "engine/primitives/points/Coordinate.hpp"
namespace fgl::engine::intersection
{
float signedDistance( const NormalVector direction, const WorldCoordinate& point, const WorldCoordinate& origin )
{
const glm::vec3 vector_between { point.vec() - origin.vec() };
const float dot { glm::dot( vector_between, direction.vec() ) };
if ( std::isnan( dot ) ) return 0.0f;
assert( !std::isinf( dot ) );
return dot;
}
void processPlane(
const Plane< CoordinateSpace::World >& plane,
const LineSegment< CoordinateSpace::World >& line,
std::vector< WorldCoordinate >& out_enter_intersections,
std::vector< WorldCoordinate >& out_exit_intersections )
{
const WorldCoordinate intersection { line.intersection( plane ) };
if ( std::isnan( intersection.vec().x ) || std::isnan( intersection.vec().y )
|| std::isnan( intersection.vec().z ) )
return;
const float dot { glm::dot( line.getDirection().vec(), plane.getDirection().vec() ) };
assert( !std::isnan( dot ) );
assert( !std::isinf( dot ) );
//! The line is entering if the line vector is pointing the same direction as the plane's vector
const bool is_line_entering { dot > 0.0f };
if ( is_line_entering )
out_enter_intersections.emplace_back( intersection );
else
out_exit_intersections.emplace_back( intersection );
return;
}
WorldCoordinate getFirstExit(
const std::vector< WorldCoordinate >& exit_intersections, const LineSegment< CoordinateSpace::World >& line )
{
assert( exit_intersections.size() > 0 );
WorldCoordinate exit_point { exit_intersections.at( 0 ) };
float distance { 0.0f };
for ( const auto intersection_point : exit_intersections )
{
const float exit_distance { signedDistance( line.getDirection(), intersection_point, line.getPosition() ) };
//if the distance is lower then it's before the previous
if ( exit_distance < distance )
{
distance = exit_distance;
exit_point = intersection_point;
}
}
return exit_point;
}
WorldCoordinate getLastEnter(
const std::vector< WorldCoordinate >& enter_intersections, const LineSegment< CoordinateSpace::World >& line )
{
assert( enter_intersections.size() > 0 );
WorldCoordinate first_exit { enter_intersections.at( 0 ) };
float distance { signedDistance( line.getDirection(), line.getEnd(), line.getPosition() ) };
//assert( distance > 0.0f );
for ( const auto intersection_point : enter_intersections )
{
const float enter_distance {
signedDistance( line.getDirection(), intersection_point, line.getPosition() )
};
//If the distance is higher then set it.
if ( enter_distance > distance )
{
distance = enter_distance;
first_exit = intersection_point;
}
}
return first_exit;
}
bool intersects( const LineSegment< CS::World >& line, const Frustum& frustum )
{
std::vector< WorldCoordinate > enter_intersections { line.getPosition() };
std::vector< WorldCoordinate > exit_intersections { line.getEnd() };
processPlane( frustum.near, line, enter_intersections, exit_intersections );
processPlane( frustum.far, line, enter_intersections, exit_intersections );
processPlane( frustum.left, line, enter_intersections, exit_intersections );
processPlane( frustum.right, line, enter_intersections, exit_intersections );
processPlane( frustum.top, line, enter_intersections, exit_intersections );
processPlane( frustum.bottom, line, enter_intersections, exit_intersections );
if ( enter_intersections.size() == 0 ) return false;
if ( exit_intersections.size() == 0 ) return false;
const auto first_exit { getFirstExit( exit_intersections, line ) };
const auto last_enter { getLastEnter( enter_intersections, line ) };
const float distance_to_exit { signedDistance( line.getDirection(), first_exit, line.getPosition() ) };
const float distance_to_enter { signedDistance( line.getDirection(), last_enter, line.getPosition() ) };
return distance_to_exit >= distance_to_enter;
}
} // namespace fgl::engine::intersection

View File

@@ -0,0 +1,18 @@
//
// Created by kj16609 on 10/28/24.
//
#pragma once
#include "engine/primitives/lines/LineSegment.hpp"
namespace fgl::engine
{
struct Frustum;
}
namespace fgl::engine::intersections
{
bool intersects( const LineSegment< CS::World >& line, const Frustum& frustum );
}

View File

@@ -0,0 +1,33 @@
//
// Created by kj16609 on 10/28/24.
//
#include "raycast.hpp"
#include "engine/primitives/vectors/Vector.hpp"
namespace fgl::engine
{
Ray constructRay( WorldCoordinate& start, WorldCoordinate& end )
{
const Ray ray { start, start.vectorTo( end ).normalize() };
return ray;
}
bool rayHit( const Ray& ray, const OrientedBoundingBox< CS::World >& obb )
{
}
bool rayHit( const Ray& ray, const AxisAlignedBoundingBox< CS::World >& aabb )
{
}
} // namespace fgl::engine

View File

@@ -0,0 +1,26 @@
//
// Created by kj16609 on 10/28/24.
//
#pragma once
#include "engine/primitives/Rotation.hpp"
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
#include "engine/primitives/points/Coordinate.hpp"
namespace fgl::engine
{
class OctTreeNode;
struct Ray
{
WorldCoordinate start;
NormalVector vector;
};
Ray constructRay( WorldCoordinate& start, WorldCoordinate& end );
bool rayHit( const Ray& ray, const OrientedBoundingBox< CS::World >& obb, OctTreeNode* root );
bool rayHit( const Ray& ray, const AxisAlignedBoundingBox< CS::World >& aabb, OctTreeNode* root );
} // namespace fgl::engine

View File

@@ -14,4 +14,7 @@ namespace fgl::engine
Camera,
Screen
};
using CS = CoordinateSpace;
} // namespace fgl::engine

View File

@@ -6,8 +6,11 @@
#include <tracy/Tracy.hpp>
#include <iosfwd>
#include <vector>
#include "boxes/AxisAlignedBoundingBox.hpp"
#include "engine/debug/drawers.hpp"
#include "engine/primitives/boxes/AxisAlignedBoundingBox.hpp"
#include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp"
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
#include "lines/InfiniteLine.hpp"
@@ -25,128 +28,8 @@ namespace fgl::engine
return result;
}
float signedDistance( const NormalVector direction, const WorldCoordinate& point, const WorldCoordinate& origin )
{
const glm::vec3 vector_between { point.vec() - origin.vec() };
const float dot { glm::dot( vector_between, direction.vec() ) };
if ( std::isnan( dot ) ) return 0.0f;
assert( !std::isinf( dot ) );
return dot;
}
void processPlane(
const Plane< CoordinateSpace::World >& plane,
const LineSegment< CoordinateSpace::World >& line,
std::vector< WorldCoordinate >& out_enter_intersections,
std::vector< WorldCoordinate >& out_exit_intersections )
{
const WorldCoordinate intersection { line.intersection( plane ) };
if ( std::isnan( intersection.vec().x ) || std::isnan( intersection.vec().y )
|| std::isnan( intersection.vec().z ) )
return;
const float dot { glm::dot( line.getDirection().vec(), plane.getDirection().vec() ) };
assert( !std::isnan( dot ) );
assert( !std::isinf( dot ) );
//! The line is entering if the line vector is pointing the same direction as the plane's vector
const bool is_line_entering { dot > 0.0f };
if ( is_line_entering )
out_enter_intersections.emplace_back( intersection );
else
out_exit_intersections.emplace_back( intersection );
return;
}
WorldCoordinate getFirstExit(
const std::vector< WorldCoordinate >& exit_intersections, const LineSegment< CoordinateSpace::World >& line )
{
assert( exit_intersections.size() > 0 );
WorldCoordinate exit_point { exit_intersections.at( 0 ) };
float distance { 0.0f };
for ( const auto intersection_point : exit_intersections )
{
const float exit_distance { signedDistance( line.getDirection(), intersection_point, line.getPosition() ) };
//if the distance is lower then it's before the previous
if ( exit_distance < distance )
{
distance = exit_distance;
exit_point = intersection_point;
}
}
return exit_point;
}
WorldCoordinate getLastEnter(
const std::vector< WorldCoordinate >& enter_intersections, const LineSegment< CoordinateSpace::World >& line )
{
assert( enter_intersections.size() > 0 );
WorldCoordinate first_exit { enter_intersections.at( 0 ) };
float distance { signedDistance( line.getDirection(), line.getEnd(), line.getPosition() ) };
//assert( distance > 0.0f );
for ( const auto intersection_point : enter_intersections )
{
const float enter_distance {
signedDistance( line.getDirection(), intersection_point, line.getPosition() )
};
//If the distance is higher then set it.
if ( enter_distance > distance )
{
distance = enter_distance;
first_exit = intersection_point;
}
}
return first_exit;
}
inline static bool show_intersect { false };
template <>
bool Frustum::intersects( const LineSegment< CoordinateSpace::World >& line ) const
{
std::vector< WorldCoordinate > enter_intersections { line.getPosition() };
std::vector< WorldCoordinate > exit_intersections { line.getEnd() };
processPlane( near, line, enter_intersections, exit_intersections );
processPlane( far, line, enter_intersections, exit_intersections );
processPlane( left, line, enter_intersections, exit_intersections );
processPlane( right, line, enter_intersections, exit_intersections );
processPlane( top, line, enter_intersections, exit_intersections );
processPlane( bottom, line, enter_intersections, exit_intersections );
if ( enter_intersections.size() == 0 ) return false;
if ( exit_intersections.size() == 0 ) return false;
const auto first_exit { getFirstExit( exit_intersections, line ) };
const auto last_enter { getLastEnter( enter_intersections, line ) };
const float distance_to_exit { signedDistance( line.getDirection(), first_exit, line.getPosition() ) };
const float distance_to_enter { signedDistance( line.getDirection(), last_enter, line.getPosition() ) };
if ( show_intersect ) [[unlikely]]
{
//TODO:
}
return distance_to_exit >= distance_to_enter;
}
FGL_FORCE_INLINE inline NormalVector Frustum::forwardVec() const
{
return near.getDirection();
@@ -162,6 +45,41 @@ namespace fgl::engine
return NormalVector( glm::cross( forwardVec().vec(), upVec().vec() ) );
}
bool Frustum::containsPoint( const WorldCoordinate coord ) const
{
static_assert(
CoordinateSpace::World == CoordinateSpace::World,
"pointInside can only be called on World coordinate Frustums" );
//Ensure the point we are not trying to test a NaN point
assert( coord.x != std::numeric_limits< decltype( coord.x ) >::quiet_NaN() );
assert( coord.y != std::numeric_limits< decltype( coord.y ) >::quiet_NaN() );
assert( coord.z != std::numeric_limits< decltype( coord.z ) >::quiet_NaN() );
//TODO: This is a biased approach.
// Approaches for non-biased:
// We can either make this non-biased by using a projection from distance shot down the FORWARD vector
// Or we can use SIMD to check all the planes at once.
return near.isForward( coord ) && far.isForward( coord ) && bottom.isForward( coord ) && top.isForward( coord )
&& right.isForward( coord ) && left.isForward( coord );
}
bool Frustum::containsAnyPoint( const std::vector< WorldCoordinate >& coords ) const
{
for ( const auto coord : coords )
if ( containsPoint( coord ) ) return true;
return false;
}
bool Frustum::containsAnyPoint( const std::array< WorldCoordinate, interface::BoundingBox::POINT_COUNT >& coords )
const
{
for ( const auto coord : coords )
if ( containsPoint( coord ) ) return true;
return false;
}
std::array< Coordinate< CoordinateSpace::World >, 4 * 2 > Frustum::points() const
{
const NormalVector pv0 { glm::cross( top.getDirection().vec(), left.getDirection().vec() ) };
@@ -214,12 +132,6 @@ namespace fgl::engine
return lines;
}
template <>
bool Frustum::intersects( const WorldCoordinate& t ) const
{
return pointInside( t );
}
//TODO: Implement frustum debug menu
[[maybe_unused]] inline static bool check_points { true };
[[maybe_unused]] inline static bool check_lines { true };
@@ -248,127 +160,6 @@ namespace fgl::engine
*/
}
template <>
bool Frustum::intersects( const std::vector< WorldCoordinate >& point_cloud ) const
{
for ( const auto point : point_cloud )
{
if ( intersects( point ) ) return true;
}
return false;
}
//! Returns the max and min of a point along an axis
std::pair< float, float > minMaxDot( const NormalVector axis, const auto points )
{
assert( points.size() > 2 );
float min { std::numeric_limits< float >::infinity() };
float max { -std::numeric_limits< float >::infinity() };
for ( std::size_t i = 0; i < points.size(); ++i )
{
const auto value { glm::dot( points[ i ].vec(), axis.vec() ) };
min = std::min( min, value );
max = std::max( max, value );
}
return std::make_pair( min, max );
}
//! Returns true if we can draw a line between the two point sets.
template < typename TL, typename TR >
//TODO: Concept this to only allow for arrays/vectors
bool testAxis( const NormalVector axis, const TL& left_points, const TR& right_points )
{
const auto [ min_left, max_left ] = minMaxDot( axis, left_points );
const auto [ min_right, max_right ] = minMaxDot( axis, right_points );
//If there is an overlap then we are unable to draw a line between the two.
return max_left < min_right || max_right < min_left;
}
// Dividing Hyperline Theorem
// Since the bounding box is oriented we need to test all points from it and 3 axis from the frustum and 3 axis from the box.
// If we find 1 line that seperates then we fail the test and can early exit
// This test might be more optimal to do then a pointInside check since it will early fail rather then early pass.
// We can also make this more optimal by discarding overlapping points. For example, Testing the right axis vector on the Frustum means we can discard the 'low' points. Since the 'high' points would be identical.
// Though this will likely be a micro-optimizaton in the long run anyways. But less tests means we might be able to almost half the points being tested.
//! Can plot line between frustum and a given set of points
template < CoordinateSpace CType, std::uint64_t FrustumPointCount, std::uint64_t BoundingBoxPointCount >
FGL_FLATTEN_HOT bool canPlotLine(
const Frustum& frustum,
const std::array< Coordinate< CType >, FrustumPointCount >& frustum_points,
const std::array< Coordinate< CType >, BoundingBoxPointCount >& bounding_points )
{
return (
testAxis( frustum.right.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.left.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.near.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.far.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.top.getDirection(), frustum_points, bounding_points )
|| testAxis( frustum.bottom.getDirection(), frustum_points, bounding_points ) );
}
template <>
FGL_FLATTEN bool Frustum::intersects( const OrientedBoundingBox< CoordinateSpace::World >& bounding_box ) const
{
const auto box_points { bounding_box.points() };
if ( intersects( box_points ) ) return true;
const auto frustum_points { this->points() };
if ( canPlotLine( *this, frustum_points, box_points ) ) return false;
// Now to test every axis from the bounding box
if ( testAxis( bounding_box.right(), frustum_points, box_points ) ) return false;
if ( testAxis( bounding_box.forward(), frustum_points, box_points ) ) return false;
if ( testAxis( bounding_box.up(), frustum_points, box_points ) ) return false;
return true;
}
template <>
FGL_FLATTEN bool Frustum::intersects( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box ) const
{
const auto box_points { bounding_box.points() };
if ( intersects( box_points ) ) return true;
const auto frustum_points { this->points() };
if ( canPlotLine( *this, frustum_points, box_points ) ) return false;
// Now to test every axis from the bounding box
if ( testAxis( bounding_box.right(), frustum_points, box_points ) ) return false;
if ( testAxis( bounding_box.forward(), frustum_points, box_points ) ) return false;
if ( testAxis( bounding_box.up(), frustum_points, box_points ) ) return false;
return true;
}
template <>
FGL_FLATTEN bool Frustum::intersects( const AxisAlignedBoundingCube< CoordinateSpace::World >& bounding_box ) const
{
const auto box_points { bounding_box.points() };
if ( intersects( box_points ) ) return true;
const auto frustum_points { this->points() };
if ( canPlotLine( *this, frustum_points, box_points ) ) return false;
// Now to test every axis from the bounding box
if ( testAxis( bounding_box.right(), frustum_points, box_points ) ) return false;
if ( testAxis( bounding_box.forward(), frustum_points, box_points ) ) return false;
if ( testAxis( bounding_box.up(), frustum_points, box_points ) ) return false;
return true;
}
namespace debug
{
void drawFrustum( const Frustum& frustum )

View File

@@ -5,7 +5,9 @@
#pragma once
#include <ostream>
#include <vector>
#include "engine/primitives/boxes/BoundingBox.hpp"
#include "engine/primitives/planes/PointPlane.hpp"
#include "engine/primitives/points/Coordinate.hpp"
#include "vectors/Vector.hpp"
@@ -89,38 +91,11 @@ namespace fgl::engine
WorldCoordinate getPosition() const { return m_position; }
//! Tests if a point is inside of the frustum
bool pointInside( const WorldCoordinate coord ) const
{
static_assert(
CoordinateSpace::World == CoordinateSpace::World,
"pointInside can only be called on World coordinate Frustums" );
//Ensure the point we are not trying to test a NaN point
assert( coord.x != std::numeric_limits< decltype( coord.x ) >::quiet_NaN() );
assert( coord.y != std::numeric_limits< decltype( coord.y ) >::quiet_NaN() );
assert( coord.z != std::numeric_limits< decltype( coord.z ) >::quiet_NaN() );
//TODO: This is a biased approach.
// Approaches for non-biased:
// We can either make this non-biased by using a projection from distance shot down the FORWARD vector
// Or we can use SIMD to check all the planes at once.
return near.isForward( coord ) && far.isForward( coord ) && bottom.isForward( coord )
&& top.isForward( coord ) && right.isForward( coord ) && left.isForward( coord );
}
//! Returns true if the frustum intersects type T
template < typename T >
bool intersects( const T& t ) const;
//! Itterates over all items in the array given, Returns false if **ANY** fail
template < typename T, std::size_t N >
bool intersects( const std::array< T, N >& ts ) const
{
for ( const auto& t : ts )
if ( !intersects( t ) ) return false;
return true;
}
bool containsPoint( const WorldCoordinate coord ) const;
//! Returns true if ANY point is inside the frustum
bool containsAnyPoint( const std::vector< WorldCoordinate >& coords ) const;
//! Used for bounding box tests
bool containsAnyPoint( const std::array< WorldCoordinate, interface::BoundingBox::POINT_COUNT >& coords ) const;
std::array< WorldCoordinate, 4 * 2 > points() const;
std::array< LineSegment< CoordinateSpace::World >, ( ( 4 * 2 ) / 2 ) * 3 > lines() const;

View File

@@ -9,7 +9,6 @@
namespace fgl::engine
{
NormalVector::NormalVector( const fgl::engine::Vector vector ) : NormalVector( vector.vec() )
{}

View File

@@ -11,6 +11,7 @@
#pragma GCC diagnostic pop
#include "engine/primitives/CoordinateSpace.hpp"
#include "engine/primitives/Rotation.hpp"
namespace fgl::engine
{

View File

@@ -20,6 +20,11 @@ namespace fgl::engine
return *this;
}
NormalVector Vector::normalize() const
{
return NormalVector( *this );
}
glm::vec3 Vector::forward() const
{
//TODO: Figure out Z shit

View File

@@ -72,6 +72,8 @@ namespace fgl::engine
{
return coord - *this;
}
NormalVector normalize() const;
};
inline Vector operator-( const Vector vec )

View File

@@ -4,6 +4,8 @@
#include "Shader.hpp"
#include <fstream>
#include "engine/debug/logging/logging.hpp"
#include "engine/rendering/devices/Device.hpp"
#include "shaders/Compiler.hpp"
@@ -15,7 +17,7 @@ namespace fgl::engine
{
if ( auto ifs = std::ifstream( path, std::ios::binary | std::ios::ate ); ifs )
{
std::vector< std::byte > data;
std::vector< std::byte > data {};
data.resize( ifs.tellg() );
ifs.seekg( 0, std::ios::beg );
@@ -23,8 +25,6 @@ namespace fgl::engine
ifs.read( reinterpret_cast< std::ifstream::char_type* >( data.data() ), data.size() );
// We now need to compile the shader before we use it.
return compileShader( path.filename().string(), data );
}
else

View File

@@ -7,7 +7,6 @@
#include <vulkan/vulkan_raii.hpp>
#include <filesystem>
#include <fstream>
namespace fgl::engine
{

View File

@@ -12,6 +12,7 @@
#include "engine/debug/drawers.hpp"
#include "engine/debug/profiling/counters.hpp"
#include "engine/gameobjects/components/ModelComponent.hpp"
#include "engine/math/intersections.hpp"
#include "engine/tree/octtree/OctTreeNode.hpp"
namespace fgl::engine
@@ -63,7 +64,7 @@ namespace fgl::engine
matrix * primitive.getBoundingBox()
};
if ( !frustum.intersects( world_bounding_box ) ) continue;
if ( !intersects( frustum, world_bounding_box ) ) continue;
//assert( primitive.m_texture );
const ModelMatrixInfo matrix_info { .model_matrix = matrix,

View File

@@ -17,6 +17,7 @@
#include "engine/assets/model/Model.hpp"
#include "engine/clock.hpp"
#include "engine/debug/drawers.hpp"
#include "engine/math/intersections.hpp"
#include "engine/primitives/Frustum.hpp"
namespace fgl::engine
@@ -254,7 +255,7 @@ namespace fgl::engine
bool OctTreeNode::isInFrustum( const Frustum& frustum ) const
{
#if ENABLE_IMGUI
if ( !isEmpty() && frustum.intersects( m_fit_bounding_box ) )
if ( !isEmpty() && intersects( frustum, m_fit_bounding_box ) )
{
if ( ( draw_inview_bounds || ( std::holds_alternative< OctTreeNodeLeaf >( this->m_node_data ) )
|| draw_branches )

View File

@@ -6,8 +6,6 @@
#include <tracy/Tracy.hpp>
#include <bitset>
#include "engine/gameobjects/GameObject.hpp"
#include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp"