488 lines
18 KiB
C++
488 lines
18 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-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.
|
|
|
|
#include "NpArticulationReducedCoordinate.h"
|
|
|
|
#include "CmPhysXCommon.h"
|
|
#include "DyFeatherstoneArticulation.h"
|
|
#include "ScArticulationSim.h"
|
|
#include "ScConstraintSim.h"
|
|
|
|
#include "PsAlignedMalloc.h"
|
|
#include "PsFoundation.h"
|
|
#include "PsPool.h"
|
|
|
|
#include "PxPvdDataStream.h"
|
|
#include "extensions/PxJoint.h"
|
|
|
|
using namespace physx;
|
|
|
|
class LLReducedArticulationPool : public Ps::Pool<Dy::FeatherstoneArticulation, Ps::AlignedAllocator<Dy::DY_ARTICULATION_MAX_SIZE> >
|
|
{
|
|
public:
|
|
LLReducedArticulationPool() {}
|
|
};
|
|
|
|
// PX_SERIALIZATION
|
|
NpArticulationReducedCoordinate* NpArticulationReducedCoordinate::createObject(PxU8*& address, PxDeserializationContext& context)
|
|
{
|
|
NpArticulationReducedCoordinate* obj = new (address) NpArticulationReducedCoordinate(PxBaseFlag::eIS_RELEASABLE);
|
|
address += sizeof(NpArticulationReducedCoordinate);
|
|
obj->importExtraData(context);
|
|
obj->resolveReferences(context);
|
|
return obj;
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::preExportDataReset()
|
|
{
|
|
//for now, no support for loop joint serialization
|
|
Ps::Array<PxJoint*> emptyLoopJoints;
|
|
PxMemCopy(&mLoopJoints, &emptyLoopJoints, sizeof(Ps::Array<PxJoint*>));
|
|
}
|
|
|
|
//~PX_SERIALIZATION
|
|
|
|
NpArticulationReducedCoordinate::NpArticulationReducedCoordinate()
|
|
: NpArticulationTemplate(PxConcreteType::eARTICULATION_REDUCED_COORDINATE, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
|
|
{
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::setArticulationFlags(PxArticulationFlags flags)
|
|
{
|
|
NP_WRITE_CHECK(mImpl.getOwnerScene());
|
|
mImpl.getScbArticulation().setArticulationFlags(flags);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::setArticulationFlag(PxArticulationFlag::Enum flag, bool value)
|
|
{
|
|
NP_WRITE_CHECK(mImpl.getOwnerScene());
|
|
PxArticulationFlags flags = mImpl.getScbArticulation().getArticulationFlags();
|
|
|
|
if(value)
|
|
flags |= flag;
|
|
else
|
|
flags &= (~flag);
|
|
|
|
mImpl.getScbArticulation().setArticulationFlags(flags);
|
|
}
|
|
|
|
PxArticulationFlags NpArticulationReducedCoordinate::getArticulationFlags() const
|
|
{
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
return mImpl.getScbArticulation().getArticulationFlags();
|
|
}
|
|
|
|
PxU32 NpArticulationReducedCoordinate::getDofs() const
|
|
{
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
return mImpl.mArticulation.getScArticulation().getDofs();
|
|
}
|
|
|
|
PxArticulationCache* NpArticulationReducedCoordinate::createCache() const
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(mImpl.getAPIScene(), "PxArticulation::createCache: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene()); // doesn't modify the scene, only reads
|
|
|
|
PxArticulationCache* cache = mImpl.mArticulation.getScArticulation().createCache();
|
|
cache->version = mImpl.mCacheVersion;
|
|
|
|
return cache;
|
|
}
|
|
|
|
PxU32 NpArticulationReducedCoordinate::getCacheDataSize() const
|
|
{
|
|
PX_CHECK_AND_RETURN_NULL(mImpl.getAPIScene(), "PxArticulation::getCacheDataSize: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene()); // doesn't modify the scene, only reads
|
|
|
|
return mImpl.mArticulation.getScArticulation().getCacheDataSize();
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::zeroCache(PxArticulationCache& cache)
|
|
{
|
|
NP_READ_CHECK(mImpl.getOwnerScene()); // doesn't modify the scene, only reads
|
|
return mImpl.mArticulation.getScArticulation().zeroCache(cache);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::applyCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag, bool autowake)
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::applyCache: object must be in a scene");
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::applyCache : cache is invalid, articulation configuration has changed! ")
|
|
|
|
//if we try to do a bulk op when sim is running, return with error
|
|
if (static_cast<NpScene*>(getScene())->getSimulationStage() != Sc::SimulationStage::eCOMPLETE)
|
|
{
|
|
Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
|
|
"NpArticulation::applyCache() not allowed while simulation is running.");
|
|
return;
|
|
}
|
|
|
|
mImpl.mArticulation.getScArticulation().applyCache(cache, flag);
|
|
|
|
if ((flag & PxArticulationCache::ePOSITION))
|
|
{
|
|
const PxU32 linkCount = mImpl.mArticulationLinks.size();
|
|
|
|
for (PxU32 i = 0; i < linkCount; ++i)
|
|
{
|
|
NpArticulationLink* link = mImpl.mArticulationLinks[i];
|
|
//in the lowlevel articulation, we have already updated bodyCore's body2World
|
|
const PxTransform internalPose = link->getScbBodyFast().getScBody().getBody2World();
|
|
link->getScbBodyFast().setBody2World(internalPose, false);
|
|
}
|
|
}
|
|
|
|
if ((flag & PxArticulationCache::ePOSITION) || (flag & PxArticulationCache::eVELOCITY))
|
|
{
|
|
const PxU32 linkCount = mImpl.mArticulationLinks.size();
|
|
|
|
for (PxU32 i = 0; i < linkCount; ++i)
|
|
{
|
|
NpArticulationLink* link = mImpl.mArticulationLinks[i];
|
|
//in the lowlevel articulation, we have already updated bodyCore's linear/angular velocity
|
|
const PxVec3 internalLinVel = link->getScbBodyFast().getScBody().getLinearVelocity();
|
|
const PxVec3 internalAngVel = link->getScbBodyFast().getScBody().getAngularVelocity();
|
|
link->getScbBodyFast().setLinearVelocity(internalLinVel);
|
|
link->getScbBodyFast().setAngularVelocity(internalAngVel);
|
|
}
|
|
}
|
|
|
|
mImpl.wakeUpInternal(false, autowake);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::copyInternalStateToCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::copyInternalStateToCache: object must be in a scene");
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::applyCache : cache is invalid, articulation configuration has changed! ")
|
|
|
|
mImpl.mArticulation.getScArticulation().copyInternalStateToCache(cache, flag);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::releaseCache(PxArticulationCache& cache) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::releaseCache: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene()); // doesn't modify the scene, only reads
|
|
|
|
mImpl.mArticulation.getScArticulation().releaseCache(cache);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::packJointData(const PxReal* maximum, PxReal* reduced) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::packJointData: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
mImpl.mArticulation.getScArticulation().packJointData(maximum, reduced);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::unpackJointData(const PxReal* reduced, PxReal* maximum) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::unpackJointData: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
mImpl.mArticulation.getScArticulation().unpackJointData(reduced, maximum);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::commonInit() const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::commonInit: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
mImpl.mArticulation.getScArticulation().commonInit();
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::computeGeneralizedGravityForce(PxArticulationCache& cache) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::computeGeneralisedGravityForce: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::computeGeneralisedGravityForce : cache is invalid, articulation configuration has changed! ");
|
|
|
|
mImpl.mArticulation.getScArticulation().computeGeneralizedGravityForce(cache);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::computeCoriolisAndCentrifugalForce(PxArticulationCache& cache) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::computeCoriolisAndCentrifugalForce: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::computeCoriolisAndCentrifugalForce : cache is invalid, articulation configuration has changed! ");
|
|
|
|
mImpl.mArticulation.getScArticulation().computeCoriolisAndCentrifugalForce(cache);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::computeGeneralizedExternalForce(PxArticulationCache& cache) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::computeGeneralizedExternalForce: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::computeGeneralizedExternalForce : cache is invalid, articulation configuration has changed! ");
|
|
|
|
mImpl.mArticulation.getScArticulation().computeGeneralizedExternalForce(cache);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::computeJointAcceleration(PxArticulationCache& cache) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::computeJointAcceleration: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::computeJointAcceleration : cache is invalid, articulation configuration has changed! ");
|
|
|
|
mImpl.mArticulation.getScArticulation().computeJointAcceleration(cache);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::computeJointForce(PxArticulationCache& cache) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::computeJointForce: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::computeJointForce : cache is invalid, articulation configuration has changed! ");
|
|
|
|
mImpl.mArticulation.getScArticulation().computeJointForce(cache);
|
|
}
|
|
|
|
|
|
void NpArticulationReducedCoordinate::computeDenseJacobian(PxArticulationCache& cache, PxU32& nRows, PxU32& nCols) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::computeDenseJacobian: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::computeDenseJacobian : cache is invalid, articulation configuration has changed! ");
|
|
|
|
mImpl.mArticulation.getScArticulation().computeDenseJacobian(cache, nRows, nCols);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::computeCoefficientMatrix(PxArticulationCache& cache) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::computeCoefficientMatrix: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::computeCoefficientMatrix : cache is invalid, articulation configuration has changed! ");
|
|
|
|
for (PxU32 i = 0; i < mLoopJoints.size(); ++i)
|
|
{
|
|
static_cast<NpConstraint*>(mLoopJoints[i]->getConstraint())->updateConstants();
|
|
}
|
|
|
|
mImpl.mArticulation.getScArticulation().computeCoefficientMatrix(cache);
|
|
}
|
|
|
|
bool NpArticulationReducedCoordinate::computeLambda(PxArticulationCache& cache, PxArticulationCache& initialState, const PxReal* const jointTorque, const PxU32 maxIter) const
|
|
{
|
|
if (!mImpl.getAPIScene())
|
|
{
|
|
physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxArticulation::computeLambda : object must be in a scened!");
|
|
return false;
|
|
}
|
|
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
if (cache.version != mImpl.mCacheVersion)
|
|
{
|
|
physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxArticulation::computeLambda : cache is invalid, articulation configuration has changed!");
|
|
return false;
|
|
}
|
|
|
|
return mImpl.mArticulation.getScArticulation().computeLambda(cache, initialState, jointTorque, getScene()->getGravity(), maxIter);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::computeGeneralizedMassMatrix(PxArticulationCache& cache) const
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulation::computeGeneralizedMassMatrix: object must be in a scene");
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
PX_CHECK_AND_RETURN(cache.version == mImpl.mCacheVersion, "PxArticulation::computeGeneralizedMassMatrix : cache is invalid, articulation configuration has changed! ");
|
|
|
|
mImpl.mArticulation.getScArticulation().computeGeneralizedMassMatrix(cache);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::addLoopJoint(PxJoint* joint)
|
|
{
|
|
NP_WRITE_CHECK(mImpl.getOwnerScene());
|
|
|
|
#if PX_CHECKED
|
|
|
|
PxRigidActor* actor0;
|
|
PxRigidActor* actor1;
|
|
|
|
joint->getActors(actor0, actor1);
|
|
|
|
PxArticulationLink* link0 = NULL;
|
|
PxArticulationLink* link1 = NULL;
|
|
|
|
if(actor0)
|
|
link0 = actor0->is<PxArticulationLink>();
|
|
|
|
if(actor1)
|
|
link1 = actor1->is<PxArticulationLink>();
|
|
|
|
PX_CHECK_AND_RETURN((link0 || link1), "PxArticulation::addLoopJoint : at least one of the PxRigidActors need to be PxArticulationLink! ");
|
|
|
|
|
|
PxArticulationBase* base0 = NULL;
|
|
PxArticulationBase* base1 = NULL;
|
|
if (link0)
|
|
base0 = &link0->getArticulation();
|
|
|
|
if (link1)
|
|
base1 = &link1->getArticulation();
|
|
|
|
PX_CHECK_AND_RETURN((base0 == this || base1 == this), "PxArticulation::addLoopJoint : at least one of the PxArticulationLink belongs to this articulation! ");
|
|
#endif
|
|
|
|
const PxU32 size = mLoopJoints.size();
|
|
if (size >= mLoopJoints.capacity())
|
|
{
|
|
mLoopJoints.reserve(size * 2 + 1);
|
|
}
|
|
|
|
mLoopJoints.pushBack(joint);
|
|
|
|
Scb::Articulation& scbArt = mImpl.getScbArticulation();
|
|
Sc::ArticulationSim* scArtSim = scbArt.getScArticulation().getSim();
|
|
|
|
NpConstraint* constraint = static_cast<NpConstraint*>(joint->getConstraint());
|
|
Sc::ConstraintSim* cSim = constraint->getScbConstraint().getScConstraint().getSim();
|
|
if(scArtSim)
|
|
scArtSim->addLoopConstraint(cSim);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::removeLoopJoint(PxJoint* joint)
|
|
{
|
|
NP_WRITE_CHECK(mImpl.getOwnerScene());
|
|
|
|
mLoopJoints.findAndReplaceWithLast(joint);
|
|
|
|
Scb::Articulation& scbArt = mImpl.getScbArticulation();
|
|
Sc::ArticulationSim* scArtSim = scbArt.getScArticulation().getSim();
|
|
|
|
NpConstraint* constraint = static_cast<NpConstraint*>(joint->getConstraint());
|
|
Sc::ConstraintSim* cSim = constraint->getScbConstraint().getScConstraint().getSim();
|
|
scArtSim->removeLoopConstraint(cSim);
|
|
}
|
|
|
|
PxU32 NpArticulationReducedCoordinate::getNbLoopJoints() const
|
|
{
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
return mLoopJoints.size();
|
|
}
|
|
|
|
PxU32 NpArticulationReducedCoordinate::getLoopJoints(PxJoint** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
|
|
{
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mLoopJoints.begin(), mLoopJoints.size());
|
|
}
|
|
|
|
PxU32 NpArticulationReducedCoordinate::getCoefficientMatrixSize() const
|
|
{
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
return mImpl.mArticulation.getScArticulation().getCoefficientMatrixSize();
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::teleportRootLink(const PxTransform& pose, bool autowake)
|
|
{
|
|
PX_CHECK_AND_RETURN(mImpl.getAPIScene(), "PxArticulationReducedCoordinate::teleportRootLink: object must be in a scene");
|
|
|
|
PX_CHECK_AND_RETURN(pose.isValid(), "PxArticulationReducedCoordinate::teleportRootLink pose is not valid.");
|
|
|
|
NP_WRITE_CHECK(mImpl.getOwnerScene());
|
|
|
|
NpArticulationLink* root = mImpl.mArticulationLinks[0];
|
|
|
|
root->setGlobalPoseInternal(pose, autowake);
|
|
}
|
|
|
|
PxSpatialVelocity NpArticulationReducedCoordinate::getLinkVelocity(const PxU32 linkId)
|
|
{
|
|
PX_CHECK_AND_RETURN_VAL(mImpl.getAPIScene(), "PxArticulationReducedCoordinate::getLinkVelocity: object must be in a scene", PxSpatialVelocity());
|
|
PX_CHECK_AND_RETURN_VAL(linkId < 64, "PxArticulationReducedCoordinate::getLinkVelocity index is not valid.", PxSpatialVelocity());
|
|
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
return mImpl.mArticulation.getScArticulation().getLinkVelocity(linkId);
|
|
}
|
|
|
|
PxSpatialVelocity NpArticulationReducedCoordinate::getLinkAcceleration(const PxU32 linkId)
|
|
{
|
|
PX_CHECK_AND_RETURN_VAL(mImpl.getAPIScene(), "PxArticulationReducedCoordinate::getLinkAcceleration: object must be in a scene", PxSpatialVelocity());
|
|
PX_CHECK_AND_RETURN_VAL(linkId < 64, "PxArticulationReducedCoordinate::getLinkAcceleration index is not valid.", PxSpatialVelocity());
|
|
|
|
NP_READ_CHECK(mImpl.getOwnerScene());
|
|
|
|
return mImpl.mArticulation.getScArticulation().getLinkAcceleration(linkId);
|
|
}
|
|
|
|
NpArticulationReducedCoordinate::~NpArticulationReducedCoordinate()
|
|
{
|
|
NpFactory::getInstance().onArticulationRelease(this);
|
|
}
|
|
|
|
PxArticulationJointBase* NpArticulationReducedCoordinate::createArticulationJoint(PxArticulationLink& parent,
|
|
const PxTransform& parentFrame,
|
|
PxArticulationLink& child,
|
|
const PxTransform& childFrame)
|
|
{
|
|
return NpFactory::getInstance().createNpArticulationJointRC(static_cast<NpArticulationLink&>(parent), parentFrame, static_cast<NpArticulationLink&>(child), childFrame);
|
|
}
|
|
|
|
void NpArticulationReducedCoordinate::releaseArticulationJoint(PxArticulationJointBase* joint)
|
|
{
|
|
NpFactory::getInstance().releaseArticulationJointRCToPool(*static_cast<NpArticulationJointReducedCoordinate*>(joint));
|
|
}
|
|
|
|
void PxArticulationImpl::recomputeLinkIDs()
|
|
{
|
|
PX_CHECK_AND_RETURN(getAPIScene(), "PxArticulation::recomputeLinkIDs: object must be in a scene");
|
|
NP_WRITE_CHECK(getOwnerScene());
|
|
|
|
if (!mArticulation.isBuffering())
|
|
{
|
|
Sc::ArticulationSim* scArtSim = getScbArticulation().getScArticulation().getSim();
|
|
|
|
if (scArtSim)
|
|
{
|
|
|
|
physx::NpArticulationLink*const* links = getLinks();
|
|
|
|
const PxU32 nbLinks = getNbLinks();
|
|
for (PxU32 i = 1; i < nbLinks; ++i)
|
|
{
|
|
physx::NpArticulationLink* link = links[i];
|
|
PxU32 cHandle = scArtSim->findBodyIndex(*link->getScbBodyFast().getScBody().getSim());
|
|
link->setLLIndex(cHandle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|