test_constraints.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // Copyright (c) Amer Koleci and Contributors.
  2. // Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
  3. #include <gtest/gtest.h>
  4. #include <cmath>
  5. #include "joltc.h"
  6. namespace BroadPhaseLayers {
  7. static constexpr JPH_BroadPhaseLayer NON_MOVING = 0;
  8. static constexpr JPH_BroadPhaseLayer MOVING = 1;
  9. static constexpr uint32_t NUM_LAYERS = 2;
  10. }
  11. namespace ObjectLayers {
  12. static constexpr JPH_ObjectLayer NON_MOVING = 0;
  13. static constexpr JPH_ObjectLayer MOVING = 1;
  14. static constexpr uint32_t NUM_LAYERS = 2;
  15. }
  16. class ConstraintTest : public ::testing::Test {
  17. protected:
  18. JPH_PhysicsSystem* physicsSystem = nullptr;
  19. JPH_BodyInterface* bodyInterface = nullptr;
  20. JPH_BroadPhaseLayerInterface* bpLayer = nullptr;
  21. JPH_ObjectLayerPairFilter* objPairFilter = nullptr;
  22. JPH_ObjectVsBroadPhaseLayerFilter* objVsBpFilter = nullptr;
  23. JPH_Body* body1 = nullptr;
  24. JPH_Body* body2 = nullptr;
  25. JPH_BodyID bodyId1, bodyId2;
  26. void SetUp() override {
  27. ASSERT_TRUE(JPH_Init());
  28. bpLayer = JPH_BroadPhaseLayerInterfaceTable_Create(ObjectLayers::NUM_LAYERS, BroadPhaseLayers::NUM_LAYERS);
  29. JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(bpLayer, ObjectLayers::NON_MOVING, BroadPhaseLayers::NON_MOVING);
  30. JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(bpLayer, ObjectLayers::MOVING, BroadPhaseLayers::MOVING);
  31. objPairFilter = JPH_ObjectLayerPairFilterTable_Create(ObjectLayers::NUM_LAYERS);
  32. JPH_ObjectLayerPairFilterTable_EnableCollision(objPairFilter, ObjectLayers::NON_MOVING, ObjectLayers::MOVING);
  33. JPH_ObjectLayerPairFilterTable_EnableCollision(objPairFilter, ObjectLayers::MOVING, ObjectLayers::MOVING);
  34. objVsBpFilter = JPH_ObjectVsBroadPhaseLayerFilterTable_Create(
  35. bpLayer, BroadPhaseLayers::NUM_LAYERS,
  36. objPairFilter, ObjectLayers::NUM_LAYERS);
  37. JPH_PhysicsSystemSettings settings = {};
  38. settings.maxBodies = 1024;
  39. settings.maxBodyPairs = 1024;
  40. settings.maxContactConstraints = 1024;
  41. settings.broadPhaseLayerInterface = bpLayer;
  42. settings.objectVsBroadPhaseLayerFilter = objVsBpFilter;
  43. settings.objectLayerPairFilter = objPairFilter;
  44. physicsSystem = JPH_PhysicsSystem_Create(&settings);
  45. bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
  46. // Create two dynamic bodies for constraint testing
  47. JPH_SphereShape* shape = JPH_SphereShape_Create(0.5f);
  48. JPH_Vec3 pos1 = {0.0f, 0.0f, 0.0f};
  49. JPH_Vec3 pos2 = {2.0f, 0.0f, 0.0f};
  50. JPH_Quat rot = {0.0f, 0.0f, 0.0f, 1.0f};
  51. JPH_BodyCreationSettings* bs1 = JPH_BodyCreationSettings_Create3((JPH_Shape*)shape, &pos1, &rot, JPH_MotionType_Dynamic, ObjectLayers::MOVING);
  52. JPH_BodyCreationSettings* bs2 = JPH_BodyCreationSettings_Create3((JPH_Shape*)shape, &pos2, &rot, JPH_MotionType_Dynamic, ObjectLayers::MOVING);
  53. body1 = JPH_BodyInterface_CreateBody(bodyInterface, bs1);
  54. body2 = JPH_BodyInterface_CreateBody(bodyInterface, bs2);
  55. bodyId1 = JPH_Body_GetID(body1);
  56. bodyId2 = JPH_Body_GetID(body2);
  57. JPH_BodyInterface_AddBody(bodyInterface, bodyId1, JPH_Activation_Activate);
  58. JPH_BodyInterface_AddBody(bodyInterface, bodyId2, JPH_Activation_Activate);
  59. JPH_BodyCreationSettings_Destroy(bs1);
  60. JPH_BodyCreationSettings_Destroy(bs2);
  61. JPH_Shape_Destroy((JPH_Shape*)shape);
  62. }
  63. void TearDown() override {
  64. if (physicsSystem) {
  65. JPH_BodyInterface_RemoveBody(bodyInterface, bodyId1);
  66. JPH_BodyInterface_RemoveBody(bodyInterface, bodyId2);
  67. JPH_BodyInterface_DestroyBody(bodyInterface, bodyId1);
  68. JPH_BodyInterface_DestroyBody(bodyInterface, bodyId2);
  69. JPH_PhysicsSystem_Destroy(physicsSystem);
  70. }
  71. JPH_Shutdown();
  72. }
  73. };
  74. TEST_F(ConstraintTest, FixedConstraint_Create) {
  75. JPH_FixedConstraintSettings settings;
  76. JPH_FixedConstraintSettings_Init(&settings);
  77. JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
  78. ASSERT_NE(constraint, nullptr);
  79. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Fixed);
  80. JPH_Vec3 lambda;
  81. JPH_FixedConstraint_GetTotalLambdaPosition(constraint, &lambda);
  82. EXPECT_FLOAT_EQ(lambda.x, 0.0f);
  83. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  84. }
  85. TEST_F(ConstraintTest, DistanceConstraint_Create) {
  86. JPH_DistanceConstraintSettings settings;
  87. JPH_DistanceConstraintSettings_Init(&settings);
  88. JPH_DistanceConstraint* constraint = JPH_DistanceConstraint_Create(&settings, body1, body2);
  89. ASSERT_NE(constraint, nullptr);
  90. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Distance);
  91. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  92. }
  93. TEST_F(ConstraintTest, DistanceConstraint_SetDistance) {
  94. JPH_DistanceConstraintSettings settings;
  95. JPH_DistanceConstraintSettings_Init(&settings);
  96. JPH_DistanceConstraint* constraint = JPH_DistanceConstraint_Create(&settings, body1, body2);
  97. ASSERT_NE(constraint, nullptr);
  98. JPH_DistanceConstraint_SetDistance(constraint, 1.0f, 3.0f);
  99. EXPECT_FLOAT_EQ(JPH_DistanceConstraint_GetMinDistance(constraint), 1.0f);
  100. EXPECT_FLOAT_EQ(JPH_DistanceConstraint_GetMaxDistance(constraint), 3.0f);
  101. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  102. }
  103. TEST_F(ConstraintTest, PointConstraint_Create) {
  104. JPH_PointConstraintSettings settings;
  105. JPH_PointConstraintSettings_Init(&settings);
  106. JPH_PointConstraint* constraint = JPH_PointConstraint_Create(&settings, body1, body2);
  107. ASSERT_NE(constraint, nullptr);
  108. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Point);
  109. JPH_Vec3 point1, point2;
  110. JPH_PointConstraint_GetLocalSpacePoint1(constraint, &point1);
  111. JPH_PointConstraint_GetLocalSpacePoint2(constraint, &point2);
  112. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  113. }
  114. TEST_F(ConstraintTest, HingeConstraint_Create) {
  115. JPH_HingeConstraintSettings settings;
  116. JPH_HingeConstraintSettings_Init(&settings);
  117. JPH_HingeConstraint* constraint = JPH_HingeConstraint_Create(&settings, body1, body2);
  118. ASSERT_NE(constraint, nullptr);
  119. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Hinge);
  120. float angle = JPH_HingeConstraint_GetCurrentAngle(constraint);
  121. EXPECT_FALSE(std::isnan(angle));
  122. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  123. }
  124. TEST_F(ConstraintTest, HingeConstraint_Limits) {
  125. JPH_HingeConstraintSettings settings;
  126. JPH_HingeConstraintSettings_Init(&settings);
  127. JPH_HingeConstraint* constraint = JPH_HingeConstraint_Create(&settings, body1, body2);
  128. ASSERT_NE(constraint, nullptr);
  129. JPH_HingeConstraint_SetLimits(constraint, -JPH_M_PI / 4.0f, JPH_M_PI / 4.0f);
  130. EXPECT_TRUE(JPH_HingeConstraint_HasLimits(constraint));
  131. EXPECT_NEAR(JPH_HingeConstraint_GetLimitsMin(constraint), -JPH_M_PI / 4.0f, 0.001f);
  132. EXPECT_NEAR(JPH_HingeConstraint_GetLimitsMax(constraint), JPH_M_PI / 4.0f, 0.001f);
  133. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  134. }
  135. TEST_F(ConstraintTest, HingeConstraint_Motor) {
  136. JPH_HingeConstraintSettings settings;
  137. JPH_HingeConstraintSettings_Init(&settings);
  138. JPH_HingeConstraint* constraint = JPH_HingeConstraint_Create(&settings, body1, body2);
  139. ASSERT_NE(constraint, nullptr);
  140. JPH_HingeConstraint_SetMotorState(constraint, JPH_MotorState_Velocity);
  141. EXPECT_EQ(JPH_HingeConstraint_GetMotorState(constraint), JPH_MotorState_Velocity);
  142. JPH_HingeConstraint_SetTargetAngularVelocity(constraint, 1.0f);
  143. EXPECT_FLOAT_EQ(JPH_HingeConstraint_GetTargetAngularVelocity(constraint), 1.0f);
  144. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  145. }
  146. TEST_F(ConstraintTest, SliderConstraint_Create) {
  147. JPH_SliderConstraintSettings settings;
  148. JPH_SliderConstraintSettings_Init(&settings);
  149. JPH_Vec3 axis = {1.0f, 0.0f, 0.0f};
  150. JPH_SliderConstraintSettings_SetSliderAxis(&settings, &axis);
  151. JPH_SliderConstraint* constraint = JPH_SliderConstraint_Create(&settings, body1, body2);
  152. ASSERT_NE(constraint, nullptr);
  153. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Slider);
  154. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  155. }
  156. TEST_F(ConstraintTest, SliderConstraint_Limits) {
  157. JPH_SliderConstraintSettings settings;
  158. JPH_SliderConstraintSettings_Init(&settings);
  159. JPH_SliderConstraint* constraint = JPH_SliderConstraint_Create(&settings, body1, body2);
  160. ASSERT_NE(constraint, nullptr);
  161. JPH_SliderConstraint_SetLimits(constraint, -1.0f, 1.0f);
  162. EXPECT_TRUE(JPH_SliderConstraint_HasLimits(constraint));
  163. EXPECT_FLOAT_EQ(JPH_SliderConstraint_GetLimitsMin(constraint), -1.0f);
  164. EXPECT_FLOAT_EQ(JPH_SliderConstraint_GetLimitsMax(constraint), 1.0f);
  165. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  166. }
  167. TEST_F(ConstraintTest, ConeConstraint_Create) {
  168. JPH_ConeConstraintSettings settings;
  169. JPH_ConeConstraintSettings_Init(&settings);
  170. JPH_ConeConstraint* constraint = JPH_ConeConstraint_Create(&settings, body1, body2);
  171. ASSERT_NE(constraint, nullptr);
  172. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Cone);
  173. JPH_ConeConstraint_SetHalfConeAngle(constraint, JPH_M_PI / 6.0f);
  174. float cosAngle = JPH_ConeConstraint_GetCosHalfConeAngle(constraint);
  175. EXPECT_NEAR(cosAngle, cosf(JPH_M_PI / 6.0f), 0.001f);
  176. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  177. }
  178. TEST_F(ConstraintTest, SwingTwistConstraint_Create) {
  179. JPH_SwingTwistConstraintSettings settings;
  180. JPH_SwingTwistConstraintSettings_Init(&settings);
  181. JPH_SwingTwistConstraint* constraint = JPH_SwingTwistConstraint_Create(&settings, body1, body2);
  182. ASSERT_NE(constraint, nullptr);
  183. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_SwingTwist);
  184. float halfConeAngle = JPH_SwingTwistConstraint_GetNormalHalfConeAngle(constraint);
  185. EXPECT_FALSE(std::isnan(halfConeAngle));
  186. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  187. }
  188. TEST_F(ConstraintTest, SixDOFConstraint_Create) {
  189. JPH_SixDOFConstraintSettings settings;
  190. JPH_SixDOFConstraintSettings_Init(&settings);
  191. JPH_SixDOFConstraint* constraint = JPH_SixDOFConstraint_Create(&settings, body1, body2);
  192. ASSERT_NE(constraint, nullptr);
  193. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_SixDOF);
  194. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  195. }
  196. TEST_F(ConstraintTest, SixDOFConstraintSettings_Axes) {
  197. JPH_SixDOFConstraintSettings settings;
  198. JPH_SixDOFConstraintSettings_Init(&settings);
  199. JPH_SixDOFConstraintSettings_MakeFreeAxis(&settings, JPH_SixDOFConstraintAxis_TranslationX);
  200. EXPECT_TRUE(JPH_SixDOFConstraintSettings_IsFreeAxis(&settings, JPH_SixDOFConstraintAxis_TranslationX));
  201. JPH_SixDOFConstraintSettings_MakeFixedAxis(&settings, JPH_SixDOFConstraintAxis_TranslationY);
  202. EXPECT_TRUE(JPH_SixDOFConstraintSettings_IsFixedAxis(&settings, JPH_SixDOFConstraintAxis_TranslationY));
  203. JPH_SixDOFConstraintSettings_SetLimitedAxis(&settings, JPH_SixDOFConstraintAxis_TranslationZ, -1.0f, 1.0f);
  204. }
  205. TEST_F(ConstraintTest, GearConstraint_Create) {
  206. JPH_GearConstraintSettings settings;
  207. JPH_GearConstraintSettings_Init(&settings);
  208. JPH_GearConstraint* constraint = JPH_GearConstraint_Create(&settings, body1, body2);
  209. ASSERT_NE(constraint, nullptr);
  210. EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Gear);
  211. float lambda = JPH_GearConstraint_GetTotalLambda(constraint);
  212. EXPECT_FLOAT_EQ(lambda, 0.0f);
  213. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  214. }
  215. TEST_F(ConstraintTest, Constraint_EnableDisable) {
  216. JPH_FixedConstraintSettings settings;
  217. JPH_FixedConstraintSettings_Init(&settings);
  218. JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
  219. ASSERT_NE(constraint, nullptr);
  220. EXPECT_TRUE(JPH_Constraint_GetEnabled((JPH_Constraint*)constraint));
  221. JPH_Constraint_SetEnabled((JPH_Constraint*)constraint, false);
  222. EXPECT_FALSE(JPH_Constraint_GetEnabled((JPH_Constraint*)constraint));
  223. JPH_Constraint_SetEnabled((JPH_Constraint*)constraint, true);
  224. EXPECT_TRUE(JPH_Constraint_GetEnabled((JPH_Constraint*)constraint));
  225. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  226. }
  227. TEST_F(ConstraintTest, Constraint_UserData) {
  228. JPH_FixedConstraintSettings settings;
  229. JPH_FixedConstraintSettings_Init(&settings);
  230. JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
  231. ASSERT_NE(constraint, nullptr);
  232. JPH_Constraint_SetUserData((JPH_Constraint*)constraint, 12345);
  233. EXPECT_EQ(JPH_Constraint_GetUserData((JPH_Constraint*)constraint), 12345u);
  234. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  235. }
  236. TEST_F(ConstraintTest, Constraint_Priority) {
  237. JPH_FixedConstraintSettings settings;
  238. JPH_FixedConstraintSettings_Init(&settings);
  239. JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
  240. ASSERT_NE(constraint, nullptr);
  241. JPH_Constraint_SetConstraintPriority((JPH_Constraint*)constraint, 100);
  242. EXPECT_EQ(JPH_Constraint_GetConstraintPriority((JPH_Constraint*)constraint), 100u);
  243. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  244. }
  245. TEST_F(ConstraintTest, TwoBodyConstraint_GetBodies) {
  246. JPH_FixedConstraintSettings settings;
  247. JPH_FixedConstraintSettings_Init(&settings);
  248. JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
  249. ASSERT_NE(constraint, nullptr);
  250. JPH_Body* b1 = JPH_TwoBodyConstraint_GetBody1((JPH_TwoBodyConstraint*)constraint);
  251. JPH_Body* b2 = JPH_TwoBodyConstraint_GetBody2((JPH_TwoBodyConstraint*)constraint);
  252. EXPECT_EQ(b1, body1);
  253. EXPECT_EQ(b2, body2);
  254. JPH_Constraint_Destroy((JPH_Constraint*)constraint);
  255. }