TransformedShape.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <Jolt/Jolt.h>
  5. #include <Jolt/Physics/Collision/TransformedShape.h>
  6. #include <Jolt/Physics/Collision/RayCast.h>
  7. #include <Jolt/Physics/Collision/ShapeCast.h>
  8. #include <Jolt/Physics/Collision/CastResult.h>
  9. #include <Jolt/Physics/Collision/Shape/SubShapeID.h>
  10. #include <Jolt/Physics/Collision/CollisionDispatch.h>
  11. #include <Jolt/Geometry/OrientedBox.h>
  12. JPH_NAMESPACE_BEGIN
  13. bool TransformedShape::CastRay(const RRayCast &inRay, RayCastResult &ioHit) const
  14. {
  15. if (mShape != nullptr)
  16. {
  17. // Transform the ray to local space, note that this drops precision which is possible because we're in local space now
  18. RayCast ray(inRay.Transformed(GetInverseCenterOfMassTransform()));
  19. // Scale the ray
  20. Vec3 inv_scale = GetShapeScale().Reciprocal();
  21. ray.mOrigin *= inv_scale;
  22. ray.mDirection *= inv_scale;
  23. // Cast the ray on the shape
  24. SubShapeIDCreator sub_shape_id(mSubShapeIDCreator);
  25. if (mShape->CastRay(ray, sub_shape_id, ioHit))
  26. {
  27. // Set body ID on the hit result
  28. ioHit.mBodyID = mBodyID;
  29. return true;
  30. }
  31. }
  32. return false;
  33. }
  34. void TransformedShape::CastRay(const RRayCast &inRay, const RayCastSettings &inRayCastSettings, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter) const
  35. {
  36. if (mShape != nullptr)
  37. {
  38. // Set the context on the collector and filter
  39. ioCollector.SetContext(this);
  40. inShapeFilter.mBodyID2 = mBodyID;
  41. // Transform the ray to local space, note that this drops precision which is possible because we're in local space now
  42. RayCast ray(inRay.Transformed(GetInverseCenterOfMassTransform()));
  43. // Scale the ray
  44. Vec3 inv_scale = GetShapeScale().Reciprocal();
  45. ray.mOrigin *= inv_scale;
  46. ray.mDirection *= inv_scale;
  47. // Cast the ray on the shape
  48. SubShapeIDCreator sub_shape_id(mSubShapeIDCreator);
  49. mShape->CastRay(ray, inRayCastSettings, sub_shape_id, ioCollector, inShapeFilter);
  50. }
  51. }
  52. void TransformedShape::CollidePoint(RVec3Arg inPoint, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) const
  53. {
  54. if (mShape != nullptr)
  55. {
  56. // Set the context on the collector and filter
  57. ioCollector.SetContext(this);
  58. inShapeFilter.mBodyID2 = mBodyID;
  59. // Transform and scale the point to local space
  60. Vec3 point = Vec3(GetInverseCenterOfMassTransform() * inPoint) / GetShapeScale();
  61. // Do point collide on the shape
  62. SubShapeIDCreator sub_shape_id(mSubShapeIDCreator);
  63. mShape->CollidePoint(point, sub_shape_id, ioCollector, inShapeFilter);
  64. }
  65. }
  66. void TransformedShape::CollideShape(const Shape *inShape, Vec3Arg inShapeScale, RMat44Arg inCenterOfMassTransform, const CollideShapeSettings &inCollideShapeSettings, RVec3Arg inBaseOffset, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) const
  67. {
  68. if (mShape != nullptr)
  69. {
  70. // Set the context on the collector and filter
  71. ioCollector.SetContext(this);
  72. inShapeFilter.mBodyID2 = mBodyID;
  73. SubShapeIDCreator sub_shape_id1, sub_shape_id2(mSubShapeIDCreator);
  74. Mat44 transform1 = inCenterOfMassTransform.PostTranslated(-inBaseOffset).ToMat44();
  75. Mat44 transform2 = GetCenterOfMassTransform().PostTranslated(-inBaseOffset).ToMat44();
  76. CollisionDispatch::sCollideShapeVsShape(inShape, mShape, inShapeScale, GetShapeScale(), transform1, transform2, sub_shape_id1, sub_shape_id2, inCollideShapeSettings, ioCollector, inShapeFilter);
  77. }
  78. }
  79. void TransformedShape::CastShape(const RShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, RVec3Arg inBaseOffset, CastShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) const
  80. {
  81. if (mShape != nullptr)
  82. {
  83. // Set the context on the collector and filter
  84. ioCollector.SetContext(this);
  85. inShapeFilter.mBodyID2 = mBodyID;
  86. // Get the shape cast relative to the base offset and convert it to floats
  87. ShapeCast shape_cast(inShapeCast.PostTranslated(-inBaseOffset));
  88. // Get center of mass of object we're casting against relative to the base offset and convert it to floats
  89. Mat44 center_of_mass_transform2 = GetCenterOfMassTransform().PostTranslated(-inBaseOffset).ToMat44();
  90. SubShapeIDCreator sub_shape_id1, sub_shape_id2(mSubShapeIDCreator);
  91. CollisionDispatch::sCastShapeVsShapeWorldSpace(shape_cast, inShapeCastSettings, mShape, GetShapeScale(), inShapeFilter, center_of_mass_transform2, sub_shape_id1, sub_shape_id2, ioCollector);
  92. }
  93. }
  94. void TransformedShape::CollectTransformedShapes(const AABox &inBox, TransformedShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) const
  95. {
  96. if (mShape != nullptr)
  97. {
  98. struct MyCollector : public TransformedShapeCollector
  99. {
  100. MyCollector(TransformedShapeCollector &ioCollector, RVec3 inShapePositionCOM) :
  101. TransformedShapeCollector(ioCollector),
  102. mCollector(ioCollector),
  103. mShapePositionCOM(inShapePositionCOM)
  104. {
  105. }
  106. virtual void AddHit(const TransformedShape &inResult) override
  107. {
  108. // Apply the center of mass offset
  109. TransformedShape ts = inResult;
  110. ts.mShapePositionCOM += mShapePositionCOM;
  111. // Pass hit on to child collector
  112. mCollector.AddHit(ts);
  113. // Update early out fraction based on child collector
  114. UpdateEarlyOutFraction(mCollector.GetEarlyOutFraction());
  115. }
  116. TransformedShapeCollector & mCollector;
  117. RVec3 mShapePositionCOM;
  118. };
  119. // Set the context on the collector
  120. ioCollector.SetContext(this);
  121. // Wrap the collector so we can add the center of mass precision, we do this to avoid losing precision because CollectTransformedShapes uses single precision floats
  122. MyCollector collector(ioCollector, mShapePositionCOM);
  123. // Take box to local space for the shape
  124. AABox box = inBox;
  125. box.Translate(-mShapePositionCOM);
  126. mShape->CollectTransformedShapes(box, Vec3::sZero(), mShapeRotation, GetShapeScale(), mSubShapeIDCreator, collector, inShapeFilter);
  127. }
  128. }
  129. void TransformedShape::GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, RVec3Arg inBaseOffset) const
  130. {
  131. if (mShape != nullptr)
  132. {
  133. // Take box to local space for the shape
  134. AABox box = inBox;
  135. box.Translate(-inBaseOffset);
  136. mShape->GetTrianglesStart(ioContext, box, Vec3(mShapePositionCOM - inBaseOffset), mShapeRotation, GetShapeScale());
  137. }
  138. }
  139. int TransformedShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials) const
  140. {
  141. if (mShape != nullptr)
  142. return mShape->GetTrianglesNext(ioContext, inMaxTrianglesRequested, outTriangleVertices, outMaterials);
  143. else
  144. return 0;
  145. }
  146. JPH_NAMESPACE_END