Files
LifeProject/LifeGraphics/camera/Frustum.h
T
2025-05-13 02:46:21 +03:00

186 lines
5.0 KiB
C++

#ifndef Frustum_h__
#define Frustum_h__
#include "math/LifeMath.h"
#include <BoundingBox3D.h>
#include "BoundingSphere.h"
namespace LifeGraphics
{
enum BoxIntersectionResult
{
Inside = 0, Outside = 1, Intersection = 2
};
enum FrustumPlane
{
Top = 0, Bottom = 0, Left = 0, Right = 0, Near = 0, Far = 0
};
static const LifeMath::float3 baseCorners[] = {
//front plane
LifeMath::float3(-1.0f, 1.0f, 1.0f),
LifeMath::float3(1.0f, 1.0f, 1.0f),
LifeMath::float3(1.0f, -1.0f, 1.0f),
LifeMath::float3(-1.0f, -1.0f, 1.0f),
//rear plane
LifeMath::float3(-1.0f, 1.0f, -1.0f),
LifeMath::float3(1.0f, 1.0f, -1.0f),
LifeMath::float3(1.0f, -1.0f, -1.0f),
LifeMath::float3(-1.0f, -1.0f, -1.0f)
};
class Frustum
{
private:
LifeMath::Plane frustrumPlanes[6];
LifeMath::float3 corners[8];
LifeMath::float4x4 vp;
public:
Frustum()
{
for (int i = 0; i < 6; i++)
frustrumPlanes[i] = LifeMath::Plane(LifeMath::float3(0.0f, 0.0f, 0.0f), LifeMath::float3(0.0f, 1.0f, 0.0f));
}
Frustum(LifeMath::Plane& _near, LifeMath::Plane& _far, LifeMath::Plane& _top, LifeMath::Plane& _bottom,
LifeMath::Plane& _left, LifeMath::Plane& _right)
{
frustrumPlanes[0] = _top;
frustrumPlanes[1] = _bottom;
frustrumPlanes[2] = _left;
frustrumPlanes[3] = _right;
frustrumPlanes[4] = _near;
frustrumPlanes[5] = _far;
}
Frustum(const LifeMath::float4x4& viewProjection)
{
UpdateFrustum(viewProjection);
}
~Frustum(){}
void UpdateFrustum(const LifeMath::float4x4& viewProjection)
{
vp = viewProjection;
// Top plane
frustrumPlanes[0] = LifeMath::Plane(
viewProjection.M14 - viewProjection.M12,
viewProjection.M24 - viewProjection.M22,
viewProjection.M34 - viewProjection.M32,
viewProjection.M44 - viewProjection.M42);
// Bottom plane
frustrumPlanes[1] = LifeMath::Plane(
viewProjection.M14 + viewProjection.M12,
viewProjection.M24 + viewProjection.M22,
viewProjection.M34 + viewProjection.M32,
viewProjection.M44 + viewProjection.M42);
// Left plane
frustrumPlanes[2] = LifeMath::Plane(
viewProjection.M14 + viewProjection.M11,
viewProjection.M24 + viewProjection.M21,
viewProjection.M34 + viewProjection.M31,
viewProjection.M44 + viewProjection.M41);
// Right plane
frustrumPlanes[3] = LifeMath::Plane(
viewProjection.M14 - viewProjection.M11,
viewProjection.M24 - viewProjection.M21,
viewProjection.M34 - viewProjection.M31,
viewProjection.M44 - viewProjection.M41);
// Near plane
frustrumPlanes[4] = LifeMath::Plane(
viewProjection.M13,
viewProjection.M23,
viewProjection.M33,
viewProjection.M43);
// Far plane
frustrumPlanes[5] = LifeMath::Plane(
viewProjection.M14 - viewProjection.M13,
viewProjection.M24 - viewProjection.M23,
viewProjection.M34 - viewProjection.M33,
viewProjection.M44 - viewProjection.M43);
// Normalize planes
for (int i = 0; i < 6; i++)
{
LifeMath::PlaneNormalize(frustrumPlanes[i]);
}
}
bool SphereInFrustum(const LifeMath::float3& center, float radius) const
{
LifeMath::float4 position = LifeMath::float4(center.X, center.Y, center.Z, 1.0f);
for (int i = 0; i < 6; i++)
if(LifeMath::PlaneDot(frustrumPlanes[i], position) + radius < 0)
return false;
return true;
}
bool SphereInFrustum(const BoundingSphere* sphere) const
{
LifeMath::float4 position = LifeMath::float4(sphere->center.X, sphere->center.Y, sphere->center.Z, 1.0f);
for (int i = 0; i < 6; i++)
if(PlaneDot(frustrumPlanes[i], position) + sphere->radius < 0)
return false;
return true;
}
bool BoxInFrustum(const LifeCore::BoundingBox3D& box) const
{
LifeMath::float3 corners[8];
box.GetCorners(corners);
for (int i = 0; i < 6; i++)
{
if (PlaneDot(frustrumPlanes[i], corners[0]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[1]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[2]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[3]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[4]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[5]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[6]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[7]) < 0)
{
return false;
}
}
return true;
}
bool BoxInFrustum(const LifeMath::float3* corners) const
{
for (int i = 0; i < 6; i++)
{
if (PlaneDot(frustrumPlanes[i], corners[0]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[1]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[2]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[3]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[4]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[5]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[6]) < 0 &&
PlaneDot(frustrumPlanes[i], corners[7]) < 0)
{
return false;
}
}
return true;
}
const LifeMath::float3* GetCorners()
{
LifeMath::float4x4 ivp;
ivp = LifeMath::Mat4x4Invert(&vp);
for (int i = 0; i < 8; i++)
{
LifeMath::Vec3TransformCoordinate(baseCorners[i], ivp, corners[i]);
}
return corners;
}
};
}
#endif // Frustum_h__