Renderer/DebugDrawer: Add support for Frustum

This commit is contained in:
SirLynix 2022-11-20 15:43:31 +01:00 committed by Jérôme Leclercq
parent f572d229d9
commit a5d4b8f28d
6 changed files with 72 additions and 3 deletions

View File

@ -32,6 +32,8 @@ namespace Nz
Frustum(const Frustum& frustum) = default;
~Frustum() = default;
Vector3<T> ComputeCorner(BoxCorner corner) const;
bool Contains(const BoundingVolume<T>& volume) const;
bool Contains(const Box<T>& box) const;
bool Contains(const OrientedBox<T>& orientedBox) const;
@ -47,8 +49,6 @@ namespace Nz
IntersectionSide Intersect(const Sphere<T>& sphere) const;
IntersectionSide Intersect(const Vector3<T>* points, std::size_t pointCount) const;
template<typename U> Frustum& Set(const Frustum<U>& frustum);
std::string ToString() const;
Frustum& operator=(const Frustum& other) = default;

View File

@ -49,6 +49,31 @@ namespace Nz
m_planes[i].Set(frustum.m_planes[i]);
}
/*!
* \brief Computes the position of a frustum corner
* \return The corner position
*
* \param corner Which corner to compute
*/
template<typename T>
Vector3<T> Frustum<T>::ComputeCorner(BoxCorner corner) const
{
switch (corner)
{
case BoxCorner::FarLeftBottom: return Plane<T>::Intersect(GetPlane(FrustumPlane::Far), GetPlane(FrustumPlane::Left), GetPlane(FrustumPlane::Bottom));
case BoxCorner::FarLeftTop: return Plane<T>::Intersect(GetPlane(FrustumPlane::Far), GetPlane(FrustumPlane::Left), GetPlane(FrustumPlane::Top));
case BoxCorner::FarRightBottom: return Plane<T>::Intersect(GetPlane(FrustumPlane::Far), GetPlane(FrustumPlane::Right), GetPlane(FrustumPlane::Bottom));
case BoxCorner::FarRightTop: return Plane<T>::Intersect(GetPlane(FrustumPlane::Far), GetPlane(FrustumPlane::Right), GetPlane(FrustumPlane::Top));
case BoxCorner::NearLeftBottom: return Plane<T>::Intersect(GetPlane(FrustumPlane::Near), GetPlane(FrustumPlane::Left), GetPlane(FrustumPlane::Bottom));
case BoxCorner::NearLeftTop: return Plane<T>::Intersect(GetPlane(FrustumPlane::Near), GetPlane(FrustumPlane::Left), GetPlane(FrustumPlane::Top));
case BoxCorner::NearRightBottom: return Plane<T>::Intersect(GetPlane(FrustumPlane::Near), GetPlane(FrustumPlane::Right), GetPlane(FrustumPlane::Bottom));
case BoxCorner::NearRightTop: return Plane<T>::Intersect(GetPlane(FrustumPlane::Near), GetPlane(FrustumPlane::Right), GetPlane(FrustumPlane::Top));
}
NazaraError("invalid frustum corner");
return Vector3<T>();
}
/*!
* \brief Checks whether or not a bounding volume is contained in the frustum
* \return true if the bounding volume is entirely in the frustum

View File

@ -49,6 +49,7 @@ namespace Nz
bool operator==(const Plane& plane) const;
bool operator!=(const Plane& plane) const;
static Vector3<T> Intersect(const Plane& p0, const Plane& p1, const Plane& p2);
static Plane Lerp(const Plane& from, const Plane& to, T interpolation);
static Plane XY();
static Plane XZ();

View File

@ -330,6 +330,28 @@ namespace Nz
return !operator==(plane);
}
/*!
* \brief Intersects three planes to retrieve a single intersection point
* \return The intersection point
*
* \param p0 First plane
* \param p1 Second plane
* \param p2 Third plane
*
* \remark All three planes must have differents normals otherwise result is undefined
*/
template<typename T>
Vector3<T> Plane<T>::Intersect(const Plane& p0, const Plane& p1, const Plane& p2)
{
// From https://donw.io/post/frustum-point-extraction/
Vector3f bxc = Vector3f::CrossProduct(p1.normal, p2.normal);
Vector3f cxa = Vector3f::CrossProduct(p2.normal, p0.normal);
Vector3f axb = Vector3f::CrossProduct(p0.normal, p1.normal);
Vector3f r = -p0.distance * bxc - p1.distance * cxa - p2.distance * axb;
return r * (T(1.0) / Vector3f::DotProduct(p0.normal, bxc));
}
/*!
* \brief Interpolates the plane to other one with a factor of interpolation
* \return A new plane which is the interpolation of two planes
@ -343,7 +365,6 @@ namespace Nz
*
* \see Lerp
*/
template<typename T>
Plane<T> Plane<T>::Lerp(const Plane& from, const Plane& to, T interpolation)
{

View File

@ -10,6 +10,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Frustum.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Renderer/Config.hpp>
@ -40,6 +41,7 @@ namespace Nz
void Draw(CommandBufferBuilder& builder);
inline void DrawBox(const Boxf& box, const Color& color);
inline void DrawFrustum(const Frustumf& frustum, const Color& color);
inline void DrawLine(const Vector3f& start, const Vector3f& end, const Color& color);
inline void DrawLine(const Vector3f& start, const Vector3f& end, const Color& startColor, const Color& endColor);
void DrawSkeleton(const Skeleton& skeleton, const Color& color);

View File

@ -26,6 +26,26 @@ namespace Nz
DrawLine({ max.x, min.y, min.z }, { max.x, min.y, max.z }, color);
}
inline void DebugDrawer::DrawFrustum(const Frustumf& frustum, const Color& color)
{
std::array<Vector3f, BoxCornerCount> corners;
for (std::size_t i = 0; i < BoxCornerCount; ++i)
corners[i] = frustum.ComputeCorner(static_cast<BoxCorner>(i));
DrawLine(corners[UnderlyingCast(BoxCorner::NearLeftBottom)], corners[UnderlyingCast(BoxCorner::NearRightBottom)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::NearLeftBottom)], corners[UnderlyingCast(BoxCorner::NearLeftTop)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::NearLeftBottom)], corners[UnderlyingCast(BoxCorner::FarLeftBottom)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::FarRightTop)], corners[UnderlyingCast(BoxCorner::FarLeftTop)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::FarRightTop)], corners[UnderlyingCast(BoxCorner::FarRightBottom)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::FarRightTop)], corners[UnderlyingCast(BoxCorner::NearRightTop)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::FarLeftBottom)], corners[UnderlyingCast(BoxCorner::FarRightBottom)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::FarLeftBottom)], corners[UnderlyingCast(BoxCorner::FarLeftTop)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::NearLeftTop)], corners[UnderlyingCast(BoxCorner::NearRightTop)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::NearLeftTop)], corners[UnderlyingCast(BoxCorner::FarLeftTop)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::NearRightBottom)], corners[UnderlyingCast(BoxCorner::NearRightTop)], color);
DrawLine(corners[UnderlyingCast(BoxCorner::NearRightBottom)], corners[UnderlyingCast(BoxCorner::FarRightBottom)], color);
}
inline void DebugDrawer::DrawLine(const Vector3f& start, const Vector3f& end, const Color& color)
{
return DrawLine(start, end, color, color);