123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470 |
- /*
- 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 "btDiscreteDynamicsWorld.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/btSimulationIslandManager.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"
- #if 0
- btAlignedObjectArray<btVector3> debugContacts;
- btAlignedObjectArray<btVector3> debugNormals;
- int startHit=2;
- int firstHit=startHit;
- #endif
- SIMD_FORCE_INLINE int btGetConstraintIslandId(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 btSortConstraintOnIslandPredicate
- {
- public:
- bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
- {
- int rIslandId0, lIslandId0;
- rIslandId0 = btGetConstraintIslandId(rhs);
- lIslandId0 = btGetConstraintIslandId(lhs);
- return lIslandId0 < rIslandId0;
- }
- };
- struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
- {
- btContactSolverInfo* m_solverInfo;
- btConstraintSolver* m_solver;
- btTypedConstraint** m_sortedConstraints;
- int m_numConstraints;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
- btAlignedObjectArray<btCollisionObject*> m_bodies;
- btAlignedObjectArray<btPersistentManifold*> m_manifolds;
- btAlignedObjectArray<btTypedConstraint*> m_constraints;
- InplaceSolverIslandCallback(
- btConstraintSolver* solver,
- btStackAlloc* stackAlloc,
- btDispatcher* dispatcher)
- : m_solverInfo(NULL),
- m_solver(solver),
- m_sortedConstraints(NULL),
- m_numConstraints(0),
- m_debugDrawer(NULL),
- m_dispatcher(dispatcher)
- {
- }
- InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
- {
- btAssert(0);
- (void)other;
- return *this;
- }
- SIMD_FORCE_INLINE void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer)
- {
- btAssert(solverInfo);
- m_solverInfo = solverInfo;
- m_sortedConstraints = sortedConstraints;
- m_numConstraints = numConstraints;
- m_debugDrawer = debugDrawer;
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.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->solveGroup(bodies, numBodies, manifolds, numManifolds, &m_sortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
- }
- else
- {
- //also add all non-contact constraints/joints for this island
- btTypedConstraint** startConstraint = 0;
- int numCurConstraints = 0;
- int i;
- //find the first constraint for this island
- for (i = 0; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
- {
- startConstraint = &m_sortedConstraints[i];
- break;
- }
- }
- //count the number of constraints in this island
- for (; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
- {
- numCurConstraints++;
- }
- }
- 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]);
- 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;
- m_solver->solveGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- }
- };
- btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
- : btDynamicsWorld(dispatcher, pairCache, collisionConfiguration),
- m_sortedConstraints(),
- m_solverIslandCallback(NULL),
- m_constraintSolver(constraintSolver),
- m_gravity(0, -10, 0),
- m_localTime(0),
- m_fixedTimeStep(0),
- m_synchronizeAllMotionStates(false),
- m_applySpeculativeContactRestitution(false),
- m_profileTimings(0),
- m_latencyMotionStateInterpolation(true)
- {
- if (!m_constraintSolver)
- {
- void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver), 16);
- m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver;
- m_ownsConstraintSolver = true;
- }
- else
- {
- m_ownsConstraintSolver = false;
- }
- {
- void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager), 16);
- m_islandManager = new (mem) btSimulationIslandManager();
- }
- m_ownsIslandManager = true;
- {
- void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback), 16);
- m_solverIslandCallback = new (mem) InplaceSolverIslandCallback(m_constraintSolver, 0, dispatcher);
- }
- }
- btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
- {
- //only delete it when we created it
- if (m_ownsIslandManager)
- {
- m_islandManager->~btSimulationIslandManager();
- btAlignedFree(m_islandManager);
- }
- if (m_solverIslandCallback)
- {
- m_solverIslandCallback->~InplaceSolverIslandCallback();
- btAlignedFree(m_solverIslandCallback);
- }
- if (m_ownsConstraintSolver)
- {
- m_constraintSolver->~btConstraintSolver();
- btAlignedFree(m_constraintSolver);
- }
- }
- void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
- {
- ///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
- ///to switch status _after_ adding kinematic objects to the world
- ///fix it for Bullet 3.x release
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body && body->getActivationState() != ISLAND_SLEEPING)
- {
- if (body->isKinematicObject())
- {
- //to calculate velocities next frame
- body->saveKinematicState(timeStep);
- }
- }
- }
- }
- void btDiscreteDynamicsWorld::debugDrawWorld()
- {
- BT_PROFILE("debugDrawWorld");
- btCollisionWorld::debugDrawWorld();
- bool drawConstraints = false;
- if (getDebugDrawer())
- {
- int mode = getDebugDrawer()->getDebugMode();
- if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
- {
- drawConstraints = true;
- }
- }
- if (drawConstraints)
- {
- for (int i = getNumConstraints() - 1; i >= 0; i--)
- {
- btTypedConstraint* constraint = getConstraint(i);
- debugDrawConstraint(constraint);
- }
- }
- if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals)))
- {
- int i;
- if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
- {
- for (i = 0; i < m_actions.size(); i++)
- {
- m_actions[i]->debugDraw(m_debugDrawer);
- }
- }
- }
- if (getDebugDrawer())
- getDebugDrawer()->flushLines();
- }
- void btDiscreteDynamicsWorld::clearForces()
- {
- ///@todo: iterate over awake simulation islands!
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- //need to check if next line is ok
- //it might break backward compatibility (people applying forces on sleeping objects get never cleared and accumulate on wake-up
- body->clearForces();
- }
- }
- ///apply gravity, call this once per timestep
- void btDiscreteDynamicsWorld::applyGravity()
- {
- ///@todo: iterate over awake simulation islands!
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body->isActive())
- {
- body->applyGravity();
- }
- }
- }
- void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
- {
- btAssert(body);
- if (body->getMotionState() && !body->isStaticOrKinematicObject())
- {
- //we need to call the update at least once, even for sleeping objects
- //otherwise the 'graphics' transform never updates properly
- ///@todo: add 'dirty' flag
- //if (body->getActivationState() != ISLAND_SLEEPING)
- {
- btTransform interpolatedTransform;
- btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
- body->getInterpolationLinearVelocity(), body->getInterpolationAngularVelocity(),
- (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime * body->getHitFraction(),
- interpolatedTransform);
- body->getMotionState()->setWorldTransform(interpolatedTransform);
- }
- }
- }
- void btDiscreteDynamicsWorld::synchronizeMotionStates()
- {
- // BT_PROFILE("synchronizeMotionStates");
- if (m_synchronizeAllMotionStates)
- {
- //iterate over all collision objects
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body)
- synchronizeSingleMotionState(body);
- }
- }
- else
- {
- //iterate over all active rigid bodies
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body->isActive())
- synchronizeSingleMotionState(body);
- }
- }
- }
- int btDiscreteDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
- {
- startProfiling(timeStep);
- int numSimulationSubSteps = 0;
- if (maxSubSteps)
- {
- //fixed timestep with interpolation
- m_fixedTimeStep = fixedTimeStep;
- m_localTime += timeStep;
- if (m_localTime >= fixedTimeStep)
- {
- numSimulationSubSteps = int(m_localTime / fixedTimeStep);
- m_localTime -= numSimulationSubSteps * fixedTimeStep;
- }
- }
- else
- {
- //variable timestep
- fixedTimeStep = timeStep;
- m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
- m_fixedTimeStep = 0;
- if (btFuzzyZero(timeStep))
- {
- numSimulationSubSteps = 0;
- maxSubSteps = 0;
- }
- else
- {
- numSimulationSubSteps = 1;
- maxSubSteps = 1;
- }
- }
- //process some debugging flags
- if (getDebugDrawer())
- {
- btIDebugDraw* debugDrawer = getDebugDrawer();
- gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
- }
- if (numSimulationSubSteps)
- {
- //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
- int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps) ? maxSubSteps : numSimulationSubSteps;
- saveKinematicState(fixedTimeStep * clampedSimulationSteps);
- applyGravity();
- for (int i = 0; i < clampedSimulationSteps; i++)
- {
- internalSingleStepSimulation(fixedTimeStep);
- synchronizeMotionStates();
- }
- }
- else
- {
- synchronizeMotionStates();
- }
- clearForces();
- #ifndef BT_NO_PROFILE
- CProfileManager::Increment_Frame_Counter();
- #endif //BT_NO_PROFILE
- return numSimulationSubSteps;
- }
- void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
- {
- BT_PROFILE("internalSingleStepSimulation");
- if (0 != m_internalPreTickCallback)
- {
- (*m_internalPreTickCallback)(this, timeStep);
- }
- ///apply gravity, predict motion
- predictUnconstraintMotion(timeStep);
- btDispatcherInfo& dispatchInfo = getDispatchInfo();
- dispatchInfo.m_timeStep = timeStep;
- dispatchInfo.m_stepCount = 0;
- dispatchInfo.m_debugDraw = getDebugDrawer();
- createPredictiveContacts(timeStep);
- ///perform collision detection
- performDiscreteCollisionDetection();
- calculateSimulationIslands();
- getSolverInfo().m_timeStep = timeStep;
- ///solve contact and other joint constraints
- solveConstraints(getSolverInfo());
- ///CallbackTriggers();
- ///integrate transforms
- integrateTransforms(timeStep);
- ///update vehicle simulation
- updateActions(timeStep);
- updateActivationState(timeStep);
- if (0 != m_internalTickCallback)
- {
- (*m_internalTickCallback)(this, timeStep);
- }
- }
- void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
- {
- m_gravity = gravity;
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body->isActive() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
- {
- body->setGravity(gravity);
- }
- }
- }
- btVector3 btDiscreteDynamicsWorld::getGravity() const
- {
- return m_gravity;
- }
- void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
- {
- btCollisionWorld::addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask);
- }
- void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
- {
- btRigidBody* body = btRigidBody::upcast(collisionObject);
- if (body)
- removeRigidBody(body);
- else
- btCollisionWorld::removeCollisionObject(collisionObject);
- }
- void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
- {
- m_nonStaticRigidBodies.remove(body);
- btCollisionWorld::removeCollisionObject(body);
- }
- void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
- {
- if (!body->isStaticOrKinematicObject() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
- {
- body->setGravity(m_gravity);
- }
- if (body->getCollisionShape())
- {
- if (!body->isStaticObject())
- {
- m_nonStaticRigidBodies.push_back(body);
- }
- else
- {
- body->setActivationState(ISLAND_SLEEPING);
- }
- bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
- int collisionFilterGroup = isDynamic ? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
- int collisionFilterMask = isDynamic ? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
- addCollisionObject(body, collisionFilterGroup, collisionFilterMask);
- }
- }
- void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
- {
- if (!body->isStaticOrKinematicObject() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
- {
- body->setGravity(m_gravity);
- }
- if (body->getCollisionShape())
- {
- if (!body->isStaticObject())
- {
- m_nonStaticRigidBodies.push_back(body);
- }
- else
- {
- body->setActivationState(ISLAND_SLEEPING);
- }
- addCollisionObject(body, group, mask);
- }
- }
- void btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
- {
- BT_PROFILE("updateActions");
- for (int i = 0; i < m_actions.size(); i++)
- {
- m_actions[i]->updateAction(this, timeStep);
- }
- }
- void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
- {
- BT_PROFILE("updateActivationState");
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body)
- {
- body->updateDeactivation(timeStep);
- if (body->wantsSleeping())
- {
- if (body->isStaticOrKinematicObject())
- {
- body->setActivationState(ISLAND_SLEEPING);
- }
- else
- {
- if (body->getActivationState() == ACTIVE_TAG)
- body->setActivationState(WANTS_DEACTIVATION);
- if (body->getActivationState() == ISLAND_SLEEPING)
- {
- body->setAngularVelocity(btVector3(0, 0, 0));
- body->setLinearVelocity(btVector3(0, 0, 0));
- }
- }
- }
- else
- {
- if (body->getActivationState() != DISABLE_DEACTIVATION)
- body->setActivationState(ACTIVE_TAG);
- }
- }
- }
- }
- void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies)
- {
- m_constraints.push_back(constraint);
- //Make sure the two bodies of a type constraint are different (possibly add this to the btTypedConstraint constructor?)
- btAssert(&constraint->getRigidBodyA() != &constraint->getRigidBodyB());
- if (disableCollisionsBetweenLinkedBodies)
- {
- constraint->getRigidBodyA().addConstraintRef(constraint);
- constraint->getRigidBodyB().addConstraintRef(constraint);
- }
- }
- void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
- {
- m_constraints.remove(constraint);
- constraint->getRigidBodyA().removeConstraintRef(constraint);
- constraint->getRigidBodyB().removeConstraintRef(constraint);
- }
- void btDiscreteDynamicsWorld::addAction(btActionInterface* action)
- {
- m_actions.push_back(action);
- }
- void btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
- {
- m_actions.remove(action);
- }
- void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
- {
- addAction(vehicle);
- }
- void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
- {
- removeAction(vehicle);
- }
- void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
- {
- addAction(character);
- }
- void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
- {
- removeAction(character);
- }
- void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
- {
- BT_PROFILE("solveConstraints");
- m_sortedConstraints.resize(m_constraints.size());
- int i;
- for (i = 0; i < getNumConstraints(); i++)
- {
- m_sortedConstraints[i] = m_constraints[i];
- }
- // btAssert(0);
- m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
- btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
- m_solverIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), getDebugDrawer());
- m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
- /// solve all the constraints for this island
- m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverIslandCallback);
- m_solverIslandCallback->processConstraints();
- m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
- }
- void btDiscreteDynamicsWorld::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());
- }
- }
- }
- }
- //Store the island id in each body
- getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
- }
- class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
- {
- public:
- btCollisionObject* m_me;
- btScalar m_allowedPenetration;
- btOverlappingPairCache* m_pairCache;
- btDispatcher* m_dispatcher;
- public:
- btClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btCollisionWorld::ClosestConvexResultCallback(fromA, toA),
- m_me(me),
- m_allowedPenetration(0.0f),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
- {
- }
- virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
- {
- if (convexResult.m_hitCollisionObject == m_me)
- return 1.0f;
- //ignore result if there is no contact response
- if (!convexResult.m_hitCollisionObject->hasContactResponse())
- return 1.0f;
- btVector3 linVelA, linVelB;
- linVelA = m_convexToWorld - m_convexFromWorld;
- linVelB = btVector3(0, 0, 0); //toB.getOrigin()-fromB.getOrigin();
- btVector3 relativeVelocity = (linVelA - linVelB);
- //don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if (convexResult.m_hitNormalLocal.dot(relativeVelocity) >= -m_allowedPenetration)
- return 1.f;
- return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
- }
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- //don't collide with itself
- if (proxy0->m_clientObject == m_me)
- return false;
- ///don't do CCD when the collision filters are not matching
- if (!ClosestConvexResultCallback::needsCollision(proxy0))
- return false;
- if (m_pairCache->getOverlapFilterCallback()) {
- btBroadphaseProxy* proxy1 = m_me->getBroadphaseHandle();
- bool collides = m_pairCache->needsBroadphaseCollision(proxy0, proxy1);
- if (!collides)
- {
- return false;
- }
- }
- btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
- if (!m_dispatcher->needsCollision(m_me, otherObj))
- return false;
- //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
- if (m_dispatcher->needsResponse(m_me, otherObj))
- {
- #if 0
- ///don't do CCD when there are already contact points (touching contact/penetration)
- btAlignedObjectArray<btPersistentManifold*> manifoldArray;
- btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
- if (collisionPair)
- {
- if (collisionPair->m_algorithm)
- {
- manifoldArray.resize(0);
- collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
- for (int j=0;j<manifoldArray.size();j++)
- {
- btPersistentManifold* manifold = manifoldArray[j];
- if (manifold->getNumContacts()>0)
- return false;
- }
- }
- }
- #endif
- return true;
- }
- return false;
- }
- };
- ///internal debugging variable. this value shouldn't be too high
- int gNumClampedCcdMotions = 0;
- void btDiscreteDynamicsWorld::createPredictiveContactsInternal(btRigidBody** bodies, int numBodies, btScalar timeStep)
- {
- btTransform predictedTrans;
- for (int i = 0; i < numBodies; i++)
- {
- btRigidBody* body = bodies[i];
- body->setHitFraction(1.f);
- if (body->isActive() && (!body->isStaticOrKinematicObject()))
- {
- body->predictIntegratedTransform(timeStep, predictedTrans);
- btScalar squareMotion = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()).length2();
- if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
- {
- BT_PROFILE("predictive convexSweepTest");
- if (body->getCollisionShape()->isConvex())
- {
- gNumClampedCcdMotions++;
- #ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
- class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
- {
- public:
- StaticOnlyCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btClosestNotMeConvexResultCallback(me, fromA, toA, pairCache, dispatcher)
- {
- }
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
- if (!otherObj->isStaticOrKinematicObject())
- return false;
- return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
- }
- };
- StaticOnlyCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
- #else
- btClosestNotMeConvexResultCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
- #endif
- //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- btSphereShape tmpSphere(body->getCcdSweptSphereRadius()); //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- sweepResults.m_allowedPenetration = getDispatchInfo().m_allowedCcdPenetration;
- sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
- sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
- btTransform modifiedPredictedTrans = predictedTrans;
- modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
- convexSweepTest(&tmpSphere, body->getWorldTransform(), modifiedPredictedTrans, sweepResults);
- if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
- {
- btVector3 distVec = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()) * sweepResults.m_closestHitFraction;
- btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
- 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;
- btManifoldPoint newPoint(btVector3(0, 0, 0), localPointB, sweepResults.m_hitNormalWorld, distance);
- bool isPredictive = true;
- int index = manifold->addManifoldPoint(newPoint, isPredictive);
- btManifoldPoint& pt = manifold->getContactPoint(index);
- pt.m_combinedRestitution = 0;
- pt.m_combinedFriction = gCalculateCombinedFrictionCallback(body, sweepResults.m_hitCollisionObject);
- pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
- pt.m_positionWorldOnB = worldPointB;
- }
- }
- }
- }
- }
- }
- 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)
- {
- btTransform predictedTrans;
- for (int i = 0; i < numBodies; i++)
- {
- btRigidBody* body = bodies[i];
- body->setHitFraction(1.f);
- if (body->isActive() && (!body->isStaticOrKinematicObject()))
- {
- body->predictIntegratedTransform(timeStep, predictedTrans);
- btScalar squareMotion = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()).length2();
- if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
- {
- BT_PROFILE("CCD motion clamping");
- if (body->getCollisionShape()->isConvex())
- {
- gNumClampedCcdMotions++;
- #ifdef USE_STATIC_ONLY
- class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
- {
- public:
- StaticOnlyCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btClosestNotMeConvexResultCallback(me, fromA, toA, pairCache, dispatcher)
- {
- }
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
- if (!otherObj->isStaticOrKinematicObject())
- return false;
- return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
- }
- };
- StaticOnlyCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
- #else
- btClosestNotMeConvexResultCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
- #endif
- //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- btSphereShape tmpSphere(body->getCcdSweptSphereRadius()); //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- sweepResults.m_allowedPenetration = getDispatchInfo().m_allowedCcdPenetration;
- sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
- sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
- btTransform modifiedPredictedTrans = predictedTrans;
- modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
- convexSweepTest(&tmpSphere, body->getWorldTransform(), modifiedPredictedTrans, sweepResults);
- if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
- {
- //printf("clamped integration to hit fraction = %f\n",fraction);
- body->setHitFraction(sweepResults.m_closestHitFraction);
- body->predictIntegratedTransform(timeStep * body->getHitFraction(), predictedTrans);
- body->setHitFraction(0.f);
- body->proceedToTransform(predictedTrans);
- #if 0
- btVector3 linVel = body->getLinearVelocity();
- btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
- btScalar maxSpeedSqr = maxSpeed*maxSpeed;
- if (linVel.length2()>maxSpeedSqr)
- {
- linVel.normalize();
- linVel*= maxSpeed;
- body->setLinearVelocity(linVel);
- btScalar ms2 = body->getLinearVelocity().length2();
- body->predictIntegratedTransform(timeStep, predictedTrans);
- btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
- btScalar smt = body->getCcdSquareMotionThreshold();
- printf("sm2=%f\n",sm2);
- }
- #else
- //don't apply the collision response right now, it will happen next frame
- //if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
- //btScalar appliedImpulse = 0.f;
- //btScalar depth = 0.f;
- //appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
- #endif
- continue;
- }
- }
- }
- body->proceedToTransform(predictedTrans);
- }
- }
- }
- 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");
- for (int i = 0; i < m_predictiveManifolds.size(); i++)
- {
- btPersistentManifold* manifold = m_predictiveManifolds[i];
- btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
- btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());
- for (int p = 0; p < manifold->getNumContacts(); p++)
- {
- const btManifoldPoint& pt = manifold->getContactPoint(p);
- btScalar combinedRestitution = gCalculateCombinedRestitutionCallback(body0, body1);
- if (combinedRestitution > 0 && pt.m_appliedImpulse != 0.f)
- //if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
- {
- btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse * combinedRestitution;
- const btVector3& pos1 = pt.getPositionWorldOnA();
- const btVector3& pos2 = pt.getPositionWorldOnB();
- btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
- btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
- if (body0)
- body0->applyImpulse(imp, rel_pos0);
- if (body1)
- body1->applyImpulse(-imp, rel_pos1);
- }
- }
- }
- }
- }
- void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
- {
- BT_PROFILE("predictUnconstraintMotion");
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (!body->isStaticOrKinematicObject())
- {
- //don't integrate/update velocities here, it happens in the constraint solver
- body->applyDamping(timeStep);
- body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
- }
- }
- }
- void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
- {
- (void)timeStep;
- #ifndef BT_NO_PROFILE
- CProfileManager::Reset();
- #endif //BT_NO_PROFILE
- }
- void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
- {
- bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
- bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
- btScalar dbgDrawSize = constraint->getDbgDrawSize();
- if (dbgDrawSize <= btScalar(0.f))
- {
- return;
- }
- switch (constraint->getConstraintType())
- {
- case POINT2POINT_CONSTRAINT_TYPE:
- {
- btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
- btTransform tr;
- tr.setIdentity();
- btVector3 pivot = p2pC->getPivotInA();
- pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
- tr.setOrigin(pivot);
- getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- // that ideally should draw the same frame
- pivot = p2pC->getPivotInB();
- pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
- tr.setOrigin(pivot);
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- }
- break;
- case HINGE_CONSTRAINT_TYPE:
- {
- btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
- btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- btScalar minAng = pHinge->getLowerLimit();
- btScalar maxAng = pHinge->getUpperLimit();
- if (minAng == maxAng)
- {
- break;
- }
- bool drawSect = true;
- if (!pHinge->hasLimit())
- {
- minAng = btScalar(0.f);
- maxAng = SIMD_2_PI;
- drawSect = false;
- }
- if (drawLimits)
- {
- btVector3& center = tr.getOrigin();
- btVector3 normal = tr.getBasis().getColumn(2);
- btVector3 axis = tr.getBasis().getColumn(0);
- getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0, 0, 0), drawSect);
- }
- }
- break;
- case CONETWIST_CONSTRAINT_TYPE:
- {
- btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
- btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if (drawLimits)
- {
- //const btScalar length = btScalar(5);
- const btScalar length = dbgDrawSize;
- static int nSegments = 8 * 4;
- btScalar fAngleInRadians = btScalar(2. * 3.1415926) * (btScalar)(nSegments - 1) / btScalar(nSegments);
- btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
- pPrev = tr * pPrev;
- for (int i = 0; i < nSegments; i++)
- {
- fAngleInRadians = btScalar(2. * 3.1415926) * (btScalar)i / btScalar(nSegments);
- btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
- pCur = tr * pCur;
- getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0, 0, 0));
- if (i % (nSegments / 8) == 0)
- getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0, 0, 0));
- pPrev = pCur;
- }
- btScalar tws = pCT->getTwistSpan();
- btScalar twa = pCT->getTwistAngle();
- bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
- if (useFrameB)
- {
- tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
- }
- else
- {
- tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
- }
- btVector3 pivot = tr.getOrigin();
- btVector3 normal = tr.getBasis().getColumn(0);
- btVector3 axis1 = tr.getBasis().getColumn(1);
- getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa - tws, -twa + tws, btVector3(0, 0, 0), true);
- }
- }
- break;
- case D6_SPRING_CONSTRAINT_TYPE:
- case D6_CONSTRAINT_TYPE:
- {
- btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
- btTransform tr = p6DOF->getCalculatedTransformA();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = p6DOF->getCalculatedTransformB();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if (drawLimits)
- {
- tr = p6DOF->getCalculatedTransformA();
- const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
- btVector3 up = tr.getBasis().getColumn(2);
- btVector3 axis = tr.getBasis().getColumn(0);
- btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
- btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
- btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
- btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
- getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
- axis = tr.getBasis().getColumn(1);
- btScalar ay = p6DOF->getAngle(1);
- btScalar az = p6DOF->getAngle(2);
- btScalar cy = btCos(ay);
- btScalar sy = btSin(ay);
- btScalar cz = btCos(az);
- btScalar sz = btSin(az);
- btVector3 ref;
- ref[0] = cy * cz * axis[0] + cy * sz * axis[1] - sy * axis[2];
- ref[1] = -sz * axis[0] + cz * axis[1];
- ref[2] = cz * sy * axis[0] + sz * sy * axis[1] + cy * axis[2];
- tr = p6DOF->getCalculatedTransformB();
- btVector3 normal = -tr.getBasis().getColumn(0);
- btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
- btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
- if (minFi > maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
- }
- else if (minFi < maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
- }
- tr = p6DOF->getCalculatedTransformA();
- btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
- btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
- getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
- }
- }
- break;
- ///note: the code for D6_SPRING_2_CONSTRAINT_TYPE is identical to D6_CONSTRAINT_TYPE, the D6_CONSTRAINT_TYPE+D6_SPRING_CONSTRAINT_TYPE will likely become obsolete/deprecated at some stage
- case D6_SPRING_2_CONSTRAINT_TYPE:
- {
- {
- btGeneric6DofSpring2Constraint* p6DOF = (btGeneric6DofSpring2Constraint*)constraint;
- btTransform tr = p6DOF->getCalculatedTransformA();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = p6DOF->getCalculatedTransformB();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if (drawLimits)
- {
- tr = p6DOF->getCalculatedTransformA();
- const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
- btVector3 up = tr.getBasis().getColumn(2);
- btVector3 axis = tr.getBasis().getColumn(0);
- btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
- btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
- if (minTh <= maxTh)
- {
- btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
- btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
- getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
- }
- axis = tr.getBasis().getColumn(1);
- btScalar ay = p6DOF->getAngle(1);
- btScalar az = p6DOF->getAngle(2);
- btScalar cy = btCos(ay);
- btScalar sy = btSin(ay);
- btScalar cz = btCos(az);
- btScalar sz = btSin(az);
- btVector3 ref;
- ref[0] = cy * cz * axis[0] + cy * sz * axis[1] - sy * axis[2];
- ref[1] = -sz * axis[0] + cz * axis[1];
- ref[2] = cz * sy * axis[0] + sz * sy * axis[1] + cy * axis[2];
- tr = p6DOF->getCalculatedTransformB();
- btVector3 normal = -tr.getBasis().getColumn(0);
- btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
- btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
- if (minFi > maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
- }
- else if (minFi < maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
- }
- tr = p6DOF->getCalculatedTransformA();
- btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
- btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
- getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
- }
- }
- break;
- }
- case SLIDER_CONSTRAINT_TYPE:
- {
- btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
- btTransform tr = pSlider->getCalculatedTransformA();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pSlider->getCalculatedTransformB();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if (drawLimits)
- {
- btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
- btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
- btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
- getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
- btVector3 normal = tr.getBasis().getColumn(0);
- btVector3 axis = tr.getBasis().getColumn(1);
- btScalar a_min = pSlider->getLowerAngLimit();
- btScalar a_max = pSlider->getUpperAngLimit();
- const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
- getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0, 0, 0), true);
- }
- }
- break;
- default:
- break;
- }
- return;
- }
- void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
- {
- if (m_ownsConstraintSolver)
- {
- btAlignedFree(m_constraintSolver);
- }
- m_ownsConstraintSolver = false;
- m_constraintSolver = solver;
- m_solverIslandCallback->m_solver = solver;
- }
- btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
- {
- return m_constraintSolver;
- }
- int btDiscreteDynamicsWorld::getNumConstraints() const
- {
- return int(m_constraints.size());
- }
- btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index)
- {
- return m_constraints[index];
- }
- const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
- {
- return m_constraints[index];
- }
- void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
- {
- int i;
- //serialize all collision objects
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
- {
- int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_RIGIDBODY_CODE, colObj);
- }
- }
- for (i = 0; i < m_constraints.size(); i++)
- {
- btTypedConstraint* constraint = m_constraints[i];
- int size = constraint->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(size, 1);
- const char* structType = constraint->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_CONSTRAINT_CODE, constraint);
- }
- }
- void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
- {
- #ifdef BT_USE_DOUBLE_PRECISION
- int len = sizeof(btDynamicsWorldDoubleData);
- btChunk* chunk = serializer->allocate(len, 1);
- btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
- #else //BT_USE_DOUBLE_PRECISION
- int len = sizeof(btDynamicsWorldFloatData);
- btChunk* chunk = serializer->allocate(len, 1);
- btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
- #endif //BT_USE_DOUBLE_PRECISION
- memset(worldInfo, 0x00, len);
- m_gravity.serialize(worldInfo->m_gravity);
- worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
- worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
- worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
- worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
- worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
- worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
- worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
- worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
- worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
- worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
- worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
- worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
- worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
- worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
- worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
- worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
- worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
- worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
- worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
- worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
- worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
-
- #ifdef BT_USE_DOUBLE_PRECISION
- const char* structType = "btDynamicsWorldDoubleData";
- #else //BT_USE_DOUBLE_PRECISION
- const char* structType = "btDynamicsWorldFloatData";
- #endif //BT_USE_DOUBLE_PRECISION
- serializer->finalizeChunk(chunk, structType, BT_DYNAMICSWORLD_CODE, worldInfo);
- }
- void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
- {
- serializer->startSerialization();
- serializeDynamicsWorldInfo(serializer);
- serializeCollisionObjects(serializer);
- serializeRigidBodies(serializer);
- serializeContactManifolds(serializer);
- serializer->finishSerialization();
- }
|