SamplesApp.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Application/Application.h>
  5. #include <UI/UIManager.h>
  6. #include <Application/DebugUI.h>
  7. #include <Physics/Collision/CollideShape.h>
  8. #include <Skeleton/SkeletonPose.h>
  9. #include <Tests/Test.h>
  10. #include <Utils/ContactListenerImpl.h>
  11. #include <Renderer/DebugRendererImp.h>
  12. #include <Physics/StateRecorderImpl.h>
  13. namespace JPH {
  14. class JobSystem;
  15. class TempAllocator;
  16. };
  17. // Application class that runs the samples
  18. class SamplesApp : public Application
  19. {
  20. public:
  21. // Constructor / destructor
  22. SamplesApp();
  23. virtual ~SamplesApp() override;
  24. // Render the frame.
  25. virtual bool RenderFrame(float inDeltaTime) override;
  26. // Override to specify the initial camera state (local to GetCameraPivot)
  27. virtual void GetInitialCamera(CameraState &ioState) const override;
  28. // Override to specify a camera pivot point and orientation (world space)
  29. virtual Mat44 GetCameraPivot(float inCameraHeading, float inCameraPitch) const override;
  30. // Get scale factor for this world, used to boost camera speed and to scale detail of the shadows
  31. virtual float GetWorldScale() const override;
  32. private:
  33. // Start running a new test
  34. void StartTest(const RTTI *inRTTI);
  35. // Run all tests one by one
  36. void RunAllTests();
  37. // Run the next test. Returns false when the application should exit.
  38. bool NextTest();
  39. // Check if we've got to start the next test. Returns false when the application should exit.
  40. bool CheckNextTest();
  41. // Probing the collision world
  42. RefConst<Shape> CreateProbeShape();
  43. bool CastProbe(float inProbeLength, float &outFraction, Vec3 &outPosition, BodyID &outID);
  44. // Shooting an object
  45. RefConst<Shape> CreateShootObjectShape();
  46. void ShootObject();
  47. // Debug functionality: firing a ball, mouse dragging
  48. void UpdateDebug();
  49. // Draw the state of the physics system
  50. void DrawPhysics();
  51. // Update the physics system with a fixed delta time
  52. void StepPhysics(JobSystem *inJobSystem);
  53. // Save state of simulation
  54. void SaveState(StateRecorderImpl &inStream);
  55. // Restore state of simulation
  56. void RestoreState(StateRecorderImpl &inStream);
  57. // Compare current physics state with inExpectedState
  58. void ValidateState(StateRecorderImpl &inExpectedState);
  59. // Global settings
  60. int mMaxConcurrentJobs = thread::hardware_concurrency(); // How many jobs to run in parallel
  61. float mUpdateFrequency = 60.0f; // Physics update frequency
  62. int mCollisionSteps = 1; // How many collision detection steps per physics update
  63. int mIntegrationSubSteps = 1; // How many integration steps per physics update
  64. TempAllocator * mTempAllocator = nullptr; // Allocator for temporary allocations
  65. JobSystem * mJobSystem = nullptr; // The job system that runs physics jobs
  66. JobSystem * mJobSystemValidating = nullptr; // The job system to use when validating determinism
  67. PhysicsSystem * mPhysicsSystem = nullptr; // The physics system that simulates the world
  68. ContactListenerImpl * mContactListener = nullptr; // Contact listener implementation
  69. PhysicsSettings mPhysicsSettings; // Main physics simulation settings
  70. // Drawing settings
  71. #ifdef JPH_DEBUG_RENDERER
  72. bool mDrawGetTriangles = false; // Draw all shapes using Shape::GetTrianglesStart/Next
  73. bool mDrawConstraints = false; // If the constraints should be drawn
  74. bool mDrawConstraintLimits = false; // If the constraint limits should be drawn
  75. bool mDrawConstraintReferenceFrame = false; // If the constraint reference frames should be drawn
  76. BodyManager::DrawSettings mBodyDrawSettings; // Settings for how to draw bodies from the body manager
  77. SkeletonPose::DrawSettings mPoseDrawSettings; // Settings for drawing skeletal poses
  78. #endif // JPH_DEBUG_RENDERER
  79. // Drawing using GetTriangles interface
  80. using ShapeToGeometryMap = unordered_map<RefConst<Shape>, DebugRenderer::GeometryRef>;
  81. ShapeToGeometryMap mShapeToGeometry;
  82. // The test to run
  83. const RTTI * mTestClass = nullptr; // RTTI information for the test we're currently running
  84. Test * mTest = nullptr; // The test we're currently running
  85. UITextButton * mTestSettingsButton = nullptr; // Button that activates the menu that the test uses to configure additional settings
  86. // Automatic cycling through tests
  87. vector<const RTTI *> mTestsToRun; // The list of tests that are still waiting to be run
  88. float mTestTimeLeft = -1.0f; // How many seconds the test is still supposed to run
  89. bool mExitAfterRunningTests = false; // When true, the application will quit when mTestsToRun becomes empty
  90. UITextButton * mNextTestButton = nullptr; // Button that activates the next test when we're running all tests
  91. // Test settings
  92. bool mInstallContactListener = false; // When true, the contact listener is installed the next time the test is reset
  93. // State recording and determinism checks
  94. bool mRecordState = false; // When true, the state of the physics system is recorded in mPlaybackFrames every physics update
  95. 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
  96. vector<StateRecorderImpl> mPlaybackFrames; // A list of recorded world states, one per physics simulation step
  97. enum class EPlaybackMode
  98. {
  99. Rewind,
  100. StepBack,
  101. Stop,
  102. StepForward,
  103. FastForward,
  104. Play
  105. };
  106. EPlaybackMode mPlaybackMode = EPlaybackMode::Play; // Current playback state. Indicates if we're playing or scrubbing back/forward.
  107. int mCurrentPlaybackFrame = -1; // Current playback frame
  108. // Which mode the probe is operating in.
  109. enum class EProbeMode
  110. {
  111. Pick,
  112. Ray,
  113. RayCollector,
  114. CollidePoint,
  115. CollideShape,
  116. CastShape,
  117. TransformedShape,
  118. GetTriangles,
  119. BroadPhaseRay,
  120. BroadPhaseBox,
  121. BroadPhaseSphere,
  122. BroadPhasePoint,
  123. BroadPhaseOrientedBox,
  124. BroadPhaseCastBox,
  125. };
  126. // Which probe shape to use.
  127. enum class EProbeShape
  128. {
  129. Sphere,
  130. Box,
  131. ConvexHull,
  132. Capsule,
  133. TaperedCapsule,
  134. Cylinder,
  135. Triangle,
  136. StaticCompound,
  137. StaticCompound2,
  138. MutableCompound,
  139. };
  140. // Probe settings
  141. EProbeMode mProbeMode = EProbeMode::Pick; // Mouse probe mode. Determines what happens under the crosshair.
  142. EProbeShape mProbeShape = EProbeShape::Sphere; // Shape to use for the mouse probe.
  143. bool mScaleShape = false; // If the shape is scaled or not. When true mShapeScale is taken into account.
  144. Vec3 mShapeScale = Vec3::sReplicate(1.0f); // Scale in local space for the probe shape.
  145. EBackFaceMode mBackFaceMode = EBackFaceMode::CollideWithBackFaces; // How to handle back facing triangles when doing a collision probe check.
  146. EActiveEdgeMode mActiveEdgeMode = EActiveEdgeMode::CollideOnlyWithActive; // How to handle active edges when doing a collision probe check.
  147. ECollectFacesMode mCollectFacesMode = ECollectFacesMode::NoFaces; // If we should collect colliding faces
  148. float mMaxSeparationDistance = 0.0f; // Max separation distance for collide shape test
  149. bool mTreatConvexAsSolid = true; // For ray casts if the shape should be treated as solid or if the ray should only collide with the surface
  150. bool mReturnDeepestPoint = true; // For shape casts, when true this will return the deepest point
  151. bool mUseShrunkenShapeAndConvexRadius = false; // Shrink then expand the shape by the convex radius
  152. int mMaxHits = 10; // The maximum number of hits to request for a collision probe.
  153. // Which object to shoot
  154. enum class EShootObjectShape
  155. {
  156. Sphere,
  157. ConvexHull,
  158. ThinBar,
  159. };
  160. // Shoot object settings
  161. EShootObjectShape mShootObjectShape = EShootObjectShape::Sphere; // Type of object to shoot
  162. float mShootObjectVelocity = 20.0f; // Speed at which objects are ejected
  163. EMotionQuality mShootObjectMotionQuality = EMotionQuality::Discrete; // Motion quality for the object that we're shooting
  164. float mShootObjectFriction = 0.2f; // Friction for the object that is shot
  165. float mShootObjectRestitution = 0.0f; // Restitution for the object that is shot
  166. bool mShootObjectScaleShape = false; // If the shape should be scaled
  167. Vec3 mShootObjectShapeScale = Vec3::sReplicate(1.0f); // Scale of the object to shoot
  168. // Mouse dragging
  169. Body * mDragAnchor = nullptr; // A anchor point for the distance constraint. Corresponds to the current crosshair position.
  170. BodyID mDragBody; // The body ID of the body that the user is currently dragging.
  171. Ref<Constraint> mDragConstraint; // The distance constraint that connects the body to be dragged and the anchor point.
  172. 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.
  173. // Timing
  174. uint mStepNumber = 0; // Which step number we're accumulating
  175. uint64 mTotalTime = 0; // How many tick we spent
  176. };