2
0

Frustum.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Jolt/Geometry/Plane.h>
  5. #include <Jolt/Geometry/AABox.h>
  6. /// A camera frustum containing of 6 planes (left, right, top, bottom, near, far) pointing inwards
  7. class [[nodiscard]] Frustum
  8. {
  9. public:
  10. /// Empty constructor
  11. Frustum() = default;
  12. /// Construct frustom from position, forward, up, field of view x and y and near and far plane.
  13. /// Note that inUp does not need to be perpendicular to inForward but cannot be collinear.
  14. inline Frustum(Vec3Arg inPosition, Vec3Arg inForward, Vec3Arg inUp, float inFOVX, float inFOVY, float inNear, float inFar)
  15. {
  16. Vec3 right = inForward.Cross(inUp).Normalized();
  17. Vec3 up = right.Cross(inForward).Normalized(); // Calculate the real up vector (inUp does not need to be perpendicular to inForward)
  18. // Near and far plane
  19. mPlanes[0] = Plane::sFromPointAndNormal(inPosition + inNear * inForward, inForward);
  20. mPlanes[1] = Plane::sFromPointAndNormal(inPosition + inFar * inForward, -inForward);
  21. // Top and bottom planes
  22. mPlanes[2] = Plane::sFromPointAndNormal(inPosition, Mat44::sRotation(right, 0.5f * inFOVY) * -up);
  23. mPlanes[3] = Plane::sFromPointAndNormal(inPosition, Mat44::sRotation(right, -0.5f * inFOVY) * up);
  24. // Left and right planes
  25. mPlanes[4] = Plane::sFromPointAndNormal(inPosition, Mat44::sRotation(up, 0.5f * inFOVX) * right);
  26. mPlanes[5] = Plane::sFromPointAndNormal(inPosition, Mat44::sRotation(up, -0.5f * inFOVX) * -right);
  27. }
  28. /// Test if frustum overlaps with axis aligned box. Note that this is a conservative estimate and can return true if the
  29. /// frustum doesn't actually overlap with the box. This is because we only test the plane axis as separating axis
  30. /// and skip checking the cross products of the edges of the frustum
  31. inline bool Overlaps(const AABox &inBox) const
  32. {
  33. // Loop over all frustum planes
  34. for (const Plane &p : mPlanes)
  35. {
  36. // Get support point (the maximum extent) in the direction of our normal
  37. Vec3 support = inBox.GetSupport(p.GetNormal());
  38. // If this is behind our plane, the box is not inside the frustum
  39. if (p.SignedDistance(support) < 0.0f)
  40. return false;
  41. }
  42. return true;
  43. }
  44. private:
  45. Plane mPlanes[6]; ///< Planes forming the frustum
  46. };