jolt-ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitmodules +3 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +228 -0
  5. data/Rakefile +180 -0
  6. data/examples/character_virtual.rb +35 -0
  7. data/examples/falling_sphere.rb +25 -0
  8. data/examples/stagecraft_binding.rb +29 -0
  9. data/ext/jolt_ruby/CMakeLists.txt +42 -0
  10. data/ext/jolt_ruby/character_helper.cpp +44 -0
  11. data/ext/jolt_ruby/constraint_helper.cpp +154 -0
  12. data/ext/jolt_ruby/extconf.rb +56 -0
  13. data/ext/jolt_ruby/helper.cpp +225 -0
  14. data/ext/jolt_ruby/helper.h +103 -0
  15. data/ext/joltc/.github/FUNDING.yml +1 -0
  16. data/ext/joltc/.github/workflows/build.yml +298 -0
  17. data/ext/joltc/.gitignore +272 -0
  18. data/ext/joltc/CMakeLists.txt +431 -0
  19. data/ext/joltc/LICENSE +21 -0
  20. data/ext/joltc/README.md +10 -0
  21. data/ext/joltc/build/cmake_vs2026_arm64.bat +3 -0
  22. data/ext/joltc/build/cmake_vs2026_clang.bat +10 -0
  23. data/ext/joltc/build/cmake_vs2026_x64.bat +3 -0
  24. data/ext/joltc/build/cmake_vs2026_x64_double.bat +3 -0
  25. data/ext/joltc/include/joltc.h +3166 -0
  26. data/ext/joltc/samples/01_HelloWorld/main.cpp +170 -0
  27. data/ext/joltc/samples/CMakeLists.txt +35 -0
  28. data/ext/joltc/src/joltc.c +4 -0
  29. data/ext/joltc/src/joltc.cpp +11812 -0
  30. data/ext/joltc/src/joltc_assert.cpp +271 -0
  31. data/ext/joltc/tests/CMakeLists.txt +77 -0
  32. data/ext/joltc/tests/test_character.cpp +149 -0
  33. data/ext/joltc/tests/test_collision.cpp +146 -0
  34. data/ext/joltc/tests/test_constraints.cpp +353 -0
  35. data/ext/joltc/tests/test_core.cpp +94 -0
  36. data/ext/joltc/tests/test_math.cpp +585 -0
  37. data/ext/joltc/tests/test_physics_system.cpp +465 -0
  38. data/ext/joltc/tests/test_shapes.cpp +789 -0
  39. data/ext/joltc/tests/test_skeleton.cpp +370 -0
  40. data/ext/joltc/tests/test_vehicle.cpp +319 -0
  41. data/generator/generate.rb +237 -0
  42. data/generator/layout_probe.cpp +489 -0
  43. data/generator/verify_layout.rb +32 -0
  44. data/lib/jolt/body.rb +147 -0
  45. data/lib/jolt/body_collection.rb +115 -0
  46. data/lib/jolt/body_dynamics.rb +93 -0
  47. data/lib/jolt/character_virtual.rb +162 -0
  48. data/lib/jolt/constraint.rb +136 -0
  49. data/lib/jolt/constraint_collection.rb +123 -0
  50. data/lib/jolt/contact_events.rb +19 -0
  51. data/lib/jolt/conversions.rb +76 -0
  52. data/lib/jolt/errors.rb +12 -0
  53. data/lib/jolt/fixed_stepper.rb +37 -0
  54. data/lib/jolt/hit.rb +5 -0
  55. data/lib/jolt/layers.rb +182 -0
  56. data/lib/jolt/native/character_functions.rb +16 -0
  57. data/lib/jolt/native/constraint_functions.rb +27 -0
  58. data/lib/jolt/native/core_functions.rb +17 -0
  59. data/lib/jolt/native/generated.rb +1995 -0
  60. data/lib/jolt/native/platform.rb +51 -0
  61. data/lib/jolt/native/query_functions.rb +43 -0
  62. data/lib/jolt/native/types.rb +28 -0
  63. data/lib/jolt/native.rb +94 -0
  64. data/lib/jolt/shape.rb +90 -0
  65. data/lib/jolt/shape_builders.rb +155 -0
  66. data/lib/jolt/system.rb +238 -0
  67. data/lib/jolt/system_characters.rb +25 -0
  68. data/lib/jolt/system_constraints.rb +36 -0
  69. data/lib/jolt/system_contacts.rb +57 -0
  70. data/lib/jolt/system_queries.rb +111 -0
  71. data/lib/jolt/transform.rb +5 -0
  72. data/lib/jolt/version.rb +5 -0
  73. data/lib/jolt.rb +83 -0
  74. data/script/smoke_gem.rb +29 -0
  75. data/script/verify_release.rb +36 -0
  76. metadata +147 -0
@@ -0,0 +1,465 @@
1
+ // Copyright (c) Amer Koleci and Contributors.
2
+ // Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
3
+
4
+ #include <gtest/gtest.h>
5
+ #include "joltc.h"
6
+ #include <cstring>
7
+
8
+ namespace BroadPhaseLayers {
9
+ static constexpr JPH_BroadPhaseLayer NON_MOVING = 0;
10
+ static constexpr JPH_BroadPhaseLayer MOVING = 1;
11
+ static constexpr uint32_t NUM_LAYERS = 2;
12
+ }
13
+
14
+ namespace ObjectLayers {
15
+ static constexpr JPH_ObjectLayer NON_MOVING = 0;
16
+ static constexpr JPH_ObjectLayer MOVING = 1;
17
+ static constexpr uint32_t NUM_LAYERS = 2;
18
+ }
19
+
20
+ class PhysicsSystemTest : public ::testing::Test {
21
+ protected:
22
+ JPH_JobSystem* jobSystem = nullptr;
23
+ JPH_BroadPhaseLayerInterface* broadPhaseLayerInterface = nullptr;
24
+ JPH_ObjectVsBroadPhaseLayerFilter* objectVsBroadPhaseLayerFilter = nullptr;
25
+ JPH_ObjectLayerPairFilter* objectLayerPairFilter = nullptr;
26
+ JPH_PhysicsSystem* physicsSystem = nullptr;
27
+
28
+ void SetUp() override {
29
+ ASSERT_TRUE(JPH_Init());
30
+
31
+ jobSystem = JPH_JobSystemThreadPool_Create(nullptr);
32
+ ASSERT_NE(jobSystem, nullptr);
33
+
34
+ broadPhaseLayerInterface = JPH_BroadPhaseLayerInterfaceTable_Create(ObjectLayers::NUM_LAYERS, BroadPhaseLayers::NUM_LAYERS);
35
+ JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(broadPhaseLayerInterface, ObjectLayers::NON_MOVING, BroadPhaseLayers::NON_MOVING);
36
+ JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(broadPhaseLayerInterface, ObjectLayers::MOVING, BroadPhaseLayers::MOVING);
37
+ ASSERT_NE(broadPhaseLayerInterface, nullptr);
38
+
39
+ objectLayerPairFilter = JPH_ObjectLayerPairFilterTable_Create(ObjectLayers::NUM_LAYERS);
40
+ JPH_ObjectLayerPairFilterTable_EnableCollision(objectLayerPairFilter, ObjectLayers::NON_MOVING, ObjectLayers::MOVING);
41
+ JPH_ObjectLayerPairFilterTable_EnableCollision(objectLayerPairFilter, ObjectLayers::MOVING, ObjectLayers::MOVING);
42
+ ASSERT_NE(objectLayerPairFilter, nullptr);
43
+
44
+ objectVsBroadPhaseLayerFilter = JPH_ObjectVsBroadPhaseLayerFilterTable_Create(
45
+ broadPhaseLayerInterface, BroadPhaseLayers::NUM_LAYERS,
46
+ objectLayerPairFilter, ObjectLayers::NUM_LAYERS);
47
+ ASSERT_NE(objectVsBroadPhaseLayerFilter, nullptr);
48
+
49
+ JPH_PhysicsSystemSettings settings = {};
50
+ settings.maxBodies = 1024;
51
+ settings.numBodyMutexes = 0;
52
+ settings.maxBodyPairs = 1024;
53
+ settings.maxContactConstraints = 1024;
54
+ settings.broadPhaseLayerInterface = broadPhaseLayerInterface;
55
+ settings.objectVsBroadPhaseLayerFilter = objectVsBroadPhaseLayerFilter;
56
+ settings.objectLayerPairFilter = objectLayerPairFilter;
57
+
58
+ physicsSystem = JPH_PhysicsSystem_Create(&settings);
59
+ ASSERT_NE(physicsSystem, nullptr);
60
+ }
61
+
62
+ void TearDown() override {
63
+ if (physicsSystem) JPH_PhysicsSystem_Destroy(physicsSystem);
64
+ if (jobSystem) JPH_JobSystem_Destroy(jobSystem);
65
+ JPH_Shutdown();
66
+ }
67
+ };
68
+
69
+ TEST_F(PhysicsSystemTest, Create_ValidSettings) {
70
+ EXPECT_NE(physicsSystem, nullptr);
71
+ }
72
+
73
+ TEST_F(PhysicsSystemTest, GetBodyInterface) {
74
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
75
+ EXPECT_NE(bodyInterface, nullptr);
76
+ }
77
+
78
+ TEST_F(PhysicsSystemTest, GetBodyInterfaceNoLock) {
79
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterfaceNoLock(physicsSystem);
80
+ EXPECT_NE(bodyInterface, nullptr);
81
+ }
82
+
83
+ TEST_F(PhysicsSystemTest, SetGravity) {
84
+ JPH_Vec3 gravity = {0.0f, -10.0f, 0.0f};
85
+ JPH_PhysicsSystem_SetGravity(physicsSystem, &gravity);
86
+
87
+ JPH_Vec3 result;
88
+ JPH_PhysicsSystem_GetGravity(physicsSystem, &result);
89
+ EXPECT_FLOAT_EQ(result.x, 0.0f);
90
+ EXPECT_FLOAT_EQ(result.y, -10.0f);
91
+ EXPECT_FLOAT_EQ(result.z, 0.0f);
92
+ }
93
+
94
+ TEST_F(PhysicsSystemTest, GetNumBodies_Initial) {
95
+ uint32_t numBodies = JPH_PhysicsSystem_GetNumBodies(physicsSystem);
96
+ EXPECT_EQ(numBodies, 0u);
97
+ }
98
+
99
+ TEST_F(PhysicsSystemTest, GetNumActiveBodies_Initial) {
100
+ uint32_t numActiveBodies = JPH_PhysicsSystem_GetNumActiveBodies(physicsSystem, JPH_BodyType_Rigid);
101
+ EXPECT_EQ(numActiveBodies, 0u);
102
+ }
103
+
104
+ TEST_F(PhysicsSystemTest, GetMaxBodies) {
105
+ uint32_t maxBodies = JPH_PhysicsSystem_GetMaxBodies(physicsSystem);
106
+ EXPECT_EQ(maxBodies, 1024u);
107
+ }
108
+
109
+ TEST_F(PhysicsSystemTest, CreateBody_Sphere) {
110
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
111
+ ASSERT_NE(bodyInterface, nullptr);
112
+
113
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
114
+ ASSERT_NE(shape, nullptr);
115
+
116
+ JPH_Vec3 position = {0.0f, 10.0f, 0.0f};
117
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
118
+
119
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
120
+ (const JPH_Shape*)shape, &position, &rotation,
121
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
122
+ ASSERT_NE(bodySettings, nullptr);
123
+
124
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
125
+ ASSERT_NE(body, nullptr);
126
+
127
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
128
+ EXPECT_NE(bodyId, 0xFFFFFFFF);
129
+
130
+ uint32_t numBodies = JPH_PhysicsSystem_GetNumBodies(physicsSystem);
131
+ EXPECT_EQ(numBodies, 1u);
132
+
133
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
134
+
135
+ uint32_t numActiveBodies = JPH_PhysicsSystem_GetNumActiveBodies(physicsSystem, JPH_BodyType_Rigid);
136
+ EXPECT_EQ(numActiveBodies, 1u);
137
+
138
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
139
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
140
+ JPH_BodyCreationSettings_Destroy(bodySettings);
141
+ JPH_Shape_Destroy((JPH_Shape*)shape);
142
+ }
143
+
144
+ TEST_F(PhysicsSystemTest, CreateBody_Box) {
145
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
146
+ ASSERT_NE(bodyInterface, nullptr);
147
+
148
+ JPH_Vec3 halfExtent = {1.0f, 1.0f, 1.0f};
149
+ JPH_BoxShape* shape = JPH_BoxShape_Create(&halfExtent, JPH_DEFAULT_CONVEX_RADIUS);
150
+ ASSERT_NE(shape, nullptr);
151
+
152
+ JPH_Vec3 position = {0.0f, 0.0f, 0.0f};
153
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
154
+
155
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
156
+ (const JPH_Shape*)shape, &position, &rotation,
157
+ JPH_MotionType_Static, ObjectLayers::NON_MOVING);
158
+
159
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
160
+ ASSERT_NE(body, nullptr);
161
+
162
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
163
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_DontActivate);
164
+
165
+ uint32_t numActiveBodies = JPH_PhysicsSystem_GetNumActiveBodies(physicsSystem, JPH_BodyType_Rigid);
166
+ EXPECT_EQ(numActiveBodies, 0u);
167
+
168
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
169
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
170
+ JPH_BodyCreationSettings_Destroy(bodySettings);
171
+ JPH_Shape_Destroy((JPH_Shape*)shape);
172
+ }
173
+
174
+ TEST_F(PhysicsSystemTest, Body_GetPosition) {
175
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
176
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
177
+
178
+ JPH_Vec3 position = {1.0f, 2.0f, 3.0f};
179
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
180
+
181
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
182
+ (const JPH_Shape*)shape, &position, &rotation,
183
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
184
+
185
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
186
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
187
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
188
+
189
+ JPH_RVec3 resultPos;
190
+ JPH_BodyInterface_GetPosition(bodyInterface, bodyId, &resultPos);
191
+ EXPECT_FLOAT_EQ(resultPos.x, 1.0f);
192
+ EXPECT_FLOAT_EQ(resultPos.y, 2.0f);
193
+ EXPECT_FLOAT_EQ(resultPos.z, 3.0f);
194
+
195
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
196
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
197
+ JPH_BodyCreationSettings_Destroy(bodySettings);
198
+ JPH_Shape_Destroy((JPH_Shape*)shape);
199
+ }
200
+
201
+ TEST_F(PhysicsSystemTest, Body_SetPosition) {
202
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
203
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
204
+
205
+ JPH_Vec3 position = {0.0f, 0.0f, 0.0f};
206
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
207
+
208
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
209
+ (const JPH_Shape*)shape, &position, &rotation,
210
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
211
+
212
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
213
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
214
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
215
+
216
+ JPH_RVec3 newPos = {5.0f, 10.0f, 15.0f};
217
+ JPH_BodyInterface_SetPosition(bodyInterface, bodyId, &newPos, JPH_Activation_Activate);
218
+
219
+ JPH_RVec3 resultPos;
220
+ JPH_BodyInterface_GetPosition(bodyInterface, bodyId, &resultPos);
221
+ EXPECT_FLOAT_EQ(resultPos.x, 5.0f);
222
+ EXPECT_FLOAT_EQ(resultPos.y, 10.0f);
223
+ EXPECT_FLOAT_EQ(resultPos.z, 15.0f);
224
+
225
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
226
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
227
+ JPH_BodyCreationSettings_Destroy(bodySettings);
228
+ JPH_Shape_Destroy((JPH_Shape*)shape);
229
+ }
230
+
231
+ TEST_F(PhysicsSystemTest, Body_SetLinearVelocity) {
232
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
233
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
234
+
235
+ JPH_Vec3 position = {0.0f, 10.0f, 0.0f};
236
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
237
+
238
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
239
+ (const JPH_Shape*)shape, &position, &rotation,
240
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
241
+
242
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
243
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
244
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
245
+
246
+ JPH_Vec3 velocity = {1.0f, 2.0f, 3.0f};
247
+ JPH_BodyInterface_SetLinearVelocity(bodyInterface, bodyId, &velocity);
248
+
249
+ JPH_Vec3 resultVel;
250
+ JPH_BodyInterface_GetLinearVelocity(bodyInterface, bodyId, &resultVel);
251
+ EXPECT_FLOAT_EQ(resultVel.x, 1.0f);
252
+ EXPECT_FLOAT_EQ(resultVel.y, 2.0f);
253
+ EXPECT_FLOAT_EQ(resultVel.z, 3.0f);
254
+
255
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
256
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
257
+ JPH_BodyCreationSettings_Destroy(bodySettings);
258
+ JPH_Shape_Destroy((JPH_Shape*)shape);
259
+ }
260
+
261
+ TEST_F(PhysicsSystemTest, Body_AddImpulse) {
262
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
263
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
264
+
265
+ JPH_Vec3 position = {0.0f, 10.0f, 0.0f};
266
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
267
+
268
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
269
+ (const JPH_Shape*)shape, &position, &rotation,
270
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
271
+
272
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
273
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
274
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
275
+
276
+ JPH_Vec3 initialVel;
277
+ JPH_BodyInterface_GetLinearVelocity(bodyInterface, bodyId, &initialVel);
278
+ EXPECT_FLOAT_EQ(initialVel.x, 0.0f);
279
+
280
+ JPH_Vec3 impulse = {10.0f, 0.0f, 0.0f};
281
+ JPH_BodyInterface_AddImpulse(bodyInterface, bodyId, &impulse);
282
+
283
+ JPH_Vec3 resultVel;
284
+ JPH_BodyInterface_GetLinearVelocity(bodyInterface, bodyId, &resultVel);
285
+ EXPECT_GT(resultVel.x, 0.0f);
286
+
287
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
288
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
289
+ JPH_BodyCreationSettings_Destroy(bodySettings);
290
+ JPH_Shape_Destroy((JPH_Shape*)shape);
291
+ }
292
+
293
+ TEST_F(PhysicsSystemTest, Body_GetMotionType) {
294
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
295
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
296
+
297
+ JPH_Vec3 position = {0.0f, 10.0f, 0.0f};
298
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
299
+
300
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
301
+ (const JPH_Shape*)shape, &position, &rotation,
302
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
303
+
304
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
305
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
306
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
307
+
308
+ JPH_MotionType motionType = JPH_BodyInterface_GetMotionType(bodyInterface, bodyId);
309
+ EXPECT_EQ(motionType, JPH_MotionType_Dynamic);
310
+
311
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
312
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
313
+ JPH_BodyCreationSettings_Destroy(bodySettings);
314
+ JPH_Shape_Destroy((JPH_Shape*)shape);
315
+ }
316
+
317
+ TEST_F(PhysicsSystemTest, Body_ActivateDeactivate) {
318
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
319
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
320
+
321
+ JPH_Vec3 position = {0.0f, 10.0f, 0.0f};
322
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
323
+
324
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
325
+ (const JPH_Shape*)shape, &position, &rotation,
326
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
327
+
328
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
329
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
330
+
331
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_DontActivate);
332
+ EXPECT_FALSE(JPH_BodyInterface_IsActive(bodyInterface, bodyId));
333
+
334
+ JPH_BodyInterface_ActivateBody(bodyInterface, bodyId);
335
+ EXPECT_TRUE(JPH_BodyInterface_IsActive(bodyInterface, bodyId));
336
+
337
+ JPH_BodyInterface_DeactivateBody(bodyInterface, bodyId);
338
+ EXPECT_FALSE(JPH_BodyInterface_IsActive(bodyInterface, bodyId));
339
+
340
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
341
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
342
+ JPH_BodyCreationSettings_Destroy(bodySettings);
343
+ JPH_Shape_Destroy((JPH_Shape*)shape);
344
+ }
345
+
346
+ TEST_F(PhysicsSystemTest, Body_Restitution) {
347
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
348
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
349
+
350
+ JPH_Vec3 position = {0.0f, 10.0f, 0.0f};
351
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
352
+
353
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
354
+ (const JPH_Shape*)shape, &position, &rotation,
355
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
356
+
357
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
358
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
359
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
360
+
361
+ JPH_BodyInterface_SetRestitution(bodyInterface, bodyId, 0.8f);
362
+ float restitution = JPH_BodyInterface_GetRestitution(bodyInterface, bodyId);
363
+ EXPECT_FLOAT_EQ(restitution, 0.8f);
364
+
365
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
366
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
367
+ JPH_BodyCreationSettings_Destroy(bodySettings);
368
+ JPH_Shape_Destroy((JPH_Shape*)shape);
369
+ }
370
+
371
+ TEST_F(PhysicsSystemTest, Body_Friction) {
372
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
373
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
374
+
375
+ JPH_Vec3 position = {0.0f, 10.0f, 0.0f};
376
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
377
+
378
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
379
+ (const JPH_Shape*)shape, &position, &rotation,
380
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
381
+
382
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
383
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
384
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
385
+
386
+ JPH_BodyInterface_SetFriction(bodyInterface, bodyId, 0.5f);
387
+ float friction = JPH_BodyInterface_GetFriction(bodyInterface, bodyId);
388
+ EXPECT_FLOAT_EQ(friction, 0.5f);
389
+
390
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
391
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
392
+ JPH_BodyCreationSettings_Destroy(bodySettings);
393
+ JPH_Shape_Destroy((JPH_Shape*)shape);
394
+ }
395
+
396
+ TEST_F(PhysicsSystemTest, Update_FallingBody) {
397
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
398
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
399
+
400
+ JPH_Vec3 position = {0.0f, 100.0f, 0.0f};
401
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
402
+
403
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
404
+ (const JPH_Shape*)shape, &position, &rotation,
405
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
406
+
407
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
408
+ JPH_BodyID bodyId = JPH_Body_GetID(body);
409
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId, JPH_Activation_Activate);
410
+
411
+ JPH_Vec3 gravity = {0.0f, -10.0f, 0.0f};
412
+ JPH_PhysicsSystem_SetGravity(physicsSystem, &gravity);
413
+
414
+ JPH_RVec3 initialPos;
415
+ JPH_BodyInterface_GetPosition(bodyInterface, bodyId, &initialPos);
416
+
417
+ JPH_PhysicsSystem_OptimizeBroadPhase(physicsSystem);
418
+ JPH_PhysicsUpdateError error = JPH_PhysicsSystem_Update(physicsSystem, 1.0f / 60.0f, 1, jobSystem);
419
+ EXPECT_EQ(error, JPH_PhysicsUpdateError_None);
420
+
421
+ JPH_RVec3 newPos;
422
+ JPH_BodyInterface_GetPosition(bodyInterface, bodyId, &newPos);
423
+ EXPECT_LT(newPos.y, initialPos.y);
424
+
425
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId);
426
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId);
427
+ JPH_BodyCreationSettings_Destroy(bodySettings);
428
+ JPH_Shape_Destroy((JPH_Shape*)shape);
429
+ }
430
+
431
+ TEST_F(PhysicsSystemTest, MultipleBodies) {
432
+ JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
433
+
434
+ const int NUM_BODIES = 10;
435
+ JPH_BodyID bodyIds[NUM_BODIES];
436
+
437
+ for (int i = 0; i < NUM_BODIES; i++) {
438
+ JPH_SphereShape* shape = JPH_SphereShape_Create(1.0f);
439
+
440
+ JPH_Vec3 position = {(float)i * 3.0f, 10.0f, 0.0f};
441
+ JPH_Quat rotation = {0.0f, 0.0f, 0.0f, 1.0f};
442
+
443
+ JPH_BodyCreationSettings* bodySettings = JPH_BodyCreationSettings_Create3(
444
+ (const JPH_Shape*)shape, &position, &rotation,
445
+ JPH_MotionType_Dynamic, ObjectLayers::MOVING);
446
+
447
+ JPH_Body* body = JPH_BodyInterface_CreateBody(bodyInterface, bodySettings);
448
+ bodyIds[i] = JPH_Body_GetID(body);
449
+ JPH_BodyInterface_AddBody(bodyInterface, bodyIds[i], JPH_Activation_Activate);
450
+
451
+ JPH_BodyCreationSettings_Destroy(bodySettings);
452
+ JPH_Shape_Destroy((JPH_Shape*)shape);
453
+ }
454
+
455
+ uint32_t numBodies = JPH_PhysicsSystem_GetNumBodies(physicsSystem);
456
+ EXPECT_EQ(numBodies, (uint32_t)NUM_BODIES);
457
+
458
+ uint32_t numActiveBodies = JPH_PhysicsSystem_GetNumActiveBodies(physicsSystem, JPH_BodyType_Rigid);
459
+ EXPECT_EQ(numActiveBodies, (uint32_t)NUM_BODIES);
460
+
461
+ for (int i = 0; i < NUM_BODIES; i++) {
462
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyIds[i]);
463
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyIds[i]);
464
+ }
465
+ }