Frustum.h 2.3 KB

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