186 lines
5.0 KiB
C++
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__
|