diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2019-01-07 15:08:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-07 15:08:41 +0100 |
commit | dab650fcaa3eb37deee5118d678a3763ac78a58a (patch) | |
tree | 3131df01280f91a61b4721eed132a5b6b21881ba /thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp | |
parent | a3a537c2cf86ff4bf82385bbd17606654f8013c4 (diff) | |
parent | 22b7c9dfa80d0f7abca40f061865c2ab3c136a74 (diff) |
Merge pull request #24740 from OBKF/update-bullet-physics
Update Bullet physics to commit 126b676
Diffstat (limited to 'thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp')
-rw-r--r-- | thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp | 2555 |
1 files changed, 1244 insertions, 1311 deletions
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp index 4306c37e49..2718da4a50 100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp @@ -13,7 +13,6 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btSequentialImpulseConstraintSolverMt.h" #include "LinearMath/btQuickprof.h" @@ -23,8 +22,6 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" - - bool btSequentialImpulseConstraintSolverMt::s_allowNestedParallelForLoops = false; // some task schedulers don't like nested loops int btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching = 250; int btSequentialImpulseConstraintSolverMt::s_minBatchSize = 50; @@ -32,613 +29,594 @@ int btSequentialImpulseConstraintSolverMt::s_maxBatchSize = 100; btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_contactBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D; btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_jointBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D; - btSequentialImpulseConstraintSolverMt::btSequentialImpulseConstraintSolverMt() { - m_numFrictionDirections = 1; - m_useBatching = false; - m_useObsoleteJointConstraints = false; + m_numFrictionDirections = 1; + m_useBatching = false; + m_useObsoleteJointConstraints = false; } - btSequentialImpulseConstraintSolverMt::~btSequentialImpulseConstraintSolverMt() { } - void btSequentialImpulseConstraintSolverMt::setupBatchedContactConstraints() { - BT_PROFILE("setupBatchedContactConstraints"); - m_batchedContactConstraints.setup( &m_tmpSolverContactConstraintPool, - m_tmpSolverBodyPool, - s_contactBatchingMethod, - s_minBatchSize, - s_maxBatchSize, - &m_scratchMemory - ); + BT_PROFILE("setupBatchedContactConstraints"); + m_batchedContactConstraints.setup(&m_tmpSolverContactConstraintPool, + m_tmpSolverBodyPool, + s_contactBatchingMethod, + s_minBatchSize, + s_maxBatchSize, + &m_scratchMemory); } - void btSequentialImpulseConstraintSolverMt::setupBatchedJointConstraints() { - BT_PROFILE("setupBatchedJointConstraints"); - m_batchedJointConstraints.setup( &m_tmpSolverNonContactConstraintPool, - m_tmpSolverBodyPool, - s_jointBatchingMethod, - s_minBatchSize, - s_maxBatchSize, - &m_scratchMemory - ); + BT_PROFILE("setupBatchedJointConstraints"); + m_batchedJointConstraints.setup(&m_tmpSolverNonContactConstraintPool, + m_tmpSolverBodyPool, + s_jointBatchingMethod, + s_minBatchSize, + s_maxBatchSize, + &m_scratchMemory); } - void btSequentialImpulseConstraintSolverMt::internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal) { - btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint]; - - btVector3 rel_pos1; - btVector3 rel_pos2; - btScalar relaxation; - - int solverBodyIdA = contactConstraint.m_solverBodyIdA; - int solverBodyIdB = contactConstraint.m_solverBodyIdB; - - btSolverBody* solverBodyA = &m_tmpSolverBodyPool[ solverBodyIdA ]; - btSolverBody* solverBodyB = &m_tmpSolverBodyPool[ solverBodyIdB ]; - - btRigidBody* colObj0 = solverBodyA->m_originalBody; - btRigidBody* colObj1 = solverBodyB->m_originalBody; - - btManifoldPoint& cp = *static_cast<btManifoldPoint*>( contactConstraint.m_originalContactPoint ); - - const btVector3& pos1 = cp.getPositionWorldOnA(); - const btVector3& pos2 = cp.getPositionWorldOnB(); - - rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin(); - rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin(); - - btVector3 vel1; - btVector3 vel2; - - solverBodyA->getVelocityInLocalPointNoDelta( rel_pos1, vel1 ); - solverBodyB->getVelocityInLocalPointNoDelta( rel_pos2, vel2 ); - - btVector3 vel = vel1 - vel2; - btScalar rel_vel = cp.m_normalWorldOnB.dot( vel ); - - setupContactConstraint( contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2 ); - - // setup rolling friction constraints - int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint]; - if (rollingFrictionIndex >= 0) - { - btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ rollingFrictionIndex ]; - btAssert( spinningFrictionConstraint.m_frictionIndex == iContactConstraint ); - setupTorsionalFrictionConstraint( spinningFrictionConstraint, - cp.m_normalWorldOnB, - solverBodyIdA, - solverBodyIdB, - cp, - cp.m_combinedSpinningFriction, - rel_pos1, - rel_pos2, - colObj0, - colObj1, - relaxation, - 0.0f, - 0.0f - ); - btVector3 axis[2]; - btPlaneSpace1( cp.m_normalWorldOnB, axis[0], axis[1] ); - axis[0].normalize(); - axis[1].normalize(); - - applyAnisotropicFriction( colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION ); - applyAnisotropicFriction( colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION ); - applyAnisotropicFriction( colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION ); - applyAnisotropicFriction( colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION ); - // put the largest axis first - if (axis[1].length2() > axis[0].length2()) - { - btSwap(axis[0], axis[1]); - } - const btScalar kRollingFrictionThreshold = 0.001f; - for (int i = 0; i < 2; ++i) - { - int iRollingFric = rollingFrictionIndex + 1 + i; - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ]; - btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint); - btVector3 dir = axis[i]; - if ( dir.length() > kRollingFrictionThreshold ) - { - setupTorsionalFrictionConstraint( rollingFrictionConstraint, - dir, - solverBodyIdA, - solverBodyIdB, - cp, - cp.m_combinedRollingFriction, - rel_pos1, - rel_pos2, - colObj0, - colObj1, - relaxation, - 0.0f, - 0.0f - ); - } - else - { - rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint - } - } - } - - // setup friction constraints - // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip); - { - ///Bullet has several options to set the friction directions - ///By default, each contact has only a single friction direction that is recomputed automatically very frame - ///based on the relative linear velocity. - ///If the relative velocity it zero, it will automatically compute a friction direction. - - ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS. - ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction. - /// - ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity. - /// - ///The user can manually override the friction directions for certain contacts using a contact callback, - ///and set the cp.m_lateralFrictionInitialized to true - ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) - ///this will give a conveyor belt effect - /// - btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex]; - btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint); - - btSolverConstraint* frictionConstraint2 = NULL; - if ( infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS ) - { - frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1]; - btAssert( frictionConstraint2->m_frictionIndex == iContactConstraint ); - } - - if ( !( infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING ) || !( cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED ) ) - { - cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; - btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); - if ( !( infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION ) && lat_rel_vel > SIMD_EPSILON ) - { - cp.m_lateralFrictionDir1 *= 1.f / btSqrt( lat_rel_vel ); - applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal ); - - if ( frictionConstraint2 ) - { - cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross( cp.m_normalWorldOnB ); - cp.m_lateralFrictionDir2.normalize();//?? - applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal ); - } - } - else - { - btPlaneSpace1( cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2 ); - - applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal ); - - if ( frictionConstraint2 ) - { - applyAnisotropicFriction( colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - applyAnisotropicFriction( colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION ); - setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal ); - } - - if ( ( infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS ) && ( infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION ) ) - { - cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED; - } - } - } - else - { - setupFrictionConstraint( *frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM ); - if ( frictionConstraint2 ) - { - setupFrictionConstraint( *frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM ); - } - } - } - - setFrictionConstraintImpulse( contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal ); -} + btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint]; + + btVector3 rel_pos1; + btVector3 rel_pos2; + btScalar relaxation; + + int solverBodyIdA = contactConstraint.m_solverBodyIdA; + int solverBodyIdB = contactConstraint.m_solverBodyIdB; + + btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB]; + + btRigidBody* colObj0 = solverBodyA->m_originalBody; + btRigidBody* colObj1 = solverBodyB->m_originalBody; + + btManifoldPoint& cp = *static_cast<btManifoldPoint*>(contactConstraint.m_originalContactPoint); + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin(); + rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin(); + + btVector3 vel1; + btVector3 vel2; + + solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1); + solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2); + + btVector3 vel = vel1 - vel2; + btScalar rel_vel = cp.m_normalWorldOnB.dot(vel); + + setupContactConstraint(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2); + + // setup rolling friction constraints + int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint]; + if (rollingFrictionIndex >= 0) + { + btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex]; + btAssert(spinningFrictionConstraint.m_frictionIndex == iContactConstraint); + setupTorsionalFrictionConstraint(spinningFrictionConstraint, + cp.m_normalWorldOnB, + solverBodyIdA, + solverBodyIdB, + cp, + cp.m_combinedSpinningFriction, + rel_pos1, + rel_pos2, + colObj0, + colObj1, + relaxation, + 0.0f, + 0.0f); + btVector3 axis[2]; + btPlaneSpace1(cp.m_normalWorldOnB, axis[0], axis[1]); + axis[0].normalize(); + axis[1].normalize(); + + applyAnisotropicFriction(colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + applyAnisotropicFriction(colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); + // put the largest axis first + if (axis[1].length2() > axis[0].length2()) + { + btSwap(axis[0], axis[1]); + } + const btScalar kRollingFrictionThreshold = 0.001f; + for (int i = 0; i < 2; ++i) + { + int iRollingFric = rollingFrictionIndex + 1 + i; + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric]; + btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint); + btVector3 dir = axis[i]; + if (dir.length() > kRollingFrictionThreshold) + { + setupTorsionalFrictionConstraint(rollingFrictionConstraint, + dir, + solverBodyIdA, + solverBodyIdB, + cp, + cp.m_combinedRollingFriction, + rel_pos1, + rel_pos2, + colObj0, + colObj1, + relaxation, + 0.0f, + 0.0f); + } + else + { + rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint + } + } + } + + // setup friction constraints + // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip); + { + ///Bullet has several options to set the friction directions + ///By default, each contact has only a single friction direction that is recomputed automatically very frame + ///based on the relative linear velocity. + ///If the relative velocity it zero, it will automatically compute a friction direction. + + ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS. + ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction. + /// + ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity. + /// + ///The user can manually override the friction directions for certain contacts using a contact callback, + ///and set the cp.m_lateralFrictionInitialized to true + ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2) + ///this will give a conveyor belt effect + /// + btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex]; + btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint); + + btSolverConstraint* frictionConstraint2 = NULL; + if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) + { + frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1]; + btAssert(frictionConstraint2->m_frictionIndex == iContactConstraint); + } + + if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED)) + { + cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); + if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON) + { + cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel); + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); + + if (frictionConstraint2) + { + cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); + cp.m_lateralFrictionDir2.normalize(); //?? + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); + } + } + else + { + btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2); + + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION); + setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); + + if (frictionConstraint2) + { + applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION); + setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal); + } + + if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION)) + { + cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED; + } + } + } + else + { + setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM); + if (frictionConstraint2) + { + setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM); + } + } + } + setFrictionConstraintImpulse(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal); +} struct SetupContactConstraintsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - const btContactSolverInfo* m_infoGlobal; - - SetupContactConstraintsLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_bc = bc; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "SetupContactConstraintsLoop" ); - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - for (int i = batch.begin; i < batch.end; ++i) - { - int iContact = m_bc->m_constraintIndices[i]; - m_solver->internalSetupContactConstraints( iContact, *m_infoGlobal ); - } - } - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + const btContactSolverInfo* m_infoGlobal; + SetupContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_bc = bc; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("SetupContactConstraintsLoop"); + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + for (int i = batch.begin; i < batch.end; ++i) + { + int iContact = m_bc->m_constraintIndices[i]; + m_solver->internalSetupContactConstraints(iContact, *m_infoGlobal); + } + } + } +}; void btSequentialImpulseConstraintSolverMt::setupAllContactConstraints(const btContactSolverInfo& infoGlobal) { - BT_PROFILE( "setupAllContactConstraints" ); - if ( m_useBatching ) - { - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - SetupContactConstraintsLoop loop( this, &batchedCons, infoGlobal ); - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = 1; - btParallelFor( phase.begin, phase.end, grainSize, loop ); - } - } - else - { - for ( int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i ) - { - internalSetupContactConstraints( i, infoGlobal ); - } - } + BT_PROFILE("setupAllContactConstraints"); + if (m_useBatching) + { + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + SetupContactConstraintsLoop loop(this, &batchedCons, infoGlobal); + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = 1; + btParallelFor(phase.begin, phase.end, grainSize, loop); + } + } + else + { + for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i) + { + internalSetupContactConstraints(i, infoGlobal); + } + } } - -int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body,btScalar timeStep) +int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep) { - // - // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers) - // - // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism) - // - int solverBodyId = -1; - bool isRigidBodyType = btRigidBody::upcast( &body ) != NULL; - if ( isRigidBodyType && !body.isStaticOrKinematicObject() ) - { - // dynamic body - // Dynamic bodies can only be in one island, so it's safe to write to the companionId - solverBodyId = body.getCompanionId(); - if ( solverBodyId < 0 ) - { - m_bodySolverArrayMutex.lock(); - // now that we have the lock, check again - solverBodyId = body.getCompanionId(); - if ( solverBodyId < 0 ) - { - solverBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &solverBody, &body, timeStep ); - body.setCompanionId( solverBodyId ); - } - m_bodySolverArrayMutex.unlock(); - } - } - else if (isRigidBodyType && body.isKinematicObject()) - { - // - // NOTE: must test for kinematic before static because some kinematic objects also - // identify as "static" - // - // Kinematic bodies can be in multiple islands at once, so it is a - // race condition to write to them, so we use an alternate method - // to record the solverBodyId - int uniqueId = body.getWorldArrayIndex(); - const int INVALID_SOLVER_BODY_ID = -1; - if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId ) - { - m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock(); - // now that we have the lock, check again - if ( m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId ) - { - m_kinematicBodyUniqueIdToSolverBodyTable.resize( uniqueId + 1, INVALID_SOLVER_BODY_ID ); - } - m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock(); - } - solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ]; - // if no table entry yet, - if ( INVALID_SOLVER_BODY_ID == solverBodyId ) - { - // need to acquire both locks - m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock(); - m_bodySolverArrayMutex.lock(); - // now that we have the lock, check again - solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ]; - if ( INVALID_SOLVER_BODY_ID == solverBodyId ) - { - // create a table entry for this body - solverBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &solverBody, &body, timeStep ); - m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId; - } - m_bodySolverArrayMutex.unlock(); - m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock(); - } - } - else - { - // all fixed bodies (inf mass) get mapped to a single solver id - if ( m_fixedBodyId < 0 ) - { - m_bodySolverArrayMutex.lock(); - // now that we have the lock, check again - if ( m_fixedBodyId < 0 ) - { - m_fixedBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &fixedBody, 0, timeStep ); - } - m_bodySolverArrayMutex.unlock(); - } - solverBodyId = m_fixedBodyId; - } - btAssert( solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size() ); + // + // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers) + // + // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism) + // + int solverBodyId = -1; + bool isRigidBodyType = btRigidBody::upcast(&body) != NULL; + if (isRigidBodyType && !body.isStaticOrKinematicObject()) + { + // dynamic body + // Dynamic bodies can only be in one island, so it's safe to write to the companionId + solverBodyId = body.getCompanionId(); + if (solverBodyId < 0) + { + m_bodySolverArrayMutex.lock(); + // now that we have the lock, check again + solverBodyId = body.getCompanionId(); + if (solverBodyId < 0) + { + solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody, &body, timeStep); + body.setCompanionId(solverBodyId); + } + m_bodySolverArrayMutex.unlock(); + } + } + else if (isRigidBodyType && body.isKinematicObject()) + { + // + // NOTE: must test for kinematic before static because some kinematic objects also + // identify as "static" + // + // Kinematic bodies can be in multiple islands at once, so it is a + // race condition to write to them, so we use an alternate method + // to record the solverBodyId + int uniqueId = body.getWorldArrayIndex(); + const int INVALID_SOLVER_BODY_ID = -1; + if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId) + { + m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock(); + // now that we have the lock, check again + if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId) + { + m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID); + } + m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock(); + } + solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId]; + // if no table entry yet, + if (INVALID_SOLVER_BODY_ID == solverBodyId) + { + // need to acquire both locks + m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock(); + m_bodySolverArrayMutex.lock(); + // now that we have the lock, check again + solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId]; + if (INVALID_SOLVER_BODY_ID == solverBodyId) + { + // create a table entry for this body + solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody, &body, timeStep); + m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId; + } + m_bodySolverArrayMutex.unlock(); + m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock(); + } + } + else + { + // all fixed bodies (inf mass) get mapped to a single solver id + if (m_fixedBodyId < 0) + { + m_bodySolverArrayMutex.lock(); + // now that we have the lock, check again + if (m_fixedBodyId < 0) + { + m_fixedBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&fixedBody, 0, timeStep); + } + m_bodySolverArrayMutex.unlock(); + } + solverBodyId = m_fixedBodyId; + } + btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size()); return solverBodyId; } - void btSequentialImpulseConstraintSolverMt::internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("internalCollectContactManifoldCachedInfo"); - for (int i = 0; i < numManifolds; ++i) - { - btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i]; - btPersistentManifold* manifold = manifoldPtr[i]; - btCollisionObject* colObj0 = (btCollisionObject*) manifold->getBody0(); - btCollisionObject* colObj1 = (btCollisionObject*) manifold->getBody1(); - - int solverBodyIdA = getOrInitSolverBodyThreadsafe( *colObj0, infoGlobal.m_timeStep ); - int solverBodyIdB = getOrInitSolverBodyThreadsafe( *colObj1, infoGlobal.m_timeStep ); - - cachedInfo->solverBodyIds[ 0 ] = solverBodyIdA; - cachedInfo->solverBodyIds[ 1 ] = solverBodyIdB; - cachedInfo->numTouchingContacts = 0; - - btSolverBody* solverBodyA = &m_tmpSolverBodyPool[ solverBodyIdA ]; - btSolverBody* solverBodyB = &m_tmpSolverBodyPool[ solverBodyIdB ]; - - // A contact manifold between 2 static object should not exist! - // check the collision flags of your objects if this assert fires. - // Incorrectly set collision object flags can degrade performance in various ways. - btAssert( !m_tmpSolverBodyPool[ solverBodyIdA ].m_invMass.isZero() || !m_tmpSolverBodyPool[ solverBodyIdB ].m_invMass.isZero() ); - - int iContact = 0; - for ( int j = 0; j < manifold->getNumContacts(); j++ ) - { - btManifoldPoint& cp = manifold->getContactPoint( j ); - - if ( cp.getDistance() <= manifold->getContactProcessingThreshold() ) - { - cachedInfo->contactPoints[ iContact ] = &cp; - cachedInfo->contactHasRollingFriction[ iContact ] = ( cp.m_combinedRollingFriction > 0.f ); - iContact++; - } - } - cachedInfo->numTouchingContacts = iContact; - } -} + BT_PROFILE("internalCollectContactManifoldCachedInfo"); + for (int i = 0; i < numManifolds; ++i) + { + btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i]; + btPersistentManifold* manifold = manifoldPtr[i]; + btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0(); + btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1(); + + int solverBodyIdA = getOrInitSolverBodyThreadsafe(*colObj0, infoGlobal.m_timeStep); + int solverBodyIdB = getOrInitSolverBodyThreadsafe(*colObj1, infoGlobal.m_timeStep); + + cachedInfo->solverBodyIds[0] = solverBodyIdA; + cachedInfo->solverBodyIds[1] = solverBodyIdB; + cachedInfo->numTouchingContacts = 0; + + btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA]; + btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB]; + // A contact manifold between 2 static object should not exist! + // check the collision flags of your objects if this assert fires. + // Incorrectly set collision object flags can degrade performance in various ways. + btAssert(!m_tmpSolverBodyPool[solverBodyIdA].m_invMass.isZero() || !m_tmpSolverBodyPool[solverBodyIdB].m_invMass.isZero()); + + int iContact = 0; + for (int j = 0; j < manifold->getNumContacts(); j++) + { + btManifoldPoint& cp = manifold->getContactPoint(j); + + if (cp.getDistance() <= manifold->getContactProcessingThreshold()) + { + cachedInfo->contactPoints[iContact] = &cp; + cachedInfo->contactHasRollingFriction[iContact] = (cp.m_combinedRollingFriction > 0.f); + iContact++; + } + } + cachedInfo->numTouchingContacts = iContact; + } +} struct CollectContactManifoldCachedInfoLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray; - btPersistentManifold** m_manifoldPtr; - const btContactSolverInfo* m_infoGlobal; - - CollectContactManifoldCachedInfoLoop( btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_cachedInfoArray = cachedInfoArray; - m_manifoldPtr = manifoldPtr; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalCollectContactManifoldCachedInfo( m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray; + btPersistentManifold** m_manifoldPtr; + const btContactSolverInfo* m_infoGlobal; + CollectContactManifoldCachedInfoLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_cachedInfoArray = cachedInfoArray; + m_manifoldPtr = manifoldPtr; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalCollectContactManifoldCachedInfo(m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal); + } +}; void btSequentialImpulseConstraintSolverMt::internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds) { - BT_PROFILE("internalAllocContactConstraints"); - // possibly parallel part - for ( int iManifold = 0; iManifold < numManifolds; ++iManifold ) - { - const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[ iManifold ]; - int contactIndex = cachedInfo.contactIndex; - int frictionIndex = contactIndex * m_numFrictionDirections; - int rollingFrictionIndex = cachedInfo.rollingFrictionIndex; - for ( int i = 0; i < cachedInfo.numTouchingContacts; i++ ) - { - btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex]; - contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[ 0 ]; - contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[ 1 ]; - contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[ i ]; - - // allocate the friction constraints - contactConstraint.m_frictionIndex = frictionIndex; - for ( int iDir = 0; iDir < m_numFrictionDirections; ++iDir ) - { - btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex]; - frictionConstraint.m_frictionIndex = contactIndex; - frictionIndex++; - } - - // allocate rolling friction constraints - if ( cachedInfo.contactHasRollingFriction[ i ] ) - { - m_rollingFrictionIndexTable[ contactIndex ] = rollingFrictionIndex; - // allocate 3 (although we may use only 2 sometimes) - for ( int i = 0; i < 3; i++ ) - { - m_tmpSolverContactRollingFrictionConstraintPool[ rollingFrictionIndex ].m_frictionIndex = contactIndex; - rollingFrictionIndex++; - } - } - else - { - // indicate there is no rolling friction for this contact point - m_rollingFrictionIndexTable[ contactIndex ] = -1; - } - contactIndex++; - } - } -} + BT_PROFILE("internalAllocContactConstraints"); + // possibly parallel part + for (int iManifold = 0; iManifold < numManifolds; ++iManifold) + { + const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold]; + int contactIndex = cachedInfo.contactIndex; + int frictionIndex = contactIndex * m_numFrictionDirections; + int rollingFrictionIndex = cachedInfo.rollingFrictionIndex; + for (int i = 0; i < cachedInfo.numTouchingContacts; i++) + { + btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex]; + contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[0]; + contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[1]; + contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[i]; + + // allocate the friction constraints + contactConstraint.m_frictionIndex = frictionIndex; + for (int iDir = 0; iDir < m_numFrictionDirections; ++iDir) + { + btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex]; + frictionConstraint.m_frictionIndex = contactIndex; + frictionIndex++; + } + // allocate rolling friction constraints + if (cachedInfo.contactHasRollingFriction[i]) + { + m_rollingFrictionIndexTable[contactIndex] = rollingFrictionIndex; + // allocate 3 (although we may use only 2 sometimes) + for (int i = 0; i < 3; i++) + { + m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex].m_frictionIndex = contactIndex; + rollingFrictionIndex++; + } + } + else + { + // indicate there is no rolling friction for this contact point + m_rollingFrictionIndexTable[contactIndex] = -1; + } + contactIndex++; + } + } +} struct AllocContactConstraintsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray; - - AllocContactConstraintsLoop( btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray ) - { - m_solver = solver; - m_cachedInfoArray = cachedInfoArray; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalAllocContactConstraints( m_cachedInfoArray + iBegin, iEnd - iBegin ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray; + AllocContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray) + { + m_solver = solver; + m_cachedInfoArray = cachedInfoArray; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalAllocContactConstraints(m_cachedInfoArray + iBegin, iEnd - iBegin); + } +}; void btSequentialImpulseConstraintSolverMt::allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) { - BT_PROFILE( "allocAllContactConstraints" ); - btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray; - cachedInfoArray.resizeNoInitialize( numManifolds ); - if (/* DISABLES CODE */ (false)) - { - // sequential - internalCollectContactManifoldCachedInfo(&cachedInfoArray[ 0 ], manifoldPtr, numManifolds, infoGlobal); - } - else - { - // may alter ordering of bodies which affects determinism - CollectContactManifoldCachedInfoLoop loop( this, &cachedInfoArray[ 0 ], manifoldPtr, infoGlobal ); - int grainSize = 200; - btParallelFor( 0, numManifolds, grainSize, loop ); - } - - { - // serial part - int numContacts = 0; - int numRollingFrictionConstraints = 0; - for ( int iManifold = 0; iManifold < numManifolds; ++iManifold ) - { - btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[ iManifold ]; - cachedInfo.contactIndex = numContacts; - cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints; - numContacts += cachedInfo.numTouchingContacts; - for (int i = 0; i < cachedInfo.numTouchingContacts; ++i) - { - if (cachedInfo.contactHasRollingFriction[i]) - { - numRollingFrictionConstraints += 3; - } - } - } - { - BT_PROFILE( "allocPools" ); - if ( m_tmpSolverContactConstraintPool.capacity() < numContacts ) - { - // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame - int extraReserve = numContacts / 16; - m_tmpSolverContactConstraintPool.reserve( numContacts + extraReserve ); - m_rollingFrictionIndexTable.reserve( numContacts + extraReserve ); - m_tmpSolverContactFrictionConstraintPool.reserve( ( numContacts + extraReserve )*m_numFrictionDirections ); - m_tmpSolverContactRollingFrictionConstraintPool.reserve( numRollingFrictionConstraints + extraReserve ); - } - m_tmpSolverContactConstraintPool.resizeNoInitialize( numContacts ); - m_rollingFrictionIndexTable.resizeNoInitialize( numContacts ); - m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize( numContacts*m_numFrictionDirections ); - m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize( numRollingFrictionConstraints ); - } - } - { - AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]); - int grainSize = 200; - btParallelFor( 0, numManifolds, grainSize, loop ); - } -} + BT_PROFILE("allocAllContactConstraints"); + btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray; + cachedInfoArray.resizeNoInitialize(numManifolds); + if (/* DISABLES CODE */ (false)) + { + // sequential + internalCollectContactManifoldCachedInfo(&cachedInfoArray[0], manifoldPtr, numManifolds, infoGlobal); + } + else + { + // may alter ordering of bodies which affects determinism + CollectContactManifoldCachedInfoLoop loop(this, &cachedInfoArray[0], manifoldPtr, infoGlobal); + int grainSize = 200; + btParallelFor(0, numManifolds, grainSize, loop); + } + { + // serial part + int numContacts = 0; + int numRollingFrictionConstraints = 0; + for (int iManifold = 0; iManifold < numManifolds; ++iManifold) + { + btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold]; + cachedInfo.contactIndex = numContacts; + cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints; + numContacts += cachedInfo.numTouchingContacts; + for (int i = 0; i < cachedInfo.numTouchingContacts; ++i) + { + if (cachedInfo.contactHasRollingFriction[i]) + { + numRollingFrictionConstraints += 3; + } + } + } + { + BT_PROFILE("allocPools"); + if (m_tmpSolverContactConstraintPool.capacity() < numContacts) + { + // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame + int extraReserve = numContacts / 16; + m_tmpSolverContactConstraintPool.reserve(numContacts + extraReserve); + m_rollingFrictionIndexTable.reserve(numContacts + extraReserve); + m_tmpSolverContactFrictionConstraintPool.reserve((numContacts + extraReserve) * m_numFrictionDirections); + m_tmpSolverContactRollingFrictionConstraintPool.reserve(numRollingFrictionConstraints + extraReserve); + } + m_tmpSolverContactConstraintPool.resizeNoInitialize(numContacts); + m_rollingFrictionIndexTable.resizeNoInitialize(numContacts); + m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(numContacts * m_numFrictionDirections); + m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(numRollingFrictionConstraints); + } + } + { + AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]); + int grainSize = 200; + btParallelFor(0, numManifolds, grainSize, loop); + } +} void btSequentialImpulseConstraintSolverMt::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) { - if (!m_useBatching) - { - btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal); - return; - } - BT_PROFILE( "convertContacts" ); - if (numManifolds > 0) - { - if ( m_fixedBodyId < 0 ) - { - m_fixedBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); - initSolverBody( &fixedBody, 0, infoGlobal.m_timeStep ); - } - allocAllContactConstraints( manifoldPtr, numManifolds, infoGlobal ); - if ( m_useBatching ) - { - setupBatchedContactConstraints(); - } - setupAllContactConstraints( infoGlobal ); - } + if (!m_useBatching) + { + btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal); + return; + } + BT_PROFILE("convertContacts"); + if (numManifolds > 0) + { + if (m_fixedBodyId < 0) + { + m_fixedBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& fixedBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&fixedBody, 0, infoGlobal.m_timeStep); + } + allocAllContactConstraints(manifoldPtr, numManifolds, infoGlobal); + if (m_useBatching) + { + setupBatchedContactConstraints(); + } + setupAllContactConstraints(infoGlobal); + } } - -void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints( btTypedConstraint** constraints, int iBegin, int iEnd ) +void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd) { - BT_PROFILE("internalInitMultipleJoints"); - for ( int i = iBegin; i < iEnd; i++ ) + BT_PROFILE("internalInitMultipleJoints"); + for (int i = iBegin; i < iEnd; i++) { btTypedConstraint* constraint = constraints[i]; btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i]; if (constraint->isEnabled()) - { - constraint->buildJacobian(); - constraint->internalSetAppliedImpulse( 0.0f ); - btJointFeedback* fb = constraint->getJointFeedback(); - if ( fb ) - { - fb->m_appliedForceBodyA.setZero(); - fb->m_appliedTorqueBodyA.setZero(); - fb->m_appliedForceBodyB.setZero(); - fb->m_appliedTorqueBodyB.setZero(); - } - constraint->getInfo1( &info1 ); - } - else + { + constraint->buildJacobian(); + constraint->internalSetAppliedImpulse(0.0f); + btJointFeedback* fb = constraint->getJointFeedback(); + if (fb) + { + fb->m_appliedForceBodyA.setZero(); + fb->m_appliedTorqueBodyA.setZero(); + fb->m_appliedForceBodyB.setZero(); + fb->m_appliedTorqueBodyB.setZero(); + } + constraint->getInfo1(&info1); + } + else { info1.m_numConstraintRows = 0; info1.nub = 0; @@ -646,158 +624,151 @@ void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints( btTypedC } } - struct InitJointsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - btTypedConstraint** m_constraints; - - InitJointsLoop( btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints ) - { - m_solver = solver; - m_constraints = constraints; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalInitMultipleJoints( m_constraints, iBegin, iEnd ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + btTypedConstraint** m_constraints; + InitJointsLoop(btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints) + { + m_solver = solver; + m_constraints = constraints; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalInitMultipleJoints(m_constraints, iBegin, iEnd); + } +}; -void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints( const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ) +void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("internalConvertMultipleJoints"); - for ( int i = iBegin; i < iEnd; ++i ) - { - const JointParams& jointParams = jointParamsArray[ i ]; - int currentRow = jointParams.m_solverConstraint; - if ( currentRow != -1 ) - { - const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[ i ]; - btAssert( currentRow < m_tmpSolverNonContactConstraintPool.size() ); - btAssert( info1.m_numConstraintRows > 0 ); - - btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[ currentRow ]; - btTypedConstraint* constraint = constraints[ i ]; - - convertJoint( currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal ); - } - } -} + BT_PROFILE("internalConvertMultipleJoints"); + for (int i = iBegin; i < iEnd; ++i) + { + const JointParams& jointParams = jointParamsArray[i]; + int currentRow = jointParams.m_solverConstraint; + if (currentRow != -1) + { + const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i]; + btAssert(currentRow < m_tmpSolverNonContactConstraintPool.size()); + btAssert(info1.m_numConstraintRows > 0); + + btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow]; + btTypedConstraint* constraint = constraints[i]; + convertJoint(currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal); + } + } +} struct ConvertJointsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray; - btTypedConstraint** m_srcConstraints; - const btContactSolverInfo& m_infoGlobal; - - ConvertJointsLoop( btSequentialImpulseConstraintSolverMt* solver, - const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray, - btTypedConstraint** srcConstraints, - const btContactSolverInfo& infoGlobal - ) : - m_jointParamsArray(jointParamsArray), - m_infoGlobal(infoGlobal) - { - m_solver = solver; - m_srcConstraints = srcConstraints; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalConvertMultipleJoints( m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal ); - } + btSequentialImpulseConstraintSolverMt* m_solver; + const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray; + btTypedConstraint** m_srcConstraints; + const btContactSolverInfo& m_infoGlobal; + + ConvertJointsLoop(btSequentialImpulseConstraintSolverMt* solver, + const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray, + btTypedConstraint** srcConstraints, + const btContactSolverInfo& infoGlobal) : m_jointParamsArray(jointParamsArray), + m_infoGlobal(infoGlobal) + { + m_solver = solver; + m_srcConstraints = srcConstraints; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalConvertMultipleJoints(m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal); + } }; - void btSequentialImpulseConstraintSolverMt::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal) { - if ( !m_useBatching ) - { - btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal); - return; - } - BT_PROFILE("convertJoints"); - bool parallelJointSetup = true; + if (!m_useBatching) + { + btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal); + return; + } + BT_PROFILE("convertJoints"); + bool parallelJointSetup = true; m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints); - if (parallelJointSetup) - { - InitJointsLoop loop(this, constraints); - int grainSize = 40; - btParallelFor(0, numConstraints, grainSize, loop); - } - else - { - internalInitMultipleJoints( constraints, 0, numConstraints ); - } + if (parallelJointSetup) + { + InitJointsLoop loop(this, constraints); + int grainSize = 40; + btParallelFor(0, numConstraints, grainSize, loop); + } + else + { + internalInitMultipleJoints(constraints, 0, numConstraints); + } int totalNumRows = 0; - btAlignedObjectArray<JointParams> jointParamsArray; - jointParamsArray.resizeNoInitialize(numConstraints); + btAlignedObjectArray<JointParams> jointParamsArray; + jointParamsArray.resizeNoInitialize(numConstraints); //calculate the total number of contraint rows - for (int i=0;i<numConstraints;i++) + for (int i = 0; i < numConstraints; i++) { - btTypedConstraint* constraint = constraints[ i ]; + btTypedConstraint* constraint = constraints[i]; - JointParams& params = jointParamsArray[ i ]; + JointParams& params = jointParamsArray[i]; const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i]; if (info1.m_numConstraintRows) { - params.m_solverConstraint = totalNumRows; - params.m_solverBodyA = getOrInitSolverBody( constraint->getRigidBodyA(), infoGlobal.m_timeStep ); - params.m_solverBodyB = getOrInitSolverBody( constraint->getRigidBodyB(), infoGlobal.m_timeStep ); + params.m_solverConstraint = totalNumRows; + params.m_solverBodyA = getOrInitSolverBody(constraint->getRigidBodyA(), infoGlobal.m_timeStep); + params.m_solverBodyB = getOrInitSolverBody(constraint->getRigidBodyB(), infoGlobal.m_timeStep); } - else + else { - params.m_solverConstraint = -1; + params.m_solverConstraint = -1; } totalNumRows += info1.m_numConstraintRows; } m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows); ///setup the btSolverConstraints - if ( parallelJointSetup ) - { - ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal); - int grainSize = 20; - btParallelFor(0, numConstraints, grainSize, loop); - } - else - { - internalConvertMultipleJoints( jointParamsArray, constraints, 0, numConstraints, infoGlobal ); - } - setupBatchedJointConstraints(); + if (parallelJointSetup) + { + ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal); + int grainSize = 20; + btParallelFor(0, numConstraints, grainSize, loop); + } + else + { + internalConvertMultipleJoints(jointParamsArray, constraints, 0, numConstraints, infoGlobal); + } + setupBatchedJointConstraints(); } - void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("internalConvertBodies"); - for (int i=iBegin; i < iEnd; i++) + BT_PROFILE("internalConvertBodies"); + for (int i = iBegin; i < iEnd; i++) { - btCollisionObject* obj = bodies[i]; + btCollisionObject* obj = bodies[i]; obj->setCompanionId(i); btSolverBody& solverBody = m_tmpSolverBodyPool[i]; - initSolverBody(&solverBody, obj, infoGlobal.m_timeStep); + initSolverBody(&solverBody, obj, infoGlobal.m_timeStep); btRigidBody* body = btRigidBody::upcast(obj); if (body && body->getInvMass()) { - btVector3 gyroForce (0,0,0); - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT) + btVector3 gyroForce(0, 0, 0); + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT) { gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce); - solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep; + solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep; } - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD) + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD) { gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep); solverBody.m_externalTorqueImpulse += gyroForce; } - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY) + if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY) { gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep); solverBody.m_externalTorqueImpulse += gyroForce; @@ -806,809 +777,772 @@ void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObj } } - struct ConvertBodiesLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - btCollisionObject** m_bodies; - int m_numBodies; - const btContactSolverInfo& m_infoGlobal; - - ConvertBodiesLoop( btSequentialImpulseConstraintSolverMt* solver, - btCollisionObject** bodies, - int numBodies, - const btContactSolverInfo& infoGlobal - ) : - m_infoGlobal(infoGlobal) - { - m_solver = solver; - m_bodies = bodies; - m_numBodies = numBodies; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalConvertBodies( m_bodies, iBegin, iEnd, m_infoGlobal ); - } + btSequentialImpulseConstraintSolverMt* m_solver; + btCollisionObject** m_bodies; + int m_numBodies; + const btContactSolverInfo& m_infoGlobal; + + ConvertBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, + btCollisionObject** bodies, + int numBodies, + const btContactSolverInfo& infoGlobal) : m_infoGlobal(infoGlobal) + { + m_solver = solver; + m_bodies = bodies; + m_numBodies = numBodies; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalConvertBodies(m_bodies, iBegin, iEnd, m_infoGlobal); + } }; - void btSequentialImpulseConstraintSolverMt::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("convertBodies"); - m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 ); - - m_tmpSolverBodyPool.resizeNoInitialize(numBodies+1); - - m_fixedBodyId = numBodies; - { - btSolverBody& fixedBody = m_tmpSolverBodyPool[ m_fixedBodyId ]; - initSolverBody( &fixedBody, NULL, infoGlobal.m_timeStep ); - } - - bool parallelBodySetup = true; - if (parallelBodySetup) - { - ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal); - int grainSize = 40; - btParallelFor(0, numBodies, grainSize, loop); - } - else - { - internalConvertBodies( bodies, 0, numBodies, infoGlobal ); - } -} + BT_PROFILE("convertBodies"); + m_kinematicBodyUniqueIdToSolverBodyTable.resize(0); + m_tmpSolverBodyPool.resizeNoInitialize(numBodies + 1); + + m_fixedBodyId = numBodies; + { + btSolverBody& fixedBody = m_tmpSolverBodyPool[m_fixedBodyId]; + initSolverBody(&fixedBody, NULL, infoGlobal.m_timeStep); + } + + bool parallelBodySetup = true; + if (parallelBodySetup) + { + ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal); + int grainSize = 40; + btParallelFor(0, numBodies, grainSize, loop); + } + else + { + internalConvertBodies(bodies, 0, numBodies, infoGlobal); + } +} btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySetup( - btCollisionObject** bodies, - int numBodies, - btPersistentManifold** manifoldPtr, - int numManifolds, - btTypedConstraint** constraints, - int numConstraints, - const btContactSolverInfo& infoGlobal, - btIDebugDraw* debugDrawer - ) + btCollisionObject** bodies, + int numBodies, + btPersistentManifold** manifoldPtr, + int numManifolds, + btTypedConstraint** constraints, + int numConstraints, + const btContactSolverInfo& infoGlobal, + btIDebugDraw* debugDrawer) { - m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1; - m_useBatching = false; - if ( numManifolds >= s_minimumContactManifoldsForBatching && - (s_allowNestedParallelForLoops || !btThreadsAreRunning()) - ) - { - m_useBatching = true; - m_batchedContactConstraints.m_debugDrawer = debugDrawer; - m_batchedJointConstraints.m_debugDrawer = debugDrawer; - } - btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup( bodies, - numBodies, - manifoldPtr, - numManifolds, - constraints, - numConstraints, - infoGlobal, - debugDrawer - ); - return 0.0f; + m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1; + m_useBatching = false; + if (numManifolds >= s_minimumContactManifoldsForBatching && + (s_allowNestedParallelForLoops || !btThreadsAreRunning())) + { + m_useBatching = true; + m_batchedContactConstraints.m_debugDrawer = debugDrawer; + m_batchedJointConstraints.m_debugDrawer = debugDrawer; + } + btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, + numBodies, + manifoldPtr, + numManifolds, + constraints, + numConstraints, + infoGlobal, + debugDrawer); + return 0.0f; } - -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd) { - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iCons = consIndices[ iiCons ]; - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iCons ]; - btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ]; - btScalar residual = resolveSplitPenetrationImpulse( bodyA, bodyB, solveManifold ); - leastSquaresResidual += residual*residual; - } - return leastSquaresResidual; + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iCons = consIndices[iiCons]; + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons]; + btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB]; + btScalar residual = resolveSplitPenetrationImpulse(bodyA, bodyB, solveManifold); + leastSquaresResidual += residual * residual; + } + return leastSquaresResidual; } - struct ContactSplitPenetrationImpulseSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - ContactSplitPenetrationImpulseSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "ContactSplitPenetrationImpulseSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + ContactSplitPenetrationImpulseSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("ContactSplitPenetrationImpulseSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; -void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) { BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations"); if (infoGlobal.m_splitImpulse) { - for ( int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++ ) - { - btScalar leastSquaresResidual = 0.f; - if (m_useBatching) - { - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - ContactSplitPenetrationImpulseSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = batchedCons.m_phaseGrainSize[iPhase]; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - } - else - { - // non-batched - leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size()); - } - if ( leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= ( infoGlobal.m_numIterations - 1 ) ) - { + for (int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++) + { + btScalar leastSquaresResidual = 0.f; + if (m_useBatching) + { + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + ContactSplitPenetrationImpulseSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = batchedCons.m_phaseGrainSize[iPhase]; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + } + else + { + // non-batched + leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size()); + } + if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1)) + { #ifdef VERBOSE_RESIDUAL_PRINTF - printf( "residual = %f at iteration #%d\n", leastSquaresResidual, iteration ); + printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration); #endif - break; - } - } + break; + } + } } } - -btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer) +btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) { - if ( !m_useBatching ) - { - return btSequentialImpulseConstraintSolver::solveSingleIteration( iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer ); - } - BT_PROFILE( "solveSingleIterationMt" ); - btScalar leastSquaresResidual = 0.f; + if (!m_useBatching) + { + return btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer); + } + BT_PROFILE("solveSingleIterationMt"); + btScalar leastSquaresResidual = 0.f; if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER) { - if (1) // uncomment this for a bit less random ((iteration & 7) == 0) + if (1) // uncomment this for a bit less random ((iteration & 7) == 0) { - randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations); + randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations); } } { ///solve all joint constraints - leastSquaresResidual += resolveAllJointConstraints(iteration); + leastSquaresResidual += resolveAllJointConstraints(iteration); - if (iteration< infoGlobal.m_numIterations) + if (iteration < infoGlobal.m_numIterations) { - // this loop is only used for cone-twist constraints, - // it would be nice to skip this loop if none of the constraints need it - if ( m_useObsoleteJointConstraints ) - { - for ( int j = 0; j<numConstraints; j++ ) - { - if ( constraints[ j ]->isEnabled() ) - { - int bodyAid = getOrInitSolverBody( constraints[ j ]->getRigidBodyA(), infoGlobal.m_timeStep ); - int bodyBid = getOrInitSolverBody( constraints[ j ]->getRigidBodyB(), infoGlobal.m_timeStep ); - btSolverBody& bodyA = m_tmpSolverBodyPool[ bodyAid ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ bodyBid ]; - constraints[ j ]->solveConstraintObsolete( bodyA, bodyB, infoGlobal.m_timeStep ); - } - } - } + // this loop is only used for cone-twist constraints, + // it would be nice to skip this loop if none of the constraints need it + if (m_useObsoleteJointConstraints) + { + for (int j = 0; j < numConstraints; j++) + { + if (constraints[j]->isEnabled()) + { + int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep); + int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep); + btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid]; + btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid]; + constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep); + } + } + } if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) { - // solve all contact, contact-friction, and rolling friction constraints interleaved - leastSquaresResidual += resolveAllContactConstraintsInterleaved(); + // solve all contact, contact-friction, and rolling friction constraints interleaved + leastSquaresResidual += resolveAllContactConstraintsInterleaved(); } - else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS + else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS { - // don't interleave them + // don't interleave them // solve all contact constraints - leastSquaresResidual += resolveAllContactConstraints(); + leastSquaresResidual += resolveAllContactConstraints(); // solve all contact friction constraints - leastSquaresResidual += resolveAllContactFrictionConstraints(); + leastSquaresResidual += resolveAllContactFrictionConstraints(); - // solve all rolling friction constraints - leastSquaresResidual += resolveAllRollingFrictionConstraints(); + // solve all rolling friction constraints + leastSquaresResidual += resolveAllRollingFrictionConstraints(); } } } - return leastSquaresResidual; + return leastSquaresResidual; } - -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration) { - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iCons = consIndices[ iiCons ]; - const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[ iCons ]; - if ( iteration < constraint.m_overrideNumSolverIterations ) - { - btSolverBody& bodyA = m_tmpSolverBodyPool[ constraint.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ constraint.m_solverBodyIdB ]; - btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, constraint ); - leastSquaresResidual += residual*residual; - } - } - return leastSquaresResidual; + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iCons = consIndices[iiCons]; + const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[iCons]; + if (iteration < constraint.m_overrideNumSolverIterations) + { + btSolverBody& bodyA = m_tmpSolverBodyPool[constraint.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[constraint.m_solverBodyIdB]; + btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, constraint); + leastSquaresResidual += residual * residual; + } + } + return leastSquaresResidual; } - -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd) { - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iCons = consIndices[ iiCons ]; - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iCons ]; - btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ]; - btScalar residual = resolveSingleConstraintRowLowerLimit( bodyA, bodyB, solveManifold ); - leastSquaresResidual += residual*residual; - } - return leastSquaresResidual; + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iCons = consIndices[iiCons]; + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons]; + btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB]; + btScalar residual = resolveSingleConstraintRowLowerLimit(bodyA, bodyB, solveManifold); + leastSquaresResidual += residual * residual; + } + return leastSquaresResidual; } - -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd) { - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iContact = consIndices[ iiCons ]; - btScalar totalImpulse = m_tmpSolverContactConstraintPool[ iContact ].m_appliedImpulse; - - // apply sliding friction - if ( totalImpulse > 0.0f ) - { - int iBegin = iContact * m_numFrictionDirections; - int iEnd = iBegin + m_numFrictionDirections; - for ( int iFriction = iBegin; iFriction < iEnd; ++iFriction ) - { - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[ iFriction++ ]; - btAssert( solveManifold.m_frictionIndex == iContact ); - - solveManifold.m_lowerLimit = -( solveManifold.m_friction*totalImpulse ); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - - btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ]; - btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, solveManifold ); - leastSquaresResidual += residual*residual; - } - } - } - return leastSquaresResidual; -} + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iContact = consIndices[iiCons]; + btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse; + // apply sliding friction + if (totalImpulse > 0.0f) + { + int iBegin = iContact * m_numFrictionDirections; + int iEnd = iBegin + m_numFrictionDirections; + for (int iFriction = iBegin; iFriction < iEnd; ++iFriction) + { + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction++]; + btAssert(solveManifold.m_frictionIndex == iContact); -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints( const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd ) -{ - btScalar leastSquaresResidual = 0.f; - for ( int iiCons = batchBegin; iiCons < batchEnd; ++iiCons ) - { - int iContact = consIndices[ iiCons ]; - int iFirstRollingFriction = m_rollingFrictionIndexTable[ iContact ]; - if ( iFirstRollingFriction >= 0 ) - { - btScalar totalImpulse = m_tmpSolverContactConstraintPool[ iContact ].m_appliedImpulse; - // apply rolling friction - if ( totalImpulse > 0.0f ) - { - int iBegin = iFirstRollingFriction; - int iEnd = iBegin + 3; - for ( int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric ) - { - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ]; - if ( rollingFrictionConstraint.m_frictionIndex != iContact ) - { - break; - } - btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; - if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction ) - { - rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; - } - - rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; - rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; - - btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint ); - leastSquaresResidual += residual*residual; - } - } - } - } - return leastSquaresResidual; -} + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; + btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB]; + btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold); + leastSquaresResidual += residual * residual; + } + } + } + return leastSquaresResidual; +} -btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved( const btAlignedObjectArray<int>& contactIndices, - int batchBegin, - int batchEnd - ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd) { - btScalar leastSquaresResidual = 0.f; - int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); - - for ( int iiCons = batchBegin; iiCons < batchEnd; iiCons++ ) - { - btScalar totalImpulse = 0; - int iContact = contactIndices[ iiCons ]; - // apply penetration constraint - { - const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[ iContact ]; - btScalar residual = resolveSingleConstraintRowLowerLimit( m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ], m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ], solveManifold ); - leastSquaresResidual += residual*residual; - totalImpulse = solveManifold.m_appliedImpulse; - } - - // apply sliding friction - if ( totalImpulse > 0.0f ) - { - int iBegin = iContact * m_numFrictionDirections; - int iEnd = iBegin + m_numFrictionDirections; - for ( int iFriction = iBegin; iFriction < iEnd; ++iFriction ) - { - btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[ iFriction ]; - btAssert( solveManifold.m_frictionIndex == iContact ); - - solveManifold.m_lowerLimit = -( solveManifold.m_friction*totalImpulse ); - solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse; - - btSolverBody& bodyA = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdA ]; - btSolverBody& bodyB = m_tmpSolverBodyPool[ solveManifold.m_solverBodyIdB ]; - btScalar residual = resolveSingleConstraintRowGeneric( bodyA, bodyB, solveManifold ); - leastSquaresResidual += residual*residual; - } - } - - // apply rolling friction - int iFirstRollingFriction = m_rollingFrictionIndexTable[ iContact ]; - if ( totalImpulse > 0.0f && iFirstRollingFriction >= 0) - { - int iBegin = iFirstRollingFriction; - int iEnd = iBegin + 3; - for ( int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric ) - { - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ iRollingFric ]; - if ( rollingFrictionConstraint.m_frictionIndex != iContact ) - { - break; - } - btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; - if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction ) - { - rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; - } - - rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; - rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; - - btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint ); - leastSquaresResidual += residual*residual; - } - } - } - return leastSquaresResidual; + btScalar leastSquaresResidual = 0.f; + for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons) + { + int iContact = consIndices[iiCons]; + int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact]; + if (iFirstRollingFriction >= 0) + { + btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse; + // apply rolling friction + if (totalImpulse > 0.0f) + { + int iBegin = iFirstRollingFriction; + int iEnd = iBegin + 3; + for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric) + { + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric]; + if (rollingFrictionConstraint.m_frictionIndex != iContact) + { + break; + } + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse; + if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction) + { + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; + } + + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint); + leastSquaresResidual += residual * residual; + } + } + } + } + return leastSquaresResidual; } - -void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering( btBatchedConstraints* batchedConstraints ) +btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices, + int batchBegin, + int batchEnd) { - btBatchedConstraints& bc = *batchedConstraints; - // randomize ordering of phases - for ( int ii = 1; ii < bc.m_phaseOrder.size(); ++ii ) - { - int iSwap = btRandInt2( ii + 1 ); - bc.m_phaseOrder.swap( ii, iSwap ); - } - - // for each batch, - for ( int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch ) - { - // randomize ordering of constraints within the batch - const btBatchedConstraints::Range& batch = bc.m_batches[ iBatch ]; - for ( int iiCons = batch.begin; iiCons < batch.end; ++iiCons ) - { - int iSwap = batch.begin + btRandInt2( iiCons - batch.begin + 1 ); - btAssert(iSwap >= batch.begin && iSwap < batch.end); - bc.m_constraintIndices.swap( iiCons, iSwap ); - } - } + btScalar leastSquaresResidual = 0.f; + int numPoolConstraints = m_tmpSolverContactConstraintPool.size(); + + for (int iiCons = batchBegin; iiCons < batchEnd; iiCons++) + { + btScalar totalImpulse = 0; + int iContact = contactIndices[iiCons]; + // apply penetration constraint + { + const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iContact]; + btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold); + leastSquaresResidual += residual * residual; + totalImpulse = solveManifold.m_appliedImpulse; + } + + // apply sliding friction + if (totalImpulse > 0.0f) + { + int iBegin = iContact * m_numFrictionDirections; + int iEnd = iBegin + m_numFrictionDirections; + for (int iFriction = iBegin; iFriction < iEnd; ++iFriction) + { + btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction]; + btAssert(solveManifold.m_frictionIndex == iContact); + + solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse); + solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse; + + btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA]; + btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB]; + btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold); + leastSquaresResidual += residual * residual; + } + } + + // apply rolling friction + int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact]; + if (totalImpulse > 0.0f && iFirstRollingFriction >= 0) + { + int iBegin = iFirstRollingFriction; + int iEnd = iBegin + 3; + for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric) + { + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric]; + if (rollingFrictionConstraint.m_frictionIndex != iContact) + { + break; + } + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse; + if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction) + { + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; + } + + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint); + leastSquaresResidual += residual * residual; + } + } + } + return leastSquaresResidual; } +void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering(btBatchedConstraints* batchedConstraints) +{ + btBatchedConstraints& bc = *batchedConstraints; + // randomize ordering of phases + for (int ii = 1; ii < bc.m_phaseOrder.size(); ++ii) + { + int iSwap = btRandInt2(ii + 1); + bc.m_phaseOrder.swap(ii, iSwap); + } + + // for each batch, + for (int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch) + { + // randomize ordering of constraints within the batch + const btBatchedConstraints::Range& batch = bc.m_batches[iBatch]; + for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons) + { + int iSwap = batch.begin + btRandInt2(iiCons - batch.begin + 1); + btAssert(iSwap >= batch.begin && iSwap < batch.end); + bc.m_constraintIndices.swap(iiCons, iSwap); + } + } +} void btSequentialImpulseConstraintSolverMt::randomizeConstraintOrdering(int iteration, int numIterations) { - // randomize ordering of joint constraints - randomizeBatchedConstraintOrdering( &m_batchedJointConstraints ); - - //contact/friction constraints are not solved more than numIterations - if ( iteration < numIterations ) - { - randomizeBatchedConstraintOrdering( &m_batchedContactConstraints ); - } -} + // randomize ordering of joint constraints + randomizeBatchedConstraintOrdering(&m_batchedJointConstraints); + //contact/friction constraints are not solved more than numIterations + if (iteration < numIterations) + { + randomizeBatchedConstraintOrdering(&m_batchedContactConstraints); + } +} struct JointSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - int m_iteration; - - JointSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration ) - { - m_solver = solver; - m_bc = bc; - m_iteration = iteration; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "JointSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleJointConstraints( m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + int m_iteration; + JointSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration) + { + m_solver = solver; + m_bc = bc; + m_iteration = iteration; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("JointSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleJointConstraints(m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllJointConstraints(int iteration) { - BT_PROFILE( "resolveAllJointConstraints" ); - const btBatchedConstraints& batchedCons = m_batchedJointConstraints; - JointSolverLoop loop( this, &batchedCons, iteration ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = 1; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - return leastSquaresResidual; + BT_PROFILE("resolveAllJointConstraints"); + const btBatchedConstraints& batchedCons = m_batchedJointConstraints; + JointSolverLoop loop(this, &batchedCons, iteration); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = 1; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + return leastSquaresResidual; } - struct ContactSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - ContactSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "ContactSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactConstraints( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + ContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("ContactSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactConstraints(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraints() { - BT_PROFILE( "resolveAllContactConstraints" ); - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - ContactSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = batchedCons.m_phaseGrainSize[iPhase]; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - return leastSquaresResidual; + BT_PROFILE("resolveAllContactConstraints"); + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + ContactSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = batchedCons.m_phaseGrainSize[iPhase]; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + return leastSquaresResidual; } - struct ContactFrictionSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - ContactFrictionSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "ContactFrictionSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactFrictionConstraints( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + ContactFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("ContactFrictionSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactFrictionConstraints() { - BT_PROFILE( "resolveAllContactFrictionConstraints" ); - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - ContactFrictionSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = batchedCons.m_phaseGrainSize[iPhase]; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - return leastSquaresResidual; + BT_PROFILE("resolveAllContactFrictionConstraints"); + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + ContactFrictionSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = batchedCons.m_phaseGrainSize[iPhase]; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + return leastSquaresResidual; } - struct InterleavedContactSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - InterleavedContactSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "InterleavedContactSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactConstraintsInterleaved( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + InterleavedContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("InterleavedContactSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactConstraintsInterleaved(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraintsInterleaved() { - BT_PROFILE( "resolveAllContactConstraintsInterleaved" ); - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - InterleavedContactSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = 1; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - return leastSquaresResidual; + BT_PROFILE("resolveAllContactConstraintsInterleaved"); + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + InterleavedContactSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = 1; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + return leastSquaresResidual; } - struct ContactRollingFrictionSolverLoop : public btIParallelSumBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btBatchedConstraints* m_bc; - - ContactRollingFrictionSolverLoop( btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc ) - { - m_solver = solver; - m_bc = bc; - } - btScalar sumLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - BT_PROFILE( "ContactFrictionSolverLoop" ); - btScalar sum = 0; - for ( int iBatch = iBegin; iBatch < iEnd; ++iBatch ) - { - const btBatchedConstraints::Range& batch = m_bc->m_batches[ iBatch ]; - sum += m_solver->resolveMultipleContactRollingFrictionConstraints( m_bc->m_constraintIndices, batch.begin, batch.end ); - } - return sum; - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btBatchedConstraints* m_bc; + ContactRollingFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc) + { + m_solver = solver; + m_bc = bc; + } + btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + BT_PROFILE("ContactFrictionSolverLoop"); + btScalar sum = 0; + for (int iBatch = iBegin; iBatch < iEnd; ++iBatch) + { + const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch]; + sum += m_solver->resolveMultipleContactRollingFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end); + } + return sum; + } +}; btScalar btSequentialImpulseConstraintSolverMt::resolveAllRollingFrictionConstraints() { - BT_PROFILE( "resolveAllRollingFrictionConstraints" ); - btScalar leastSquaresResidual = 0.f; - // - // We do not generate batches for rolling friction constraints. We assume that - // one of two cases is true: - // - // 1. either most bodies in the simulation have rolling friction, in which case we can use the - // batches for contacts and use a lookup table to translate contact indices to rolling friction - // (ignoring any contact indices that don't map to a rolling friction constraint). As long as - // most contacts have a corresponding rolling friction constraint, this should parallelize well. - // - // -OR- - // - // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the - // batches from contacts as most of the contacts won't have corresponding rolling friction - // constraints and most threads would end up doing very little work. Most of the time would - // go to threading overhead, so we don't bother with threading. - // - int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); - if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size()) - { - // use batching if there are many rolling friction constraints - const btBatchedConstraints& batchedCons = m_batchedContactConstraints; - ContactRollingFrictionSolverLoop loop( this, &batchedCons ); - btScalar leastSquaresResidual = 0.f; - for ( int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase ) - { - int iPhase = batchedCons.m_phaseOrder[ iiPhase ]; - const btBatchedConstraints::Range& phase = batchedCons.m_phases[ iPhase ]; - int grainSize = 1; - leastSquaresResidual += btParallelSum( phase.begin, phase.end, grainSize, loop ); - } - } - else - { - // no batching, also ignores SOLVER_RANDMIZE_ORDER - for ( int j = 0; j < numRollingFrictionPoolConstraints; j++ ) - { - btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[ j ]; - if ( rollingFrictionConstraint.m_frictionIndex >= 0 ) - { - btScalar totalImpulse = m_tmpSolverContactConstraintPool[ rollingFrictionConstraint.m_frictionIndex ].m_appliedImpulse; - if ( totalImpulse > 0.0f ) - { - btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse; - if ( rollingFrictionMagnitude > rollingFrictionConstraint.m_friction ) - rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; - - rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; - rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; - - btScalar residual = resolveSingleConstraintRowGeneric( m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdA ], m_tmpSolverBodyPool[ rollingFrictionConstraint.m_solverBodyIdB ], rollingFrictionConstraint ); - leastSquaresResidual += residual*residual; - } - } - } - } - return leastSquaresResidual; + BT_PROFILE("resolveAllRollingFrictionConstraints"); + btScalar leastSquaresResidual = 0.f; + // + // We do not generate batches for rolling friction constraints. We assume that + // one of two cases is true: + // + // 1. either most bodies in the simulation have rolling friction, in which case we can use the + // batches for contacts and use a lookup table to translate contact indices to rolling friction + // (ignoring any contact indices that don't map to a rolling friction constraint). As long as + // most contacts have a corresponding rolling friction constraint, this should parallelize well. + // + // -OR- + // + // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the + // batches from contacts as most of the contacts won't have corresponding rolling friction + // constraints and most threads would end up doing very little work. Most of the time would + // go to threading overhead, so we don't bother with threading. + // + int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size(); + if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size()) + { + // use batching if there are many rolling friction constraints + const btBatchedConstraints& batchedCons = m_batchedContactConstraints; + ContactRollingFrictionSolverLoop loop(this, &batchedCons); + btScalar leastSquaresResidual = 0.f; + for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase) + { + int iPhase = batchedCons.m_phaseOrder[iiPhase]; + const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase]; + int grainSize = 1; + leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop); + } + } + else + { + // no batching, also ignores SOLVER_RANDMIZE_ORDER + for (int j = 0; j < numRollingFrictionPoolConstraints; j++) + { + btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j]; + if (rollingFrictionConstraint.m_frictionIndex >= 0) + { + btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse; + if (totalImpulse > 0.0f) + { + btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse; + if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction) + rollingFrictionMagnitude = rollingFrictionConstraint.m_friction; + + rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude; + rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude; + + btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint); + leastSquaresResidual += residual * residual; + } + } + } + } + return leastSquaresResidual; } - -void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ) +void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { - BT_PROFILE("internalWriteBackContacts"); - writeBackContacts(iBegin, iEnd, infoGlobal); - //for ( int iContact = iBegin; iContact < iEnd; ++iContact) - //{ - // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ]; - // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint; - // btAssert( pt ); - // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse; - // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse; - // if ( m_numFrictionDirections == 2 ) - // { - // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse; - // } - //} + BT_PROFILE("internalWriteBackContacts"); + writeBackContacts(iBegin, iEnd, infoGlobal); + //for ( int iContact = iBegin; iContact < iEnd; ++iContact) + //{ + // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ]; + // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint; + // btAssert( pt ); + // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse; + // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse; + // if ( m_numFrictionDirections == 2 ) + // { + // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse; + // } + //} } - -void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ) +void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { BT_PROFILE("internalWriteBackJoints"); - writeBackJoints(iBegin, iEnd, infoGlobal); + writeBackJoints(iBegin, iEnd, infoGlobal); } - -void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies( int iBegin, int iEnd, const btContactSolverInfo& infoGlobal ) +void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal) { BT_PROFILE("internalWriteBackBodies"); - writeBackBodies( iBegin, iEnd, infoGlobal ); + writeBackBodies(iBegin, iEnd, infoGlobal); } - struct WriteContactPointsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btContactSolverInfo* m_infoGlobal; - - WriteContactPointsLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalWriteBackContacts( iBegin, iEnd, *m_infoGlobal ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btContactSolverInfo* m_infoGlobal; + WriteContactPointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalWriteBackContacts(iBegin, iEnd, *m_infoGlobal); + } +}; struct WriteJointsLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btContactSolverInfo* m_infoGlobal; - - WriteJointsLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalWriteBackJoints( iBegin, iEnd, *m_infoGlobal ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btContactSolverInfo* m_infoGlobal; + WriteJointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalWriteBackJoints(iBegin, iEnd, *m_infoGlobal); + } +}; struct WriteBodiesLoop : public btIParallelForBody { - btSequentialImpulseConstraintSolverMt* m_solver; - const btContactSolverInfo* m_infoGlobal; - - WriteBodiesLoop( btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal ) - { - m_solver = solver; - m_infoGlobal = &infoGlobal; - } - void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE - { - m_solver->internalWriteBackBodies( iBegin, iEnd, *m_infoGlobal ); - } -}; + btSequentialImpulseConstraintSolverMt* m_solver; + const btContactSolverInfo* m_infoGlobal; + WriteBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal) + { + m_solver = solver; + m_infoGlobal = &infoGlobal; + } + void forLoop(int iBegin, int iEnd) const BT_OVERRIDE + { + m_solver->internalWriteBackBodies(iBegin, iEnd, *m_infoGlobal); + } +}; btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal) { BT_PROFILE("solveGroupCacheFriendlyFinish"); if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) - { - WriteContactPointsLoop loop( this, infoGlobal ); - int grainSize = 500; - btParallelFor( 0, m_tmpSolverContactConstraintPool.size(), grainSize, loop ); - } - - { - WriteJointsLoop loop( this, infoGlobal ); - int grainSize = 400; - btParallelFor( 0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop ); - } - { - WriteBodiesLoop loop( this, infoGlobal ); - int grainSize = 100; - btParallelFor( 0, m_tmpSolverBodyPool.size(), grainSize, loop ); - } + { + WriteContactPointsLoop loop(this, infoGlobal); + int grainSize = 500; + btParallelFor(0, m_tmpSolverContactConstraintPool.size(), grainSize, loop); + } + + { + WriteJointsLoop loop(this, infoGlobal); + int grainSize = 400; + btParallelFor(0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop); + } + { + WriteBodiesLoop loop(this, infoGlobal); + int grainSize = 100; + btParallelFor(0, m_tmpSolverBodyPool.size(), grainSize, loop); + } m_tmpSolverContactConstraintPool.resizeNoInitialize(0); m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0); @@ -1618,4 +1552,3 @@ btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(bt m_tmpSolverBodyPool.resizeNoInitialize(0); return 0.f; } - |