jolt_shape_3d.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /**************************************************************************/
  2. /* jolt_shape_3d.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "jolt_shape_3d.h"
  31. #include "../misc/jolt_type_conversions.h"
  32. #include "../objects/jolt_shaped_object_3d.h"
  33. #include "jolt_custom_double_sided_shape.h"
  34. #include "jolt_custom_user_data_shape.h"
  35. #include "Jolt/Physics/Collision/Shape/MutableCompoundShape.h"
  36. #include "Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h"
  37. #include "Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h"
  38. #include "Jolt/Physics/Collision/Shape/ScaledShape.h"
  39. #include "Jolt/Physics/Collision/Shape/SphereShape.h"
  40. #include "Jolt/Physics/Collision/Shape/StaticCompoundShape.h"
  41. namespace {
  42. constexpr float DEFAULT_SOLVER_BIAS = 0.0;
  43. } // namespace
  44. String JoltShape3D::_owners_to_string() const {
  45. const int owner_count = ref_counts_by_owner.size();
  46. if (owner_count == 0) {
  47. return "'<unknown>' and 0 other object(s)";
  48. }
  49. const JoltShapedObject3D &random_owner = *ref_counts_by_owner.begin()->key;
  50. return vformat("'%s' and %d other object(s)", random_owner.to_string(), owner_count - 1);
  51. }
  52. JoltShape3D::~JoltShape3D() = default;
  53. void JoltShape3D::add_owner(JoltShapedObject3D *p_owner) {
  54. ref_counts_by_owner[p_owner]++;
  55. }
  56. void JoltShape3D::remove_owner(JoltShapedObject3D *p_owner) {
  57. if (--ref_counts_by_owner[p_owner] <= 0) {
  58. ref_counts_by_owner.erase(p_owner);
  59. }
  60. }
  61. void JoltShape3D::remove_self() {
  62. // `remove_owner` will be called when we `remove_shape`, so we need to copy the map since the
  63. // iterator would be invalidated from underneath us.
  64. const HashMap<JoltShapedObject3D *, int> ref_counts_by_owner_copy = ref_counts_by_owner;
  65. for (const KeyValue<JoltShapedObject3D *, int> &E : ref_counts_by_owner_copy) {
  66. E.key->remove_shape(this);
  67. }
  68. }
  69. float JoltShape3D::get_solver_bias() const {
  70. return DEFAULT_SOLVER_BIAS;
  71. }
  72. void JoltShape3D::set_solver_bias(float p_bias) {
  73. if (!Math::is_equal_approx(p_bias, DEFAULT_SOLVER_BIAS)) {
  74. WARN_PRINT(vformat("Custom solver bias for shapes is not supported when using Jolt Physics. Any such value will be ignored. This shape belongs to %s.", _owners_to_string()));
  75. }
  76. }
  77. JPH::ShapeRefC JoltShape3D::try_build() {
  78. jolt_ref_mutex.lock();
  79. if (jolt_ref == nullptr) {
  80. jolt_ref = _build();
  81. }
  82. jolt_ref_mutex.unlock();
  83. return jolt_ref;
  84. }
  85. void JoltShape3D::destroy() {
  86. jolt_ref_mutex.lock();
  87. jolt_ref = nullptr;
  88. jolt_ref_mutex.unlock();
  89. for (const KeyValue<JoltShapedObject3D *, int> &E : ref_counts_by_owner) {
  90. E.key->_shapes_changed();
  91. }
  92. }
  93. JPH::ShapeRefC JoltShape3D::with_scale(const JPH::Shape *p_shape, const Vector3 &p_scale) {
  94. ERR_FAIL_NULL_V(p_shape, nullptr);
  95. const JPH::ScaledShapeSettings shape_settings(p_shape, to_jolt(p_scale));
  96. const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
  97. ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to scale shape with {scale=%v}. It returned the following error: '%s'.", p_scale, to_godot(shape_result.GetError())));
  98. return shape_result.Get();
  99. }
  100. JPH::ShapeRefC JoltShape3D::with_basis_origin(const JPH::Shape *p_shape, const Basis &p_basis, const Vector3 &p_origin) {
  101. ERR_FAIL_NULL_V(p_shape, nullptr);
  102. const JPH::RotatedTranslatedShapeSettings shape_settings(to_jolt(p_origin), to_jolt(p_basis), p_shape);
  103. const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
  104. ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to offset shape with {basis=%s origin=%v}. It returned the following error: '%s'.", p_basis, p_origin, to_godot(shape_result.GetError())));
  105. return shape_result.Get();
  106. }
  107. JPH::ShapeRefC JoltShape3D::with_center_of_mass_offset(const JPH::Shape *p_shape, const Vector3 &p_offset) {
  108. ERR_FAIL_NULL_V(p_shape, nullptr);
  109. const JPH::OffsetCenterOfMassShapeSettings shape_settings(to_jolt(p_offset), p_shape);
  110. const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
  111. ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to offset center of mass with {offset=%v}. It returned the following error: '%s'.", p_offset, to_godot(shape_result.GetError())));
  112. return shape_result.Get();
  113. }
  114. JPH::ShapeRefC JoltShape3D::with_center_of_mass(const JPH::Shape *p_shape, const Vector3 &p_center_of_mass) {
  115. ERR_FAIL_NULL_V(p_shape, nullptr);
  116. const Vector3 center_of_mass_inner = to_godot(p_shape->GetCenterOfMass());
  117. const Vector3 center_of_mass_offset = p_center_of_mass - center_of_mass_inner;
  118. if (center_of_mass_offset == Vector3()) {
  119. return p_shape;
  120. }
  121. return with_center_of_mass_offset(p_shape, center_of_mass_offset);
  122. }
  123. JPH::ShapeRefC JoltShape3D::with_user_data(const JPH::Shape *p_shape, uint64_t p_user_data) {
  124. JoltCustomUserDataShapeSettings shape_settings(p_shape);
  125. shape_settings.mUserData = (JPH::uint64)p_user_data;
  126. const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
  127. ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to override user data. It returned the following error: '%s'.", to_godot(shape_result.GetError())));
  128. return shape_result.Get();
  129. }
  130. JPH::ShapeRefC JoltShape3D::with_double_sided(const JPH::Shape *p_shape, bool p_back_face_collision) {
  131. ERR_FAIL_NULL_V(p_shape, nullptr);
  132. const JoltCustomDoubleSidedShapeSettings shape_settings(p_shape, p_back_face_collision);
  133. const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
  134. ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to make shape double-sided. It returned the following error: '%s'.", to_godot(shape_result.GetError())));
  135. return shape_result.Get();
  136. }
  137. JPH::ShapeRefC JoltShape3D::without_custom_shapes(const JPH::Shape *p_shape) {
  138. switch (p_shape->GetSubType()) {
  139. case JoltCustomShapeSubType::RAY:
  140. case JoltCustomShapeSubType::MOTION: {
  141. // Replace unsupported shapes with a small sphere.
  142. return new JPH::SphereShape(0.1f);
  143. }
  144. case JoltCustomShapeSubType::OVERRIDE_USER_DATA:
  145. case JoltCustomShapeSubType::DOUBLE_SIDED: {
  146. const JPH::DecoratedShape *shape = static_cast<const JPH::DecoratedShape *>(p_shape);
  147. // Replace unsupported decorator shapes with the inner shape.
  148. return without_custom_shapes(shape->GetInnerShape());
  149. }
  150. case JPH::EShapeSubType::StaticCompound: {
  151. const JPH::StaticCompoundShape *shape = static_cast<const JPH::StaticCompoundShape *>(p_shape);
  152. JPH::StaticCompoundShapeSettings settings;
  153. for (const JPH::CompoundShape::SubShape &sub_shape : shape->GetSubShapes()) {
  154. settings.AddShape(shape->GetCenterOfMass() + sub_shape.GetPositionCOM() - sub_shape.GetRotation() * sub_shape.mShape->GetCenterOfMass(), sub_shape.GetRotation(), without_custom_shapes(sub_shape.mShape));
  155. }
  156. const JPH::ShapeSettings::ShapeResult shape_result = settings.Create();
  157. ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to recreate static compound shape during filtering of custom shapes. It returned the following error: '%s'.", to_godot(shape_result.GetError())));
  158. return shape_result.Get();
  159. }
  160. case JPH::EShapeSubType::MutableCompound: {
  161. const JPH::MutableCompoundShape *shape = static_cast<const JPH::MutableCompoundShape *>(p_shape);
  162. JPH::MutableCompoundShapeSettings settings;
  163. for (const JPH::MutableCompoundShape::SubShape &sub_shape : shape->GetSubShapes()) {
  164. settings.AddShape(shape->GetCenterOfMass() + sub_shape.GetPositionCOM() - sub_shape.GetRotation() * sub_shape.mShape->GetCenterOfMass(), sub_shape.GetRotation(), without_custom_shapes(sub_shape.mShape));
  165. }
  166. const JPH::ShapeSettings::ShapeResult shape_result = settings.Create();
  167. ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to recreate mutable compound shape during filtering of custom shapes. It returned the following error: '%s'.", to_godot(shape_result.GetError())));
  168. return shape_result.Get();
  169. }
  170. case JPH::EShapeSubType::RotatedTranslated: {
  171. const JPH::RotatedTranslatedShape *shape = static_cast<const JPH::RotatedTranslatedShape *>(p_shape);
  172. const JPH::Shape *inner_shape = shape->GetInnerShape();
  173. const JPH::ShapeRefC new_inner_shape = without_custom_shapes(inner_shape);
  174. if (inner_shape == new_inner_shape) {
  175. return p_shape;
  176. }
  177. return new JPH::RotatedTranslatedShape(shape->GetPosition(), shape->GetRotation(), new_inner_shape);
  178. }
  179. case JPH::EShapeSubType::Scaled: {
  180. const JPH::ScaledShape *shape = static_cast<const JPH::ScaledShape *>(p_shape);
  181. const JPH::Shape *inner_shape = shape->GetInnerShape();
  182. const JPH::ShapeRefC new_inner_shape = without_custom_shapes(inner_shape);
  183. if (inner_shape == new_inner_shape) {
  184. return p_shape;
  185. }
  186. return new JPH::ScaledShape(new_inner_shape, shape->GetScale());
  187. }
  188. case JPH::EShapeSubType::OffsetCenterOfMass: {
  189. const JPH::OffsetCenterOfMassShape *shape = static_cast<const JPH::OffsetCenterOfMassShape *>(p_shape);
  190. const JPH::Shape *inner_shape = shape->GetInnerShape();
  191. const JPH::ShapeRefC new_inner_shape = without_custom_shapes(inner_shape);
  192. if (inner_shape == new_inner_shape) {
  193. return p_shape;
  194. }
  195. return new JPH::OffsetCenterOfMassShape(new_inner_shape, shape->GetOffset());
  196. }
  197. default: {
  198. return p_shape;
  199. }
  200. }
  201. }
  202. Vector3 JoltShape3D::make_scale_valid(const JPH::Shape *p_shape, const Vector3 &p_scale) {
  203. return to_godot(p_shape->MakeScaleValid(to_jolt(p_scale)));
  204. }
  205. bool JoltShape3D::is_scale_valid(const Vector3 &p_scale, const Vector3 &p_valid_scale, real_t p_tolerance) {
  206. return Math::is_equal_approx(p_scale.x, p_valid_scale.x, p_tolerance) && Math::is_equal_approx(p_scale.y, p_valid_scale.y, p_tolerance) && Math::is_equal_approx(p_scale.z, p_valid_scale.z, p_tolerance);
  207. }