main.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright (c) Amer Koleci and Contributors.
  2. // Distributed under the MIT license. See the LICENSE file in the project root for more information.
  3. #include "joltc.h"
  4. #include <stdbool.h>
  5. #include <stdlib.h> // malloc, free
  6. #include <string.h> // memset
  7. // STL includes
  8. #include <iostream>
  9. static void TraceImpl(const char* message)
  10. {
  11. // Print to the TTY
  12. std::cout << message << std::endl;
  13. }
  14. namespace Layers
  15. {
  16. static constexpr JPH_ObjectLayer NON_MOVING = 0;
  17. static constexpr JPH_ObjectLayer MOVING = 1;
  18. static constexpr JPH_ObjectLayer NUM_LAYERS = 2;
  19. };
  20. namespace BroadPhaseLayers
  21. {
  22. static constexpr JPH_BroadPhaseLayer NON_MOVING(0);
  23. static constexpr JPH_BroadPhaseLayer MOVING(1);
  24. static constexpr uint32_t NUM_LAYERS(2);
  25. };
  26. int main(void)
  27. {
  28. if (!JPH_Init())
  29. return 1;
  30. JPH_SetTraceHandler(TraceImpl);
  31. //JPH_SetAssertFailureHandler(JPH_AssertFailureFunc handler);
  32. JPH_JobSystem* jobSystem = JPH_JobSystemThreadPool_Create(nullptr);
  33. // We use only 2 layers: one for non-moving objects and one for moving objects
  34. JPH_ObjectLayerPairFilter* objectLayerPairFilterTable = JPH_ObjectLayerPairFilterTable_Create(2);
  35. JPH_ObjectLayerPairFilterTable_EnableCollision(objectLayerPairFilterTable, Layers::NON_MOVING, Layers::MOVING);
  36. JPH_ObjectLayerPairFilterTable_EnableCollision(objectLayerPairFilterTable, Layers::MOVING, Layers::NON_MOVING);
  37. // We use a 1-to-1 mapping between object layers and broadphase layers
  38. JPH_BroadPhaseLayerInterface* broadPhaseLayerInterfaceTable = JPH_BroadPhaseLayerInterfaceTable_Create(2, 2);
  39. JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(broadPhaseLayerInterfaceTable, Layers::NON_MOVING, BroadPhaseLayers::NON_MOVING);
  40. JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(broadPhaseLayerInterfaceTable, Layers::MOVING, BroadPhaseLayers::MOVING);
  41. JPH_ObjectVsBroadPhaseLayerFilter* objectVsBroadPhaseLayerFilter = JPH_ObjectVsBroadPhaseLayerFilterTable_Create(broadPhaseLayerInterfaceTable, 2, objectLayerPairFilterTable, 2);
  42. JPH_PhysicsSystemSettings settings = {};
  43. settings.maxBodies = 65536;
  44. settings.numBodyMutexes = 0;
  45. settings.maxBodyPairs = 65536;
  46. settings.maxContactConstraints = 65536;
  47. settings.broadPhaseLayerInterface = broadPhaseLayerInterfaceTable;
  48. settings.objectLayerPairFilter = objectLayerPairFilterTable;
  49. settings.objectVsBroadPhaseLayerFilter = objectVsBroadPhaseLayerFilter;
  50. JPH_PhysicsSystem* system = JPH_PhysicsSystem_Create(&settings);
  51. JPH_BodyInterface* bodyInterface = JPH_PhysicsSystem_GetBodyInterface(system);
  52. JPH_BodyID floorId = {};
  53. {
  54. // Next we can create a rigid body to serve as the floor, we make a large box
  55. // Create the settings for the collision volume (the shape).
  56. // Note that for simple shapes (like boxes) you can also directly construct a BoxShape.
  57. JPH_Vec3 boxHalfExtents = { 100.0f, 1.0f, 100.0f };
  58. JPH_BoxShape* floorShape = JPH_BoxShape_Create(&boxHalfExtents, JPH_DEFAULT_CONVEX_RADIUS);
  59. JPH_Vec3 floorPosition = { 0.0f, -1.0f, 0.0f };
  60. JPH_BodyCreationSettings* floorSettings = JPH_BodyCreationSettings_Create3(
  61. (const JPH_Shape*)floorShape,
  62. &floorPosition,
  63. nullptr, // Identity,
  64. JPH_MotionType_Static,
  65. Layers::NON_MOVING);
  66. // Create the actual rigid body
  67. floorId = JPH_BodyInterface_CreateAndAddBody(bodyInterface, floorSettings, JPH_Activation_DontActivate);
  68. JPH_BodyCreationSettings_Destroy(floorSettings);
  69. }
  70. // Sphere
  71. JPH_BodyID sphereId = {};
  72. {
  73. JPH_SphereShape* sphereShape = JPH_SphereShape_Create(50.0f);
  74. JPH_Vec3 spherePosition = { 0.0f, 2.0f, 0.0f };
  75. JPH_BodyCreationSettings* sphereSettings = JPH_BodyCreationSettings_Create3(
  76. (const JPH_Shape*)sphereShape,
  77. &spherePosition,
  78. nullptr, // Identity,
  79. JPH_MotionType_Dynamic,
  80. Layers::MOVING);
  81. sphereId = JPH_BodyInterface_CreateAndAddBody(bodyInterface, sphereSettings, JPH_Activation_Activate);
  82. JPH_BodyCreationSettings_Destroy(sphereSettings);
  83. }
  84. // Now you can interact with the dynamic body, in this case we're going to give it a velocity.
  85. // (note that if we had used CreateBody then we could have set the velocity straight on the body before adding it to the physics system)
  86. JPH_Vec3 sphereLinearVelocity = { 0.0f, -5.0f, 0.0f };
  87. JPH_BodyInterface_SetLinearVelocity(bodyInterface, sphereId, &sphereLinearVelocity);
  88. {
  89. static constexpr float cCharacterHeightStanding = 1.35f;
  90. static constexpr float cCharacterRadiusStanding = 0.3f;
  91. static constexpr float cCharacterHeightCrouching = 0.8f;
  92. static constexpr float cCharacterRadiusCrouching = 0.3f;
  93. static constexpr float cInnerShapeFraction = 0.9f;
  94. JPH_CapsuleShape* capsuleShape = JPH_CapsuleShape_Create(0.5f * cCharacterHeightStanding, cCharacterRadiusStanding);
  95. JPH_Vec3 position = { 0, 0.5f * cCharacterHeightStanding + cCharacterRadiusStanding, 0 };
  96. auto mStandingShape = JPH_RotatedTranslatedShape_Create(&position, nullptr, (JPH_Shape*)capsuleShape);
  97. JPH_CharacterVirtualSettings characterSettings{};
  98. JPH_CharacterVirtualSettings_Init(&characterSettings);
  99. characterSettings.base.shape = (const JPH_Shape*)mStandingShape;
  100. characterSettings.base.supportingVolume = { {0, 1, 0}, -cCharacterRadiusStanding }; // Accept contacts that touch the lower sphere of the capsule
  101. static const JPH_RVec3 characterVirtualPosition = { -5.0f, 0, 3.0f };
  102. auto mAnimatedCharacterVirtual = JPH_CharacterVirtual_Create(&characterSettings, &characterVirtualPosition, nullptr, 0, system);
  103. }
  104. JPH_SixDOFConstraintSettings jointSettings;
  105. JPH_SixDOFConstraintSettings_Init(&jointSettings);
  106. // We simulate the physics world in discrete time steps. 60 Hz is a good rate to update the physics system.
  107. const float cDeltaTime = 1.0f / 60.0f;
  108. // Optional step: Before starting the physics simulation you can optimize the broad phase. This improves collision detection performance (it's pointless here because we only have 2 bodies).
  109. // You should definitely not call this every frame or when e.g. streaming in a new level section as it is an expensive operation.
  110. // Instead insert all new objects in batches instead of 1 at a time to keep the broad phase efficient.
  111. JPH_PhysicsSystem_OptimizeBroadPhase(system);
  112. // Now we're ready to simulate the body, keep simulating until it goes to sleep
  113. uint32_t step = 0;
  114. while (JPH_BodyInterface_IsActive(bodyInterface, sphereId))
  115. {
  116. // Next step
  117. ++step;
  118. // Output current position and velocity of the sphere
  119. JPH_RVec3 position;
  120. JPH_Vec3 velocity;
  121. JPH_BodyInterface_GetCenterOfMassPosition(bodyInterface, sphereId, &position);
  122. JPH_BodyInterface_GetLinearVelocity(bodyInterface, sphereId, &velocity);
  123. std::cout << "Step " << step << ": Position = (" << position.x << ", " << position.y << ", " << position.z << "), Velocity = (" << velocity.x << ", " << velocity.y << ", " << velocity.z << ")" << std::endl;
  124. // If you take larger steps than 1 / 60th of a second you need to do multiple collision steps in order to keep the simulation stable. Do 1 collision step per 1 / 60th of a second (round up).
  125. const int cCollisionSteps = 1;
  126. // Step the world
  127. JPH_PhysicsSystem_Update(system, cDeltaTime, cCollisionSteps, jobSystem);
  128. }
  129. // Remove the destroy sphere from the physics system. Note that the sphere itself keeps all of its state and can be re-added at any time.
  130. JPH_BodyInterface_RemoveAndDestroyBody(bodyInterface, sphereId);
  131. // Remove and destroy the floor
  132. JPH_BodyInterface_RemoveAndDestroyBody(bodyInterface, floorId);
  133. JPH_JobSystem_Destroy(jobSystem);
  134. JPH_PhysicsSystem_Destroy(system);
  135. JPH_Shutdown();
  136. return 0;
  137. }