221
Source/Engine/Physics/PhysX/PhysicsStepperPhysX.h
Normal file
221
Source/Engine/Physics/PhysX/PhysicsStepperPhysX.h
Normal file
@@ -0,0 +1,221 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if COMPILE_WITH_PHYSX
|
||||
|
||||
#include "Types.h"
|
||||
#include <ThirdParty/PhysX/task/PxTask.h>
|
||||
#include <ThirdParty/PhysX/foundation/PxSimpleTypes.h>
|
||||
#include <ThirdParty/PhysX/foundation/PsSync.h>
|
||||
|
||||
class MultiThreadStepper;
|
||||
|
||||
class PhysicsStepper
|
||||
{
|
||||
public:
|
||||
|
||||
PhysicsStepper()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~PhysicsStepper()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual bool advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize) = 0;
|
||||
virtual void wait(PxScene* scene) = 0;
|
||||
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize) = 0;
|
||||
|
||||
virtual void setSubStepper(const PxReal stepSize, const PxU32 maxSteps)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void renderDone()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class StepperTask : public PxLightCpuTask
|
||||
{
|
||||
public:
|
||||
|
||||
void setStepper(MultiThreadStepper* stepper)
|
||||
{
|
||||
mStepper = stepper;
|
||||
}
|
||||
|
||||
MultiThreadStepper* getStepper()
|
||||
{
|
||||
return mStepper;
|
||||
}
|
||||
|
||||
const MultiThreadStepper* getStepper() const
|
||||
{
|
||||
return mStepper;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [PxLightCpuTask]
|
||||
const char* getName() const override
|
||||
{
|
||||
return "Stepper Task";
|
||||
}
|
||||
|
||||
void run() override;
|
||||
|
||||
protected:
|
||||
|
||||
MultiThreadStepper* mStepper = nullptr;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Physics simulation task used by the stepper.
|
||||
/// </summary>
|
||||
/// <seealso cref="StepperTask" />
|
||||
class StepperTaskSimulate : public StepperTask
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StepperTaskSimulate"/> class.
|
||||
/// </summary>
|
||||
StepperTaskSimulate()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [StepperTask]
|
||||
void run() override;
|
||||
};
|
||||
|
||||
class MultiThreadStepper : public PhysicsStepper
|
||||
{
|
||||
public:
|
||||
|
||||
MultiThreadStepper()
|
||||
: mFirstCompletionPending(false)
|
||||
, mScene(nullptr)
|
||||
, mSync(nullptr)
|
||||
, mCurrentSubStep(0)
|
||||
, mNbSubSteps(0)
|
||||
{
|
||||
mCompletion0.setStepper(this);
|
||||
mCompletion1.setStepper(this);
|
||||
mSimulateTask.setStepper(this);
|
||||
}
|
||||
|
||||
~MultiThreadStepper();
|
||||
|
||||
bool advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize) override;
|
||||
virtual void substepDone(StepperTask* ownerTask);
|
||||
void renderDone() override;
|
||||
|
||||
// if mNbSubSteps is 0 then the sync will never
|
||||
// be set so waiting would cause a deadlock
|
||||
void wait(PxScene* scene) override
|
||||
{
|
||||
if (mNbSubSteps && mSync)
|
||||
mSync->wait();
|
||||
}
|
||||
|
||||
virtual void shutdown();
|
||||
|
||||
virtual void reset() = 0;
|
||||
void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize) override = 0;
|
||||
virtual void simulate(PxBaseTask* ownerTask);
|
||||
|
||||
PxReal getSubStepSize() const
|
||||
{
|
||||
return mSubStepSize;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void substep(StepperTask& completionTask);
|
||||
|
||||
// we need two completion tasks because when multistepping we can't submit completion0 from the
|
||||
// substepDone function which is running inside completion0
|
||||
bool mFirstCompletionPending;
|
||||
StepperTaskSimulate mSimulateTask;
|
||||
StepperTask mCompletion0, mCompletion1;
|
||||
PxScene* mScene;
|
||||
shdfnd::Sync* mSync;
|
||||
|
||||
PxU32 mCurrentSubStep;
|
||||
PxU32 mNbSubSteps;
|
||||
PxReal mSubStepSize;
|
||||
void* mScratchBlock;
|
||||
PxU32 mScratchBlockSize;
|
||||
};
|
||||
|
||||
// The way this should be called is:
|
||||
// bool stepped = advance(dt)
|
||||
//
|
||||
// ... reads from the scene graph for rendering
|
||||
//
|
||||
// if(stepped) renderDone()
|
||||
//
|
||||
// ... anything that doesn't need access to the the physics scene
|
||||
//
|
||||
// if(stepped) sFixedStepper.wait()
|
||||
//
|
||||
// Note that per-substep callbacks to the sample need to be issued out of here,
|
||||
// between fetchResults and simulate
|
||||
|
||||
class FixedStepper : public MultiThreadStepper
|
||||
{
|
||||
protected:
|
||||
|
||||
PxReal mAccumulator;
|
||||
PxReal mFixedSubStepSize;
|
||||
PxU32 mMaxSubSteps;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FixedStepper"/> class.
|
||||
/// </summary>
|
||||
FixedStepper()
|
||||
: MultiThreadStepper()
|
||||
, mAccumulator(0)
|
||||
, mFixedSubStepSize(0.013f)
|
||||
, mMaxSubSteps(1)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Setups the specified step size and the maximum amount of them.
|
||||
/// </summary>
|
||||
/// <param name="stepSize">Size of the step (in seconds).</param>
|
||||
/// <param name="maxSubsetps">The maximum amount of subsetps.</param>
|
||||
void Setup(const float stepSize, const uint32 maxSubsetps = 1)
|
||||
{
|
||||
mFixedSubStepSize = stepSize;
|
||||
mMaxSubSteps = maxSubsetps;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// [MultiThreadStepper]
|
||||
void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize) override;
|
||||
|
||||
void reset() override
|
||||
{
|
||||
mAccumulator = 0.0f;
|
||||
}
|
||||
|
||||
void setSubStepper(const PxReal stepSize, const PxU32 maxSteps) override
|
||||
{
|
||||
mFixedSubStepSize = stepSize;
|
||||
mMaxSubSteps = maxSteps;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user