MultiThreaded Demo:
- fixing various race conditions throughout (usage of static vars, etc)
- addition of a few lightweight mutexes (which are compiled out by default)
- slight code rearrangement in discreteDynamicsWorld to facilitate multithreading
- PoolAllocator::allocate() can now be called when pool is full without
crashing (null pointer returned)
- PoolAllocator allocate and freeMemory, are OPTIONALLY threadsafe
(default is un-threadsafe)
- CollisionDispatcher no longer checks if the pool allocator is full
before calling allocate(), instead it just calls allocate() and
checks if the return is null -- this avoids a race condition
- SequentialImpulseConstraintSolver OPTIONALLY uses different logic in
getOrInitSolverBody() to avoid a race condition with kinematic bodies
- addition of 2 classes which together allow simulation islands to be run
in parallel:
- btSimulationIslandManagerMt
- btDiscreteDynamicsWorldMt
- MultiThreadedDemo example in the example browser demonstrating use of
OpenMP, Microsoft PPL, and Intel TBB
- use multithreading for other demos
- benchmark demo: add parallel raycasting
This commit is contained in:
@@ -21,6 +21,7 @@ SET(BulletDynamics_SRCS
|
||||
ConstraintSolver/btTypedConstraint.cpp
|
||||
ConstraintSolver/btUniversalConstraint.cpp
|
||||
Dynamics/btDiscreteDynamicsWorld.cpp
|
||||
Dynamics/btDiscreteDynamicsWorldMt.cpp
|
||||
Dynamics/btRigidBody.cpp
|
||||
Dynamics/btSimpleDynamicsWorld.cpp
|
||||
# Dynamics/Bullet-C-API.cpp
|
||||
@@ -70,6 +71,7 @@ SET(ConstraintSolver_HDRS
|
||||
SET(Dynamics_HDRS
|
||||
Dynamics/btActionInterface.h
|
||||
Dynamics/btDiscreteDynamicsWorld.h
|
||||
Dynamics/btDiscreteDynamicsWorldMt.h
|
||||
Dynamics/btDynamicsWorld.h
|
||||
Dynamics/btSimpleDynamicsWorld.h
|
||||
Dynamics/btRigidBody.h
|
||||
|
||||
@@ -716,8 +716,64 @@ btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionCon
|
||||
|
||||
int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body,btScalar timeStep)
|
||||
{
|
||||
#if BT_THREADSAFE
|
||||
int solverBodyId = -1;
|
||||
if ( !body.isStaticOrKinematicObject() )
|
||||
{
|
||||
// dynamic body
|
||||
// Dynamic bodies can only be in one island, so it's safe to write to the companionId
|
||||
solverBodyId = body.getCompanionId();
|
||||
if ( solverBodyId < 0 )
|
||||
{
|
||||
if ( btRigidBody* rb = btRigidBody::upcast( &body ) )
|
||||
{
|
||||
solverBodyId = m_tmpSolverBodyPool.size();
|
||||
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
||||
initSolverBody( &solverBody, &body, timeStep );
|
||||
body.setCompanionId( solverBodyId );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( body.isStaticObject() )
|
||||
{
|
||||
// all fixed bodies (inf mass) get mapped to a single solver id
|
||||
if ( m_fixedBodyId < 0 )
|
||||
{
|
||||
m_fixedBodyId = m_tmpSolverBodyPool.size();
|
||||
btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
|
||||
initSolverBody( &fixedBody, 0, timeStep );
|
||||
}
|
||||
solverBodyId = m_fixedBodyId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// kinematic
|
||||
// Kinematic bodies can be in multiple islands at once, so it is a
|
||||
// race condition to write to them, so we use an alternate method
|
||||
// to record the solverBodyId
|
||||
int uniqueId = body.getUniqueId();
|
||||
const int INVALID_SOLVER_BODY_ID = -1;
|
||||
if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
|
||||
{
|
||||
m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
|
||||
}
|
||||
solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ];
|
||||
// if no table entry yet,
|
||||
if ( solverBodyId == INVALID_SOLVER_BODY_ID )
|
||||
{
|
||||
// create a table entry for this body
|
||||
btRigidBody* rb = btRigidBody::upcast( &body );
|
||||
solverBodyId = m_tmpSolverBodyPool.size();
|
||||
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
|
||||
initSolverBody( &solverBody, &body, timeStep );
|
||||
m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId;
|
||||
}
|
||||
}
|
||||
btAssert( solverBodyId < m_tmpSolverBodyPool.size() );
|
||||
return solverBodyId;
|
||||
#else // BT_THREADSAFE
|
||||
|
||||
int solverBodyIdA = -1;
|
||||
int solverBodyIdA = -1;
|
||||
|
||||
if (body.getCompanionId() >= 0)
|
||||
{
|
||||
@@ -749,6 +805,7 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
|
||||
}
|
||||
|
||||
return solverBodyIdA;
|
||||
#endif // BT_THREADSAFE
|
||||
|
||||
}
|
||||
#include <stdio.h>
|
||||
@@ -1263,7 +1320,9 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
||||
{
|
||||
bodies[i]->setCompanionId(-1);
|
||||
}
|
||||
|
||||
#if BT_THREADSAFE
|
||||
m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 );
|
||||
#endif // BT_THREADSAFE
|
||||
|
||||
m_tmpSolverBodyPool.reserve(numBodies+1);
|
||||
m_tmpSolverBodyPool.resize(0);
|
||||
|
||||
@@ -45,6 +45,14 @@ protected:
|
||||
btAlignedObjectArray<btTypedConstraint::btConstraintInfo1> m_tmpConstraintSizesPool;
|
||||
int m_maxOverrideNumSolverIterations;
|
||||
int m_fixedBodyId;
|
||||
// When running solvers on multiple threads, a race condition exists for Kinematic objects that
|
||||
// participate in more than one solver.
|
||||
// The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body
|
||||
// for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island
|
||||
// (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once.
|
||||
// To avoid this race condition, this solver does not write the companionId, instead it stores the solver body
|
||||
// index in this solver-local table, indexed by the uniqueId of the body.
|
||||
btAlignedObjectArray<int> m_kinematicBodyUniqueIdToSolverBodyTable; // only used for multithreading
|
||||
|
||||
btSingleConstraintRowSolver m_resolveSingleConstraintRowGeneric;
|
||||
btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit;
|
||||
|
||||
@@ -878,25 +878,12 @@ public:
|
||||
int gNumClampedCcdMotions=0;
|
||||
|
||||
|
||||
void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
|
||||
void btDiscreteDynamicsWorld::createPredictiveContactsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep)
|
||||
{
|
||||
BT_PROFILE("createPredictiveContacts");
|
||||
|
||||
{
|
||||
BT_PROFILE("release predictive contact manifolds");
|
||||
|
||||
for (int i=0;i<m_predictiveManifolds.size();i++)
|
||||
{
|
||||
btPersistentManifold* manifold = m_predictiveManifolds[i];
|
||||
this->m_dispatcher1->releaseManifold(manifold);
|
||||
}
|
||||
m_predictiveManifolds.clear();
|
||||
}
|
||||
|
||||
btTransform predictedTrans;
|
||||
for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
|
||||
for ( int i=0;i<numBodies;i++)
|
||||
{
|
||||
btRigidBody* body = m_nonStaticRigidBodies[i];
|
||||
btRigidBody* body = bodies[i];
|
||||
body->setHitFraction(1.f);
|
||||
|
||||
if (body->isActive() && (!body->isStaticOrKinematicObject()))
|
||||
@@ -953,7 +940,9 @@ void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
|
||||
|
||||
|
||||
btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject);
|
||||
btMutexLock( &m_predictiveManifoldsMutex );
|
||||
m_predictiveManifolds.push_back(manifold);
|
||||
btMutexUnlock( &m_predictiveManifoldsMutex );
|
||||
|
||||
btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec;
|
||||
btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB;
|
||||
@@ -974,13 +963,35 @@ void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
|
||||
}
|
||||
}
|
||||
}
|
||||
void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
|
||||
|
||||
void btDiscreteDynamicsWorld::releasePredictiveContacts()
|
||||
{
|
||||
BT_PROFILE( "release predictive contact manifolds" );
|
||||
|
||||
for ( int i = 0; i < m_predictiveManifolds.size(); i++ )
|
||||
{
|
||||
btPersistentManifold* manifold = m_predictiveManifolds[ i ];
|
||||
this->m_dispatcher1->releaseManifold( manifold );
|
||||
}
|
||||
m_predictiveManifolds.clear();
|
||||
}
|
||||
|
||||
void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
|
||||
{
|
||||
BT_PROFILE("createPredictiveContacts");
|
||||
releasePredictiveContacts();
|
||||
if (m_nonStaticRigidBodies.size() > 0)
|
||||
{
|
||||
createPredictiveContactsInternal( &m_nonStaticRigidBodies[ 0 ], m_nonStaticRigidBodies.size(), timeStep );
|
||||
}
|
||||
}
|
||||
|
||||
void btDiscreteDynamicsWorld::integrateTransformsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep )
|
||||
{
|
||||
BT_PROFILE("integrateTransforms");
|
||||
btTransform predictedTrans;
|
||||
for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
|
||||
for (int i=0;i<numBodies;i++)
|
||||
{
|
||||
btRigidBody* body = m_nonStaticRigidBodies[i];
|
||||
btRigidBody* body = bodies[i];
|
||||
body->setHitFraction(1.f);
|
||||
|
||||
if (body->isActive() && (!body->isStaticOrKinematicObject()))
|
||||
@@ -1080,7 +1091,17 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
|
||||
|
||||
}
|
||||
|
||||
///this should probably be switched on by default, but it is not well tested yet
|
||||
}
|
||||
|
||||
void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
|
||||
{
|
||||
BT_PROFILE("integrateTransforms");
|
||||
if (m_nonStaticRigidBodies.size() > 0)
|
||||
{
|
||||
integrateTransformsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
|
||||
}
|
||||
|
||||
///this should probably be switched on by default, but it is not well tested yet
|
||||
if (m_applySpeculativeContactRestitution)
|
||||
{
|
||||
BT_PROFILE("apply speculative contact restitution");
|
||||
@@ -1114,14 +1135,12 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
|
||||
{
|
||||
BT_PROFILE("predictUnconstraintMotion");
|
||||
|
||||
@@ -30,6 +30,7 @@ class btIDebugDraw;
|
||||
struct InplaceSolverIslandCallback;
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btThreads.h"
|
||||
|
||||
|
||||
///btDiscreteDynamicsWorld provides discrete rigid body simulation
|
||||
@@ -68,9 +69,11 @@ protected:
|
||||
bool m_latencyMotionStateInterpolation;
|
||||
|
||||
btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds;
|
||||
btSpinMutex m_predictiveManifoldsMutex; // used to synchronize threads creating predictive contacts
|
||||
|
||||
virtual void predictUnconstraintMotion(btScalar timeStep);
|
||||
|
||||
void integrateTransformsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ); // can be called in parallel
|
||||
virtual void integrateTransforms(btScalar timeStep);
|
||||
|
||||
virtual void calculateSimulationIslands();
|
||||
@@ -85,7 +88,9 @@ protected:
|
||||
|
||||
virtual void internalSingleStepSimulation( btScalar timeStep);
|
||||
|
||||
void createPredictiveContacts(btScalar timeStep);
|
||||
void releasePredictiveContacts();
|
||||
void createPredictiveContactsInternal( btRigidBody** bodies, int numBodies, btScalar timeStep ); // can be called in parallel
|
||||
virtual void createPredictiveContacts(btScalar timeStep);
|
||||
|
||||
virtual void saveKinematicState(btScalar timeStep);
|
||||
|
||||
|
||||
168
src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
Normal file
168
src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btDiscreteDynamicsWorldMt.h"
|
||||
|
||||
//collision detection
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btSimulationIslandManagerMt.h"
|
||||
#include "LinearMath/btTransformUtil.h"
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
|
||||
//rigidbody & constraints
|
||||
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
|
||||
#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
|
||||
|
||||
|
||||
#include "LinearMath/btIDebugDraw.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
|
||||
|
||||
#include "BulletDynamics/Dynamics/btActionInterface.h"
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
#include "LinearMath/btMotionState.h"
|
||||
|
||||
#include "LinearMath/btSerializer.h"
|
||||
|
||||
|
||||
struct InplaceSolverIslandCallbackMt : public btSimulationIslandManagerMt::IslandCallback
|
||||
{
|
||||
btContactSolverInfo* m_solverInfo;
|
||||
btConstraintSolver* m_solver;
|
||||
btIDebugDraw* m_debugDrawer;
|
||||
btDispatcher* m_dispatcher;
|
||||
|
||||
InplaceSolverIslandCallbackMt(
|
||||
btConstraintSolver* solver,
|
||||
btStackAlloc* stackAlloc,
|
||||
btDispatcher* dispatcher)
|
||||
:m_solverInfo(NULL),
|
||||
m_solver(solver),
|
||||
m_debugDrawer(NULL),
|
||||
m_dispatcher(dispatcher)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
InplaceSolverIslandCallbackMt& operator=(InplaceSolverIslandCallbackMt& other)
|
||||
{
|
||||
btAssert(0);
|
||||
(void)other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btIDebugDraw* debugDrawer)
|
||||
{
|
||||
btAssert(solverInfo);
|
||||
m_solverInfo = solverInfo;
|
||||
m_debugDrawer = debugDrawer;
|
||||
}
|
||||
|
||||
|
||||
virtual void processIsland( btCollisionObject** bodies,
|
||||
int numBodies,
|
||||
btPersistentManifold** manifolds,
|
||||
int numManifolds,
|
||||
btTypedConstraint** constraints,
|
||||
int numConstraints,
|
||||
int islandId
|
||||
)
|
||||
{
|
||||
m_solver->solveGroup( bodies,
|
||||
numBodies,
|
||||
manifolds,
|
||||
numManifolds,
|
||||
constraints,
|
||||
numConstraints,
|
||||
*m_solverInfo,
|
||||
m_debugDrawer,
|
||||
m_dispatcher
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
|
||||
: btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
|
||||
{
|
||||
if (m_ownsIslandManager)
|
||||
{
|
||||
m_islandManager->~btSimulationIslandManager();
|
||||
btAlignedFree( m_islandManager);
|
||||
}
|
||||
{
|
||||
void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallbackMt),16);
|
||||
m_solverIslandCallbackMt = new (mem) InplaceSolverIslandCallbackMt (m_constraintSolver, 0, dispatcher);
|
||||
}
|
||||
{
|
||||
void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt),16);
|
||||
btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt();
|
||||
m_islandManager = im;
|
||||
im->setMinimumSolverBatchSize( m_solverInfo.m_minimumSolverBatchSize );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt()
|
||||
{
|
||||
if (m_solverIslandCallbackMt)
|
||||
{
|
||||
m_solverIslandCallbackMt->~InplaceSolverIslandCallbackMt();
|
||||
btAlignedFree(m_solverIslandCallbackMt);
|
||||
}
|
||||
if (m_ownsConstraintSolver)
|
||||
{
|
||||
m_constraintSolver->~btConstraintSolver();
|
||||
btAlignedFree(m_constraintSolver);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo)
|
||||
{
|
||||
BT_PROFILE("solveConstraints");
|
||||
|
||||
|
||||
m_solverIslandCallbackMt->setup(&solverInfo, getDebugDrawer());
|
||||
m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
|
||||
|
||||
/// solve all the constraints for this island
|
||||
btSimulationIslandManagerMt* im = static_cast<btSimulationIslandManagerMt*>(m_islandManager);
|
||||
im->buildAndProcessIslands( getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, m_solverIslandCallbackMt );
|
||||
|
||||
m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
|
||||
}
|
||||
|
||||
|
||||
void btDiscreteDynamicsWorldMt::addCollisionObject(btCollisionObject* collisionObject, short int collisionFilterGroup, short int collisionFilterMask)
|
||||
{
|
||||
collisionObject->setUniqueId(m_collisionObjects.size());
|
||||
btDiscreteDynamicsWorld::addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask);
|
||||
}
|
||||
44
src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
Normal file
44
src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_DISCRETE_DYNAMICS_WORLD_MT_H
|
||||
#define BT_DISCRETE_DYNAMICS_WORLD_MT_H
|
||||
|
||||
#include "btDiscreteDynamicsWorld.h"
|
||||
|
||||
struct InplaceSolverIslandCallbackMt;
|
||||
|
||||
///
|
||||
/// btDiscreteDynamicsWorldMt -- a version of DiscreteDynamicsWorld with some minor changes to support
|
||||
/// solving simulation islands on multiple threads.
|
||||
///
|
||||
ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld
|
||||
{
|
||||
protected:
|
||||
InplaceSolverIslandCallbackMt* m_solverIslandCallbackMt;
|
||||
|
||||
virtual void solveConstraints(btContactSolverInfo& solverInfo);
|
||||
|
||||
public:
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::StaticFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
|
||||
|
||||
btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
|
||||
virtual ~btDiscreteDynamicsWorldMt();
|
||||
};
|
||||
|
||||
#endif //BT_DISCRETE_DYNAMICS_WORLD_H
|
||||
@@ -215,12 +215,12 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
|
||||
jointNodeArray.reserve(2*m_allConstraintPtrArray.size());
|
||||
}
|
||||
|
||||
static btMatrixXu J3;
|
||||
btMatrixXu& J3 = m_scratchJ3;
|
||||
{
|
||||
BT_PROFILE("J3.resize");
|
||||
J3.resize(2*m,8);
|
||||
}
|
||||
static btMatrixXu JinvM3;
|
||||
btMatrixXu& JinvM3 = m_scratchJInvM3;
|
||||
{
|
||||
BT_PROFILE("JinvM3.resize/setZero");
|
||||
|
||||
@@ -230,7 +230,7 @@ void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
|
||||
}
|
||||
int cur=0;
|
||||
int rowOffset = 0;
|
||||
static btAlignedObjectArray<int> ofs;
|
||||
btAlignedObjectArray<int>& ofs = m_scratchOfs;
|
||||
{
|
||||
BT_PROFILE("ofs resize");
|
||||
ofs.resize(0);
|
||||
@@ -489,7 +489,7 @@ void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal)
|
||||
}
|
||||
}
|
||||
|
||||
static btMatrixXu Minv;
|
||||
btMatrixXu& Minv = m_scratchMInv;
|
||||
Minv.resize(6*numBodies,6*numBodies);
|
||||
Minv.setZero();
|
||||
for (int i=0;i<numBodies;i++)
|
||||
@@ -506,7 +506,7 @@ void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal)
|
||||
setElem(Minv,i*6+3+r,i*6+3+c,orgBody? orgBody->getInvInertiaTensorWorld()[r][c] : 0);
|
||||
}
|
||||
|
||||
static btMatrixXu J;
|
||||
btMatrixXu& J = m_scratchJ;
|
||||
J.resize(numConstraintRows,6*numBodies);
|
||||
J.setZero();
|
||||
|
||||
@@ -541,10 +541,10 @@ void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal)
|
||||
}
|
||||
}
|
||||
|
||||
static btMatrixXu J_transpose;
|
||||
btMatrixXu& J_transpose = m_scratchJTranspose;
|
||||
J_transpose= J.transpose();
|
||||
|
||||
static btMatrixXu tmp;
|
||||
btMatrixXu& tmp = m_scratchTmp;
|
||||
|
||||
{
|
||||
{
|
||||
|
||||
@@ -43,6 +43,17 @@ protected:
|
||||
btMLCPSolverInterface* m_solver;
|
||||
int m_fallback;
|
||||
|
||||
/// The following scratch variables are not stateful -- contents are cleared prior to each use.
|
||||
/// They are only cached here to avoid extra memory allocations and deallocations and to ensure
|
||||
/// that multiple instances of the solver can be run in parallel.
|
||||
btMatrixXu m_scratchJ3;
|
||||
btMatrixXu m_scratchJInvM3;
|
||||
btAlignedObjectArray<int> m_scratchOfs;
|
||||
btMatrixXu m_scratchMInv;
|
||||
btMatrixXu m_scratchJ;
|
||||
btMatrixXu m_scratchJTranspose;
|
||||
btMatrixXu m_scratchTmp;
|
||||
|
||||
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
|
||||
virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user