123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- /*
- 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.
- */
- #include "btMultiBodyDynamicsWorld.h"
- #include "btMultiBodyConstraintSolver.h"
- #include "btMultiBody.h"
- #include "btMultiBodyLinkCollider.h"
- #include "bullet/BulletCollision//CollisionDispatch/btSimulationIslandManager.h"
- #include "bullet/LinearMath/btQuickprof.h"
- #include "btMultiBodyConstraint.h"
-
- void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, short group, short mask)
- {
- m_multiBodies.push_back(body);
- }
- void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
- {
- m_multiBodies.remove(body);
- }
- void btMultiBodyDynamicsWorld::calculateSimulationIslands()
- {
- BT_PROFILE("calculateSimulationIslands");
- getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
- {
- //merge islands based on speculative contact manifolds too
- for (int i=0;i<this->m_predictiveManifolds.size();i++)
- {
- btPersistentManifold* manifold = m_predictiveManifolds[i];
-
- const btCollisionObject* colObj0 = manifold->getBody0();
- const btCollisionObject* colObj1 = manifold->getBody1();
-
- if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
- ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
- {
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
- }
- }
- }
-
- {
- int i;
- int numConstraints = int(m_constraints.size());
- for (i=0;i< numConstraints ; i++ )
- {
- btTypedConstraint* constraint = m_constraints[i];
- if (constraint->isEnabled())
- {
- const btRigidBody* colObj0 = &constraint->getRigidBodyA();
- const btRigidBody* colObj1 = &constraint->getRigidBodyB();
- if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
- ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
- {
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),(colObj1)->getIslandTag());
- }
- }
- }
- }
- //merge islands linked by Featherstone link colliders
- for (int i=0;i<m_multiBodies.size();i++)
- {
- btMultiBody* body = m_multiBodies[i];
- {
- btMultiBodyLinkCollider* prev = body->getBaseCollider();
- for (int b=0;b<body->getNumLinks();b++)
- {
- btMultiBodyLinkCollider* cur = body->getLink(b).m_collider;
-
- if (((cur) && (!(cur)->isStaticOrKinematicObject())) &&
- ((prev) && (!(prev)->isStaticOrKinematicObject())))
- {
- int tagPrev = prev->getIslandTag();
- int tagCur = cur->getIslandTag();
- getSimulationIslandManager()->getUnionFind().unite(tagPrev, tagCur);
- }
- if (cur && !cur->isStaticOrKinematicObject())
- prev = cur;
-
- }
- }
- }
- //merge islands linked by multibody constraints
- {
- for (int i=0;i<this->m_multiBodyConstraints.size();i++)
- {
- btMultiBodyConstraint* c = m_multiBodyConstraints[i];
- int tagA = c->getIslandIdA();
- int tagB = c->getIslandIdB();
- if (tagA>=0 && tagB>=0)
- getSimulationIslandManager()->getUnionFind().unite(tagA, tagB);
- }
- }
- //Store the island id in each body
- getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
- }
- void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
- {
- BT_PROFILE("btMultiBodyDynamicsWorld::updateActivationState");
-
-
- for ( int i=0;i<m_multiBodies.size();i++)
- {
- btMultiBody* body = m_multiBodies[i];
- if (body)
- {
- body->checkMotionAndSleepIfRequired(timeStep);
- if (!body->isAwake())
- {
- btMultiBodyLinkCollider* col = body->getBaseCollider();
- if (col && col->getActivationState() == ACTIVE_TAG)
- {
- col->setActivationState( WANTS_DEACTIVATION);
- col->setDeactivationTime(0.f);
- }
- for (int b=0;b<body->getNumLinks();b++)
- {
- btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
- if (col && col->getActivationState() == ACTIVE_TAG)
- {
- col->setActivationState( WANTS_DEACTIVATION);
- col->setDeactivationTime(0.f);
- }
- }
- } else
- {
- btMultiBodyLinkCollider* col = body->getBaseCollider();
- if (col && col->getActivationState() != DISABLE_DEACTIVATION)
- col->setActivationState( ACTIVE_TAG );
- for (int b=0;b<body->getNumLinks();b++)
- {
- btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
- if (col && col->getActivationState() != DISABLE_DEACTIVATION)
- col->setActivationState( ACTIVE_TAG );
- }
- }
- }
- }
- 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_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++;
- }
- }
- for (i=0;i<m_numMultiBodyConstraints;i++)
- {
- if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
- {
-
- startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
- break;
- }
- }
- //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);
- m_multiBodyConstraints.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)
- {
- btAlignedObjectArray<btScalar> scratch_r;
- btAlignedObjectArray<btVector3> scratch_v;
- 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;
- m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
- for (i=0;i<m_multiBodyConstraints.size();i++)
- {
- m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
- }
- m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
- 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");
- for (int i=0;i<this->m_multiBodies.size();i++)
- {
- btMultiBody* bod = m_multiBodies[i];
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b=0;b<bod->getNumLinks();b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING)
- isSleeping = true;
- }
- if (!isSleeping)
- {
- scratch_r.resize(bod->getNumLinks()+1);
- scratch_v.resize(bod->getNumLinks()+1);
- scratch_m.resize(bod->getNumLinks()+1);
- bod->clearForcesAndTorques();
- bod->addBaseForce(m_gravity * bod->getBaseMass());
- for (int j = 0; j < bod->getNumLinks(); ++j)
- {
- bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
- }
- bod->stepVelocities(solverInfo.m_timeStep, scratch_r, scratch_v, scratch_m);
- }
- }
- }
- m_solverMultiBodyIslandCallback->processConstraints();
-
- m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
- }
- void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
- {
- btDiscreteDynamicsWorld::integrateTransforms(timeStep);
- {
- BT_PROFILE("btMultiBody stepPositions");
- //integrate and update the Featherstone hierarchies
- btAlignedObjectArray<btQuaternion> world_to_local;
- btAlignedObjectArray<btVector3> local_origin;
- for (int b=0;b<m_multiBodies.size();b++)
- {
- btMultiBody* bod = m_multiBodies[b];
- bool isSleeping = false;
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b=0;b<bod->getNumLinks();b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState()==ISLAND_SLEEPING)
- isSleeping = true;
- }
- if (!isSleeping)
- {
- int nLinks = bod->getNumLinks();
- ///base + num links
- world_to_local.resize(nLinks+1);
- local_origin.resize(nLinks+1);
- bod->stepPositions(timeStep);
-
- world_to_local[0] = bod->getWorldToBaseRot();
- local_origin[0] = bod->getBasePos();
- if (bod->getBaseCollider())
- {
- btVector3 posr = local_origin[0];
- float pos[4]={posr.x(),posr.y(),posr.z(),1};
- float quat[4]={-world_to_local[0].x(),-world_to_local[0].y(),-world_to_local[0].z(),world_to_local[0].w()};
- btTransform tr;
- tr.setIdentity();
- tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
- bod->getBaseCollider()->setWorldTransform(tr);
- }
-
- for (int k=0;k<bod->getNumLinks();k++)
- {
- const int parent = bod->getParent(k);
- world_to_local[k+1] = bod->getParentToLocalRot(k) * world_to_local[parent+1];
- local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , bod->getRVector(k)));
- }
- for (int m=0;m<bod->getNumLinks();m++)
- {
- btMultiBodyLinkCollider* col = bod->getLink(m).m_collider;
- if (col)
- {
- int link = col->m_link;
- btAssert(link == m);
- int index = link+1;
- btVector3 posr = local_origin[index];
- float pos[4]={posr.x(),posr.y(),posr.z(),1};
- float quat[4]={-world_to_local[index].x(),-world_to_local[index].y(),-world_to_local[index].z(),world_to_local[index].w()};
- btTransform tr;
- tr.setIdentity();
- tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
- col->setWorldTransform(tr);
- }
- }
- } else
- {
- bod->clearVelocities();
- }
- }
- }
- }
- void btMultiBodyDynamicsWorld::addMultiBodyConstraint( btMultiBodyConstraint* constraint)
- {
- m_multiBodyConstraints.push_back(constraint);
- }
- void btMultiBodyDynamicsWorld::removeMultiBodyConstraint( btMultiBodyConstraint* constraint)
- {
- m_multiBodyConstraints.remove(constraint);
- }
|