// // 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-2019 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 PXDV_ARTICULATION_H #define PXDV_ARTICULATION_H #include "foundation/PxVec3.h" #include "foundation/PxQuat.h" #include "foundation/PxTransform.h" #include "PsVecMath.h" #include "PsUtilities.h" #include "CmUtils.h" #include "CmSpatialVector.h" #include "PxArticulationJoint.h" #include "PxArticulation.h" #include "foundation/PxMemory.h" #include "DyArticulationCore.h" #include "DyArticulationJointCore.h" namespace physx { struct PxsBodyCore; class PxsConstraintBlockManager; class PxsContactManagerOutputIterator; struct PxSolverConstraintDesc; struct PxSolverBodyData; class PxContactJoint; struct PxTGSSolverBodyData; struct PxTGSSolverBodyTxInertia; struct PxSolverConstraintDesc; namespace Dy { struct SpatialSubspaceMatrix; struct ConstraintWriteback; class ThreadContext; static const size_t DY_ARTICULATION_MAX_SIZE = 64; class ArticulationJointCoreData; struct Constraint; class Context; struct ArticulationJointCore : public ArticulationJointCoreBase { //= ATTENTION! ===================================================================================== // Changing the data layout of this class breaks the binary serialization format. See comments for // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION // accordingly. //================================================================================================== // drive model PxQuat targetPosition; PxVec3 targetVelocity; PxReal spring;//old PxReal damping;//old PxReal internalCompliance;//old PxReal externalCompliance;//old // limit model PxReal swingLimitContactDistance;//old PxReal tangentialStiffness;//old PxReal tangentialDamping;//old bool swingLimited;//old bool twistLimited;//old PxU8 driveType; //both PxReal twistLimitContactDistance; //old PxReal tanQSwingY;//old PxReal tanQSwingZ;//old PxReal tanQSwingPad;//old PxReal tanQTwistHigh;//old PxReal tanQTwistLow;//old PxReal tanQTwistPad;//old ArticulationJointCore() { //Cm::markSerializedMem(this, sizeof(ArticulationJointCore)); parentPose = PxTransform(PxIdentity); childPose = PxTransform(PxIdentity); internalCompliance = 0.0f; externalCompliance = 0.0f; swingLimitContactDistance = 0.05f; twistLimitContactDistance = 0.05f; driveType = PxArticulationJointDriveType::eTARGET; jointType = PxArticulationJointType::eFIX; for(PxU32 i=0; i static size_t sizeof16() { return (sizeof(T) + 15)&~15; } template T* alloc(PxU32 count) { size_t s = sizeof16(); PX_ASSERT(taken + s*count <= size); T* result = reinterpret_cast(base + taken); taken += s*count; return result; } }; static const size_t DY_ARTICULATION_IDMASK = DY_ARTICULATION_MAX_SIZE - 1; #if PX_VC #pragma warning(push) #pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value. #endif PX_ALIGN_PREFIX(64) class ArticulationV { PX_NOCOPY(ArticulationV) public: enum Enum { eReducedCoordinate = 0, eMaximumCoordinate = 1 }; ArticulationV(void* userData, Enum type) : mUserData (userData), mContext (NULL), mType (type), mUpdateSolverData (true), mDirty (false), mMaxDepth (0) {} virtual ~ArticulationV() {} virtual void onUpdateSolverDesc() {} virtual bool resize(const PxU32 linkCount); virtual void addBody() { mAcceleration.pushBack(Cm::SpatialVector(PxVec3(0.f), PxVec3(0.f))); mUpdateSolverData = true; } virtual void removeBody() { mUpdateSolverData = true; } PX_FORCE_INLINE bool updateSolverData() { return mUpdateSolverData; } PX_FORCE_INLINE void setDirty(const bool dirty) { mDirty = dirty; } PX_FORCE_INLINE bool getDirty() const { return mDirty; } PX_FORCE_INLINE PxU32 getMaxDepth() const { return mMaxDepth; } PX_FORCE_INLINE void setMaxDepth(const PxU32 depth) { mMaxDepth = depth; } // solver methods PX_FORCE_INLINE PxU32 getBodyCount() const { return mSolverDesc.linkCount; } PX_FORCE_INLINE PxU32 getSolverDataSize() const { return mSolverDesc.solverDataSize; } PX_FORCE_INLINE PxU32 getTotalDataSize() const { return mSolverDesc.totalDataSize; } PX_FORCE_INLINE void getSolverDesc(ArticulationSolverDesc& d) const { d = mSolverDesc; } PX_FORCE_INLINE ArticulationSolverDesc& getSolverDesc() { return mSolverDesc; } PX_FORCE_INLINE const ArticulationCore* getCore() const { return mSolverDesc.core; } PX_FORCE_INLINE PxU16 getIterationCounts() const { return mSolverDesc.core->solverIterationCounts; } PX_FORCE_INLINE void* getUserData() const { return mUserData; } PX_FORCE_INLINE PxU32 getType() const { return mType; } PX_FORCE_INLINE void setDyContext(Dy::Context* context) { mContext = context; } // get data sizes for allocation at higher levels virtual void getDataSizes(PxU32 linkCount, PxU32& solverDataSize, PxU32& totalSize, PxU32& scratchSize) = 0; virtual PxU32 getDofs() { return 0; } virtual PxU32 getDof(const PxU32 /*linkID*/) { return 0; } virtual bool applyCache(PxArticulationCache& /*cache*/, const PxArticulationCacheFlags /*flag*/) {return false;} virtual void copyInternalStateToCache(PxArticulationCache&/* cache*/, const PxArticulationCacheFlags /*flag*/) {} virtual void packJointData(const PxReal* /*maximum*/, PxReal* /*reduced*/) {} virtual void unpackJointData(const PxReal* /*reduced*/, PxReal* /*maximum*/) {} virtual void initializeCommonData() {} virtual void getGeneralizedGravityForce(const PxVec3& /*gravity*/, PxArticulationCache& /*cache*/) {} virtual void getCoriolisAndCentrifugalForce(PxArticulationCache& /*cache*/) {} virtual void getGeneralizedExternalForce(PxArticulationCache& /*cache*/) {} virtual void getJointAcceleration(const PxVec3& /*gravity*/, PxArticulationCache& /*cache*/){} virtual void getJointForce(PxArticulationCache& /*cache*/){} virtual void getCoefficientMatrix(const PxReal /*dt*/, const PxU32 /*linkID*/, const PxContactJoint* /*joints*/, const PxU32 /*nbContacts*/, PxArticulationCache& /*cache*/){} virtual void getDenseJacobian(PxArticulationCache& /*cache*/, PxU32&, PxU32&) {} virtual void getCoefficientMatrixWithLoopJoints(ArticulationLoopConstraint* /*lConstraints*/, const PxU32 /*nbJoints*/, PxArticulationCache& /*cache*/) {} virtual bool getLambda( ArticulationLoopConstraint* /*lConstraints*/, const PxU32 /*nbJoints*/, PxArticulationCache& /*cache*/, PxArticulationCache& /*initialState*/, const PxReal* /*jointTorque*/, const PxVec3& /*gravity*/, const PxU32 /*maxIter*/) { return false; } virtual void getGeneralizedMassMatrix(PxArticulationCache& /*cache*/){} virtual void getGeneralizedMassMatrixCRB(PxArticulationCache& /*cache*/){} virtual void teleportRootLink(){} virtual void getImpulseResponse( PxU32 linkID, Cm::SpatialVectorF* Z, const Cm::SpatialVector& impulse, Cm::SpatialVector& deltaV) const = 0; virtual void getImpulseResponse( PxU32 linkID, Cm::SpatialVectorV* Z, const Cm::SpatialVectorV& impulse, Cm::SpatialVectorV& deltaV) const = 0; virtual void getImpulseSelfResponse( PxU32 linkID0, PxU32 linkID1, Cm::SpatialVectorF* Z, const Cm::SpatialVector& impulse0, const Cm::SpatialVector& impulse1, Cm::SpatialVector& deltaV0, Cm::SpatialVector& deltaV1) const = 0; virtual Cm::SpatialVectorV getLinkVelocity(const PxU32 linkID) const = 0; virtual Cm::SpatialVectorV getLinkMotionVector(const PxU32 linkID) const = 0; virtual PxReal getLinkMaxPenBias(const PxU32 linkID) const = 0; virtual void pxcFsApplyImpulse( PxU32 linkID, Ps::aos::Vec3V linear, Ps::aos::Vec3V angular, Cm::SpatialVectorF* Z, Cm::SpatialVectorF* deltaV) = 0; virtual void pxcFsApplyImpulses( PxU32 linkID, const Ps::aos::Vec3V& linear, const Ps::aos::Vec3V& angular, PxU32 linkID2, const Ps::aos::Vec3V& linear2, const Ps::aos::Vec3V& angular2, Cm::SpatialVectorF* Z, Cm::SpatialVectorF* deltaV) = 0; virtual void solveInternalConstraints(const PxReal dt, const PxReal invDt, Cm::SpatialVectorF* impulses, Cm::SpatialVectorF* DeltaV, bool velIteration, bool isTGS, const PxReal elapsedTime) = 0; virtual void writebackInternalConstraints(bool isTGS) = 0; virtual void prepareStaticConstraints(const PxReal /*dt*/, const PxReal /*invDt*/, PxsContactManagerOutputIterator& /*outputs*/, ThreadContext& /*threadContext*/, PxReal /*correlationDist*/, PxReal /*bounceThreshold*/, PxReal /*frictionOffsetThreshold*/, PxReal /*solverOffsetSlop*/, PxReal /*ccdMaxSeparation*/, PxSolverBodyData* /*solverBodyData*/, PxsConstraintBlockManager& /*blockManager*/, Dy::ConstraintWriteback* /*constraintWritebackPool*/) {} virtual void prepareStaticConstraintsTGS(const PxReal /*stepDt*/, const PxReal /*totalDt*/, const PxReal /*invStepDt*/, const PxReal /*invTotalDt*/, PxsContactManagerOutputIterator& /*outputs*/, ThreadContext& /*threadContext*/, PxReal /*correlationDist*/, PxReal /*bounceThreshold*/, PxReal /*frictionOffsetThreshold*/, PxTGSSolverBodyData* /*solverBodyData*/, PxTGSSolverBodyTxInertia* /*txInertia*/, PxsConstraintBlockManager& /*blockManager*/, Dy::ConstraintWriteback* /*constraintWritebackPool*/, const PxU32 /*nbSubsteps*/, const PxReal /*lengthScale*/) {} virtual void pxcFsGetVelocities(PxU32 linkID, PxU32 linkID1, Cm::SpatialVectorV& v0, Cm::SpatialVectorV& v1) = 0; virtual Cm::SpatialVectorV pxcFsGetVelocity(PxU32 linkID) = 0; virtual Cm::SpatialVectorV pxcFsGetVelocityTGS(PxU32 linkID) = 0; virtual const PxTransform& getCurrentTransform(PxU32 linkID) const= 0; virtual const PxQuat& getDeltaQ(PxU32 linkID) const = 0; virtual bool storeStaticConstraint(const PxSolverConstraintDesc& /*desc*/) { return false; } virtual bool willStoreStaticConstraint() { return false; } //this is called by island gen to determine whether the articulation should be awake or sleep virtual Cm::SpatialVector getMotionVelocity(const PxU32 linkID) const = 0; virtual Cm::SpatialVector getMotionAcceleration(const PxU32 linkID) const = 0; void setupLinks(PxU32 nbLinks, Dy::ArticulationLink* links) { //if this is needed, we need to re-allocated the link data resize(nbLinks); getSolverDesc().links = links; getSolverDesc().linkCount = Ps::to8(nbLinks); //if this is needed, we need to re-allocated the joint data onUpdateSolverDesc(); } virtual void fillIndexedManager(const PxU32 linkId, Dy::ArticulationLinkHandle& handle, PxU8& indexType) = 0; //These variables are used in the constraint partition PxU16 maxSolverFrictionProgress; PxU16 maxSolverNormalProgress; PxU32 solverProgress; PxU8 numTotalConstraints; protected: void* mUserData; Dy::Context* mContext; PxU32 mType; ArticulationSolverDesc mSolverDesc; Ps::Array mAcceleration; // supplied by Sc-layer to feed into articulations bool mUpdateSolverData; bool mDirty; //any of links update configulations, the boolean will be set to true PxU32 mMaxDepth; } PX_ALIGN_SUFFIX(64); #if PX_VC #pragma warning(pop) #endif PX_FORCE_INLINE ArticulationV* getArticulation(ArticulationLinkHandle handle) { return reinterpret_cast(handle & ~DY_ARTICULATION_IDMASK); } PX_FORCE_INLINE bool isArticulationRootLink(ArticulationLinkHandle handle) { return !(handle & DY_ARTICULATION_IDMASK); } PX_FORCE_INLINE PxU32 getLinkIndex(ArticulationLinkHandle handle) { return PxU32(handle&DY_ARTICULATION_IDMASK); } } } #endif