Frustum.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  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 frustum from position, forward, up, field of view x and y and near 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)
  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 plane
  20. mPlanes[0] = Plane::sFromPointAndNormal(inPosition + inNear * inForward, inForward);
  21. // Top and bottom planes
  22. mPlanes[1] = Plane::sFromPointAndNormal(inPosition, Mat44::sRotation(right, 0.5f * inFOVY) * -up);
  23. mPlanes[2] = Plane::sFromPointAndNormal(inPosition, Mat44::sRotation(right, -0.5f * inFOVY) * up);
  24. // Left and right planes
  25. mPlanes[3] = Plane::sFromPointAndNormal(inPosition, Mat44::sRotation(up, 0.5f * inFOVX) * right);
  26. mPlanes[4] = 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[5]; ///< Planes forming the frustum
  46. };