// 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-2025 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 PXS_SIMULATION_CONTROLLER_H
#define PXS_SIMULATION_CONTROLLER_H

#include "PxDirectGPUAPI.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxPreprocessor.h"
#include "foundation/PxTransform.h"
#include "foundation/PxPinnedBitMap.h"
#include "foundation/PxPinnedArray.h"
#include "foundation/PxUserAllocated.h"
#include "PxScene.h"
#include "PxParticleSystem.h"
#include "PxArticulationTendonData.h"
#include "PxNodeIndex.h"

namespace physx
{
	namespace Dy
	{
		class Context;
		struct Constraint;
		class FeatherstoneArticulation;
		struct ArticulationJointCore;
		class ParticleSystemCore;
		class ParticleSystem;
		
#if PX_SUPPORT_GPU_PHYSX
		class DeformableSurface;
		class DeformableVolume;
#endif
	}

	namespace Bp
	{
		class BoundsArray;
		class BroadPhase;
		class AABBManagerBase;
	}

	namespace IG
	{
		class IslandSim;
	}

	namespace Sc
	{
		class BodySim;
		class ShapeSimBase;
	}

	class PxsTransformCache;
	class PxvNphaseImplementationContext;
	class PxBaseTask;
	class PxsContext;

	class PxsRigidBody;
	class PxsKernelWranglerManager;
	class PxsHeapMemoryAllocatorManager;
	class PxgParticleSystemCore;
	struct PxConeLimitedConstraint;

	struct PxsShapeCore;

	class PxPhysXGpu;

	struct PxgSolverConstraintManagerConstants;
	struct PxsExternalAccelerationProvider;
	
	class PxsSimulationControllerCallback : public PxUserAllocated
	{
	public:
		virtual void	updateScBodyAndShapeSim(PxBaseTask* continuation) = 0;
		virtual PxU32	getNbCcdBodies() = 0;

		virtual ~PxsSimulationControllerCallback() {}
	};

#if PX_SUPPORT_OMNI_PVD
	class PxsSimulationControllerOVDCallbacks : public PxUserAllocated
	{
	public:
		virtual void    processRigidDynamicSet(const PxsRigidBody* const * rigids, const void* dataVec, const PxRigidDynamicGPUIndex* gpuIndices, PxRigidDynamicGPUAPIWriteType::Enum dataType, PxU32 nbElements) = 0;
		virtual void    processArticulationSet(const Dy::FeatherstoneArticulation* const * simBodyVec, const void* dataVec, const PxArticulationGPUIndex* indexVec, PxArticulationGPUAPIWriteType::Enum dataType, PxU32 nbElements,
			PxU32 maxLinks, PxU32 maxDofs, PxU32 maxFixedTendons, PxU32 maxTendonJoints, PxU32 maxSpatialTendons, PxU32 maxSpatialTendonAttachments) = 0;
		
		// Returns the number of elements in a data block as well as the size of the datablock, see PxArticulationGPUAPIWriteType::Enum for where the sizes etc are derived
		PX_FORCE_INLINE void getArticulationDataElements(PxArticulationGPUAPIWriteType::Enum dataType, PxU32 maxLinks, PxU32 maxDofs, PxU32 maxFixedTendons, PxU32 maxTendonJoints, PxU32 maxSpatialTendons, PxU32 maxSpatialTendonAttachments,
			PxU32& nbSubElements, PxU32& blockSize) const;

		virtual ~PxsSimulationControllerOVDCallbacks() {}
	};
#endif

	class PxsSimulationController : public PxUserAllocated
	{
	public:
					PxsSimulationController(PxsSimulationControllerCallback* callback, PxIntBool gpu) : mCallback(callback), mGPU(gpu)	{}
		virtual		~PxsSimulationController(){}

		virtual void addPxgShape(Sc::ShapeSimBase* /*shapeSimBase*/, const PxsShapeCore* /*shapeCore*/, PxNodeIndex /*nodeIndex*/, PxU32 /*index*/){}
		virtual void setPxgShapeBodyNodeIndex(PxNodeIndex /*nodeIndex*/, PxU32 /*index*/) {}
		virtual void removePxgShape(PxU32 /*index*/){}

		virtual void addDynamic(PxsRigidBody* /*rigidBody*/, const PxNodeIndex& /*nodeIndex*/){}
		virtual void addDynamics(PxsRigidBody** /*rigidBody*/, const PxU32* /*nodeIndex*/, PxU32 /*nbBodies*/) {}
		virtual void addArticulation(Dy::FeatherstoneArticulation* /*articulation*/, const PxNodeIndex& /*nodeIndex*/) {}
		virtual void releaseArticulation(Dy::FeatherstoneArticulation* /*articulation*/, const PxNodeIndex& /*nodeIndex*/) {}
		virtual void releaseDeferredArticulationIds() {}

#if PX_SUPPORT_GPU_PHYSX
		virtual void addSoftBody(Dy::DeformableVolume* /*deformableVolume*/, const PxNodeIndex& /*nodeIndex*/)	{}
		virtual void releaseSoftBody(Dy::DeformableVolume* /*deformableVolume*/) 	{}
		virtual void releaseDeferredSoftBodyIds() 	{}
		virtual void activateSoftbody(Dy::DeformableVolume* /*deformableVolume*/) 	{}
		virtual void deactivateSoftbody(Dy::DeformableVolume* /*deformableVolume*/) 	{}
		virtual void activateSoftbodySelfCollision(Dy::DeformableVolume* /*deformableVolume*/) 	{}
		virtual void deactivateSoftbodySelfCollision(Dy::DeformableVolume* /*deformableVolume*/) 	{}
		virtual void setSoftBodyWakeCounter(Dy::DeformableVolume* /*deformableVolume*/) 	{}

		virtual void addParticleFilter(Dy::DeformableVolume* /*deformableVolume*/, Dy::ParticleSystem* /*particleSystem*/,
			PxU32 /*particleId*/, PxU32 /*userBufferId*/, PxU32 /*tetId*/) 	{}
		virtual void removeParticleFilter(Dy::DeformableVolume* /*deformableVolume*/,
			const Dy::ParticleSystem* /*particleSystem*/, PxU32 /*particleId*/, PxU32 /*userBufferId*/, PxU32 /*tetId*/) 	{}

		virtual PxU32 addParticleAttachment(Dy::DeformableVolume* /*deformableVolume*/, const Dy::ParticleSystem* /*particleSystem*/,
			PxU32 /*particleId*/, PxU32 /*userBufferId*/, PxU32 /*tetId*/, const PxVec4& /*barycentrics*/, const bool /*isActive*/) 	{ return 0; }
		virtual void removeParticleAttachment(Dy::DeformableVolume* /*deformableVolume*/, PxU32 /*handle*/) 	{}

		virtual void addRigidFilter(Dy::DeformableVolume* /*deformableVolume*/, const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*vertIndex*/) 	{}
		virtual void removeRigidFilter(Dy::DeformableVolume* /*deformableVolume*/,
			const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*vertIndex*/) 	{}

		virtual PxU32 addRigidAttachment(Dy::DeformableVolume* /*deformableVolume*/, const PxNodeIndex& /*softBodyNodeIndex*/,
			PxsRigidBody* /*rigidBody*/, const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*vertIndex*/, const PxVec3& /*actorSpacePose*/,
			PxConeLimitedConstraint* /*constraint*/, const bool /*isActive*/, bool /*doConversion*/) 	{ return 0; }
		virtual void removeRigidAttachment(Dy::DeformableVolume* /*deformableVolume*/, PxU32 /*handle*/) 	{}

		virtual void addTetRigidFilter(Dy::DeformableVolume* /*deformableVolume*/,
			const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*tetId*/) 	{}

		virtual PxU32 addTetRigidAttachment(Dy::DeformableVolume* /*deformableVolume*/,
			PxsRigidBody* /*rigidBody*/, const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*tetIdx*/, 
			const PxVec4& /*barycentrics*/, const PxVec3& /*actorSpacePose*/, PxConeLimitedConstraint* /*constraint*/,
			const bool /*isActive*/, bool /*doConversion*/) { return 0; }

		virtual void removeTetRigidFilter(Dy::DeformableVolume* /*deformableVolume*/, 
			const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*tetId*/) 	{}

		virtual void addSoftBodyFilter(Dy::DeformableVolume* /*deformableVolume0*/, Dy::DeformableVolume* /*deformableVolume1*/, PxU32 /*tetIdx0*/, 
			PxU32 /*tetIdx1*/) 	{}
		virtual void removeSoftBodyFilter(Dy::DeformableVolume* /*deformableVolume0*/, Dy::DeformableVolume* /*deformableVolume1*/, PxU32 /*tetIdx0*/,
			PxU32 /*tetId1*/) 	{}
		virtual void addSoftBodyFilters(Dy::DeformableVolume* /*deformableVolume0*/, Dy::DeformableVolume* /*deformableVolume1*/, PxU32* /*tetIndices0*/, PxU32* /*tetIndices1*/,
			PxU32 /*tetIndicesSize*/) 	{}
		virtual void removeSoftBodyFilters(Dy::DeformableVolume* /*deformableVolume0*/, Dy::DeformableVolume* /*deformableVolume1*/, PxU32* /*tetIndices0*/, PxU32* /*tetIndices1*/,
			PxU32 /*tetIndicesSize*/) 	{}

		virtual PxU32 addSoftBodyAttachment(Dy::DeformableVolume* /*deformableVolume0*/, Dy::DeformableVolume* /*deformableVolume1*/, PxU32 /*tetIdx0*/, PxU32 /*tetIdx1*/,
			const PxVec4& /*tetBarycentric0*/, const PxVec4& /*tetBarycentric1*/,
			PxConeLimitedConstraint* /*constraint*/, PxReal /*constraintOffset*/, const bool /*isActive*/, bool /*doConversion*/) { return 0; }

		virtual void removeSoftBodyAttachment(Dy::DeformableVolume* /*deformableVolume0*/, PxU32 /*handle*/) 	{}

		virtual void addClothFilter(Dy::DeformableVolume* /*deformableVolume*/, Dy::DeformableSurface* /*deformableSurface*/, PxU32 /*triIdx*/, PxU32 /*tetIdx*/) 	{}
		virtual void removeClothFilter(Dy::DeformableVolume* /*deformableVolume*/, Dy::DeformableSurface* /*deformableSurface*/, PxU32 /*triIdx*/, PxU32 /*tetIdx*/) 	{}

		virtual void addVertClothFilter(Dy::DeformableVolume* /*deformableVolume*/, Dy::DeformableSurface* /*deformableSurface*/, PxU32 /*vertIdx*/, PxU32 /*tetIdx*/) 	{}
		virtual void removeVertClothFilter(Dy::DeformableVolume* /*deformableVolume*/, Dy::DeformableSurface* /*deformableSurface*/, PxU32 /*vertIdx*/, PxU32 /*tetIdx*/) 	{}

		virtual PxU32 addClothAttachment(Dy::DeformableVolume* /*deformableVolume*/, Dy::DeformableSurface* /*deformableSurface*/, PxU32 /*triIdx*/,
			const PxVec4& /*triBarycentric*/, PxU32 /*tetIdx*/, const PxVec4& /*tetBarycentric*/, 
			PxConeLimitedConstraint* /*constraint*/, PxReal /*constraintOffset*/,
			const bool /*isActive*/, bool /*doConversion*/) { return 0; }

		virtual void removeClothAttachment(Dy::DeformableVolume* /*deformableVolume*/,PxU32 /*handle*/) 	{}

		virtual void addFEMCloth(Dy::DeformableSurface*, const PxNodeIndex&) {}
		virtual void releaseFEMCloth(Dy::DeformableSurface*) 	{}
		virtual void releaseDeferredFEMClothIds() 	{}
		virtual void activateCloth(Dy::DeformableSurface*) 	{}
		virtual void deactivateCloth(Dy::DeformableSurface*) 	{}
		virtual void setClothWakeCounter(Dy::DeformableSurface*) 	{}

		virtual PxU32 addRigidAttachment(Dy::DeformableSurface* /*cloth*/, const PxNodeIndex& /*clothNodeIndex*/,
			PxsRigidBody* /*rigidBody*/, const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*vertIndex*/, const PxVec3& /*actorSpacePose*/,
			PxConeLimitedConstraint* /*constraint*/, const bool /*isActive*/) 	{ return 0; }
		virtual void removeRigidAttachment(Dy::DeformableSurface* /*cloth*/, PxU32 /*handle*/) 	{}

		virtual void addTriRigidFilter(Dy::DeformableSurface* /*deformableSurface*/,
			const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*triIdx*/) 	{}

		virtual void removeTriRigidFilter(Dy::DeformableSurface* /*deformableSurface*/, 
			const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*triIdx*/) 	{}

		virtual PxU32 addTriRigidAttachment(Dy::DeformableSurface* /*deformableSurface*/,
			PxsRigidBody* /*rigidBody*/, const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*triIdx*/, const PxVec4& /*barycentrics*/, 
			const PxVec3& /*actorSpacePose*/, PxConeLimitedConstraint* /*constraint*/,
			const bool /*isActive*/) { return 0; }

		virtual void removeTriRigidAttachment(Dy::DeformableSurface* /*deformableSurface*/, PxU32 /*handle*/) 	{}

		virtual void addClothFilter(Dy::DeformableSurface* /*deformableSurface0*/, Dy::DeformableSurface* /*deformableSurface1*/, PxU32 /*triIdx0*/, PxU32 /*triIdx1*/) 	{}
		virtual void removeClothFilter(Dy::DeformableSurface* /*deformableSurface0*/, Dy::DeformableSurface* /*deformableSurface1*/, PxU32 /*triIdx0*/, PxU32 /*triIdx1*/) 	{}

		virtual PxU32 addTriClothAttachment(Dy::DeformableSurface* /*deformableSurface0*/, Dy::DeformableSurface* /*deformableSurface1*/, PxU32 /*triIdx0*/, PxU32 /*triIdx1*/,
			const PxVec4& /*triBarycentric0*/, const PxVec4& /*triBarycentric1*/, const bool /*addToActive*/) { return 0; }

		virtual void removeTriClothAttachment(Dy::DeformableSurface* /*deformableSurface*/, PxU32 /*handle*/) 	{}

		virtual void addParticleSystem(Dy::ParticleSystem* /*particleSystem*/, const PxNodeIndex& /*nodeIndex*/) 	{}
		virtual void releaseParticleSystem(Dy::ParticleSystem* /*particleSystem*/) 	{}
		virtual void releaseDeferredParticleSystemIds() 	{}

#endif

		virtual void setEnableOVDReadback(bool) {}
		virtual bool getEnableOVDReadback() const { return false; }
		virtual void setEnableOVDCollisionReadback(bool) {}
		virtual bool getEnableOVDCollisionReadback() const { return false; }

#if PX_SUPPORT_OMNI_PVD
		virtual void setOVDCallbacks(PxsSimulationControllerOVDCallbacks& /*ovdCallbacks*/) {}
#endif

		virtual void updateDynamic(Dy::FeatherstoneArticulation* /*articulation*/, const PxNodeIndex& /*nodeIndex*/) {}
		virtual void addJoint(const Dy::Constraint&) {}
		virtual void updateJoint(const PxU32 /*edgeIndex*/, Dy::Constraint* /*constraint*/){}
		virtual void updateBodies(PxsRigidBody** /*rigidBodies*/, PxU32* /*nodeIndices*/, const PxU32 /*nbBodies*/, PxsExternalAccelerationProvider* /*externalAccelerations*/) {}
//		virtual void updateBody(PxsRigidBody* /*rigidBody*/, const PxU32 /*nodeIndex*/) {}
		virtual void updateBodies(PxBaseTask* /*continuation*/){}
		virtual void updateShapes(PxBaseTask* /*continuation*/) {}
		virtual	void preIntegrateAndUpdateBound(PxBaseTask* /*continuation*/, const PxVec3 /*gravity*/, const PxReal /*dt*/){}
		virtual void updateParticleSystemsAndSoftBodies(){}
		virtual void sortContacts(){}
		virtual void update(PxBitMapPinned& /*changedHandleMap*/){}
		virtual void updateArticulation(Dy::FeatherstoneArticulation* /*articulation*/, const PxNodeIndex& /*nodeIndex*/) {}
		virtual void updateArticulationJoint(Dy::FeatherstoneArticulation* /*articulation*/, const PxNodeIndex& /*nodeIndex*/) {}
//		virtual void updateArticulationTendon(Dy::FeatherstoneArticulation* /*articulation*/, const PxNodeIndex& /*nodeIndex*/) {}
		virtual void updateArticulationExtAccel(Dy::FeatherstoneArticulation* /*articulation*/, const PxNodeIndex& /*nodeIndex*/) {}
		virtual void updateArticulationAfterIntegration(PxsContext*	/*llContext*/, Bp::AABBManagerBase* /*aabbManager*/,
			PxArray<Sc::BodySim*>& /*ccdBodies*/, PxBaseTask* /*continuation*/, IG::IslandSim& /*islandSim*/, float /*dt*/)	{}

		virtual void mergeChangedAABBMgHandle() {}
		virtual void gpuDmabackData(PxsTransformCache& /*cache*/, Bp::BoundsArray& /*boundArray*/, PxBitMapPinned& /*changedAABBMgrHandles*/, bool /*enableDirectGPUAPI*/){}
		virtual void	updateScBodyAndShapeSim(PxsTransformCache& cache, Bp::BoundsArray& boundArray, PxBaseTask* continuation) = 0;
		virtual PxU32* getActiveBodies()		{ return NULL;	}
		virtual PxU32* getDeactiveBodies()		{ return NULL;	}
		virtual void** getRigidBodies()			{ return NULL;	}
		virtual PxU32	getNbBodies()			{ return 0;	}

		virtual PxU32*	getUnfrozenShapes()		{ return NULL;	}
		virtual PxU32*	getFrozenShapes()		{ return NULL;	}
		virtual Sc::ShapeSimBase** getShapeSims()	{ return NULL;	}
		virtual PxU32	getNbFrozenShapes()		{ return 0;	}
		virtual PxU32	getNbUnfrozenShapes()	{ return 0;	}
		virtual PxU32	getNbShapes()			{ return 0;	}

		virtual void	clear() { }
		virtual void	setBounds(Bp::BoundsArray* /*boundArray*/){}
		virtual void	reserve(const PxU32 /*nbBodies*/) {}

		virtual PxU32   getArticulationRemapIndex(const PxU32 /*nodeIndex*/) { return PX_INVALID_U32;}

		//KS - the methods below here should probably be wrapped in if PX_SUPPORT_GPU_PHYSX
		// PT: isn't the whole class only needed for GPU anyway?
		// AD: Yes.

		virtual void 	setDeformableSurfaceGpuPostSolveCallback(PxPostSolveCallback* /*postSolveCallback*/) { }
		virtual void 	setDeformableVolumeGpuPostSolveCallback(PxPostSolveCallback* /*postSolveCallback*/) { }

		// NEW DIRECT-GPU API

		virtual bool	getRigidDynamicData(void* /*data*/, const PxRigidDynamicGPUIndex* /*gpuIndices*/, PxRigidDynamicGPUAPIReadType::Enum /*dataType*/, PxU32 /*nbElements*/, float /*oneOverDt*/, CUevent /*startEvent*/, CUevent /*finishEvent*/) const { return false; }
		virtual bool 	setRigidDynamicData(const void* /*data*/, const PxRigidDynamicGPUIndex* /*gpuIndices*/, PxRigidDynamicGPUAPIWriteType::Enum /*dataType*/, PxU32 /*nbElements*/, CUevent /*startEvent*/, CUevent /*finishEvent*/) { return false; }

		virtual bool 	getArticulationData(void* /*data*/, const PxArticulationGPUIndex* /*gpuIndices*/, PxArticulationGPUAPIReadType::Enum /*dataType*/, PxU32 /*nbElements*/, CUevent /*startEvent*/, CUevent /*finishEvent*/) const { return false; }
		virtual bool 	setArticulationData(const void* /*data*/, const PxArticulationGPUIndex* /*gpuIndices*/, PxArticulationGPUAPIWriteType::Enum /*dataType*/, PxU32 /*nbElements*/, CUevent /*startEvent*/, CUevent /*finishEvent*/) { return false; }
		virtual	bool	computeArticulationData(void* /*data*/, const PxArticulationGPUIndex* /*gpuIndices*/, PxArticulationGPUAPIComputeType::Enum /*operation*/, PxU32 /*nbElements*/, CUevent /*startEvent*/, CUevent /*finishEvent*/) { return false; }

		virtual bool 	evaluateSDFDistances(PxVec4* /*localGradientAndSDFConcatenated*/, const PxShapeGPUIndex* /*shapeIndices*/, const PxVec4* /*localSamplePointsConcatenated*/, const PxU32* /*samplePointCountPerShape*/, PxU32 /*nbElements*/, PxU32 /*maxPointCount*/, CUevent /*startEvent = NULL*/, CUevent /*finishEvent = NULL*/) { return false; }
		virtual	bool	copyContactData(void* /*data*/, PxU32* /*numContactPairs*/, const PxU32 /*maxContactPairs*/, CUevent /*startEvent*/, CUevent /*copyEvent*/) { return false; }

		virtual PxArticulationGPUAPIMaxCounts getArticulationGPUAPIMaxCounts()	const	{ return PxArticulationGPUAPIMaxCounts(); }

		virtual	bool	getD6JointData(void* /*data*/, const PxD6JointGPUIndex* /*gpuIndices*/, PxD6JointGPUAPIReadType::Enum /*dataType*/, PxU32 /*nbElements*/, PxF32 /*oneOverDt*/, CUevent /*startEvent*/, CUevent /*finishEvent*/) const { return false; }

		// END NEW DIRECT-GPU API

		// DEPRECATED DIRECT-GPU API

		PX_DEPRECATED virtual	void	copySoftBodyDataDEPRECATED(void** /*data*/, void* /*dataSizes*/, void* /*softBodyIndices*/, PxSoftBodyGpuDataFlag::Enum /*flag*/, const PxU32 /*nbCopySoftBodies*/, const PxU32 /*maxSize*/, CUevent /*copyEvent*/) {}
		PX_DEPRECATED virtual	void	applySoftBodyDataDEPRECATED(void** /*data*/, void* /*dataSizes*/, void* /*softBodyIndices*/, PxSoftBodyGpuDataFlag::Enum /*flag*/, const PxU32 /*nbUpdatedSoftBodies*/, const PxU32 /*maxSize*/, CUevent /*applyEvent*/, CUevent /*signalEvent*/) {}
		PX_DEPRECATED virtual 	void	applyParticleBufferDataDEPRECATED(const PxU32* /*indices*/, const PxGpuParticleBufferIndexPair* /*indexPairs*/, const PxParticleBufferFlags* /*flags*/, PxU32 /*nbUpdatedBuffers*/, CUevent /*waitEvent*/, CUevent /*signalEvent*/) {}

		// END DEPRECATED DIRECT-GPU API

		virtual	PxU32	getInternalShapeIndex(const PxsShapeCore& /*shapeCore*/)	{ return PX_INVALID_U32;	}

		virtual void	syncParticleData()	{}

		virtual void    updateBoundsAndShapes(Bp::AABBManagerBase& /*aabbManager*/, bool /*useDirectApi*/){}

#if PX_SUPPORT_GPU_PHYSX
		virtual PxU32					getNbDeactivatedDeformableSurfaces()	const	{ return 0;		}
		virtual PxU32					getNbActivatedDeformableSurfaces()		const	{ return 0;		}

		virtual Dy::DeformableSurface**	getDeactivatedDeformableSurfaces()		const	{ return NULL;	}
		virtual Dy::DeformableSurface**	getActivatedDeformableSurfaces()		const	{ return NULL;	}

		virtual PxU32					getNbDeactivatedDeformableVolumes()		const	{ return 0;		}
		virtual PxU32					getNbActivatedDeformableVolumes()		const	{ return 0;		}

		virtual Dy::DeformableVolume**	getDeactivatedDeformableVolumes()		const	{ return NULL;	}
		virtual Dy::DeformableVolume**	getActivatedDeformableVolumes()			const	{ return NULL;	}

		virtual const PxReal*			getDeformableVolumeWakeCounters()		const	{ return NULL; }

		virtual bool					hasDeformableSurfaces()					const	{ return false;	}
		virtual bool					hasDeformableVolumes()					const	{ return false;	}
#endif

	protected:
		PxsSimulationControllerCallback*	mCallback;
	public:
		const PxIntBool						mGPU;	// PT: true for GPU version, used to quickly skip calls for CPU version
	};

#if PX_SUPPORT_OMNI_PVD
	PX_FORCE_INLINE void PxsSimulationControllerOVDCallbacks::getArticulationDataElements(PxArticulationGPUAPIWriteType::Enum dataType, PxU32 maxLinks, PxU32 maxDofs, PxU32 maxFixedTendons, PxU32 maxTendonJoints, PxU32 maxSpatialTendons, PxU32 maxSpatialTendonAttachments,
		PxU32& nbSubElements, PxU32& blockSize) const
	{
		PxU32 singleSubElementSize = 0;
		switch(dataType)
		{
		case PxArticulationGPUAPIWriteType::eJOINT_POSITION:
		case PxArticulationGPUAPIWriteType::eJOINT_VELOCITY:
		case PxArticulationGPUAPIWriteType::eJOINT_FORCE:
		case PxArticulationGPUAPIWriteType::eJOINT_TARGET_VELOCITY:
		case PxArticulationGPUAPIWriteType::eJOINT_TARGET_POSITION:
		{
			nbSubElements = maxDofs;
			singleSubElementSize = sizeof(PxReal);
			break;
		}
		case PxArticulationGPUAPIWriteType::eROOT_GLOBAL_POSE:
		{
			nbSubElements = 1;
			singleSubElementSize = sizeof(PxTransform);
			break;
		}
		case PxArticulationGPUAPIWriteType::eROOT_LINEAR_VELOCITY:
		case PxArticulationGPUAPIWriteType::eROOT_ANGULAR_VELOCITY:
		{
			nbSubElements = 1;
			singleSubElementSize = sizeof(PxVec3);
			break;
		}
		case PxArticulationGPUAPIWriteType::eLINK_FORCE:
		case PxArticulationGPUAPIWriteType::eLINK_TORQUE:
		{
			nbSubElements = maxLinks;
			singleSubElementSize = sizeof(PxVec3);
			break;
		}
		case PxArticulationGPUAPIWriteType::eFIXED_TENDON:
		{
			nbSubElements = maxFixedTendons;
			singleSubElementSize = sizeof(PxGpuFixedTendonData);
			break;
		}
		case PxArticulationGPUAPIWriteType::eFIXED_TENDON_JOINT:
		{
			nbSubElements = maxFixedTendons * maxTendonJoints;
			singleSubElementSize = sizeof(PxGpuTendonJointCoefficientData);
			break;
		}
		case PxArticulationGPUAPIWriteType::eSPATIAL_TENDON:
		{
			nbSubElements = maxSpatialTendons;
			singleSubElementSize = sizeof(PxGpuSpatialTendonData);
			break;
		}
		case PxArticulationGPUAPIWriteType::eSPATIAL_TENDON_ATTACHMENT:
		{
			nbSubElements = maxSpatialTendons * maxSpatialTendonAttachments;
			singleSubElementSize = sizeof(PxGpuTendonAttachmentData);
			break;
		}
		default:
			PX_ALWAYS_ASSERT();
			nbSubElements = 0;
			singleSubElementSize = 0;
			break;
		}
		blockSize = singleSubElementSize * nbSubElements;
	}
#endif

}

#endif
