Files
CosmicEngine/lib/All/JoltPhysics/Samples/SamplesApp.h

238 lines
11 KiB
C
Raw Normal View History

// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#pragma once
#include <Application/Application.h>
#include <UI/UIManager.h>
#include <Application/DebugUI.h>
#include <Jolt/Physics/Collision/CollideShape.h>
#include <Jolt/Skeleton/SkeletonPose.h>
#include <Tests/Test.h>
#include <Utils/ContactListenerImpl.h>
#include <Renderer/DebugRendererImp.h>
#include <Jolt/Physics/StateRecorderImpl.h>
#include <Layers.h>
namespace JPH {
class JobSystem;
class TempAllocator;
};
// Application class that runs the samples
class SamplesApp : public Application
{
public:
// Constructor / destructor
SamplesApp(const String &inCommandLine);
virtual ~SamplesApp() override;
// Update the application
virtual bool UpdateFrame(float inDeltaTime) override;
// Override to specify the initial camera state (local to GetCameraPivot)
virtual void GetInitialCamera(CameraState &ioState) const override;
// Override to specify a camera pivot point and orientation (world space)
virtual RMat44 GetCameraPivot(float inCameraHeading, float inCameraPitch) const override;
// Get scale factor for this world, used to boost camera speed and to scale detail of the shadows
virtual float GetWorldScale() const override;
private:
// Start running a new test
void StartTest(const RTTI *inRTTI);
// Run all tests one by one
void RunAllTests();
// Run the next test. Returns false when the application should exit.
bool NextTest();
// Check if we've got to start the next test. Returns false when the application should exit.
bool CheckNextTest();
// Create a snapshot of the physics system and save it to disc
void TakeSnapshot();
// Create a snapshot of the physics system, save it to disc and immediately reload it
void TakeAndReloadSnapshot();
// Probing the collision world
RefConst<Shape> CreateProbeShape();
bool CastProbe(float inProbeLength, float &outFraction, RVec3 &outPosition, BodyID &outID);
// Shooting an object
RefConst<Shape> CreateShootObjectShape();
void ShootObject();
// Debug functionality: firing a ball, mouse dragging
void UpdateDebug(float inDeltaTime);
// Draw the state of the physics system
void DrawPhysics();
// Update the physics system with a fixed delta time
void StepPhysics(JobSystem *inJobSystem);
// Save state of simulation
void SaveState(StateRecorderImpl &inStream);
// Restore state of simulation
void RestoreState(StateRecorderImpl &inStream);
// Compare current physics state with inExpectedState
void ValidateState(StateRecorderImpl &inExpectedState);
// Global settings
int mMaxConcurrentJobs = thread::hardware_concurrency(); // How many jobs to run in parallel
float mUpdateFrequency = 60.0f; // Physics update frequency, measured in Hz (cycles per second)
int mCollisionSteps = 1; // How many collision detection steps per physics update
TempAllocator * mTempAllocator = nullptr; // Allocator for temporary allocations
JobSystem * mJobSystem = nullptr; // The job system that runs physics jobs
JobSystem * mJobSystemValidating = nullptr; // The job system to use when validating determinism
BPLayerInterfaceImpl mBroadPhaseLayerInterface; // The broadphase layer interface that maps object layers to broadphase layers
ObjectVsBroadPhaseLayerFilterImpl mObjectVsBroadPhaseLayerFilter; // Class that filters object vs broadphase layers
ObjectLayerPairFilterImpl mObjectVsObjectLayerFilter; // Class that filters object vs object layers
PhysicsSystem * mPhysicsSystem = nullptr; // The physics system that simulates the world
ContactListenerImpl * mContactListener = nullptr; // Contact listener implementation
PhysicsSettings mPhysicsSettings; // Main physics simulation settings
// Drawing settings
#ifdef JPH_DEBUG_RENDERER
bool mDrawGetTriangles = false; // Draw all shapes using Shape::GetTrianglesStart/Next
bool mDrawConstraints = false; // If the constraints should be drawn
bool mDrawConstraintLimits = false; // If the constraint limits should be drawn
bool mDrawConstraintReferenceFrame = false; // If the constraint reference frames should be drawn
bool mDrawBroadPhaseBounds = false; // If the bounds of the broadphase should be drawn
BodyManager::DrawSettings mBodyDrawSettings; // Settings for how to draw bodies from the body manager
SkeletonPose::DrawSettings mPoseDrawSettings; // Settings for drawing skeletal poses
#endif // JPH_DEBUG_RENDERER
// Drawing using GetTriangles interface
using ShapeToGeometryMap = UnorderedMap<RefConst<Shape>, DebugRenderer::GeometryRef>;
ShapeToGeometryMap mShapeToGeometry;
// The test to run
const RTTI * mTestClass = nullptr; // RTTI information for the test we're currently running
Test * mTest = nullptr; // The test we're currently running
UITextButton * mTestSettingsButton = nullptr; // Button that activates the menu that the test uses to configure additional settings
int mShowDescription = 0; // If > 0, render the description of the test
// Automatic cycling through tests
bool mIsRunningAllTests = false; // If the user selected the 'Run All Tests' option
float mTestTimeLeft = -1.0f; // How many seconds the test is still supposed to run
bool mExitAfterRunningTests = false; // When true, the application will quit when mTestsToRun becomes empty
// Test settings
bool mInstallContactListener = false; // When true, the contact listener is installed the next time the test is reset
// State recording and determinism checks
bool mRecordState = false; // When true, the state of the physics system is recorded in mPlaybackFrames every physics update
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
struct PlayBackFrame
{
StateRecorderImpl mInputState; // State of the player inputs at the beginning of the step
StateRecorderImpl mState; // Main simulation state
};
Array<PlayBackFrame> mPlaybackFrames; // A list of recorded world states, one per physics simulation step
enum class EPlaybackMode
{
Rewind,
StepBack,
Stop,
StepForward,
FastForward,
Play
};
EPlaybackMode mPlaybackMode = EPlaybackMode::Play; // Current playback state. Indicates if we're playing or scrubbing back/forward.
int mCurrentPlaybackFrame = -1; // Current playback frame
// Which mode the probe is operating in.
enum class EProbeMode
{
Pick,
Ray,
RayCollector,
CollidePoint,
CollideShape,
CollideShapeWithInternalEdgeRemoval,
CastShape,
CollideSoftBody,
TransformedShape,
GetTriangles,
BroadPhaseRay,
BroadPhaseBox,
BroadPhaseSphere,
BroadPhasePoint,
BroadPhaseOrientedBox,
BroadPhaseCastBox,
};
// Which probe shape to use.
enum class EProbeShape
{
Sphere,
Box,
ConvexHull,
Capsule,
TaperedCapsule,
Cylinder,
Triangle,
RotatedTranslated,
StaticCompound,
StaticCompound2,
MutableCompound,
Mesh,
};
// Probe settings
EProbeMode mProbeMode = EProbeMode::Pick; // Mouse probe mode. Determines what happens under the crosshair.
EProbeShape mProbeShape = EProbeShape::Sphere; // Shape to use for the mouse probe.
bool mScaleShape = false; // If the shape is scaled or not. When true mShapeScale is taken into account.
Vec3 mShapeScale = Vec3::sOne(); // Scale in local space for the probe shape.
EBackFaceMode mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces; // How to handle back facing triangles when doing a collision probe check.
EBackFaceMode mBackFaceModeConvex = EBackFaceMode::CollideWithBackFaces; // How to handle back facing convex shapes when doing a collision probe check.
EActiveEdgeMode mActiveEdgeMode = EActiveEdgeMode::CollideOnlyWithActive; // How to handle active edges when doing a collision probe check.
ECollectFacesMode mCollectFacesMode = ECollectFacesMode::NoFaces; // If we should collect colliding faces
float mMaxSeparationDistance = 0.0f; // Max separation distance for collide shape test
bool mTreatConvexAsSolid = true; // For ray casts if the shape should be treated as solid or if the ray should only collide with the surface
bool mReturnDeepestPoint = true; // For shape casts, when true this will return the deepest point
bool mUseShrunkenShapeAndConvexRadius = false; // Shrink then expand the shape by the convex radius
bool mDrawSupportingFace = false; // Draw the result of GetSupportingFace
int mMaxHits = 10; // The maximum number of hits to request for a collision probe.
bool mClosestHitPerBody = false; // If we are only interested in the closest hit for every body
// Which object to shoot
enum class EShootObjectShape
{
Sphere,
ConvexHull,
ThinBar,
SoftBodyCube,
};
// Shoot object settings
EShootObjectShape mShootObjectShape = EShootObjectShape::Sphere; // Type of object to shoot
float mShootObjectVelocity = 20.0f; // Speed at which objects are ejected
EMotionQuality mShootObjectMotionQuality = EMotionQuality::Discrete; // Motion quality for the object that we're shooting
float mShootObjectFriction = 0.2f; // Friction for the object that is shot
float mShootObjectRestitution = 0.0f; // Restitution for the object that is shot
bool mShootObjectScaleShape = false; // If the shape should be scaled
Vec3 mShootObjectShapeScale = Vec3::sOne(); // Scale of the object to shoot
bool mWasShootKeyPressed = false; // Remembers if the shoot key was pressed last frame
// Mouse dragging
Body * mDragAnchor = nullptr; // Rigid bodies only: A anchor point for the distance constraint. Corresponds to the current crosshair position.
BodyID mDragBody; // The body ID of the body that the user is currently dragging.
Ref<Constraint> mDragConstraint; // Rigid bodies only: The distance constraint that connects the body to be dragged and the anchor point.
uint mDragVertexIndex = ~uint(0); // Soft bodies only: The vertex index of the body that the user is currently dragging.
float mDragVertexPreviousInvMass = 0.0f; // Soft bodies only: The inverse mass of the vertex that the user is currently dragging.
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.
// Timing
uint mStepNumber = 0; // Which step number we're accumulating
chrono::microseconds mTotalTime { 0 }; // How many nano seconds we spent simulating
};