// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#include "Plane.h"
#include "Vector3.h"
#include "Matrix.h"
#include "CollisionsHelper.h"
///
/// Defines a frustum which can be used in frustum culling, zoom to Extents (zoom to fit) operations, (matrix, frustum, camera) interchange, and many kind of intersection testing.
///
API_STRUCT(InBuild) struct FLAXENGINE_API BoundingFrustum
{
friend CollisionsHelper;
private:
Matrix _matrix;
union
{
struct
{
Plane _pNear;
Plane _pFar;
Plane _pLeft;
Plane _pRight;
Plane _pTop;
Plane _pBottom;
};
Plane _planes[6];
};
public:
///
/// Empty constructor.
///
BoundingFrustum() = default;
///
/// Initializes a new instance of the struct.
///
/// The combined matrix that usually takes View * Projection matrix.
BoundingFrustum(const Matrix& matrix)
{
SetMatrix(matrix);
}
public:
String ToString() const;
public:
///
/// Gets the matrix that describes this bounding frustum.
///
FORCE_INLINE const Matrix& GetMatrix() const
{
return _matrix;
}
///
/// Gets the matrix that describes this bounding frustum.
///
FORCE_INLINE Matrix GetMatrix()
{
return _matrix;
}
///
/// Gets the inverted matrix to that describes this bounding frustum.
///
/// The result matrix.
FORCE_INLINE void GetInvMatrix(Matrix& result) const
{
Matrix::Invert(_matrix, result);
}
///
/// Sets the matrix (made from view and projection matrices) that describes this bounding frustum.
///
/// The view matrix.
/// The projection matrix.
void SetMatrix(const Matrix& view, const Matrix& projection)
{
Matrix viewProjection;
Matrix::Multiply(view, projection, viewProjection);
SetMatrix(viewProjection);
}
///
/// Sets the matrix that describes this bounding frustum.
///
/// The matrix (View*Projection).
void SetMatrix(const Matrix& matrix);
///
/// Gets the near.
///
FORCE_INLINE Plane GetNear() const
{
return _pNear;
}
///
/// Gets the far plane of the BoundingFrustum.
///
FORCE_INLINE Plane GetFar() const
{
return _pFar;
}
///
/// Gets the left plane of the BoundingFrustum.
///
FORCE_INLINE Plane GetLeft() const
{
return _pLeft;
}
///
/// Gets the right plane of the BoundingFrustum.
///
FORCE_INLINE Plane GetRight() const
{
return _pRight;
}
///
/// Gets the top plane of the BoundingFrustum.
///
FORCE_INLINE Plane GetTop() const
{
return _pTop;
}
///
/// Gets the bottom plane of the BoundingFrustum.
///
FORCE_INLINE Plane GetBottom() const
{
return _pBottom;
}
///
/// Gets the one of the 6 planes related to this frustum.
///
/// The index where 0 for Left, 1 for Right, 2 for Top, 3 for Bottom, 4 for Near, 5 for Far.
/// The plane.
Plane GetPlane(int32 index) const;
///
/// Gets the the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner).
///
/// The corners.
void GetCorners(Float3 corners[8]) const;
///
/// Gets the the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner).
///
/// The corners.
void GetCorners(Double3 corners[8]) const;
///
/// Gets bounding box that contains whole frustum.
///
/// The result box.
void GetBox(BoundingBox& result) const;
///
/// Gets bounding sphere that contains whole frustum.
///
/// The result sphere.
void GetSphere(BoundingSphere& result) const;
///
/// Determines whether this frustum is orthographic.
///
FORCE_INLINE bool IsOrthographic() const
{
return _pLeft.Normal == -_pRight.Normal && _pTop.Normal == -_pBottom.Normal;
}
///
/// Gets the width of the frustum at specified depth.
///
/// The depth at which to calculate frustum width.
/// The width of the frustum at the specified depth.
float GetWidthAtDepth(float depth) const;
///
/// Gets the height of the frustum at specified depth.
///
/// The depth at which to calculate frustum height.
/// The height of the frustum at the specified depth.
float GetHeightAtDepth(float depth) const;
public:
FORCE_INLINE bool operator==(const BoundingFrustum& other) const
{
return _matrix == other._matrix;
}
FORCE_INLINE bool operator!=(const BoundingFrustum& other) const
{
return _matrix != other._matrix;
}
public:
///
/// Checks whether a point lays inside, intersects or lays outside the frustum.
///
/// The point.
/// The type of the containment.
ContainmentType Contains(const Vector3& point) const;
///
/// Determines the intersection relationship between the frustum and a bounding box.
///
/// The box.
/// The type of the containment.
FORCE_INLINE ContainmentType Contains(const BoundingBox& box) const
{
return CollisionsHelper::FrustumContainsBox(*this, box);
}
///
/// Determines the intersection relationship between the frustum and a bounding sphere.
///
/// The sphere.
/// The type of the containment.
ContainmentType Contains(const BoundingSphere& sphere) const;
///
/// Checks whether the current BoundingFrustum intersects a BoundingSphere.
///
/// The sphere.
/// True if the current BoundingFrustum intersects a BoundingSphere, otherwise false.
bool Intersects(const BoundingSphere& sphere) const;
///
/// Checks whether the current BoundingFrustum intersects a BoundingBox.
///
/// The box
/// True if the current BoundingFrustum intersects a BoundingBox, otherwise false.
FORCE_INLINE bool Intersects(const BoundingBox& box) const
{
return CollisionsHelper::FrustumContainsBox(*this, box) != ContainmentType::Disjoint;
}
};
template<>
struct TIsPODType
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(BoundingFrustum, "{}", v.GetMatrix());