SamplesApp.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Application/Application.h>
  6. #include <UI/UIManager.h>
  7. #include <Application/DebugUI.h>
  8. #include <Jolt/Physics/Collision/CollideShape.h>
  9. #include <Jolt/Skeleton/SkeletonPose.h>
  10. #include <Tests/Test.h>
  11. #include <Utils/ContactListenerImpl.h>
  12. #include <Renderer/DebugRendererImp.h>
  13. #include <Jolt/Physics/StateRecorderImpl.h>
  14. #include <Layers.h>
  15. namespace JPH {
  16. class JobSystem;
  17. class TempAllocator;
  18. class ComputeSystemCPU;
  19. };
  20. // Application class that runs the samples
  21. class SamplesApp : public Application
  22. {
  23. public:
  24. // Constructor / destructor
  25. SamplesApp(const String &inCommandLine);
  26. virtual ~SamplesApp() override;
  27. // Update the application
  28. virtual bool UpdateFrame(float inDeltaTime) override;
  29. // Override to specify the initial camera state (local to GetCameraPivot)
  30. virtual void GetInitialCamera(CameraState &ioState) const override;
  31. // Override to specify a camera pivot point and orientation (world space)
  32. virtual RMat44 GetCameraPivot(float inCameraHeading, float inCameraPitch) const override;
  33. // Get scale factor for this world, used to boost camera speed and to scale detail of the shadows
  34. virtual float GetWorldScale() const override;
  35. private:
  36. // Start running a new test
  37. void StartTest(const RTTI *inRTTI);
  38. // Run all tests one by one
  39. void RunAllTests();
  40. // Run the next test. Returns false when the application should exit.
  41. bool NextTest();
  42. // Check if we've got to start the next test. Returns false when the application should exit.
  43. bool CheckNextTest();
  44. // Create a snapshot of the physics system and save it to disc
  45. void TakeSnapshot();
  46. // Create a snapshot of the physics system, save it to disc and immediately reload it
  47. void TakeAndReloadSnapshot();
  48. // Probing the collision world
  49. RefConst<Shape> CreateProbeShape();
  50. bool CastProbe(float inProbeLength, float &outFraction, RVec3 &outPosition, BodyID &outID);
  51. // Shooting an object
  52. RefConst<Shape> CreateShootObjectShape();
  53. void ShootObject();
  54. // Debug functionality: firing a ball, mouse dragging
  55. void UpdateDebug(float inDeltaTime);
  56. // Draw the state of the physics system
  57. void DrawPhysics();
  58. // Update the physics system with a fixed delta time
  59. void StepPhysics(JobSystem *inJobSystem);
  60. // Save state of simulation
  61. void SaveState(StateRecorderImpl &inStream);
  62. // Restore state of simulation
  63. void RestoreState(StateRecorderImpl &inStream);
  64. // Compare current physics state with inExpectedState
  65. void ValidateState(StateRecorderImpl &inExpectedState);
  66. // Global settings
  67. int mMaxConcurrentJobs = thread::hardware_concurrency(); // How many jobs to run in parallel
  68. float mUpdateFrequency = 60.0f; // Physics update frequency, measured in Hz (cycles per second)
  69. int mCollisionSteps = 1; // How many collision detection steps per physics update
  70. TempAllocator * mTempAllocator = nullptr; // Allocator for temporary allocations
  71. JobSystem * mJobSystem = nullptr; // The job system that runs physics jobs
  72. JobSystem * mJobSystemValidating = nullptr; // The job system to use when validating determinism
  73. Ref<ComputeSystem> mComputeSystem = nullptr; // The compute system to use for compute jobs
  74. Ref<ComputeQueue> mComputeQueue = nullptr; // The compute queue to use for compute jobs
  75. #ifdef JPH_USE_CPU_COMPUTE
  76. Ref<ComputeSystemCPU> mComputeSystemCPU = nullptr; // The compute system to use for CPU compute jobs
  77. Ref<ComputeQueue> mComputeQueueCPU = nullptr; // The compute queue to use for CPU compute jobs
  78. #endif // JPH_USE_CPU_COMPUTE
  79. BPLayerInterfaceImpl mBroadPhaseLayerInterface; // The broadphase layer interface that maps object layers to broadphase layers
  80. ObjectVsBroadPhaseLayerFilterImpl mObjectVsBroadPhaseLayerFilter; // Class that filters object vs broadphase layers
  81. ObjectLayerPairFilterImpl mObjectVsObjectLayerFilter; // Class that filters object vs object layers
  82. PhysicsSystem * mPhysicsSystem = nullptr; // The physics system that simulates the world
  83. ContactListenerImpl * mContactListener = nullptr; // Contact listener implementation
  84. PhysicsSettings mPhysicsSettings; // Main physics simulation settings
  85. // Drawing settings
  86. #ifdef JPH_DEBUG_RENDERER
  87. bool mDrawGetTriangles = false; // Draw all shapes using Shape::GetTrianglesStart/Next
  88. bool mDrawConstraints = false; // If the constraints should be drawn
  89. bool mDrawConstraintLimits = false; // If the constraint limits should be drawn
  90. bool mDrawConstraintReferenceFrame = false; // If the constraint reference frames should be drawn
  91. bool mDrawBroadPhaseBounds = false; // If the bounds of the broadphase should be drawn
  92. BodyManager::DrawSettings mBodyDrawSettings; // Settings for how to draw bodies from the body manager
  93. SkeletonPose::DrawSettings mPoseDrawSettings; // Settings for drawing skeletal poses
  94. #endif // JPH_DEBUG_RENDERER
  95. // Drawing using GetTriangles interface
  96. using ShapeToGeometryMap = UnorderedMap<RefConst<Shape>, DebugRenderer::GeometryRef>;
  97. ShapeToGeometryMap mShapeToGeometry;
  98. // The test to run
  99. const RTTI * mTestClass = nullptr; // RTTI information for the test we're currently running
  100. Test * mTest = nullptr; // The test we're currently running
  101. UITextButton * mTestSettingsButton = nullptr; // Button that activates the menu that the test uses to configure additional settings
  102. int mShowDescription = 0; // If > 0, render the description of the test
  103. // Automatic cycling through tests
  104. bool mIsRunningAllTests = false; // If the user selected the 'Run All Tests' option
  105. float mTestTimeLeft = -1.0f; // How many seconds the test is still supposed to run
  106. bool mExitAfterRunningTests = false; // When true, the application will quit when mTestsToRun becomes empty
  107. // Test settings
  108. bool mInstallContactListener = false; // When true, the contact listener is installed the next time the test is reset
  109. #ifdef JPH_USE_CPU_COMPUTE
  110. bool mUseGPUCompute = true; // When true, uses the GPU compute system for compute jobs
  111. #endif // JPH_USE_CPU_COMPUTE
  112. // State recording and determinism checks
  113. bool mRecordState = false; // When true, the state of the physics system is recorded in mPlaybackFrames every physics update
  114. bool mCheckDeterminism = false; // When true, the physics state is rolled back after every update and run again to verify that the state is the same
  115. struct PlayBackFrame
  116. {
  117. StateRecorderImpl mInputState; // State of the player inputs at the beginning of the step
  118. StateRecorderImpl mState; // Main simulation state
  119. };
  120. Array<PlayBackFrame> mPlaybackFrames; // A list of recorded world states, one per physics simulation step
  121. enum class EPlaybackMode
  122. {
  123. Rewind,
  124. StepBack,
  125. Stop,
  126. StepForward,
  127. FastForward,
  128. Play
  129. };
  130. EPlaybackMode mPlaybackMode = EPlaybackMode::Play; // Current playback state. Indicates if we're playing or scrubbing back/forward.
  131. int mCurrentPlaybackFrame = -1; // Current playback frame
  132. // Which mode the probe is operating in.
  133. enum class EProbeMode
  134. {
  135. Pick,
  136. Ray,
  137. RayCollector,
  138. CollidePoint,
  139. CollideShape,
  140. CollideShapeWithInternalEdgeRemoval,
  141. CastShape,
  142. CollideSoftBody,
  143. TransformedShape,
  144. GetTriangles,
  145. BroadPhaseRay,
  146. BroadPhaseBox,
  147. BroadPhaseSphere,
  148. BroadPhasePoint,
  149. BroadPhaseOrientedBox,
  150. BroadPhaseCastBox,
  151. };
  152. // Which probe shape to use.
  153. enum class EProbeShape
  154. {
  155. Sphere,
  156. Box,
  157. ConvexHull,
  158. Capsule,
  159. TaperedCapsule,
  160. Cylinder,
  161. Triangle,
  162. RotatedTranslated,
  163. StaticCompound,
  164. StaticCompound2,
  165. MutableCompound,
  166. Mesh,
  167. };
  168. // Probe settings
  169. EProbeMode mProbeMode = EProbeMode::Pick; // Mouse probe mode. Determines what happens under the crosshair.
  170. EProbeShape mProbeShape = EProbeShape::Sphere; // Shape to use for the mouse probe.
  171. bool mScaleShape = false; // If the shape is scaled or not. When true mShapeScale is taken into account.
  172. Vec3 mShapeScale = Vec3::sOne(); // Scale in local space for the probe shape.
  173. EBackFaceMode mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces; // How to handle back facing triangles when doing a collision probe check.
  174. EBackFaceMode mBackFaceModeConvex = EBackFaceMode::CollideWithBackFaces; // How to handle back facing convex shapes when doing a collision probe check.
  175. EActiveEdgeMode mActiveEdgeMode = EActiveEdgeMode::CollideOnlyWithActive; // How to handle active edges when doing a collision probe check.
  176. ECollectFacesMode mCollectFacesMode = ECollectFacesMode::NoFaces; // If we should collect colliding faces
  177. float mMaxSeparationDistance = 0.0f; // Max separation distance for collide shape test
  178. bool mTreatConvexAsSolid = true; // For ray casts if the shape should be treated as solid or if the ray should only collide with the surface
  179. bool mReturnDeepestPoint = true; // For shape casts, when true this will return the deepest point
  180. bool mUseShrunkenShapeAndConvexRadius = false; // Shrink then expand the shape by the convex radius
  181. bool mDrawSupportingFace = false; // Draw the result of GetSupportingFace
  182. int mMaxHits = 10; // The maximum number of hits to request for a collision probe.
  183. bool mClosestHitPerBody = false; // If we are only interested in the closest hit for every body
  184. // Which object to shoot
  185. enum class EShootObjectShape
  186. {
  187. Sphere,
  188. ConvexHull,
  189. ThinBar,
  190. SoftBodyCube,
  191. };
  192. // Shoot object settings
  193. EShootObjectShape mShootObjectShape = EShootObjectShape::Sphere; // Type of object to shoot
  194. float mShootObjectVelocity = 20.0f; // Speed at which objects are ejected
  195. EMotionQuality mShootObjectMotionQuality = EMotionQuality::Discrete; // Motion quality for the object that we're shooting
  196. float mShootObjectFriction = 0.2f; // Friction for the object that is shot
  197. float mShootObjectRestitution = 0.0f; // Restitution for the object that is shot
  198. bool mShootObjectScaleShape = false; // If the shape should be scaled
  199. Vec3 mShootObjectShapeScale = Vec3::sOne(); // Scale of the object to shoot
  200. bool mWasShootKeyPressed = false; // Remembers if the shoot key was pressed last frame
  201. // Mouse dragging
  202. Body * mDragAnchor = nullptr; // Rigid bodies only: A anchor point for the distance constraint. Corresponds to the current crosshair position.
  203. BodyID mDragBody; // The body ID of the body that the user is currently dragging.
  204. Ref<Constraint> mDragConstraint; // Rigid bodies only: The distance constraint that connects the body to be dragged and the anchor point.
  205. uint mDragVertexIndex = ~uint(0); // Soft bodies only: The vertex index of the body that the user is currently dragging.
  206. float mDragVertexPreviousInvMass = 0.0f; // Soft bodies only: The inverse mass of the vertex that the user is currently dragging.
  207. float mDragFraction; // Fraction along cDragRayLength (see cpp) where the hit occurred. This will be combined with the crosshair position to get a 3d anchor point.
  208. // Timing
  209. uint mStepNumber = 0; // Which step number we're accumulating
  210. chrono::microseconds mTotalTime { 0 }; // How many nano seconds we spent simulating
  211. };