2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 #include "btMultiBodyDynamicsWorld.h"
17 #include "btMultiBodyConstraintSolver.h"
18 #include "btMultiBody.h"
19 #include "btMultiBodyLinkCollider.h"
20 #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
21 #include "LinearMath/btQuickprof.h"
22 #include "btMultiBodyConstraint.h"
23 #include "LinearMath/btIDebugDraw.h"
24 #include "LinearMath/btSerializer.h"
26 void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, int group, int mask)
28 m_multiBodies.push_back(body);
31 void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
33 m_multiBodies.remove(body);
36 void btMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
38 btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
39 predictMultiBodyTransforms(timeStep);
42 void btMultiBodyDynamicsWorld::calculateSimulationIslands()
44 BT_PROFILE("calculateSimulationIslands");
46 getSimulationIslandManager()->updateActivationState(getCollisionWorld(), getCollisionWorld()->getDispatcher());
49 //merge islands based on speculative contact manifolds too
50 for (int i = 0; i < this->m_predictiveManifolds.size(); i++)
52 btPersistentManifold* manifold = m_predictiveManifolds[i];
54 const btCollisionObject* colObj0 = manifold->getBody0();
55 const btCollisionObject* colObj1 = manifold->getBody1();
57 if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
58 ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
60 getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
67 int numConstraints = int(m_constraints.size());
68 for (i = 0; i < numConstraints; i++)
70 btTypedConstraint* constraint = m_constraints[i];
71 if (constraint->isEnabled())
73 const btRigidBody* colObj0 = &constraint->getRigidBodyA();
74 const btRigidBody* colObj1 = &constraint->getRigidBodyB();
76 if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
77 ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
79 getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
85 //merge islands linked by Featherstone link colliders
86 for (int i = 0; i < m_multiBodies.size(); i++)
88 btMultiBody* body = m_multiBodies[i];
90 btMultiBodyLinkCollider* prev = body->getBaseCollider();
92 for (int b = 0; b < body->getNumLinks(); b++)
94 btMultiBodyLinkCollider* cur = body->getLink(b).m_collider;
96 if (((cur) && (!(cur)->isStaticOrKinematicObject())) &&
97 ((prev) && (!(prev)->isStaticOrKinematicObject())))
99 int tagPrev = prev->getIslandTag();
100 int tagCur = cur->getIslandTag();
101 getSimulationIslandManager()->getUnionFind().unite(tagPrev, tagCur);
103 if (cur && !cur->isStaticOrKinematicObject())
109 //merge islands linked by multibody constraints
111 for (int i = 0; i < this->m_multiBodyConstraints.size(); i++)
113 btMultiBodyConstraint* c = m_multiBodyConstraints[i];
114 int tagA = c->getIslandIdA();
115 int tagB = c->getIslandIdB();
116 if (tagA >= 0 && tagB >= 0)
117 getSimulationIslandManager()->getUnionFind().unite(tagA, tagB);
121 //Store the island id in each body
122 getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
125 void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
127 BT_PROFILE("btMultiBodyDynamicsWorld::updateActivationState");
129 for (int i = 0; i < m_multiBodies.size(); i++)
131 btMultiBody* body = m_multiBodies[i];
134 body->checkMotionAndSleepIfRequired(timeStep);
135 if (!body->isAwake())
137 btMultiBodyLinkCollider* col = body->getBaseCollider();
138 if (col && col->getActivationState() == ACTIVE_TAG)
140 if (body->hasFixedBase())
142 col->setActivationState(FIXED_BASE_MULTI_BODY);
145 col->setActivationState(WANTS_DEACTIVATION);
148 col->setDeactivationTime(0.f);
150 for (int b = 0; b < body->getNumLinks(); b++)
152 btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
153 if (col && col->getActivationState() == ACTIVE_TAG)
155 col->setActivationState(WANTS_DEACTIVATION);
156 col->setDeactivationTime(0.f);
162 btMultiBodyLinkCollider* col = body->getBaseCollider();
163 if (col && col->getActivationState() != DISABLE_DEACTIVATION)
164 col->setActivationState(ACTIVE_TAG);
166 for (int b = 0; b < body->getNumLinks(); b++)
168 btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
169 if (col && col->getActivationState() != DISABLE_DEACTIVATION)
170 col->setActivationState(ACTIVE_TAG);
176 btDiscreteDynamicsWorld::updateActivationState(timeStep);
179 void btMultiBodyDynamicsWorld::getAnalyticsData(btAlignedObjectArray<btSolverAnalyticsData>& islandAnalyticsData) const
181 islandAnalyticsData = m_solverMultiBodyIslandCallback->m_islandAnalyticsData;
184 btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
185 : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
186 m_multiBodyConstraintSolver(constraintSolver)
188 //split impulse is not yet supported for Featherstone hierarchies
189 // getSolverInfo().m_splitImpulse = false;
190 getSolverInfo().m_solverMode |= SOLVER_USE_2_FRICTION_DIRECTIONS;
191 m_solverMultiBodyIslandCallback = new MultiBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
194 btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld()
196 delete m_solverMultiBodyIslandCallback;
199 void btMultiBodyDynamicsWorld::setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
201 m_multiBodyConstraintSolver = solver;
202 m_solverMultiBodyIslandCallback->setMultiBodyConstraintSolver(solver);
203 btDiscreteDynamicsWorld::setConstraintSolver(solver);
206 void btMultiBodyDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
208 if (solver->getSolverType() == BT_MULTIBODY_SOLVER)
210 m_multiBodyConstraintSolver = (btMultiBodyConstraintSolver*)solver;
212 btDiscreteDynamicsWorld::setConstraintSolver(solver);
215 void btMultiBodyDynamicsWorld::forwardKinematics()
217 for (int b = 0; b < m_multiBodies.size(); b++)
219 btMultiBody* bod = m_multiBodies[b];
220 bod->forwardKinematics(m_scratch_world_to_local, m_scratch_local_origin);
223 void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
225 solveExternalForces(solverInfo);
227 solveInternalConstraints(solverInfo);
230 void btMultiBodyDynamicsWorld::buildIslands()
232 m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverMultiBodyIslandCallback);
235 void btMultiBodyDynamicsWorld::solveInternalConstraints(btContactSolverInfo& solverInfo)
237 /// solve all the constraints for this island
238 m_solverMultiBodyIslandCallback->processConstraints();
239 m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
241 BT_PROFILE("btMultiBody stepVelocities");
242 for (int i = 0; i < this->m_multiBodies.size(); i++)
244 btMultiBody* bod = m_multiBodies[i];
246 bool isSleeping = false;
248 if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
252 for (int b = 0; b < bod->getNumLinks(); b++)
254 if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
260 //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
261 m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
262 m_scratch_v.resize(bod->getNumLinks() + 1);
263 m_scratch_m.resize(bod->getNumLinks() + 1);
265 if (bod->internalNeedsJointFeedback())
267 if (!bod->isUsingRK4Integration())
269 if (bod->internalNeedsJointFeedback())
271 bool isConstraintPass = true;
272 bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
273 getSolverInfo().m_jointFeedbackInWorldSpace,
274 getSolverInfo().m_jointFeedbackInJointFrame);
281 for (int i = 0; i < this->m_multiBodies.size(); i++)
283 btMultiBody* bod = m_multiBodies[i];
284 bod->processDeltaVeeMultiDof2();
288 void btMultiBodyDynamicsWorld::solveExternalForces(btContactSolverInfo& solverInfo)
292 BT_PROFILE("solveConstraints");
294 clearMultiBodyConstraintForces();
296 m_sortedConstraints.resize(m_constraints.size());
298 for (i = 0; i < getNumConstraints(); i++)
300 m_sortedConstraints[i] = m_constraints[i];
302 m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
303 btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
305 m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
306 for (i = 0; i < m_multiBodyConstraints.size(); i++)
308 m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
310 m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
312 btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
314 m_solverMultiBodyIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
315 m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
317 #ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
319 BT_PROFILE("btMultiBody addForce");
320 for (int i = 0; i < this->m_multiBodies.size(); i++)
322 btMultiBody* bod = m_multiBodies[i];
324 bool isSleeping = false;
326 if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
330 for (int b = 0; b < bod->getNumLinks(); b++)
332 if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
338 //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
339 m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
340 m_scratch_v.resize(bod->getNumLinks() + 1);
341 m_scratch_m.resize(bod->getNumLinks() + 1);
343 bod->addBaseForce(m_gravity * bod->getBaseMass());
345 for (int j = 0; j < bod->getNumLinks(); ++j)
347 bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
352 #endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
355 BT_PROFILE("btMultiBody stepVelocities");
356 for (int i = 0; i < this->m_multiBodies.size(); i++)
358 btMultiBody* bod = m_multiBodies[i];
360 bool isSleeping = false;
362 if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
366 for (int b = 0; b < bod->getNumLinks(); b++)
368 if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
374 //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
375 m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
376 m_scratch_v.resize(bod->getNumLinks() + 1);
377 m_scratch_m.resize(bod->getNumLinks() + 1);
378 bool doNotUpdatePos = false;
379 bool isConstraintPass = false;
381 if (!bod->isUsingRK4Integration())
383 bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep,
384 m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
385 getSolverInfo().m_jointFeedbackInWorldSpace,
386 getSolverInfo().m_jointFeedbackInJointFrame);
391 int numDofs = bod->getNumDofs() + 6;
392 int numPosVars = bod->getNumPosVars() + 7;
393 btAlignedObjectArray<btScalar> scratch_r2;
394 scratch_r2.resize(2 * numPosVars + 8 * numDofs);
396 btScalar* pMem = &scratch_r2[0];
397 btScalar* scratch_q0 = pMem;
399 btScalar* scratch_qx = pMem;
401 btScalar* scratch_qd0 = pMem;
403 btScalar* scratch_qd1 = pMem;
405 btScalar* scratch_qd2 = pMem;
407 btScalar* scratch_qd3 = pMem;
409 btScalar* scratch_qdd0 = pMem;
411 btScalar* scratch_qdd1 = pMem;
413 btScalar* scratch_qdd2 = pMem;
415 btScalar* scratch_qdd3 = pMem;
417 btAssert((pMem - (2 * numPosVars + 8 * numDofs)) == &scratch_r2[0]);
420 //copy q0 to scratch_q0 and qd0 to scratch_qd0
421 scratch_q0[0] = bod->getWorldToBaseRot().x();
422 scratch_q0[1] = bod->getWorldToBaseRot().y();
423 scratch_q0[2] = bod->getWorldToBaseRot().z();
424 scratch_q0[3] = bod->getWorldToBaseRot().w();
425 scratch_q0[4] = bod->getBasePos().x();
426 scratch_q0[5] = bod->getBasePos().y();
427 scratch_q0[6] = bod->getBasePos().z();
429 for (int link = 0; link < bod->getNumLinks(); ++link)
431 for (int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
432 scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
435 for (int dof = 0; dof < numDofs; ++dof)
436 scratch_qd0[dof] = bod->getVelocityVector()[dof];
441 btScalar *scratch_qx, *scratch_q0;
445 for (int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
446 scratch_qx[dof] = scratch_q0[dof];
448 } pResetQx = {bod, scratch_qx, scratch_q0};
452 void operator()(btScalar dt, const btScalar* pDer, const btScalar* pCurVal, btScalar* pVal, int size)
454 for (int i = 0; i < size; ++i)
455 pVal[i] = pCurVal[i] + dt * pDer[i];
462 void operator()(btMultiBody* pBody, const btScalar* pData)
464 btScalar* pVel = const_cast<btScalar*>(pBody->getVelocityVector());
466 for (int i = 0; i < pBody->getNumDofs() + 6; ++i)
469 } pCopyToVelocityVector;
473 void operator()(const btScalar* pSrc, btScalar* pDst, int start, int size)
475 for (int i = 0; i < size; ++i)
476 pDst[i] = pSrc[start + i];
481 btScalar h = solverInfo.m_timeStep;
482 #define output &m_scratch_r[bod->getNumDofs()]
483 //calc qdd0 from: q0 & qd0
484 bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
485 isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
486 getSolverInfo().m_jointFeedbackInJointFrame);
487 pCopy(output, scratch_qdd0, 0, numDofs);
488 //calc q1 = q0 + h/2 * qd0
490 bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd0);
491 //calc qd1 = qd0 + h/2 * qdd0
492 pEulerIntegrate(btScalar(.5) * h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
494 //calc qdd1 from: q1 & qd1
495 pCopyToVelocityVector(bod, scratch_qd1);
496 bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
497 isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
498 getSolverInfo().m_jointFeedbackInJointFrame);
499 pCopy(output, scratch_qdd1, 0, numDofs);
500 //calc q2 = q0 + h/2 * qd1
502 bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd1);
503 //calc qd2 = qd0 + h/2 * qdd1
504 pEulerIntegrate(btScalar(.5) * h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
506 //calc qdd2 from: q2 & qd2
507 pCopyToVelocityVector(bod, scratch_qd2);
508 bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
509 isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
510 getSolverInfo().m_jointFeedbackInJointFrame);
511 pCopy(output, scratch_qdd2, 0, numDofs);
512 //calc q3 = q0 + h * qd2
514 bod->stepPositionsMultiDof(h, scratch_qx, scratch_qd2);
515 //calc qd3 = qd0 + h * qdd2
516 pEulerIntegrate(h, scratch_qdd2, scratch_qd0, scratch_qd3, numDofs);
518 //calc qdd3 from: q3 & qd3
519 pCopyToVelocityVector(bod, scratch_qd3);
520 bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
521 isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
522 getSolverInfo().m_jointFeedbackInJointFrame);
523 pCopy(output, scratch_qdd3, 0, numDofs);
526 //calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
527 //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
528 btAlignedObjectArray<btScalar> delta_q;
529 delta_q.resize(numDofs);
530 btAlignedObjectArray<btScalar> delta_qd;
531 delta_qd.resize(numDofs);
532 for (int i = 0; i < numDofs; ++i)
534 delta_q[i] = h / btScalar(6.) * (scratch_qd0[i] + 2 * scratch_qd1[i] + 2 * scratch_qd2[i] + scratch_qd3[i]);
535 delta_qd[i] = h / btScalar(6.) * (scratch_qdd0[i] + 2 * scratch_qdd1[i] + 2 * scratch_qdd2[i] + scratch_qdd3[i]);
536 //delta_q[i] = h*scratch_qd0[i];
537 //delta_qd[i] = h*scratch_qdd0[i];
540 pCopyToVelocityVector(bod, scratch_qd0);
541 bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
545 btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
546 pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
548 for (int i = 0; i < numDofs; ++i)
549 pRealBuf[i] = delta_q[i];
551 //bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
552 bod->setPosUpdated(true);
555 //ugly hack which resets the cached data to t0 (needed for constraint solver)
557 for (int link = 0; link < bod->getNumLinks(); ++link)
558 bod->getLink(link).updateCacheMultiDof();
559 bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m,
560 isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
561 getSolverInfo().m_jointFeedbackInJointFrame);
566 #ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
567 bod->clearForcesAndTorques();
568 #endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
575 void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
577 btDiscreteDynamicsWorld::integrateTransforms(timeStep);
578 integrateMultiBodyTransforms(timeStep);
581 void btMultiBodyDynamicsWorld::integrateMultiBodyTransforms(btScalar timeStep)
583 BT_PROFILE("btMultiBody stepPositions");
584 //integrate and update the Featherstone hierarchies
586 for (int b = 0; b < m_multiBodies.size(); b++)
588 btMultiBody* bod = m_multiBodies[b];
589 bool isSleeping = false;
590 if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
594 for (int b = 0; b < bod->getNumLinks(); b++)
596 if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
603 int nLinks = bod->getNumLinks();
605 ///base + num m_links
606 if (!bod->isPosUpdated())
607 bod->stepPositionsMultiDof(timeStep);
610 btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
611 pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
613 bod->stepPositionsMultiDof(1, 0, pRealBuf);
614 bod->setPosUpdated(false);
618 m_scratch_world_to_local.resize(nLinks + 1);
619 m_scratch_local_origin.resize(nLinks + 1);
620 bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
621 bod->substractSplitV();
625 bod->clearVelocities();
630 void btMultiBodyDynamicsWorld::predictMultiBodyTransforms(btScalar timeStep)
632 BT_PROFILE("btMultiBody stepPositions");
633 //integrate and update the Featherstone hierarchies
635 for (int b = 0; b < m_multiBodies.size(); b++)
637 btMultiBody* bod = m_multiBodies[b];
638 bool isSleeping = false;
639 if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
643 for (int b = 0; b < bod->getNumLinks(); b++)
645 if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
651 int nLinks = bod->getNumLinks();
652 bod->predictPositionsMultiDof(timeStep);
653 m_scratch_world_to_local.resize(nLinks + 1);
654 m_scratch_local_origin.resize(nLinks + 1);
655 bod->updateCollisionObjectInterpolationWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
659 bod->clearVelocities();
664 void btMultiBodyDynamicsWorld::addMultiBodyConstraint(btMultiBodyConstraint* constraint)
666 m_multiBodyConstraints.push_back(constraint);
669 void btMultiBodyDynamicsWorld::removeMultiBodyConstraint(btMultiBodyConstraint* constraint)
671 m_multiBodyConstraints.remove(constraint);
674 void btMultiBodyDynamicsWorld::debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint)
676 constraint->debugDraw(getDebugDrawer());
679 void btMultiBodyDynamicsWorld::debugDrawWorld()
681 BT_PROFILE("btMultiBodyDynamicsWorld debugDrawWorld");
683 btDiscreteDynamicsWorld::debugDrawWorld();
685 bool drawConstraints = false;
686 if (getDebugDrawer())
688 int mode = getDebugDrawer()->getDebugMode();
689 if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
691 drawConstraints = true;
696 BT_PROFILE("btMultiBody debugDrawWorld");
698 for (int c = 0; c < m_multiBodyConstraints.size(); c++)
700 btMultiBodyConstraint* constraint = m_multiBodyConstraints[c];
701 debugDrawMultiBodyConstraint(constraint);
704 for (int b = 0; b < m_multiBodies.size(); b++)
706 btMultiBody* bod = m_multiBodies[b];
707 bod->forwardKinematics(m_scratch_world_to_local1, m_scratch_local_origin1);
709 if (mode & btIDebugDraw::DBG_DrawFrames)
711 getDebugDrawer()->drawTransform(bod->getBaseWorldTransform(), 0.1);
714 for (int m = 0; m < bod->getNumLinks(); m++)
716 const btTransform& tr = bod->getLink(m).m_cachedWorldTransform;
717 if (mode & btIDebugDraw::DBG_DrawFrames)
719 getDebugDrawer()->drawTransform(tr, 0.1);
721 //draw the joint axis
722 if (bod->getLink(m).m_jointType == btMultibodyLink::eRevolute)
724 btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_topVec) * 0.1;
726 btVector4 color(0, 0, 0, 1); //1,1,1);
727 btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
728 btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
729 getDebugDrawer()->drawLine(from, to, color);
731 if (bod->getLink(m).m_jointType == btMultibodyLink::eFixed)
733 btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_bottomVec) * 0.1;
735 btVector4 color(0, 0, 0, 1); //1,1,1);
736 btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
737 btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
738 getDebugDrawer()->drawLine(from, to, color);
740 if (bod->getLink(m).m_jointType == btMultibodyLink::ePrismatic)
742 btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_bottomVec) * 0.1;
744 btVector4 color(0, 0, 0, 1); //1,1,1);
745 btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
746 btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
747 getDebugDrawer()->drawLine(from, to, color);
755 void btMultiBodyDynamicsWorld::applyGravity()
757 btDiscreteDynamicsWorld::applyGravity();
758 #ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
759 BT_PROFILE("btMultiBody addGravity");
760 for (int i = 0; i < this->m_multiBodies.size(); i++)
762 btMultiBody* bod = m_multiBodies[i];
764 bool isSleeping = false;
766 if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
770 for (int b = 0; b < bod->getNumLinks(); b++)
772 if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
778 bod->addBaseForce(m_gravity * bod->getBaseMass());
780 for (int j = 0; j < bod->getNumLinks(); ++j)
782 bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
786 #endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
789 void btMultiBodyDynamicsWorld::clearMultiBodyConstraintForces()
791 for (int i = 0; i < this->m_multiBodies.size(); i++)
793 btMultiBody* bod = m_multiBodies[i];
794 bod->clearConstraintForces();
797 void btMultiBodyDynamicsWorld::clearMultiBodyForces()
800 // BT_PROFILE("clearMultiBodyForces");
801 for (int i = 0; i < this->m_multiBodies.size(); i++)
803 btMultiBody* bod = m_multiBodies[i];
805 bool isSleeping = false;
807 if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
811 for (int b = 0; b < bod->getNumLinks(); b++)
813 if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
819 btMultiBody* bod = m_multiBodies[i];
820 bod->clearForcesAndTorques();
825 void btMultiBodyDynamicsWorld::clearForces()
827 btDiscreteDynamicsWorld::clearForces();
829 #ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
830 clearMultiBodyForces();
834 void btMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
836 serializer->startSerialization();
838 serializeDynamicsWorldInfo(serializer);
840 serializeMultiBodies(serializer);
842 serializeRigidBodies(serializer);
844 serializeCollisionObjects(serializer);
846 serializeContactManifolds(serializer);
848 serializer->finishSerialization();
851 void btMultiBodyDynamicsWorld::serializeMultiBodies(btSerializer* serializer)
854 //serialize all collision objects
855 for (i = 0; i < m_multiBodies.size(); i++)
857 btMultiBody* mb = m_multiBodies[i];
859 int len = mb->calculateSerializeBufferSize();
860 btChunk* chunk = serializer->allocate(len, 1);
861 const char* structType = mb->serialize(chunk->m_oldPtr, serializer);
862 serializer->finalizeChunk(chunk, structType, BT_MULTIBODY_CODE, mb);
866 //serialize all multibody links (collision objects)
867 for (i = 0; i < m_collisionObjects.size(); i++)
869 btCollisionObject* colObj = m_collisionObjects[i];
870 if (colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
872 int len = colObj->calculateSerializeBufferSize();
873 btChunk* chunk = serializer->allocate(len, 1);
874 const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
875 serializer->finalizeChunk(chunk, structType, BT_MB_LINKCOLLIDER_CODE, colObj);
880 void btMultiBodyDynamicsWorld::saveKinematicState(btScalar timeStep)
882 btDiscreteDynamicsWorld::saveKinematicState(timeStep);
883 for(int i = 0; i < m_multiBodies.size(); i++)
885 btMultiBody* body = m_multiBodies[i];
886 if(body->isBaseKinematic())
887 body->saveKinematicState(timeStep);
892 //void btMultiBodyDynamicsWorld::setSplitIslands(bool split)
894 // m_islandManager->setSplitIslands(split);