#ifndef Frustum_h__ #define Frustum_h__ #include "math/LifeMath.h" #include #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__