230 lines
7.0 KiB
C++
230 lines
7.0 KiB
C++
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
|
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
|
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
|
|
|
#ifndef SAMPLE_STEPPER_H
|
|
#define SAMPLE_STEPPER_H
|
|
|
|
#include "SampleAllocator.h"
|
|
#include "SampleAllocatorSDKClasses.h"
|
|
#include "RendererMemoryMacros.h"
|
|
#include "task/PxTask.h"
|
|
#include "PxPhysicsAPI.h"
|
|
#include "PsTime.h"
|
|
|
|
class PhysXSample;
|
|
|
|
class Stepper: public SampleAllocateable
|
|
{
|
|
public:
|
|
Stepper() : mSample(NULL) {}
|
|
virtual ~Stepper() {}
|
|
|
|
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 postRender(const PxReal stepSize) = 0;
|
|
|
|
virtual void setSubStepper(const PxReal stepSize, const PxU32 maxSteps) {}
|
|
virtual void renderDone() {}
|
|
virtual void shutdown() {}
|
|
|
|
PxReal getSimulationTime() const { return mSimulationTime; }
|
|
|
|
PhysXSample& getSample() { return *mSample; }
|
|
const PhysXSample& getSample() const { return *mSample; }
|
|
void setSample(PhysXSample* sample) { mSample = sample; }
|
|
|
|
protected:
|
|
PhysXSample* mSample;
|
|
Ps::Time mTimer;
|
|
PxReal mSimulationTime;
|
|
|
|
};
|
|
|
|
class MultiThreadStepper;
|
|
class StepperTask : public physx::PxLightCpuTask
|
|
{
|
|
public:
|
|
void setStepper(MultiThreadStepper* stepper) { mStepper = stepper; }
|
|
MultiThreadStepper* getStepper() { return mStepper; }
|
|
const MultiThreadStepper* getStepper() const { return mStepper; }
|
|
const char* getName() const { return "Stepper Task"; }
|
|
void run();
|
|
protected:
|
|
MultiThreadStepper* mStepper;
|
|
};
|
|
|
|
class StepperTaskSimulate : public StepperTask
|
|
{
|
|
|
|
public:
|
|
StepperTaskSimulate(){}
|
|
void run();
|
|
};
|
|
|
|
class MultiThreadStepper : public Stepper
|
|
{
|
|
public:
|
|
MultiThreadStepper()
|
|
: mFirstCompletionPending(false)
|
|
, mScene(NULL)
|
|
, mSync(NULL)
|
|
, mCurrentSubStep(0)
|
|
, mNbSubSteps(0)
|
|
{
|
|
mCompletion0.setStepper(this);
|
|
mCompletion1.setStepper(this);
|
|
mSimulateTask.setStepper(this);
|
|
}
|
|
|
|
~MultiThreadStepper() {}
|
|
|
|
virtual bool advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize);
|
|
virtual void substepDone(StepperTask* ownerTask);
|
|
virtual void renderDone();
|
|
virtual void postRender(const PxReal stepSize){}
|
|
|
|
// if mNbSubSteps is 0 then the sync will never
|
|
// be set so waiting would cause a deadlock
|
|
virtual void wait(PxScene* scene) { if(mNbSubSteps && mSync)mSync->wait(); }
|
|
virtual void shutdown() { DELETESINGLE(mSync); }
|
|
virtual void reset() = 0;
|
|
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize) = 0;
|
|
virtual void simulate(physx::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;
|
|
PsSyncAlloc* mSync;
|
|
|
|
PxU32 mCurrentSubStep;
|
|
PxU32 mNbSubSteps;
|
|
PxReal mSubStepSize;
|
|
void* mScratchBlock;
|
|
PxU32 mScratchBlockSize;
|
|
};
|
|
|
|
class DebugStepper : public Stepper
|
|
{
|
|
public:
|
|
DebugStepper(const PxReal stepSize) : mStepSize(stepSize) {}
|
|
|
|
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize)
|
|
{
|
|
substepCount = 1;
|
|
substepSize = mStepSize;
|
|
}
|
|
|
|
virtual bool advance(PxScene* scene, PxReal dt, void* scratchBlock, PxU32 scratchBlockSize);
|
|
|
|
virtual void postRender(const PxReal stepSize)
|
|
{
|
|
}
|
|
|
|
virtual void setSubStepper(const PxReal stepSize, const PxU32 maxSteps)
|
|
{
|
|
mStepSize = stepSize;
|
|
}
|
|
|
|
virtual void wait(PxScene* scene);
|
|
|
|
PxReal mStepSize;
|
|
};
|
|
|
|
// 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 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
|
|
{
|
|
public:
|
|
FixedStepper(const PxReal subStepSize, const PxU32 maxSubSteps)
|
|
: MultiThreadStepper()
|
|
, mAccumulator(0)
|
|
, mFixedSubStepSize(subStepSize)
|
|
, mMaxSubSteps(maxSubSteps)
|
|
{
|
|
}
|
|
|
|
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize);
|
|
virtual void reset() { mAccumulator = 0.0f; }
|
|
|
|
virtual void setSubStepper(const PxReal stepSize, const PxU32 maxSteps) { mFixedSubStepSize = stepSize; mMaxSubSteps = maxSteps;}
|
|
|
|
virtual void postRender(const PxReal stepSize)
|
|
{
|
|
}
|
|
|
|
PxReal mAccumulator;
|
|
PxReal mFixedSubStepSize;
|
|
PxU32 mMaxSubSteps;
|
|
};
|
|
|
|
|
|
class VariableStepper : public MultiThreadStepper
|
|
{
|
|
public:
|
|
VariableStepper(const PxReal minSubStepSize, const PxReal maxSubStepSize, const PxU32 maxSubSteps)
|
|
: MultiThreadStepper()
|
|
, mAccumulator(0)
|
|
, mMinSubStepSize(minSubStepSize)
|
|
, mMaxSubStepSize(maxSubStepSize)
|
|
, mMaxSubSteps(maxSubSteps)
|
|
{
|
|
}
|
|
|
|
virtual void substepStrategy(const PxReal stepSize, PxU32& substepCount, PxReal& substepSize);
|
|
virtual void reset() { mAccumulator = 0.0f; }
|
|
|
|
private:
|
|
VariableStepper& operator=(const VariableStepper&);
|
|
PxReal mAccumulator;
|
|
const PxReal mMinSubStepSize;
|
|
const PxReal mMaxSubStepSize;
|
|
const PxU32 mMaxSubSteps;
|
|
};
|
|
#endif
|