ShapeCast.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Geometry/AABox.h>
  5. #include <Physics/Collision/CollideShape.h>
  6. #include <Physics/Collision/Shape/Shape.h>
  7. namespace JPH {
  8. /// Structure that holds a single shape cast (a shape moving along a linear path in 3d space with no rotation)
  9. struct ShapeCast
  10. {
  11. /// Constructor
  12. ShapeCast(const Shape *inShape, Vec3Arg inScale, Mat44Arg inCenterOfMassStart, Vec3Arg inDirection, const AABox &inWorldSpaceBounds) :
  13. mShape(inShape),
  14. mScale(inScale),
  15. mCenterOfMassStart(inCenterOfMassStart),
  16. mDirection(inDirection),
  17. mShapeWorldBounds(inWorldSpaceBounds)
  18. {
  19. }
  20. /// Constructor
  21. ShapeCast(const Shape *inShape, Vec3Arg inScale, Mat44Arg inCenterOfMassStart, Vec3Arg inDirection) :
  22. ShapeCast(inShape, inScale, inCenterOfMassStart, inDirection, inShape->GetWorldSpaceBounds(inCenterOfMassStart, inScale))
  23. {
  24. }
  25. /// Transform this shape cast using inTransform. Multiply transform on the left left hand side.
  26. ShapeCast PostTransformed(Mat44Arg inTransform) const
  27. {
  28. Mat44 start = inTransform * mCenterOfMassStart;
  29. Vec3 direction = inTransform.Multiply3x3(mDirection);
  30. return { mShape, mScale, start, direction };
  31. }
  32. const Shape * mShape; ///< Shape that's being cast (cannot be mesh shape). Note that this structure does not assume ownership over the shape for performance reasons.
  33. const Vec3 mScale; ///< Scale in local space of the shape being cast
  34. const Mat44 mCenterOfMassStart; ///< Start position and orientation of the center of mass of the shape (i.e. mCenterOfMassStart = Start * Mat44::sTranslation(mShape->GetCenterOfMass()) if you want to cast the shape in the space it was created)
  35. const Vec3 mDirection; ///< Direction and length of the cast (anything beyond this length will not be reported as a hit)
  36. const AABox mShapeWorldBounds; ///< Cached shape's world bounds, calculated in constructor
  37. };
  38. /// Settings to be passed with a shape cast
  39. class ShapeCastSettings : public CollideSettingsBase
  40. {
  41. public:
  42. /// How backfacing triangles should be treated (should we report moving out of a triangle?)
  43. EBackFaceMode mBackFaceModeTriangles = EBackFaceMode::IgnoreBackFaces;
  44. /// How backfacing convex objects should be treated (should we report starting inside an object and moving out?)
  45. EBackFaceMode mBackFaceModeConvex = EBackFaceMode::IgnoreBackFaces;
  46. /// Indicates if we want to shrink the shape by the convex radius and then expand it again. This speeds up collision detection and gives a more accurate normal at the cost of a more 'rounded' shape.
  47. bool mUseShrunkenShapeAndConvexRadius = false;
  48. /// When true, and the shape is intersecting at the beginning of the cast (fraction = 0) then this will calculate the deepest penetration point (costing additional CPU time)
  49. bool mReturnDeepestPoint = false;
  50. };
  51. /// Result of a shape cast test
  52. class ShapeCastResult : public CollideShapeResult
  53. {
  54. public:
  55. /// Default constructor
  56. ShapeCastResult() = default;
  57. /// Constructor
  58. /// @param inFraction Fraction at which the cast hit
  59. /// @param inContactPoint1 Contact point on shape 1
  60. /// @param inContactPoint2 Contact point on shape 2
  61. /// @param inContactNormalOrPenetrationDepth Contact normal pointing from shape 1 to 2 or penetration depth vector when the objects are penetrating (also from 1 to 2)
  62. /// @param inBackFaceHit If this hit was a back face hit
  63. /// @param inSubShapeID1 Sub shape id for shape 1
  64. /// @param inSubShapeID2 Sub shape id for shape 2
  65. /// @param inBodyID2 BodyID that was hit
  66. ShapeCastResult(float inFraction, Vec3Arg inContactPoint1, Vec3Arg inContactPoint2, Vec3Arg inContactNormalOrPenetrationDepth, bool inBackFaceHit, const SubShapeID &inSubShapeID1, const SubShapeID &inSubShapeID2, const BodyID &inBodyID2) :
  67. CollideShapeResult(inContactPoint1, inContactPoint2, inContactNormalOrPenetrationDepth, (inContactPoint2 - inContactPoint1).Length(), inSubShapeID1, inSubShapeID2, inBodyID2),
  68. mFraction(inFraction),
  69. mIsBackFaceHit(inBackFaceHit)
  70. {
  71. }
  72. /// Function required by the CollisionCollector. A smaller fraction is considered to be a 'better hit'. For rays/cast shapes we can just use the collision fraction. The fraction and penetration depth are combined in such a way that deeper hits at fraction 0 go first.
  73. inline float GetEarlyOutFraction() const { return mFraction > 0.0f? mFraction : -mPenetrationDepth; }
  74. float mFraction; ///< This is the fraction where the shape hit the other shape: CenterOfMassOnHit = Start + value * (End - Start)
  75. bool mIsBackFaceHit; ///< True if the shape was hit from the back side
  76. };
  77. } // JPH