335 lines
9.9 KiB
C++
335 lines
9.9 KiB
C++
//
|
|
// Created by kj16609 on 1/27/24.
|
|
//
|
|
|
|
#include "OrientedBoundingBox.hpp"
|
|
|
|
#include <tracy/Tracy.hpp>
|
|
|
|
#include <array>
|
|
|
|
#include "AxisAlignedBoundingBox.hpp"
|
|
#include "engine/assets/model/ModelVertex.hpp"
|
|
#include "engine/debug/logging/logging.hpp"
|
|
#include "engine/primitives/lines/LineSegment.hpp"
|
|
#include "engine/primitives/points/Coordinate.hpp"
|
|
|
|
namespace fgl::engine
|
|
{
|
|
|
|
template < CoordinateSpace CType >
|
|
consteval std::array< std::uint32_t, OrientedBoundingBox< CType >::indicies_count > OrientedBoundingBox<
|
|
CType >::triangleIndicies()
|
|
{
|
|
/**
|
|
* Order (Top)
|
|
* 1 =========== 0
|
|
* || ||
|
|
* || ||
|
|
* 2 =========== 3
|
|
*
|
|
* Order (Bottom)
|
|
* 5 =========== 4
|
|
* || ||
|
|
* || ||
|
|
* 6 =========== 7
|
|
*
|
|
* Order (Side - 1)
|
|
* 2 =========== 3
|
|
* || ||
|
|
* || ||
|
|
* 6 =========== 7
|
|
*
|
|
* Order (Side - 2)
|
|
* 1 =========== 0
|
|
* || ||
|
|
* || ||
|
|
* 5 =========== 4
|
|
*
|
|
* Order (Side - 3)
|
|
* 3 =========== 0
|
|
* || ||
|
|
* || ||
|
|
* 7 =========== 4
|
|
*
|
|
* Order (Side - 4)
|
|
* 2 =========== 1
|
|
* || ||
|
|
* || ||
|
|
* 6 =========== 5
|
|
*/
|
|
|
|
// clang-format off
|
|
std::array< std::uint32_t, indicies_count > data {
|
|
{
|
|
//Top tris
|
|
0, 1, 2,
|
|
1, 2, 3,
|
|
//Bottom tris
|
|
4, 5, 6,
|
|
5, 6, 7,
|
|
//Side 1
|
|
2, 3, 6,
|
|
3, 6, 7,
|
|
//Side 2
|
|
1, 0, 5,
|
|
0, 5, 4,
|
|
//Side 3
|
|
3, 0, 7,
|
|
0, 7, 4,
|
|
//Side 4
|
|
2, 1, 6,
|
|
1, 6, 5 }
|
|
};
|
|
// clang-format on
|
|
|
|
return data;
|
|
}
|
|
|
|
template < CoordinateSpace CType >
|
|
std::array< Coordinate< CType >, interface::BoundingBox::POINT_COUNT > OrientedBoundingBox< CType >::points() const
|
|
{
|
|
// xp == x positive (Highest x point)
|
|
// xn == x negative (Lowest x point)
|
|
|
|
//const glm::vec3 xp_yp_zp { m_transform.translation.vec() + static_cast< glm::vec3 >( m_transform.scale ) };
|
|
//const glm::vec3 xn_yn_zn { m_transform.translation.vec() - static_cast< glm::vec3 >( m_transform.scale ) };
|
|
|
|
constexpr glm::vec3 xp_yp_zp { 1.0f, 1.0f, 1.0f };
|
|
constexpr glm::vec3 xn_yn_zn { -xp_yp_zp };
|
|
|
|
constexpr auto xn { xn_yn_zn.x };
|
|
constexpr auto yn { xn_yn_zn.y };
|
|
constexpr auto zn { xn_yn_zn.z };
|
|
|
|
constexpr auto xp { xp_yp_zp.x };
|
|
constexpr auto yp { xp_yp_zp.y };
|
|
constexpr auto zp { xp_yp_zp.z };
|
|
|
|
//Top
|
|
constexpr glm::vec3 xn_yp_zp { xn, yp, zp }; // (- + +)
|
|
constexpr glm::vec3 xn_yp_zn { xn, yp, zn }; // (- + -)
|
|
constexpr glm::vec3 xp_yp_zn { xp, yp, zn }; // (+ + -)
|
|
|
|
/*
|
|
* Top-Down view (X,Y,Z)
|
|
* (-,+,+) =========== (+,+,+)
|
|
* || ||
|
|
* || ||
|
|
* (-,+,-) =========== (+,+,-)
|
|
*
|
|
* Order (Top)
|
|
* 1 =========== 0
|
|
* || ||
|
|
* || ||
|
|
* 2 =========== 3
|
|
*
|
|
* Order (Bottom)
|
|
* 5 =========== 4
|
|
* || ||
|
|
* || ||
|
|
* 6 =========== 7
|
|
*/
|
|
|
|
// points[ 0 ] = Coordinate< CType >( xp_yp_zp );
|
|
// points[ 1 ] = Coordinate< CType >( xn_yp_zp );
|
|
// points[ 2 ] = Coordinate< CType >( xn_yp_zn );
|
|
// points[ 3 ] = Coordinate< CType >( xp_yp_zn );
|
|
|
|
//Bottom
|
|
constexpr glm::vec3 xn_yn_zp { xn, yn, zp }; // (- - +)
|
|
constexpr glm::vec3 xp_yn_zn { xp, yn, zn }; // (+ - -)
|
|
constexpr glm::vec3 xp_yn_zp { xp, yn, zp }; // (+ - +)
|
|
|
|
/*
|
|
* Bottom-Top view (X,Y,Z)
|
|
* (-,-,+) =========== (+,-,+)
|
|
* || ||
|
|
* || ||
|
|
* (-,-,-) =========== (+,-,-)
|
|
*/
|
|
|
|
// points[ 4 ] = Coordinate< CType >( xp_yn_zp );
|
|
// points[ 5 ] = Coordinate< CType >( xn_yn_zp );
|
|
// points[ 6 ] = Coordinate< CType >( xn_yn_zn );
|
|
// points[ 7 ] = Coordinate< CType >( xp_yn_zn );
|
|
|
|
constexpr static std::array< Coordinate< CType >, POINT_COUNT > const_points {
|
|
Coordinate< CType >( xp_yp_zp ), Coordinate< CType >( xn_yp_zp ), Coordinate< CType >( xn_yp_zn ),
|
|
Coordinate< CType >( xp_yp_zn ), Coordinate< CType >( xp_yn_zp ), Coordinate< CType >( xn_yn_zp ),
|
|
Coordinate< CType >( xn_yn_zn ), Coordinate< CType >( xp_yn_zn )
|
|
};
|
|
|
|
std::array< Coordinate< CType >, POINT_COUNT > points {};
|
|
|
|
static_assert( const_points.size() == points.size() );
|
|
|
|
const glm::mat4 rot_mat { transform_mode == TransformMode::Matrix ? m_matrix : m_transform.mat4() };
|
|
|
|
for ( auto i = 0; i < const_points.size(); ++i )
|
|
{
|
|
FGL_ASSUME( i < POINT_COUNT + 1 );
|
|
|
|
const glm::vec3 point { const_points[ i ].vec() };
|
|
|
|
points[ i ] = Coordinate< CType >( rot_mat * glm::vec4( point, 1.0f ) );
|
|
}
|
|
|
|
return points;
|
|
}
|
|
|
|
template < CoordinateSpace CType >
|
|
OrientedBoundingBox< CType > OrientedBoundingBox< CType >::combine( const OrientedBoundingBox< CType >& other )
|
|
const
|
|
{
|
|
ZoneScoped;
|
|
assert( m_transform.translation.vec() != constants::DEFAULT_VEC3 );
|
|
assert( m_transform.scale != glm::vec3( 0.0f ) );
|
|
|
|
assert( other.m_transform.translation.vec() != constants::DEFAULT_VEC3 );
|
|
assert( other.m_transform.scale != glm::vec3( 0.0f ) );
|
|
|
|
const auto& other_points { other.points() };
|
|
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 >( combined_points );
|
|
}
|
|
|
|
template < CoordinateSpace CType >
|
|
AxisAlignedBoundingBox< CType > OrientedBoundingBox< CType >::alignToWorld() const
|
|
{
|
|
const auto points { this->points() };
|
|
glm::vec3 max { std::numeric_limits< glm::vec3::type >::infinity() };
|
|
glm::vec3 min { -std::numeric_limits< glm::vec3::type >::infinity() };
|
|
|
|
for ( const auto& point : points )
|
|
{
|
|
max.x = glm::max( max.x, point.x );
|
|
max.y = glm::max( max.y, point.y );
|
|
max.z = glm::max( max.z, point.z );
|
|
|
|
min.x = glm::min( min.x, point.x );
|
|
min.y = glm::min( min.y, point.y );
|
|
min.z = glm::min( min.z, point.z );
|
|
}
|
|
|
|
return AxisAlignedBoundingBox< CType >( Coordinate< CType >( max ), Coordinate< CType >( min ) );
|
|
}
|
|
|
|
template < CoordinateSpace CType >
|
|
std::array< LineSegment< CType >, interface::BoundingBox::LINE_COUNT > OrientedBoundingBox< CType >::lines() const
|
|
{
|
|
const auto points { this->points() };
|
|
|
|
std::array< LineSegment< CType >, LINE_COUNT > lines;
|
|
|
|
//Top
|
|
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[ 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[ 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;
|
|
|
|
constexpr auto inf_float { std::numeric_limits< float >::infinity() };
|
|
|
|
// neg (min)
|
|
glm::vec3 top_right_forward { -inf_float };
|
|
// pos (max)
|
|
glm::vec3 bottom_left_back { inf_float };
|
|
|
|
assert( points.size() > 0 );
|
|
|
|
for ( const auto& pos : points )
|
|
{
|
|
const auto vec { pos.vec() };
|
|
top_right_forward.x = std::max( vec.x, top_right_forward.x );
|
|
top_right_forward.y = std::max( vec.y, top_right_forward.y );
|
|
top_right_forward.z = std::max( vec.z, top_right_forward.z );
|
|
|
|
bottom_left_back.x = std::min( vec.x, bottom_left_back.x );
|
|
bottom_left_back.y = std::min( vec.y, bottom_left_back.y );
|
|
bottom_left_back.z = std::min( vec.z, bottom_left_back.z );
|
|
}
|
|
|
|
assert( top_right_forward.x != -inf_float );
|
|
assert( top_right_forward.y != -inf_float );
|
|
assert( top_right_forward.z != -inf_float );
|
|
|
|
assert( bottom_left_back.x != inf_float );
|
|
assert( bottom_left_back.y != inf_float );
|
|
assert( bottom_left_back.z != inf_float );
|
|
|
|
//Calculate midpoint
|
|
const glm::vec3 midpoint { ( top_right_forward + bottom_left_back ) / glm::vec3( 2.0f ) };
|
|
const glm::vec3 scale { glm::abs( bottom_left_back - midpoint ) };
|
|
|
|
return { Coordinate< CType >( midpoint ), scale };
|
|
}
|
|
|
|
OrientedBoundingBox< CoordinateSpace::Model > generateBoundingFromVerts( const std::vector< ModelVertex >& verts )
|
|
{
|
|
assert( verts.size() > 0 );
|
|
log::debug( "Generating bounding box for {} verts", verts.size() );
|
|
|
|
constexpr auto inf_float { std::numeric_limits< float >::infinity() };
|
|
// neg (min)
|
|
glm::vec3 top_right_forward { -inf_float };
|
|
// pos (max)
|
|
glm::vec3 bottom_left_back { inf_float };
|
|
|
|
for ( const auto& vert : verts )
|
|
{
|
|
const auto& pos { vert.m_position };
|
|
top_right_forward.x = std::max( pos.x, top_right_forward.x );
|
|
top_right_forward.y = std::max( pos.y, top_right_forward.y );
|
|
top_right_forward.z = std::max( pos.z, top_right_forward.z );
|
|
|
|
bottom_left_back.x = std::min( pos.x, bottom_left_back.x );
|
|
bottom_left_back.y = std::min( pos.y, bottom_left_back.y );
|
|
bottom_left_back.z = std::min( pos.z, bottom_left_back.z );
|
|
}
|
|
|
|
assert( top_right_forward.x != -inf_float );
|
|
assert( top_right_forward.y != -inf_float );
|
|
assert( top_right_forward.z != -inf_float );
|
|
|
|
assert( bottom_left_back.x != inf_float );
|
|
assert( bottom_left_back.y != inf_float );
|
|
assert( bottom_left_back.z != inf_float );
|
|
|
|
//Calculate midpoint
|
|
const glm::vec3 midpoint { ( top_right_forward + bottom_left_back ) / glm::vec3( 2.0f ) };
|
|
const glm::vec3 scale { glm::abs( bottom_left_back - midpoint ) };
|
|
|
|
return OrientedBoundingBox< CoordinateSpace::Model >( Coordinate< CoordinateSpace::Model >( midpoint ), scale );
|
|
}
|
|
|
|
//Synthesize the template
|
|
template struct OrientedBoundingBox< CoordinateSpace::Model >;
|
|
template struct OrientedBoundingBox< CoordinateSpace::World >;
|
|
|
|
} // namespace fgl::engine
|