Plane.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. JPH_NAMESPACE_BEGIN
  6. /// An infinite plane described by the formula X . Normal + Constant = 0.
  7. class [[nodiscard]] Plane
  8. {
  9. public:
  10. JPH_OVERRIDE_NEW_DELETE
  11. /// Constructor
  12. Plane() = default;
  13. explicit Plane(Vec4Arg inNormalAndConstant) : mNormalAndConstant(inNormalAndConstant) { }
  14. Plane(Vec3Arg inNormal, float inConstant) : mNormalAndConstant(inNormal, inConstant) { }
  15. /// Create from point and normal
  16. static Plane sFromPointAndNormal(Vec3Arg inPoint, Vec3Arg inNormal) { return Plane(Vec4(inNormal, -inNormal.Dot(inPoint))); }
  17. /// Create from point and normal, double precision version that more accurately calculates the plane constant
  18. static Plane sFromPointAndNormal(DVec3Arg inPoint, Vec3Arg inNormal) { return Plane(Vec4(inNormal, -float(DVec3(inNormal).Dot(inPoint)))); }
  19. /// Create from 3 counter clockwise points
  20. static Plane sFromPointsCCW(Vec3Arg inV1, Vec3Arg inV2, Vec3Arg inV3) { return sFromPointAndNormal(inV1, (inV2 - inV1).Cross(inV3 - inV1).Normalized()); }
  21. // Properties
  22. Vec3 GetNormal() const { return Vec3(mNormalAndConstant); }
  23. void SetNormal(Vec3Arg inNormal) { mNormalAndConstant = Vec4(inNormal, mNormalAndConstant.GetW()); }
  24. float GetConstant() const { return mNormalAndConstant.GetW(); }
  25. void SetConstant(float inConstant) { mNormalAndConstant.SetW(inConstant); }
  26. /// Store as 4 floats
  27. void StoreFloat4(Float4 *outV) const { mNormalAndConstant.StoreFloat4(outV); }
  28. /// Offset the plane (positive value means move it in the direction of the plane normal)
  29. Plane Offset(float inDistance) const { return Plane(mNormalAndConstant - Vec4(Vec3::sZero(), inDistance)); }
  30. /// Transform the plane by a matrix
  31. inline Plane GetTransformed(Mat44Arg inTransform) const
  32. {
  33. Vec3 transformed_normal = inTransform.Multiply3x3(GetNormal());
  34. return Plane(transformed_normal, GetConstant() - inTransform.GetTranslation().Dot(transformed_normal));
  35. }
  36. /// Scale the plane, can handle non-uniform and negative scaling
  37. inline Plane Scaled(Vec3Arg inScale) const
  38. {
  39. Vec3 scaled_normal = GetNormal() / inScale;
  40. float scaled_normal_length = scaled_normal.Length();
  41. return Plane(scaled_normal / scaled_normal_length, GetConstant() / scaled_normal_length);
  42. }
  43. /// Distance point to plane
  44. float SignedDistance(Vec3Arg inPoint) const { return inPoint.Dot(GetNormal()) + GetConstant(); }
  45. /// Project inPoint onto the plane
  46. Vec3 ProjectPointOnPlane(Vec3Arg inPoint) const { return inPoint - GetNormal() * SignedDistance(inPoint); }
  47. /// Returns intersection point between 3 planes
  48. static bool sIntersectPlanes(const Plane &inP1, const Plane &inP2, const Plane &inP3, Vec3 &outPoint)
  49. {
  50. // We solve the equation:
  51. // |ax, ay, az, aw| | x | | 0 |
  52. // |bx, by, bz, bw| * | y | = | 0 |
  53. // |cx, cy, cz, cw| | z | | 0 |
  54. // | 0, 0, 0, 1| | 1 | | 1 |
  55. // Where normal of plane 1 = (ax, ay, az), plane constant of 1 = aw, normal of plane 2 = (bx, by, bz) etc.
  56. // This involves inverting the matrix and multiplying it with [0, 0, 0, 1]
  57. // Fetch the normals and plane constants for the three planes
  58. Vec4 a = inP1.mNormalAndConstant;
  59. Vec4 b = inP2.mNormalAndConstant;
  60. Vec4 c = inP3.mNormalAndConstant;
  61. // Result is a vector that we have to divide by:
  62. float denominator = Vec3(a).Dot(Vec3(b).Cross(Vec3(c)));
  63. if (denominator == 0.0f)
  64. return false;
  65. // The numerator is:
  66. // [aw*(bz*cy-by*cz)+ay*(bw*cz-bz*cw)+az*(by*cw-bw*cy)]
  67. // [aw*(bx*cz-bz*cx)+ax*(bz*cw-bw*cz)+az*(bw*cx-bx*cw)]
  68. // [aw*(by*cx-bx*cy)+ax*(bw*cy-by*cw)+ay*(bx*cw-bw*cx)]
  69. Vec4 numerator =
  70. a.SplatW() * (b.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, SWIZZLE_UNUSED>() - b.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, SWIZZLE_UNUSED>())
  71. + a.Swizzle<SWIZZLE_Y, SWIZZLE_X, SWIZZLE_X, SWIZZLE_UNUSED>() * (b.Swizzle<SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Y, SWIZZLE_UNUSED>() - b.Swizzle<SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Y, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_UNUSED>())
  72. + a.Swizzle<SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_UNUSED>() * (b.Swizzle<SWIZZLE_Y, SWIZZLE_W, SWIZZLE_X, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_W, SWIZZLE_X, SWIZZLE_W, SWIZZLE_UNUSED>() - b.Swizzle<SWIZZLE_W, SWIZZLE_X, SWIZZLE_W, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_Y, SWIZZLE_W, SWIZZLE_X, SWIZZLE_UNUSED>());
  73. outPoint = Vec3(numerator) / denominator;
  74. return true;
  75. }
  76. private:
  77. #ifdef JPH_OBJECT_STREAM
  78. friend void CreateRTTIPlane(class RTTI &); // For JPH_IMPLEMENT_SERIALIZABLE_OUTSIDE_CLASS
  79. #endif
  80. Vec4 mNormalAndConstant; ///< XYZ = normal, W = constant, plane: x . normal + constant = 0
  81. };
  82. JPH_NAMESPACE_END