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,353 @@
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 <cmath>
6
+ #include "joltc.h"
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 ConstraintTest : public ::testing::Test {
21
+ protected:
22
+ JPH_PhysicsSystem* physicsSystem = nullptr;
23
+ JPH_BodyInterface* bodyInterface = nullptr;
24
+ JPH_BroadPhaseLayerInterface* bpLayer = nullptr;
25
+ JPH_ObjectLayerPairFilter* objPairFilter = nullptr;
26
+ JPH_ObjectVsBroadPhaseLayerFilter* objVsBpFilter = nullptr;
27
+ JPH_Body* body1 = nullptr;
28
+ JPH_Body* body2 = nullptr;
29
+ JPH_BodyID bodyId1, bodyId2;
30
+
31
+ void SetUp() override {
32
+ ASSERT_TRUE(JPH_Init());
33
+
34
+ bpLayer = JPH_BroadPhaseLayerInterfaceTable_Create(ObjectLayers::NUM_LAYERS, BroadPhaseLayers::NUM_LAYERS);
35
+ JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(bpLayer, ObjectLayers::NON_MOVING, BroadPhaseLayers::NON_MOVING);
36
+ JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(bpLayer, ObjectLayers::MOVING, BroadPhaseLayers::MOVING);
37
+
38
+ objPairFilter = JPH_ObjectLayerPairFilterTable_Create(ObjectLayers::NUM_LAYERS);
39
+ JPH_ObjectLayerPairFilterTable_EnableCollision(objPairFilter, ObjectLayers::NON_MOVING, ObjectLayers::MOVING);
40
+ JPH_ObjectLayerPairFilterTable_EnableCollision(objPairFilter, ObjectLayers::MOVING, ObjectLayers::MOVING);
41
+
42
+ objVsBpFilter = JPH_ObjectVsBroadPhaseLayerFilterTable_Create(
43
+ bpLayer, BroadPhaseLayers::NUM_LAYERS,
44
+ objPairFilter, ObjectLayers::NUM_LAYERS);
45
+
46
+ JPH_PhysicsSystemSettings settings = {};
47
+ settings.maxBodies = 1024;
48
+ settings.maxBodyPairs = 1024;
49
+ settings.maxContactConstraints = 1024;
50
+ settings.broadPhaseLayerInterface = bpLayer;
51
+ settings.objectVsBroadPhaseLayerFilter = objVsBpFilter;
52
+ settings.objectLayerPairFilter = objPairFilter;
53
+
54
+ physicsSystem = JPH_PhysicsSystem_Create(&settings);
55
+ bodyInterface = JPH_PhysicsSystem_GetBodyInterface(physicsSystem);
56
+
57
+ // Create two dynamic bodies for constraint testing
58
+ JPH_SphereShape* shape = JPH_SphereShape_Create(0.5f);
59
+ JPH_Vec3 pos1 = {0.0f, 0.0f, 0.0f};
60
+ JPH_Vec3 pos2 = {2.0f, 0.0f, 0.0f};
61
+ JPH_Quat rot = {0.0f, 0.0f, 0.0f, 1.0f};
62
+
63
+ JPH_BodyCreationSettings* bs1 = JPH_BodyCreationSettings_Create3((JPH_Shape*)shape, &pos1, &rot, JPH_MotionType_Dynamic, ObjectLayers::MOVING);
64
+ JPH_BodyCreationSettings* bs2 = JPH_BodyCreationSettings_Create3((JPH_Shape*)shape, &pos2, &rot, JPH_MotionType_Dynamic, ObjectLayers::MOVING);
65
+
66
+ body1 = JPH_BodyInterface_CreateBody(bodyInterface, bs1);
67
+ body2 = JPH_BodyInterface_CreateBody(bodyInterface, bs2);
68
+ bodyId1 = JPH_Body_GetID(body1);
69
+ bodyId2 = JPH_Body_GetID(body2);
70
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId1, JPH_Activation_Activate);
71
+ JPH_BodyInterface_AddBody(bodyInterface, bodyId2, JPH_Activation_Activate);
72
+
73
+ JPH_BodyCreationSettings_Destroy(bs1);
74
+ JPH_BodyCreationSettings_Destroy(bs2);
75
+ JPH_Shape_Destroy((JPH_Shape*)shape);
76
+ }
77
+
78
+ void TearDown() override {
79
+ if (physicsSystem) {
80
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId1);
81
+ JPH_BodyInterface_RemoveBody(bodyInterface, bodyId2);
82
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId1);
83
+ JPH_BodyInterface_DestroyBody(bodyInterface, bodyId2);
84
+ JPH_PhysicsSystem_Destroy(physicsSystem);
85
+ }
86
+ JPH_Shutdown();
87
+ }
88
+ };
89
+
90
+ TEST_F(ConstraintTest, FixedConstraint_Create) {
91
+ JPH_FixedConstraintSettings settings;
92
+ JPH_FixedConstraintSettings_Init(&settings);
93
+
94
+ JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
95
+ ASSERT_NE(constraint, nullptr);
96
+
97
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Fixed);
98
+
99
+ JPH_Vec3 lambda;
100
+ JPH_FixedConstraint_GetTotalLambdaPosition(constraint, &lambda);
101
+ EXPECT_FLOAT_EQ(lambda.x, 0.0f);
102
+
103
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
104
+ }
105
+
106
+ TEST_F(ConstraintTest, DistanceConstraint_Create) {
107
+ JPH_DistanceConstraintSettings settings;
108
+ JPH_DistanceConstraintSettings_Init(&settings);
109
+
110
+ JPH_DistanceConstraint* constraint = JPH_DistanceConstraint_Create(&settings, body1, body2);
111
+ ASSERT_NE(constraint, nullptr);
112
+
113
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Distance);
114
+
115
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
116
+ }
117
+
118
+ TEST_F(ConstraintTest, DistanceConstraint_SetDistance) {
119
+ JPH_DistanceConstraintSettings settings;
120
+ JPH_DistanceConstraintSettings_Init(&settings);
121
+
122
+ JPH_DistanceConstraint* constraint = JPH_DistanceConstraint_Create(&settings, body1, body2);
123
+ ASSERT_NE(constraint, nullptr);
124
+
125
+ JPH_DistanceConstraint_SetDistance(constraint, 1.0f, 3.0f);
126
+ EXPECT_FLOAT_EQ(JPH_DistanceConstraint_GetMinDistance(constraint), 1.0f);
127
+ EXPECT_FLOAT_EQ(JPH_DistanceConstraint_GetMaxDistance(constraint), 3.0f);
128
+
129
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
130
+ }
131
+
132
+ TEST_F(ConstraintTest, PointConstraint_Create) {
133
+ JPH_PointConstraintSettings settings;
134
+ JPH_PointConstraintSettings_Init(&settings);
135
+
136
+ JPH_PointConstraint* constraint = JPH_PointConstraint_Create(&settings, body1, body2);
137
+ ASSERT_NE(constraint, nullptr);
138
+
139
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Point);
140
+
141
+ JPH_Vec3 point1, point2;
142
+ JPH_PointConstraint_GetLocalSpacePoint1(constraint, &point1);
143
+ JPH_PointConstraint_GetLocalSpacePoint2(constraint, &point2);
144
+
145
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
146
+ }
147
+
148
+ TEST_F(ConstraintTest, HingeConstraint_Create) {
149
+ JPH_HingeConstraintSettings settings;
150
+ JPH_HingeConstraintSettings_Init(&settings);
151
+
152
+ JPH_HingeConstraint* constraint = JPH_HingeConstraint_Create(&settings, body1, body2);
153
+ ASSERT_NE(constraint, nullptr);
154
+
155
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Hinge);
156
+
157
+ float angle = JPH_HingeConstraint_GetCurrentAngle(constraint);
158
+ EXPECT_FALSE(std::isnan(angle));
159
+
160
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
161
+ }
162
+
163
+ TEST_F(ConstraintTest, HingeConstraint_Limits) {
164
+ JPH_HingeConstraintSettings settings;
165
+ JPH_HingeConstraintSettings_Init(&settings);
166
+
167
+ JPH_HingeConstraint* constraint = JPH_HingeConstraint_Create(&settings, body1, body2);
168
+ ASSERT_NE(constraint, nullptr);
169
+
170
+ JPH_HingeConstraint_SetLimits(constraint, -JPH_M_PI / 4.0f, JPH_M_PI / 4.0f);
171
+ EXPECT_TRUE(JPH_HingeConstraint_HasLimits(constraint));
172
+ EXPECT_NEAR(JPH_HingeConstraint_GetLimitsMin(constraint), -JPH_M_PI / 4.0f, 0.001f);
173
+ EXPECT_NEAR(JPH_HingeConstraint_GetLimitsMax(constraint), JPH_M_PI / 4.0f, 0.001f);
174
+
175
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
176
+ }
177
+
178
+ TEST_F(ConstraintTest, HingeConstraint_Motor) {
179
+ JPH_HingeConstraintSettings settings;
180
+ JPH_HingeConstraintSettings_Init(&settings);
181
+
182
+ JPH_HingeConstraint* constraint = JPH_HingeConstraint_Create(&settings, body1, body2);
183
+ ASSERT_NE(constraint, nullptr);
184
+
185
+ JPH_HingeConstraint_SetMotorState(constraint, JPH_MotorState_Velocity);
186
+ EXPECT_EQ(JPH_HingeConstraint_GetMotorState(constraint), JPH_MotorState_Velocity);
187
+
188
+ JPH_HingeConstraint_SetTargetAngularVelocity(constraint, 1.0f);
189
+ EXPECT_FLOAT_EQ(JPH_HingeConstraint_GetTargetAngularVelocity(constraint), 1.0f);
190
+
191
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
192
+ }
193
+
194
+ TEST_F(ConstraintTest, SliderConstraint_Create) {
195
+ JPH_SliderConstraintSettings settings;
196
+ JPH_SliderConstraintSettings_Init(&settings);
197
+
198
+ JPH_Vec3 axis = {1.0f, 0.0f, 0.0f};
199
+ JPH_SliderConstraintSettings_SetSliderAxis(&settings, &axis);
200
+
201
+ JPH_SliderConstraint* constraint = JPH_SliderConstraint_Create(&settings, body1, body2);
202
+ ASSERT_NE(constraint, nullptr);
203
+
204
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Slider);
205
+
206
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
207
+ }
208
+
209
+ TEST_F(ConstraintTest, SliderConstraint_Limits) {
210
+ JPH_SliderConstraintSettings settings;
211
+ JPH_SliderConstraintSettings_Init(&settings);
212
+
213
+ JPH_SliderConstraint* constraint = JPH_SliderConstraint_Create(&settings, body1, body2);
214
+ ASSERT_NE(constraint, nullptr);
215
+
216
+ JPH_SliderConstraint_SetLimits(constraint, -1.0f, 1.0f);
217
+ EXPECT_TRUE(JPH_SliderConstraint_HasLimits(constraint));
218
+ EXPECT_FLOAT_EQ(JPH_SliderConstraint_GetLimitsMin(constraint), -1.0f);
219
+ EXPECT_FLOAT_EQ(JPH_SliderConstraint_GetLimitsMax(constraint), 1.0f);
220
+
221
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
222
+ }
223
+
224
+ TEST_F(ConstraintTest, ConeConstraint_Create) {
225
+ JPH_ConeConstraintSettings settings;
226
+ JPH_ConeConstraintSettings_Init(&settings);
227
+
228
+ JPH_ConeConstraint* constraint = JPH_ConeConstraint_Create(&settings, body1, body2);
229
+ ASSERT_NE(constraint, nullptr);
230
+
231
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Cone);
232
+
233
+ JPH_ConeConstraint_SetHalfConeAngle(constraint, JPH_M_PI / 6.0f);
234
+ float cosAngle = JPH_ConeConstraint_GetCosHalfConeAngle(constraint);
235
+ EXPECT_NEAR(cosAngle, cosf(JPH_M_PI / 6.0f), 0.001f);
236
+
237
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
238
+ }
239
+
240
+ TEST_F(ConstraintTest, SwingTwistConstraint_Create) {
241
+ JPH_SwingTwistConstraintSettings settings;
242
+ JPH_SwingTwistConstraintSettings_Init(&settings);
243
+
244
+ JPH_SwingTwistConstraint* constraint = JPH_SwingTwistConstraint_Create(&settings, body1, body2);
245
+ ASSERT_NE(constraint, nullptr);
246
+
247
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_SwingTwist);
248
+
249
+ float halfConeAngle = JPH_SwingTwistConstraint_GetNormalHalfConeAngle(constraint);
250
+ EXPECT_FALSE(std::isnan(halfConeAngle));
251
+
252
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
253
+ }
254
+
255
+ TEST_F(ConstraintTest, SixDOFConstraint_Create) {
256
+ JPH_SixDOFConstraintSettings settings;
257
+ JPH_SixDOFConstraintSettings_Init(&settings);
258
+
259
+ JPH_SixDOFConstraint* constraint = JPH_SixDOFConstraint_Create(&settings, body1, body2);
260
+ ASSERT_NE(constraint, nullptr);
261
+
262
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_SixDOF);
263
+
264
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
265
+ }
266
+
267
+ TEST_F(ConstraintTest, SixDOFConstraintSettings_Axes) {
268
+ JPH_SixDOFConstraintSettings settings;
269
+ JPH_SixDOFConstraintSettings_Init(&settings);
270
+
271
+ JPH_SixDOFConstraintSettings_MakeFreeAxis(&settings, JPH_SixDOFConstraintAxis_TranslationX);
272
+ EXPECT_TRUE(JPH_SixDOFConstraintSettings_IsFreeAxis(&settings, JPH_SixDOFConstraintAxis_TranslationX));
273
+
274
+ JPH_SixDOFConstraintSettings_MakeFixedAxis(&settings, JPH_SixDOFConstraintAxis_TranslationY);
275
+ EXPECT_TRUE(JPH_SixDOFConstraintSettings_IsFixedAxis(&settings, JPH_SixDOFConstraintAxis_TranslationY));
276
+
277
+ JPH_SixDOFConstraintSettings_SetLimitedAxis(&settings, JPH_SixDOFConstraintAxis_TranslationZ, -1.0f, 1.0f);
278
+ }
279
+
280
+ TEST_F(ConstraintTest, GearConstraint_Create) {
281
+ JPH_GearConstraintSettings settings;
282
+ JPH_GearConstraintSettings_Init(&settings);
283
+
284
+ JPH_GearConstraint* constraint = JPH_GearConstraint_Create(&settings, body1, body2);
285
+ ASSERT_NE(constraint, nullptr);
286
+
287
+ EXPECT_EQ(JPH_Constraint_GetSubType((JPH_Constraint*)constraint), JPH_ConstraintSubType_Gear);
288
+
289
+ float lambda = JPH_GearConstraint_GetTotalLambda(constraint);
290
+ EXPECT_FLOAT_EQ(lambda, 0.0f);
291
+
292
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
293
+ }
294
+
295
+ TEST_F(ConstraintTest, Constraint_EnableDisable) {
296
+ JPH_FixedConstraintSettings settings;
297
+ JPH_FixedConstraintSettings_Init(&settings);
298
+
299
+ JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
300
+ ASSERT_NE(constraint, nullptr);
301
+
302
+ EXPECT_TRUE(JPH_Constraint_GetEnabled((JPH_Constraint*)constraint));
303
+
304
+ JPH_Constraint_SetEnabled((JPH_Constraint*)constraint, false);
305
+ EXPECT_FALSE(JPH_Constraint_GetEnabled((JPH_Constraint*)constraint));
306
+
307
+ JPH_Constraint_SetEnabled((JPH_Constraint*)constraint, true);
308
+ EXPECT_TRUE(JPH_Constraint_GetEnabled((JPH_Constraint*)constraint));
309
+
310
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
311
+ }
312
+
313
+ TEST_F(ConstraintTest, Constraint_UserData) {
314
+ JPH_FixedConstraintSettings settings;
315
+ JPH_FixedConstraintSettings_Init(&settings);
316
+
317
+ JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
318
+ ASSERT_NE(constraint, nullptr);
319
+
320
+ JPH_Constraint_SetUserData((JPH_Constraint*)constraint, 12345);
321
+ EXPECT_EQ(JPH_Constraint_GetUserData((JPH_Constraint*)constraint), 12345u);
322
+
323
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
324
+ }
325
+
326
+ TEST_F(ConstraintTest, Constraint_Priority) {
327
+ JPH_FixedConstraintSettings settings;
328
+ JPH_FixedConstraintSettings_Init(&settings);
329
+
330
+ JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
331
+ ASSERT_NE(constraint, nullptr);
332
+
333
+ JPH_Constraint_SetConstraintPriority((JPH_Constraint*)constraint, 100);
334
+ EXPECT_EQ(JPH_Constraint_GetConstraintPriority((JPH_Constraint*)constraint), 100u);
335
+
336
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
337
+ }
338
+
339
+ TEST_F(ConstraintTest, TwoBodyConstraint_GetBodies) {
340
+ JPH_FixedConstraintSettings settings;
341
+ JPH_FixedConstraintSettings_Init(&settings);
342
+
343
+ JPH_FixedConstraint* constraint = JPH_FixedConstraint_Create(&settings, body1, body2);
344
+ ASSERT_NE(constraint, nullptr);
345
+
346
+ JPH_Body* b1 = JPH_TwoBodyConstraint_GetBody1((JPH_TwoBodyConstraint*)constraint);
347
+ JPH_Body* b2 = JPH_TwoBodyConstraint_GetBody2((JPH_TwoBodyConstraint*)constraint);
348
+
349
+ EXPECT_EQ(b1, body1);
350
+ EXPECT_EQ(b2, body2);
351
+
352
+ JPH_Constraint_Destroy((JPH_Constraint*)constraint);
353
+ }
@@ -0,0 +1,94 @@
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
+
7
+ class CoreTest : public ::testing::Test {
8
+ protected:
9
+ void SetUp() override {}
10
+ void TearDown() override {}
11
+ };
12
+
13
+ // ============================================================================
14
+ // Init/Shutdown Tests
15
+ // ============================================================================
16
+
17
+ TEST_F(CoreTest, Init_Shutdown) {
18
+ EXPECT_TRUE(JPH_Init());
19
+ JPH_Shutdown();
20
+ }
21
+
22
+ TEST_F(CoreTest, Init_Multiple_Times) {
23
+ // First init
24
+ EXPECT_TRUE(JPH_Init());
25
+ JPH_Shutdown();
26
+
27
+ // Second init should also work
28
+ EXPECT_TRUE(JPH_Init());
29
+ JPH_Shutdown();
30
+ }
31
+
32
+ // ============================================================================
33
+ // JobSystem Tests
34
+ // ============================================================================
35
+
36
+ class JobSystemTest : public ::testing::Test {
37
+ protected:
38
+ void SetUp() override {
39
+ ASSERT_TRUE(JPH_Init());
40
+ }
41
+ void TearDown() override {
42
+ JPH_Shutdown();
43
+ }
44
+ };
45
+
46
+ TEST_F(JobSystemTest, ThreadPool_Create_Default) {
47
+ JPH_JobSystem* jobSystem = JPH_JobSystemThreadPool_Create(nullptr);
48
+ ASSERT_NE(jobSystem, nullptr);
49
+ JPH_JobSystem_Destroy(jobSystem);
50
+ }
51
+
52
+ TEST_F(JobSystemTest, ThreadPool_Create_WithConfig) {
53
+ JobSystemThreadPoolConfig config = {};
54
+ config.maxJobs = JPH_MAX_PHYSICS_JOBS;
55
+ config.maxBarriers = JPH_MAX_PHYSICS_BARRIERS;
56
+ config.numThreads = 2;
57
+
58
+ JPH_JobSystem* jobSystem = JPH_JobSystemThreadPool_Create(&config);
59
+ ASSERT_NE(jobSystem, nullptr);
60
+ JPH_JobSystem_Destroy(jobSystem);
61
+ }
62
+
63
+ // ============================================================================
64
+ // TraceHandler Tests
65
+ // ============================================================================
66
+
67
+ static bool g_traceHandlerCalled = false;
68
+ static void TestTraceHandler(const char* message) {
69
+ g_traceHandlerCalled = true;
70
+ }
71
+
72
+ TEST_F(JobSystemTest, SetTraceHandler) {
73
+ g_traceHandlerCalled = false;
74
+ JPH_SetTraceHandler(TestTraceHandler);
75
+ // Note: We can't easily trigger a trace message, but at least we verify the function doesn't crash
76
+ JPH_SetTraceHandler(nullptr);
77
+ }
78
+
79
+ // ============================================================================
80
+ // AssertFailureHandler Tests
81
+ // ============================================================================
82
+
83
+ static bool g_assertHandlerCalled = false;
84
+ static bool TestAssertHandler(const char* expression, const char* message, const char* file, uint32_t line) {
85
+ g_assertHandlerCalled = true;
86
+ return true; // Continue execution
87
+ }
88
+
89
+ TEST_F(JobSystemTest, SetAssertFailureHandler) {
90
+ g_assertHandlerCalled = false;
91
+ JPH_SetAssertFailureHandler(TestAssertHandler);
92
+ // Note: We can't easily trigger an assert, but at least we verify the function doesn't crash
93
+ JPH_SetAssertFailureHandler(nullptr);
94
+ }