Revision control

++ // Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
++ // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
++ // SPDX-FileCopyrightText: Copyright (c) 2008-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
++ // SPDX-License-Identifier: Apache-2.0
++
++ #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 "CmPinnableArray.h"
++ #include "CmPinnableBitMap.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;
++
++ struct PxsShapeCore;
++
++ 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 PxU32 addRigidAttachment(Dy::DeformableVolume* /*deformableVolume*/, const PxNodeIndex& /*softBodyNodeIndex*/,
++ PxsRigidBody* /*rigidBody*/, const PxNodeIndex& /*rigidNodeIndex*/, PxU32 /*vertIndex*/, const PxVec3& /*actorSpacePose*/,
++ 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*/,
++ 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*/,
++ 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*/,
++ 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*/,
++ 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*/,
++ 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*/) {}
++ // Read back and emit to OVD the force/torque the given rigid dynamics hold on the GPU, for a
++ // full-state snapshot (late attach). gpuIndices are PxRigidDynamic node indices. No-op on CPU.
++ virtual void ovdSnapshotRigidDynamicForces(const PxRigidDynamicGPUIndex* /*gpuIndices*/, PxU32 /*nbElements*/) {}
++ // Same, for articulation link force/torque set through the direct-GPU articulation API. gpuIndices
++ // are PxArticulationReducedCoordinate GPU indices. No-op on CPU.
++ virtual void ovdSnapshotArticulationForces(const PxArticulationGPUIndex* /*gpuIndices*/, PxU32 /*nbElements*/) {}
++ #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(Cm::PinnableBitMap& /*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*/, bool /*isSleepingDisabled*/) {}
++
++ virtual void mergeChangedAABBMgHandle() {}
++ virtual void gpuDmabackData(PxsTransformCache& /*cache*/, Bp::BoundsArray& /*boundArray*/, Cm::PinnableBitMap& /*changedAABBMgrHandles*/, bool /*enableDirectGPUAPI*/){}
++ virtual void updateScBodyAndShapeSim(PxsTransformCache& cache, Bp::BoundsArray& boundArray, PxBaseTask* continuation) = 0;
++
++ // PdHC: Returns pointer to GPU-computed rigid body accelerations, or NULL if not available.
++ // Accelerations are computed on GPU using velocity-delta in gpuMemDmaBack for both
++ // DirectGPU and non-DirectGPU (CPU Frontend + GPU Backend) modes.
++ // GPU implementations (PxgSimulationController) provide actual data; CPU implementations return NULL.
++ virtual const void* getRigidBodyAccelerations() const { return NULL; }
++
++ 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*/, 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
++
++
++ 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