CompoundShapeVisitors.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Jolt/Physics/Collision/Shape/CompoundShape.h>
  5. #include <Jolt/Physics/Collision/Shape/SubShapeID.h>
  6. #include <Jolt/Physics/Collision/RayCast.h>
  7. #include <Jolt/Physics/Collision/CastResult.h>
  8. #include <Jolt/Physics/Collision/ShapeCast.h>
  9. #include <Jolt/Physics/Collision/TransformedShape.h>
  10. #include <Jolt/Physics/Collision/CollisionDispatch.h>
  11. #include <Jolt/Geometry/RayAABox.h>
  12. #include <Jolt/Geometry/AABox4.h>
  13. #include <Jolt/Geometry/OrientedBox.h>
  14. JPH_NAMESPACE_BEGIN
  15. struct CompoundShape::CastRayVisitor
  16. {
  17. JPH_INLINE CastRayVisitor(const RayCast &inRay, const CompoundShape *inShape, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) :
  18. mRay(inRay),
  19. mHit(ioHit),
  20. mSubShapeIDCreator(inSubShapeIDCreator),
  21. mSubShapeBits(inShape->GetSubShapeIDBits())
  22. {
  23. // Determine ray properties of cast
  24. mInvDirection.Set(inRay.mDirection);
  25. }
  26. /// Returns true when collision detection should abort because it's not possible to find a better hit
  27. JPH_INLINE bool ShouldAbort() const
  28. {
  29. return mHit.mFraction <= 0.0f;
  30. }
  31. /// Test ray against 4 bounding boxes and returns the distance where the ray enters the bounding box
  32. JPH_INLINE Vec4 TestBounds(Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ) const
  33. {
  34. return RayAABox4(mRay.mOrigin, mInvDirection, inBoundsMinX, inBoundsMinY, inBoundsMinZ, inBoundsMaxX, inBoundsMaxY, inBoundsMaxZ);
  35. }
  36. /// Test the ray against a single subshape
  37. JPH_INLINE void VisitShape(const SubShape &inSubShape, uint32 inSubShapeIndex)
  38. {
  39. // Create ID for sub shape
  40. SubShapeIDCreator shape2_sub_shape_id = mSubShapeIDCreator.PushID(inSubShapeIndex, mSubShapeBits);
  41. // Transform the ray
  42. Mat44 transform = Mat44::sInverseRotationTranslation(inSubShape.GetRotation(), inSubShape.GetPositionCOM());
  43. RayCast ray = mRay.Transformed(transform);
  44. if (inSubShape.mShape->CastRay(ray, shape2_sub_shape_id, mHit))
  45. mReturnValue = true;
  46. }
  47. RayInvDirection mInvDirection;
  48. const RayCast & mRay;
  49. RayCastResult & mHit;
  50. SubShapeIDCreator mSubShapeIDCreator;
  51. uint mSubShapeBits;
  52. bool mReturnValue = false;
  53. };
  54. struct CompoundShape::CastRayVisitorCollector
  55. {
  56. JPH_INLINE CastRayVisitorCollector(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const CompoundShape *inShape, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter) :
  57. mRay(inRay),
  58. mCollector(ioCollector),
  59. mSubShapeIDCreator(inSubShapeIDCreator),
  60. mSubShapeBits(inShape->GetSubShapeIDBits()),
  61. mRayCastSettings(inRayCastSettings),
  62. mShapeFilter(inShapeFilter)
  63. {
  64. // Determine ray properties of cast
  65. mInvDirection.Set(inRay.mDirection);
  66. }
  67. /// Returns true when collision detection should abort because it's not possible to find a better hit
  68. JPH_INLINE bool ShouldAbort() const
  69. {
  70. return mCollector.ShouldEarlyOut();
  71. }
  72. /// Test ray against 4 bounding boxes and returns the distance where the ray enters the bounding box
  73. JPH_INLINE Vec4 TestBounds(Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ) const
  74. {
  75. return RayAABox4(mRay.mOrigin, mInvDirection, inBoundsMinX, inBoundsMinY, inBoundsMinZ, inBoundsMaxX, inBoundsMaxY, inBoundsMaxZ);
  76. }
  77. /// Test the ray against a single subshape
  78. JPH_INLINE void VisitShape(const SubShape &inSubShape, uint32 inSubShapeIndex)
  79. {
  80. // Create ID for sub shape
  81. SubShapeIDCreator shape2_sub_shape_id = mSubShapeIDCreator.PushID(inSubShapeIndex, mSubShapeBits);
  82. // Transform the ray
  83. Mat44 transform = Mat44::sInverseRotationTranslation(inSubShape.GetRotation(), inSubShape.GetPositionCOM());
  84. RayCast ray = mRay.Transformed(transform);
  85. inSubShape.mShape->CastRay(ray, mRayCastSettings, shape2_sub_shape_id, mCollector, mShapeFilter);
  86. }
  87. RayInvDirection mInvDirection;
  88. const RayCast & mRay;
  89. CastRayCollector & mCollector;
  90. SubShapeIDCreator mSubShapeIDCreator;
  91. uint mSubShapeBits;
  92. RayCastSettings mRayCastSettings;
  93. const ShapeFilter & mShapeFilter;
  94. };
  95. struct CompoundShape::CollidePointVisitor
  96. {
  97. JPH_INLINE CollidePointVisitor(Vec3Arg inPoint, const CompoundShape *inShape, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) :
  98. mPoint(inPoint),
  99. mSubShapeIDCreator(inSubShapeIDCreator),
  100. mCollector(ioCollector),
  101. mSubShapeBits(inShape->GetSubShapeIDBits()),
  102. mShapeFilter(inShapeFilter)
  103. {
  104. }
  105. /// Returns true when collision detection should abort because it's not possible to find a better hit
  106. JPH_INLINE bool ShouldAbort() const
  107. {
  108. return mCollector.ShouldEarlyOut();
  109. }
  110. /// Test if point overlaps with 4 boxes, returns true for the ones that do
  111. JPH_INLINE UVec4 TestBounds(Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ) const
  112. {
  113. return AABox4VsPoint(mPoint, inBoundsMinX, inBoundsMinY, inBoundsMinZ, inBoundsMaxX, inBoundsMaxY, inBoundsMaxZ);
  114. }
  115. /// Test the point against a single subshape
  116. JPH_INLINE void VisitShape(const SubShape &inSubShape, uint32 inSubShapeIndex)
  117. {
  118. // Create ID for sub shape
  119. SubShapeIDCreator shape2_sub_shape_id = mSubShapeIDCreator.PushID(inSubShapeIndex, mSubShapeBits);
  120. // Transform the point
  121. Mat44 transform = Mat44::sInverseRotationTranslation(inSubShape.GetRotation(), inSubShape.GetPositionCOM());
  122. inSubShape.mShape->CollidePoint(transform * mPoint, shape2_sub_shape_id, mCollector, mShapeFilter);
  123. }
  124. Vec3 mPoint;
  125. SubShapeIDCreator mSubShapeIDCreator;
  126. CollidePointCollector & mCollector;
  127. uint mSubShapeBits;
  128. const ShapeFilter & mShapeFilter;
  129. };
  130. struct CompoundShape::CastShapeVisitor
  131. {
  132. JPH_INLINE CastShapeVisitor(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const CompoundShape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector) :
  133. mBoxCenter(inShapeCast.mShapeWorldBounds.GetCenter()),
  134. mBoxExtent(inShapeCast.mShapeWorldBounds.GetExtent()),
  135. mScale(inScale),
  136. mShapeCast(inShapeCast),
  137. mShapeCastSettings(inShapeCastSettings),
  138. mShapeFilter(inShapeFilter),
  139. mCollector(ioCollector),
  140. mCenterOfMassTransform2(inCenterOfMassTransform2),
  141. mSubShapeIDCreator1(inSubShapeIDCreator1),
  142. mSubShapeIDCreator2(inSubShapeIDCreator2),
  143. mSubShapeBits(inShape->GetSubShapeIDBits())
  144. {
  145. // Determine ray properties of cast
  146. mInvDirection.Set(inShapeCast.mDirection);
  147. }
  148. /// Returns true when collision detection should abort because it's not possible to find a better hit
  149. JPH_INLINE bool ShouldAbort() const
  150. {
  151. return mCollector.ShouldEarlyOut();
  152. }
  153. /// Tests the shape cast against 4 boundign boxes, returns the distance along the shape cast where the shape first enters the bounding box
  154. JPH_INLINE Vec4 TestBounds(Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ) const
  155. {
  156. // Scale the bounding boxes
  157. Vec4 bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z;
  158. AABox4Scale(mScale, inBoundsMinX, inBoundsMinY, inBoundsMinZ, inBoundsMaxX, inBoundsMaxY, inBoundsMaxZ, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  159. // Enlarge them by the casted shape's box extents
  160. AABox4EnlargeWithExtent(mBoxExtent, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  161. // Test ray against the bounding boxes
  162. return RayAABox4(mBoxCenter, mInvDirection, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  163. }
  164. /// Test the cast shape against a single subshape
  165. JPH_INLINE void VisitShape(const SubShape &inSubShape, uint32 inSubShapeIndex)
  166. {
  167. JPH_ASSERT(inSubShape.IsValidScale(mScale));
  168. // Create ID for sub shape
  169. SubShapeIDCreator shape2_sub_shape_id = mSubShapeIDCreator2.PushID(inSubShapeIndex, mSubShapeBits);
  170. // Calculate the local transform for this sub shape
  171. Mat44 local_transform = Mat44::sRotationTranslation(inSubShape.GetRotation(), mScale * inSubShape.GetPositionCOM());
  172. // Transform the center of mass of 2
  173. Mat44 center_of_mass_transform2 = mCenterOfMassTransform2 * local_transform;
  174. // Transform the shape cast
  175. ShapeCast shape_cast = mShapeCast.PostTransformed(local_transform.InversedRotationTranslation());
  176. CollisionDispatch::sCastShapeVsShapeLocalSpace(shape_cast, mShapeCastSettings, inSubShape.mShape, inSubShape.TransformScale(mScale), mShapeFilter, center_of_mass_transform2, mSubShapeIDCreator1, shape2_sub_shape_id, mCollector);
  177. }
  178. RayInvDirection mInvDirection;
  179. Vec3 mBoxCenter;
  180. Vec3 mBoxExtent;
  181. Vec3 mScale;
  182. const ShapeCast & mShapeCast;
  183. const ShapeCastSettings & mShapeCastSettings;
  184. const ShapeFilter & mShapeFilter;
  185. CastShapeCollector & mCollector;
  186. Mat44 mCenterOfMassTransform2;
  187. SubShapeIDCreator mSubShapeIDCreator1;
  188. SubShapeIDCreator mSubShapeIDCreator2;
  189. uint mSubShapeBits;
  190. };
  191. struct CompoundShape::CollectTransformedShapesVisitor
  192. {
  193. JPH_INLINE CollectTransformedShapesVisitor(const AABox &inBox, const CompoundShape *inShape, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale, const SubShapeIDCreator &inSubShapeIDCreator, TransformedShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) :
  194. mBox(inBox),
  195. mLocalBox(Mat44::sInverseRotationTranslation(inRotation, inPositionCOM), inBox),
  196. mPositionCOM(inPositionCOM),
  197. mRotation(inRotation),
  198. mScale(inScale),
  199. mSubShapeIDCreator(inSubShapeIDCreator),
  200. mCollector(ioCollector),
  201. mSubShapeBits(inShape->GetSubShapeIDBits()),
  202. mShapeFilter(inShapeFilter)
  203. {
  204. }
  205. /// Returns true when collision detection should abort because it's not possible to find a better hit
  206. JPH_INLINE bool ShouldAbort() const
  207. {
  208. return mCollector.ShouldEarlyOut();
  209. }
  210. /// Tests 4 bounding boxes against the query box, returns true for the ones that collide
  211. JPH_INLINE UVec4 TestBounds(Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ) const
  212. {
  213. // Scale the bounding boxes of this node
  214. Vec4 bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z;
  215. AABox4Scale(mScale, inBoundsMinX, inBoundsMinY, inBoundsMinZ, inBoundsMaxX, inBoundsMaxY, inBoundsMaxZ, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  216. // Test which nodes collide
  217. return AABox4VsBox(mLocalBox, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  218. }
  219. /// Collect the transformed sub shapes for a single subshape
  220. JPH_INLINE void VisitShape(const SubShape &inSubShape, uint32 inSubShapeIndex)
  221. {
  222. JPH_ASSERT(inSubShape.IsValidScale(mScale));
  223. // Create ID for sub shape
  224. SubShapeIDCreator sub_shape_id = mSubShapeIDCreator.PushID(inSubShapeIndex, mSubShapeBits);
  225. // Calculate world transform for sub shape
  226. Vec3 position = mPositionCOM + mRotation * (mScale * inSubShape.GetPositionCOM());
  227. Quat rotation = mRotation * inSubShape.GetRotation();
  228. // Recurse to sub shape
  229. inSubShape.mShape->CollectTransformedShapes(mBox, position, rotation, inSubShape.TransformScale(mScale), sub_shape_id, mCollector, mShapeFilter);
  230. }
  231. AABox mBox;
  232. OrientedBox mLocalBox;
  233. Vec3 mPositionCOM;
  234. Quat mRotation;
  235. Vec3 mScale;
  236. SubShapeIDCreator mSubShapeIDCreator;
  237. TransformedShapeCollector & mCollector;
  238. uint mSubShapeBits;
  239. const ShapeFilter & mShapeFilter;
  240. };
  241. struct CompoundShape::CollideCompoundVsShapeVisitor
  242. {
  243. JPH_INLINE CollideCompoundVsShapeVisitor(const CompoundShape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) :
  244. mCollideShapeSettings(inCollideShapeSettings),
  245. mCollector(ioCollector),
  246. mShape2(inShape2),
  247. mScale1(inScale1),
  248. mScale2(inScale2),
  249. mTransform1(inCenterOfMassTransform1),
  250. mTransform2(inCenterOfMassTransform2),
  251. mSubShapeIDCreator1(inSubShapeIDCreator1),
  252. mSubShapeIDCreator2(inSubShapeIDCreator2),
  253. mSubShapeBits(inShape1->GetSubShapeIDBits()),
  254. mShapeFilter(inShapeFilter)
  255. {
  256. // Get transform from shape 2 to shape 1
  257. Mat44 transform2_to_1 = inCenterOfMassTransform1.InversedRotationTranslation() * inCenterOfMassTransform2;
  258. // Convert bounding box of 2 into space of 1
  259. mBoundsOf2InSpaceOf1 = inShape2->GetLocalBounds().Scaled(inScale2).Transformed(transform2_to_1);
  260. }
  261. /// Returns true when collision detection should abort because it's not possible to find a better hit
  262. JPH_INLINE bool ShouldAbort() const
  263. {
  264. return mCollector.ShouldEarlyOut();
  265. }
  266. /// Tests the bounds of shape 2 vs 4 bounding boxes, returns true for the ones that intersect
  267. JPH_INLINE UVec4 TestBounds(Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ) const
  268. {
  269. // Scale the bounding boxes
  270. Vec4 bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z;
  271. AABox4Scale(mScale1, inBoundsMinX, inBoundsMinY, inBoundsMinZ, inBoundsMaxX, inBoundsMaxY, inBoundsMaxZ, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  272. // Test which boxes collide
  273. return AABox4VsBox(mBoundsOf2InSpaceOf1, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  274. }
  275. /// Test the shape against a single subshape
  276. JPH_INLINE void VisitShape(const SubShape &inSubShape, uint32 inSubShapeIndex)
  277. {
  278. // Get world transform of 1
  279. Mat44 transform1 = mTransform1 * inSubShape.GetLocalTransformNoScale(mScale1);
  280. // Create ID for sub shape
  281. SubShapeIDCreator shape1_sub_shape_id = mSubShapeIDCreator1.PushID(inSubShapeIndex, mSubShapeBits);
  282. CollisionDispatch::sCollideShapeVsShape(inSubShape.mShape, mShape2, inSubShape.TransformScale(mScale1), mScale2, transform1, mTransform2, shape1_sub_shape_id, mSubShapeIDCreator2, mCollideShapeSettings, mCollector, mShapeFilter);
  283. }
  284. const CollideShapeSettings & mCollideShapeSettings;
  285. CollideShapeCollector & mCollector;
  286. const Shape * mShape2;
  287. Vec3 mScale1;
  288. Vec3 mScale2;
  289. Mat44 mTransform1;
  290. Mat44 mTransform2;
  291. AABox mBoundsOf2InSpaceOf1;
  292. SubShapeIDCreator mSubShapeIDCreator1;
  293. SubShapeIDCreator mSubShapeIDCreator2;
  294. uint mSubShapeBits;
  295. const ShapeFilter & mShapeFilter;
  296. };
  297. struct CompoundShape::CollideShapeVsCompoundVisitor
  298. {
  299. JPH_INLINE CollideShapeVsCompoundVisitor(const Shape *inShape1, const CompoundShape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) :
  300. mCollideShapeSettings(inCollideShapeSettings),
  301. mCollector(ioCollector),
  302. mShape1(inShape1),
  303. mScale1(inScale1),
  304. mScale2(inScale2),
  305. mTransform1(inCenterOfMassTransform1),
  306. mTransform2(inCenterOfMassTransform2),
  307. mSubShapeIDCreator1(inSubShapeIDCreator1),
  308. mSubShapeIDCreator2(inSubShapeIDCreator2),
  309. mSubShapeBits(inShape2->GetSubShapeIDBits()),
  310. mShapeFilter(inShapeFilter)
  311. {
  312. // Get transform from shape 1 to shape 2
  313. Mat44 transform1_to_2 = inCenterOfMassTransform2.InversedRotationTranslation() * inCenterOfMassTransform1;
  314. // Convert bounding box of 1 into space of 2
  315. mBoundsOf1InSpaceOf2 = inShape1->GetLocalBounds().Scaled(inScale1).Transformed(transform1_to_2);
  316. mBoundsOf1InSpaceOf2.ExpandBy(Vec3::sReplicate(inCollideShapeSettings.mMaxSeparationDistance));
  317. }
  318. /// Returns true when collision detection should abort because it's not possible to find a better hit
  319. JPH_INLINE bool ShouldAbort() const
  320. {
  321. return mCollector.ShouldEarlyOut();
  322. }
  323. /// Tests the bounds of shape 1 vs 4 bounding boxes, returns true for the ones that intersect
  324. JPH_INLINE UVec4 TestBounds(Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ) const
  325. {
  326. // Scale the bounding boxes
  327. Vec4 bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z;
  328. AABox4Scale(mScale2, inBoundsMinX, inBoundsMinY, inBoundsMinZ, inBoundsMaxX, inBoundsMaxY, inBoundsMaxZ, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  329. // Test which bounding boxes collide
  330. return AABox4VsBox(mBoundsOf1InSpaceOf2, bounds_min_x, bounds_min_y, bounds_min_z, bounds_max_x, bounds_max_y, bounds_max_z);
  331. }
  332. /// Test the shape against a single subshape
  333. JPH_INLINE void VisitShape(const SubShape &inSubShape, uint32 inSubShapeIndex)
  334. {
  335. // Create ID for sub shape
  336. SubShapeIDCreator shape2_sub_shape_id = mSubShapeIDCreator2.PushID(inSubShapeIndex, mSubShapeBits);
  337. // Get world transform of 2
  338. Mat44 transform2 = mTransform2 * inSubShape.GetLocalTransformNoScale(mScale2);
  339. CollisionDispatch::sCollideShapeVsShape(mShape1, inSubShape.mShape, mScale1, inSubShape.TransformScale(mScale2), mTransform1, transform2, mSubShapeIDCreator1, shape2_sub_shape_id, mCollideShapeSettings, mCollector, mShapeFilter);
  340. }
  341. const CollideShapeSettings & mCollideShapeSettings;
  342. CollideShapeCollector & mCollector;
  343. const Shape * mShape1;
  344. Vec3 mScale1;
  345. Vec3 mScale2;
  346. Mat44 mTransform1;
  347. Mat44 mTransform2;
  348. AABox mBoundsOf1InSpaceOf2;
  349. SubShapeIDCreator mSubShapeIDCreator1;
  350. SubShapeIDCreator mSubShapeIDCreator2;
  351. uint mSubShapeBits;
  352. const ShapeFilter & mShapeFilter;
  353. };
  354. template <class BoxType>
  355. struct CompoundShape::GetIntersectingSubShapesVisitor
  356. {
  357. JPH_INLINE GetIntersectingSubShapesVisitor(const BoxType &inBox, uint *outSubShapeIndices, int inMaxSubShapeIndices) :
  358. mBox(inBox),
  359. mSubShapeIndices(outSubShapeIndices),
  360. mMaxSubShapeIndices(inMaxSubShapeIndices)
  361. {
  362. }
  363. /// Returns true when collision detection should abort because the buffer is full
  364. JPH_INLINE bool ShouldAbort() const
  365. {
  366. return mNumResults >= mMaxSubShapeIndices;
  367. }
  368. /// Tests the box vs 4 bounding boxes, returns true for the ones that intersect
  369. JPH_INLINE UVec4 TestBounds(Vec4Arg inBoundsMinX, Vec4Arg inBoundsMinY, Vec4Arg inBoundsMinZ, Vec4Arg inBoundsMaxX, Vec4Arg inBoundsMaxY, Vec4Arg inBoundsMaxZ) const
  370. {
  371. // Test which bounding boxes collide
  372. return AABox4VsBox(mBox, inBoundsMinX, inBoundsMinY, inBoundsMinZ, inBoundsMaxX, inBoundsMaxY, inBoundsMaxZ);
  373. }
  374. /// Records a hit
  375. JPH_INLINE void VisitShape([[maybe_unused]] const SubShape &inSubShape, uint32 inSubShapeIndex)
  376. {
  377. JPH_ASSERT(mNumResults < mMaxSubShapeIndices);
  378. *mSubShapeIndices++ = inSubShapeIndex;
  379. mNumResults++;
  380. }
  381. /// Get the number of indices that were found
  382. JPH_INLINE int GetNumResults() const
  383. {
  384. return mNumResults;
  385. }
  386. private:
  387. BoxType mBox;
  388. uint * mSubShapeIndices;
  389. int mMaxSubShapeIndices;
  390. int mNumResults = 0;
  391. };
  392. JPH_NAMESPACE_END