Fix some crashes in FeatherstoneMultiBodyDemo, when using a fixed base
Create two btMultiBody, one fixed and one free base Preparation towards btMultiBodyConstraint
This commit is contained in:
@@ -209,18 +209,27 @@ void FeatherstoneMultiBodyDemo::initPhysics()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
createFeatherstoneMultiBody(world, 10, btVector3 (20,29.5,-2), true);
|
||||||
|
|
||||||
|
createFeatherstoneMultiBody(world, 5, btVector3 (0,29.5,-2), false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeatherstoneMultiBodyDemo::createFeatherstoneMultiBody(class btMultiBodyDynamicsWorld* world, int numLinks, const btVector3& basePosition,bool isFixedBase)
|
||||||
|
{
|
||||||
{
|
{
|
||||||
int n_links = 5;
|
int n_links = numLinks;
|
||||||
float mass = 13.5;
|
float mass = 13.5;
|
||||||
btVector3 inertia(91,344,253);
|
btVector3 inertia(91,344,253);
|
||||||
bool isFixedBase = false;
|
|
||||||
bool canSleep = true;//false;
|
bool canSleep = true;//false;
|
||||||
|
|
||||||
btMultiBody * bod = new btMultiBody(n_links, mass, inertia, isFixedBase, canSleep);
|
btMultiBody * bod = new btMultiBody(n_links, mass, inertia, isFixedBase, canSleep);
|
||||||
btVector3 pos(0,9.5,-2);
|
|
||||||
//btQuaternion orn(btVector3(0,0,1),-0.25*SIMD_HALF_PI);//0,0,0,1);
|
//btQuaternion orn(btVector3(0,0,1),-0.25*SIMD_HALF_PI);//0,0,0,1);
|
||||||
btQuaternion orn(0,0,0,1);
|
btQuaternion orn(0,0,0,1);
|
||||||
bod->setBasePos(pos);
|
bod->setBasePos(basePosition);
|
||||||
bod->setWorldToBaseRot(orn);
|
bod->setWorldToBaseRot(orn);
|
||||||
btVector3 vel(0,0,0);
|
btVector3 vel(0,0,0);
|
||||||
bod->setBaseVel(vel);
|
bod->setBaseVel(vel);
|
||||||
@@ -342,10 +351,9 @@ void FeatherstoneMultiBodyDemo::initPhysics()
|
|||||||
world->addMultiBody(bod);
|
world->addMultiBody(bod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FeatherstoneMultiBodyDemo::clientResetScene()
|
void FeatherstoneMultiBodyDemo::clientResetScene()
|
||||||
{
|
{
|
||||||
exitPhysics();
|
exitPhysics();
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ class FeatherstoneMultiBodyDemo : public PlatformDemoApplication
|
|||||||
|
|
||||||
btDefaultCollisionConfiguration* m_collisionConfiguration;
|
btDefaultCollisionConfiguration* m_collisionConfiguration;
|
||||||
|
|
||||||
|
|
||||||
|
void createFeatherstoneMultiBody(class btMultiBodyDynamicsWorld* world, int numLinks, const btVector3& basePosition,bool isFixedBase);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FeatherstoneMultiBodyDemo()
|
FeatherstoneMultiBodyDemo()
|
||||||
|
|||||||
35
src/BulletDynamics/Featherstone/btMultiBodyConstraint.h
Normal file
35
src/BulletDynamics/Featherstone/btMultiBodyConstraint.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2013 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_MULTIBODY_CONSTRAINT_H
|
||||||
|
#define BT_MULTIBODY_CONSTRAINT_H
|
||||||
|
|
||||||
|
class btMultiBodyConstraint
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
int getIslandIdA() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int getIslandIdB() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BT_MULTIBODY_CONSTRAINT_H
|
||||||
|
|
||||||
@@ -203,11 +203,15 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
|
|||||||
const int ndofA = multiBodyA->getNumLinks() + 6;
|
const int ndofA = multiBodyA->getNumLinks() + 6;
|
||||||
|
|
||||||
solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
|
solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
|
||||||
|
|
||||||
if (solverConstraint.m_deltaVelAindex <0)
|
if (solverConstraint.m_deltaVelAindex <0)
|
||||||
{
|
{
|
||||||
solverConstraint.m_deltaVelAindex = m_deltaVelocities.size();
|
solverConstraint.m_deltaVelAindex = m_deltaVelocities.size();
|
||||||
multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
|
multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
|
||||||
m_deltaVelocities.resize(m_deltaVelocities.size()+ndofA);
|
m_deltaVelocities.resize(m_deltaVelocities.size()+ndofA);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
btAssert(m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex+ndofA);
|
||||||
}
|
}
|
||||||
|
|
||||||
solverConstraint.m_jacAindex = m_jacobians.size();
|
solverConstraint.m_jacAindex = m_jacobians.size();
|
||||||
@@ -260,11 +264,16 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
|
|||||||
btVector3 vec;
|
btVector3 vec;
|
||||||
btScalar denom0 = 0.f;
|
btScalar denom0 = 0.f;
|
||||||
btScalar denom1 = 0.f;
|
btScalar denom1 = 0.f;
|
||||||
|
btScalar* jacB = 0;
|
||||||
|
btScalar* jacA = 0;
|
||||||
|
btScalar* lambdaA =0;
|
||||||
|
btScalar* lambdaB =0;
|
||||||
|
int ndofA = 0;
|
||||||
if (multiBodyA)
|
if (multiBodyA)
|
||||||
{
|
{
|
||||||
const int ndofA = multiBodyA->getNumLinks() + 6;
|
ndofA = multiBodyA->getNumLinks() + 6;
|
||||||
btScalar* jacA = &m_jacobians[solverConstraint.m_jacAindex];
|
jacA = &m_jacobians[solverConstraint.m_jacAindex];
|
||||||
btScalar* lambdaA = &m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
|
lambdaA = &m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
|
||||||
for (int i = 0; i < ndofA; ++i)
|
for (int i = 0; i < ndofA; ++i)
|
||||||
{
|
{
|
||||||
float j = jacA[i] ;
|
float j = jacA[i] ;
|
||||||
@@ -282,8 +291,8 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
|
|||||||
if (multiBodyB)
|
if (multiBodyB)
|
||||||
{
|
{
|
||||||
const int ndofB = multiBodyB->getNumLinks() + 6;
|
const int ndofB = multiBodyB->getNumLinks() + 6;
|
||||||
btScalar* jacB = &m_jacobians[solverConstraint.m_jacBindex];
|
jacB = &m_jacobians[solverConstraint.m_jacBindex];
|
||||||
btScalar* lambdaB = &m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
|
lambdaB = &m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
|
||||||
for (int i = 0; i < ndofB; ++i)
|
for (int i = 0; i < ndofB; ++i)
|
||||||
{
|
{
|
||||||
float j = jacB[i] ;
|
float j = jacB[i] ;
|
||||||
@@ -300,8 +309,26 @@ void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btScalar denom = relaxation/(denom0+denom1);
|
if (multiBodyA && (multiBodyA==multiBodyB))
|
||||||
solverConstraint.m_jacDiagABInv = denom;
|
{
|
||||||
|
// ndof1 == ndof2 in this case
|
||||||
|
for (int i = 0; i < ndofA; ++i)
|
||||||
|
{
|
||||||
|
denom1 += jacB[i] * lambdaA[i];
|
||||||
|
denom1 += jacA[i] * lambdaB[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float d = denom0+denom1;
|
||||||
|
if (btFabs(d)>SIMD_EPSILON)
|
||||||
|
{
|
||||||
|
|
||||||
|
solverConstraint.m_jacDiagABInv = relaxation/(d);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
solverConstraint.m_jacDiagABInv = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -692,3 +719,17 @@ btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies,int
|
|||||||
{
|
{
|
||||||
return btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
|
return btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher)
|
||||||
|
{
|
||||||
|
m_tmpMultiBodyConstraints = multiBodyConstraints;
|
||||||
|
m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
|
||||||
|
|
||||||
|
btSequentialImpulseConstraintSolver::solveGroup(bodies,numBodies,manifold,numManifolds,constraints,numConstraints,info,debugDrawer,dispatcher);
|
||||||
|
|
||||||
|
m_tmpMultiBodyConstraints = 0;
|
||||||
|
m_tmpNumMultiBodyConstraints = 0;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ subject to the following restrictions:
|
|||||||
|
|
||||||
|
|
||||||
class btMultiBody;
|
class btMultiBody;
|
||||||
|
class btMultiBodyConstraint;
|
||||||
|
|
||||||
ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraintSolver : public btSequentialImpulseConstraintSolver
|
ATTRIBUTE_ALIGNED16(class) btMultiBodyConstraintSolver : public btSequentialImpulseConstraintSolver
|
||||||
{
|
{
|
||||||
@@ -43,8 +43,9 @@ protected:
|
|||||||
btAlignedObjectArray<btVector3> scratch_v;
|
btAlignedObjectArray<btVector3> scratch_v;
|
||||||
btAlignedObjectArray<btMatrix3x3> scratch_m;
|
btAlignedObjectArray<btMatrix3x3> scratch_m;
|
||||||
|
|
||||||
// virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
|
//temp storage for multi body constraints for a specific island/group called by 'solveGroup'
|
||||||
// virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal);
|
btMultiBodyConstraint** m_tmpMultiBodyConstraints;
|
||||||
|
int m_tmpNumMultiBodyConstraints;
|
||||||
|
|
||||||
void resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c);
|
void resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c);
|
||||||
void convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal);
|
void convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal);
|
||||||
@@ -68,7 +69,10 @@ public:
|
|||||||
|
|
||||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||||
|
|
||||||
|
///this method should not be called, it was just used during porting/integration of Featherstone btMultiBody, providing backwards compatibility but no support for btMultiBodyConstraint (only contact constraints)
|
||||||
virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
|
virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
|
||||||
|
|
||||||
|
virtual void solveMultiBodyGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer,btDispatcher* dispatcher);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,19 +19,9 @@ subject to the following restrictions:
|
|||||||
#include "btMultiBodyLinkCollider.h"
|
#include "btMultiBodyLinkCollider.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
|
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
|
||||||
#include "LinearMath/btQuickprof.h"
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
#include "btMultiBodyConstraint.h"
|
||||||
|
|
||||||
btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
|
|
||||||
:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
|
|
||||||
{
|
|
||||||
//split impulse is not yet supported for Featherstone hierarchies
|
|
||||||
getSolverInfo().m_splitImpulse = false;
|
|
||||||
getSolverInfo().m_solverMode |=SOLVER_USE_2_FRICTION_DIRECTIONS;
|
|
||||||
}
|
|
||||||
|
|
||||||
btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld ()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, short group, short mask)
|
void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, short group, short mask)
|
||||||
@@ -156,14 +146,268 @@ void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
|
|||||||
|
|
||||||
btDiscreteDynamicsWorld::updateActivationState(timeStep);
|
btDiscreteDynamicsWorld::updateActivationState(timeStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
|
||||||
|
{
|
||||||
|
int islandId;
|
||||||
|
|
||||||
|
const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
|
||||||
|
const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
|
||||||
|
islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag();
|
||||||
|
return islandId;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class btSortConstraintOnIslandPredicate2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) const
|
||||||
|
{
|
||||||
|
int rIslandId0,lIslandId0;
|
||||||
|
rIslandId0 = btGetConstraintIslandId2(rhs);
|
||||||
|
lIslandId0 = btGetConstraintIslandId2(lhs);
|
||||||
|
return lIslandId0 < rIslandId0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
|
||||||
|
{
|
||||||
|
int islandId;
|
||||||
|
|
||||||
|
int islandTagA = lhs->getIslandIdA();
|
||||||
|
int islandTagB = lhs->getIslandIdB();
|
||||||
|
islandId= islandTagA>=0?islandTagA:islandTagB;
|
||||||
|
return islandId;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class btSortMultiBodyConstraintOnIslandPredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool operator() ( const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs ) const
|
||||||
|
{
|
||||||
|
int rIslandId0,lIslandId0;
|
||||||
|
rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
|
||||||
|
lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
|
||||||
|
return lIslandId0 < rIslandId0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
|
||||||
|
{
|
||||||
|
btContactSolverInfo* m_solverInfo;
|
||||||
|
btMultiBodyConstraintSolver* m_solver;
|
||||||
|
btMultiBodyConstraint** m_multiBodySortedConstraints;
|
||||||
|
int m_numMultiBodyConstraints;
|
||||||
|
|
||||||
|
btTypedConstraint** m_sortedConstraints;
|
||||||
|
int m_numConstraints;
|
||||||
|
btIDebugDraw* m_debugDrawer;
|
||||||
|
btDispatcher* m_dispatcher;
|
||||||
|
|
||||||
|
btAlignedObjectArray<btCollisionObject*> m_bodies;
|
||||||
|
btAlignedObjectArray<btPersistentManifold*> m_manifolds;
|
||||||
|
btAlignedObjectArray<btTypedConstraint*> m_constraints;
|
||||||
|
btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
|
||||||
|
|
||||||
|
|
||||||
|
MultiBodyInplaceSolverIslandCallback( btMultiBodyConstraintSolver* solver,
|
||||||
|
btDispatcher* dispatcher)
|
||||||
|
:m_solverInfo(NULL),
|
||||||
|
m_solver(solver),
|
||||||
|
m_multiBodySortedConstraints(NULL),
|
||||||
|
m_numConstraints(0),
|
||||||
|
m_debugDrawer(NULL),
|
||||||
|
m_dispatcher(dispatcher)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiBodyInplaceSolverIslandCallback& operator=(MultiBodyInplaceSolverIslandCallback& other)
|
||||||
|
{
|
||||||
|
btAssert(0);
|
||||||
|
(void)other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE void setup ( btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
|
||||||
|
{
|
||||||
|
btAssert(solverInfo);
|
||||||
|
m_solverInfo = solverInfo;
|
||||||
|
|
||||||
|
m_multiBodySortedConstraints = sortedMultiBodyConstraints;
|
||||||
|
m_numMultiBodyConstraints = numMultiBodyConstraints;
|
||||||
|
m_sortedConstraints = sortedConstraints;
|
||||||
|
m_numConstraints = numConstraints;
|
||||||
|
|
||||||
|
m_debugDrawer = debugDrawer;
|
||||||
|
m_bodies.resize (0);
|
||||||
|
m_manifolds.resize (0);
|
||||||
|
m_constraints.resize (0);
|
||||||
|
m_multiBodyConstraints.resize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void processIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId)
|
||||||
|
{
|
||||||
|
if (islandId<0)
|
||||||
|
{
|
||||||
|
///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
|
||||||
|
m_solver->solveMultiBodyGroup( bodies,numBodies,manifolds, numManifolds,m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//also add all non-contact constraints/joints for this island
|
||||||
|
btTypedConstraint** startConstraint = 0;
|
||||||
|
btMultiBodyConstraint** startMultiBodyConstraint = 0;
|
||||||
|
|
||||||
|
int numCurConstraints = 0;
|
||||||
|
int numCurMultiBodyConstraints = 0;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
//find the first constraint for this island
|
||||||
|
for (i=0;i<m_numMultiBodyConstraints;i++)
|
||||||
|
{
|
||||||
|
if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
|
||||||
|
{
|
||||||
|
startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<m_numConstraints;i++)
|
||||||
|
{
|
||||||
|
if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
|
||||||
|
{
|
||||||
|
startConstraint = &m_sortedConstraints[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//count the number of constraints in this island
|
||||||
|
for (;i<m_numConstraints;i++)
|
||||||
|
{
|
||||||
|
if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
|
||||||
|
{
|
||||||
|
numCurConstraints++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//count the number of multi body constraints in this island
|
||||||
|
for (;i<m_numMultiBodyConstraints;i++)
|
||||||
|
{
|
||||||
|
if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
|
||||||
|
{
|
||||||
|
numCurMultiBodyConstraints++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_solverInfo->m_minimumSolverBatchSize<=1)
|
||||||
|
{
|
||||||
|
m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
|
||||||
|
for (i=0;i<numBodies;i++)
|
||||||
|
m_bodies.push_back(bodies[i]);
|
||||||
|
for (i=0;i<numManifolds;i++)
|
||||||
|
m_manifolds.push_back(manifolds[i]);
|
||||||
|
for (i=0;i<numCurConstraints;i++)
|
||||||
|
m_constraints.push_back(startConstraint[i]);
|
||||||
|
for (i=0;i<numCurMultiBodyConstraints;i++)
|
||||||
|
m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
|
||||||
|
|
||||||
|
if ((m_constraints.size()+m_manifolds.size())>m_solverInfo->m_minimumSolverBatchSize)
|
||||||
|
{
|
||||||
|
processConstraints();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//printf("deferred\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processConstraints()
|
||||||
|
{
|
||||||
|
|
||||||
|
btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
|
||||||
|
btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
|
||||||
|
btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
|
||||||
|
btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
|
||||||
|
|
||||||
|
m_solver->solveMultiBodyGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo,m_debugDrawer,m_dispatcher);
|
||||||
|
m_bodies.resize(0);
|
||||||
|
m_manifolds.resize(0);
|
||||||
|
m_constraints.resize(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btMultiBodyConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
|
||||||
|
:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
|
||||||
|
m_multiBodyConstraintSolver(constraintSolver)
|
||||||
|
{
|
||||||
|
//split impulse is not yet supported for Featherstone hierarchies
|
||||||
|
getSolverInfo().m_splitImpulse = false;
|
||||||
|
getSolverInfo().m_solverMode |=SOLVER_USE_2_FRICTION_DIRECTIONS;
|
||||||
|
m_solverMultiBodyIslandCallback = new MultiBodyInplaceSolverIslandCallback(constraintSolver,dispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld ()
|
||||||
|
{
|
||||||
|
delete m_solverMultiBodyIslandCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
|
void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
|
||||||
{
|
{
|
||||||
|
|
||||||
btVector3 g = m_gravity;
|
btVector3 g = m_gravity;
|
||||||
btAlignedObjectArray<btScalar> scratch_r;
|
btAlignedObjectArray<btScalar> scratch_r;
|
||||||
btAlignedObjectArray<btVector3> scratch_v;
|
btAlignedObjectArray<btVector3> scratch_v;
|
||||||
btAlignedObjectArray<btMatrix3x3> scratch_m;
|
btAlignedObjectArray<btMatrix3x3> scratch_m;
|
||||||
|
|
||||||
|
|
||||||
|
BT_PROFILE("solveConstraints");
|
||||||
|
|
||||||
|
m_sortedConstraints.resize( m_constraints.size());
|
||||||
|
int i;
|
||||||
|
for (i=0;i<getNumConstraints();i++)
|
||||||
|
{
|
||||||
|
m_sortedConstraints[i] = m_constraints[i];
|
||||||
|
}
|
||||||
|
m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
|
||||||
|
btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
|
||||||
|
|
||||||
|
for (i=0;i<m_multiBodyConstraints.size();i++)
|
||||||
|
{
|
||||||
|
m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
|
||||||
|
|
||||||
|
|
||||||
|
m_solverMultiBodyIslandCallback->setup(&solverInfo,constraintsPtr,m_sortedConstraints.size(),sortedMultiBodyConstraints,m_sortedMultiBodyConstraints.size(), getDebugDrawer());
|
||||||
|
m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
|
||||||
|
|
||||||
|
/// solve all the constraints for this island
|
||||||
|
m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),m_solverMultiBodyIslandCallback);
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
BT_PROFILE("btMultiBody addForce and stepVelocities");
|
BT_PROFILE("btMultiBody addForce and stepVelocities");
|
||||||
for (int i=0;i<this->m_multiBodies.size();i++)
|
for (int i=0;i<this->m_multiBodies.size();i++)
|
||||||
@@ -193,7 +437,11 @@ void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
btDiscreteDynamicsWorld::solveConstraints(solverInfo);
|
|
||||||
|
m_solverMultiBodyIslandCallback->processConstraints();
|
||||||
|
|
||||||
|
m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
|
void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
|
||||||
@@ -263,3 +511,15 @@ void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void btMultiBodyDynamicsWorld::addMultiBodyConstraint( btMultiBodyConstraint* constraint)
|
||||||
|
{
|
||||||
|
m_multiBodyConstraints.push_back(constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void btMultiBodyDynamicsWorld::removeMultiBodyConstraint( btMultiBodyConstraint* constraint)
|
||||||
|
{
|
||||||
|
m_multiBodyConstraints.remove(constraint);
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ subject to the following restrictions:
|
|||||||
|
|
||||||
|
|
||||||
class btMultiBody;
|
class btMultiBody;
|
||||||
|
class btMultiBodyConstraint;
|
||||||
class btMultiBodyConstraintSolver;
|
class btMultiBodyConstraintSolver;
|
||||||
|
struct MultiBodyInplaceSolverIslandCallback;
|
||||||
|
|
||||||
///The btMultiBodyDynamicsWorld adds Featherstone multi body dynamics to Bullet
|
///The btMultiBodyDynamicsWorld adds Featherstone multi body dynamics to Bullet
|
||||||
///This implementation is still preliminary/experimental.
|
///This implementation is still preliminary/experimental.
|
||||||
@@ -28,6 +30,10 @@ class btMultiBodyDynamicsWorld : public btDiscreteDynamicsWorld
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
btAlignedObjectArray<btMultiBody*> m_multiBodies;
|
btAlignedObjectArray<btMultiBody*> m_multiBodies;
|
||||||
|
btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
|
||||||
|
btAlignedObjectArray<btMultiBodyConstraint*> m_sortedMultiBodyConstraints;
|
||||||
|
btMultiBodyConstraintSolver* m_multiBodyConstraintSolver;
|
||||||
|
MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback;
|
||||||
|
|
||||||
virtual void calculateSimulationIslands();
|
virtual void calculateSimulationIslands();
|
||||||
virtual void updateActivationState(btScalar timeStep);
|
virtual void updateActivationState(btScalar timeStep);
|
||||||
@@ -43,6 +49,8 @@ public:
|
|||||||
|
|
||||||
virtual void removeMultiBody(btMultiBody* body);
|
virtual void removeMultiBody(btMultiBody* body);
|
||||||
|
|
||||||
|
virtual void addMultiBodyConstraint( btMultiBodyConstraint* constraint);
|
||||||
|
|
||||||
|
virtual void removeMultiBodyConstraint( btMultiBodyConstraint* constraint);
|
||||||
};
|
};
|
||||||
#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
|
#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
|
||||||
|
|||||||
@@ -33,13 +33,16 @@ public:
|
|||||||
:m_multiBody(multiBody),
|
:m_multiBody(multiBody),
|
||||||
m_link(link)
|
m_link(link)
|
||||||
{
|
{
|
||||||
if (link>=0 || (multiBody && !multiBody->hasFixedBase()))
|
//we need to remove the 'CF_STATIC_OBJECT' flag, otherwise links/base doesn't merge islands
|
||||||
|
//this means that some constraints might point to bodies that are not in the islands, causing crashes
|
||||||
|
//if (link>=0 || (multiBody && !multiBody->hasFixedBase()))
|
||||||
{
|
{
|
||||||
m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
|
m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
|
||||||
} else
|
|
||||||
{
|
|
||||||
m_collisionFlags |= (btCollisionObject::CF_STATIC_OBJECT);
|
|
||||||
}
|
}
|
||||||
|
// else
|
||||||
|
//{
|
||||||
|
// m_collisionFlags |= (btCollisionObject::CF_STATIC_OBJECT);
|
||||||
|
//}
|
||||||
|
|
||||||
m_internalType = CO_FEATHERSTONE_LINK;
|
m_internalType = CO_FEATHERSTONE_LINK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user