2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 //#define COMPUTE_IMPULSE_DENOM 1
17 //It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
19 #include "btSequentialImpulseConstraintSolver.h"
20 #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
21 #include "BulletDynamics/Dynamics/btRigidBody.h"
22 #include "btContactConstraint.h"
23 #include "btSolve2LinearConstraint.h"
24 #include "btContactSolverInfo.h"
25 #include "LinearMath/btIDebugDraw.h"
26 #include "btJacobianEntry.h"
27 #include "LinearMath/btMinMax.h"
28 #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
30 #include "LinearMath/btStackAlloc.h"
31 #include "LinearMath/btQuickprof.h"
32 #include "btSolverBody.h"
33 #include "btSolverConstraint.h"
34 #include "LinearMath/btAlignedObjectArray.h"
35 #include <string.h> //for memset
37 int gNumSplitImpulseRecoveries = 0;
39 btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
45 btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
50 #include <emmintrin.h>
51 #define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
52 static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
54 __m128 result = _mm_mul_ps( vec0, vec1);
55 return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) );
59 // Project Gauss Seidel or the equivalent Sequential Impulse
60 void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
63 __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
64 __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
65 __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
66 __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
67 __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
68 __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
69 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
70 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
71 btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
72 btSimdScalar resultLowerLess,resultUpperLess;
73 resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
74 resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
75 __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
76 deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
77 c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
78 __m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp);
79 deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) );
80 c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) );
81 __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
82 __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
83 __m128 impulseMagnitude = deltaImpulse;
84 body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
85 body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
86 body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
87 body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
89 resolveSingleConstraintRowGeneric(body1,body2,c);
93 // Project Gauss Seidel or the equivalent Sequential Impulse
94 void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
96 btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
97 const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
98 const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
100 // const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
101 deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
102 deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
104 const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
105 if (sum < c.m_lowerLimit)
107 deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
108 c.m_appliedImpulse = c.m_lowerLimit;
110 else if (sum > c.m_upperLimit)
112 deltaImpulse = c.m_upperLimit-c.m_appliedImpulse;
113 c.m_appliedImpulse = c.m_upperLimit;
117 c.m_appliedImpulse = sum;
119 body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
120 body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
123 void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
126 __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
127 __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
128 __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
129 __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
130 __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
131 __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
132 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
133 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
134 btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
135 btSimdScalar resultLowerLess,resultUpperLess;
136 resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
137 resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
138 __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
139 deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
140 c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
141 __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
142 __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
143 __m128 impulseMagnitude = deltaImpulse;
144 body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
145 body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
146 body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
147 body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
149 resolveSingleConstraintRowLowerLimit(body1,body2,c);
153 // Project Gauss Seidel or the equivalent Sequential Impulse
154 void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
156 btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
157 const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
158 const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
160 deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
161 deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
162 const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
163 if (sum < c.m_lowerLimit)
165 deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
166 c.m_appliedImpulse = c.m_lowerLimit;
170 c.m_appliedImpulse = sum;
172 body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
173 body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
177 void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly(
180 const btSolverConstraint& c)
182 if (c.m_rhsPenetration)
184 gNumSplitImpulseRecoveries++;
185 btScalar deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm;
186 const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
187 const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
189 deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
190 deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
191 const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
192 if (sum < c.m_lowerLimit)
194 deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse;
195 c.m_appliedPushImpulse = c.m_lowerLimit;
199 c.m_appliedPushImpulse = sum;
201 body1.internalApplyPushImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
202 body2.internalApplyPushImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
206 void btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
209 if (!c.m_rhsPenetration)
212 gNumSplitImpulseRecoveries++;
214 __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
215 __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
216 __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
217 __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm)));
218 __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128));
219 __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetPushVelocity().mVec128));
220 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
221 deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
222 btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
223 btSimdScalar resultLowerLess,resultUpperLess;
224 resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
225 resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
226 __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
227 deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
228 c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
229 __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
230 __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
231 __m128 impulseMagnitude = deltaImpulse;
232 body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
233 body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
234 body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
235 body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
237 resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c);
243 unsigned long btSequentialImpulseConstraintSolver::btRand2()
245 m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff;
251 //See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
252 int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
254 // seems good; xor-fold and modulus
255 const unsigned long un = static_cast<unsigned long>(n);
256 unsigned long r = btRand2();
258 // note: probably more aggressive than it needs to be -- might be
259 // able to get away without one or two of the innermost branches.
260 if (un <= 0x00010000UL) {
262 if (un <= 0x00000100UL) {
264 if (un <= 0x00000010UL) {
266 if (un <= 0x00000004UL) {
268 if (un <= 0x00000002UL) {
276 return (int) (r % un);
281 void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject)
283 btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0;
285 solverBody->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
286 solverBody->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
287 solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f);
288 solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
292 solverBody->internalGetInvMass() = btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor();
293 solverBody->m_originalBody = rb;
294 solverBody->m_angularFactor = rb->getAngularFactor();
297 solverBody->internalGetInvMass().setValue(0,0,0);
298 solverBody->m_originalBody = 0;
299 solverBody->m_angularFactor.setValue(1,1,1);
308 btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution)
310 btScalar rest = restitution * -rel_vel;
316 void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection);
317 void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection)
319 if (colObj && colObj->hasAnisotropicFriction())
321 // transform to local coordinates
322 btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
323 const btVector3& friction_scaling = colObj->getAnisotropicFriction();
324 //apply anisotropic friction
325 loc_lateral *= friction_scaling;
326 // ... and transform it back to global coordinates
327 frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
332 void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
336 btRigidBody* body0=btRigidBody::upcast(colObj0);
337 btRigidBody* body1=btRigidBody::upcast(colObj1);
339 solverConstraint.m_contactNormal = normalAxis;
341 solverConstraint.m_solverBodyA = body0 ? body0 : &getFixedBody();
342 solverConstraint.m_solverBodyB = body1 ? body1 : &getFixedBody();
344 solverConstraint.m_friction = cp.m_combinedFriction;
345 solverConstraint.m_originalContactPoint = 0;
347 solverConstraint.m_appliedImpulse = 0.f;
348 solverConstraint.m_appliedPushImpulse = 0.f;
351 btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
352 solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
353 solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0);
356 btVector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal);
357 solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
358 solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0);
361 #ifdef COMPUTE_IMPULSE_DENOM
362 btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal);
363 btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal);
366 btScalar denom0 = 0.f;
367 btScalar denom1 = 0.f;
370 vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
371 denom0 = body0->getInvMass() + normalAxis.dot(vec);
375 vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
376 denom1 = body1->getInvMass() + normalAxis.dot(vec);
380 #endif //COMPUTE_IMPULSE_DENOM
381 btScalar denom = relaxation/(denom0+denom1);
382 solverConstraint.m_jacDiagABInv = denom;
385 solverConstraint.m_jac = btJacobianEntry (
386 rel_pos1,rel_pos2,solverConstraint.m_contactNormal,
387 body0->getInvInertiaDiagLocal(),
389 body1->getInvInertiaDiagLocal(),
390 body1->getInvMass());
391 #endif //_USE_JACOBIAN
396 btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?body0->getLinearVelocity():btVector3(0,0,0))
397 + solverConstraint.m_relpos1CrossNormal.dot(body0?body0->getAngularVelocity():btVector3(0,0,0));
398 btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?body1->getLinearVelocity():btVector3(0,0,0))
399 + solverConstraint.m_relpos2CrossNormal.dot(body1?body1->getAngularVelocity():btVector3(0,0,0));
401 rel_vel = vel1Dotn+vel2Dotn;
403 // btScalar positionalError = 0.f;
405 btSimdScalar velocityError = desiredVelocity - rel_vel;
406 btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
407 solverConstraint.m_rhs = velocityImpulse;
408 solverConstraint.m_cfm = cfmSlip;
409 solverConstraint.m_lowerLimit = 0;
410 solverConstraint.m_upperLimit = 1e10f;
416 btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
418 btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
419 solverConstraint.m_frictionIndex = frictionIndex;
420 setupFrictionConstraint(solverConstraint, normalAxis, solverBodyA, solverBodyB, cp, rel_pos1, rel_pos2,
421 colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
422 return solverConstraint;
425 int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body)
428 int solverBodyIdA = -1;
430 if (body.getCompanionId() >= 0)
432 //body has already been converted
433 solverBodyIdA = body.getCompanionId();
436 btRigidBody* rb = btRigidBody::upcast(&body);
437 if (rb && rb->getInvMass())
439 solverBodyIdA = m_tmpSolverBodyPool.size();
440 btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
441 initSolverBody(&solverBody,&body);
442 body.setCompanionId(solverBodyIdA);
445 return 0;//assume first one is a fixed solver body
448 return solverBodyIdA;
455 void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
456 btCollisionObject* colObj0, btCollisionObject* colObj1,
457 btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
458 btVector3& vel, btScalar& rel_vel, btScalar& relaxation,
459 btVector3& rel_pos1, btVector3& rel_pos2)
461 btRigidBody* rb0 = btRigidBody::upcast(colObj0);
462 btRigidBody* rb1 = btRigidBody::upcast(colObj1);
464 const btVector3& pos1 = cp.getPositionWorldOnA();
465 const btVector3& pos2 = cp.getPositionWorldOnB();
467 // btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
468 // btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
469 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
470 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
474 btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
475 solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
476 btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
477 solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
480 #ifdef COMPUTE_IMPULSE_DENOM
481 btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
482 btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
485 btScalar denom0 = 0.f;
486 btScalar denom1 = 0.f;
489 vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
490 denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
494 vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
495 denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
497 #endif //COMPUTE_IMPULSE_DENOM
499 btScalar denom = relaxation/(denom0+denom1);
500 solverConstraint.m_jacDiagABInv = denom;
503 solverConstraint.m_contactNormal = cp.m_normalWorldOnB;
504 solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB);
505 solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(-cp.m_normalWorldOnB);
510 btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
511 btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
513 rel_vel = cp.m_normalWorldOnB.dot(vel);
515 btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
518 solverConstraint.m_friction = cp.m_combinedFriction;
520 btScalar restitution = 0.f;
522 if (cp.m_lifeTime>infoGlobal.m_restingContactRestitutionThreshold)
527 restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution);
528 if (restitution <= btScalar(0.))
535 ///warm starting (or zero if disabled)
536 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
538 solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
540 rb0->internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
542 rb1->internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
545 solverConstraint.m_appliedImpulse = 0.f;
548 solverConstraint.m_appliedPushImpulse = 0.f;
552 btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0?rb0->getLinearVelocity():btVector3(0,0,0))
553 + solverConstraint.m_relpos1CrossNormal.dot(rb0?rb0->getAngularVelocity():btVector3(0,0,0));
554 btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1?rb1->getLinearVelocity():btVector3(0,0,0))
555 + solverConstraint.m_relpos2CrossNormal.dot(rb1?rb1->getAngularVelocity():btVector3(0,0,0));
557 rel_vel = vel1Dotn+vel2Dotn;
559 btScalar positionalError = 0.f;
560 btScalar velocityError = restitution - rel_vel;// * damping;
565 velocityError -= penetration / infoGlobal.m_timeStep;
568 positionalError = -penetration * infoGlobal.m_erp/infoGlobal.m_timeStep;
571 btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
572 btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
573 if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
575 //combine position and velocity into rhs
576 solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
577 solverConstraint.m_rhsPenetration = 0.f;
580 //split position and velocity into rhs and m_rhsPenetration
581 solverConstraint.m_rhs = velocityImpulse;
582 solverConstraint.m_rhsPenetration = penetrationImpulse;
584 solverConstraint.m_cfm = 0.f;
585 solverConstraint.m_lowerLimit = 0;
586 solverConstraint.m_upperLimit = 1e10f;
596 void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint,
597 btRigidBody* rb0, btRigidBody* rb1,
598 btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
600 if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING)
603 btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
604 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
606 frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
608 rb0->internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
610 rb1->internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse);
613 frictionConstraint1.m_appliedImpulse = 0.f;
617 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
619 btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
620 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
622 frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
624 rb0->internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
626 rb1->internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse);
629 frictionConstraint2.m_appliedImpulse = 0.f;
634 btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
635 frictionConstraint1.m_appliedImpulse = 0.f;
636 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
638 btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
639 frictionConstraint2.m_appliedImpulse = 0.f;
647 void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal)
649 btCollisionObject* colObj0=0,*colObj1=0;
651 colObj0 = (btCollisionObject*)manifold->getBody0();
652 colObj1 = (btCollisionObject*)manifold->getBody1();
655 btRigidBody* solverBodyA = btRigidBody::upcast(colObj0);
656 btRigidBody* solverBodyB = btRigidBody::upcast(colObj1);
658 ///avoid collision response between two static objects
659 if ((!solverBodyA || !solverBodyA->getInvMass()) && (!solverBodyB || !solverBodyB->getInvMass()))
662 for (int j=0;j<manifold->getNumContacts();j++)
665 btManifoldPoint& cp = manifold->getContactPoint(j);
667 if (cp.getDistance() <= manifold->getContactProcessingThreshold())
675 int frictionIndex = m_tmpSolverContactConstraintPool.size();
676 btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
677 btRigidBody* rb0 = btRigidBody::upcast(colObj0);
678 btRigidBody* rb1 = btRigidBody::upcast(colObj1);
679 solverConstraint.m_solverBodyA = rb0? rb0 : &getFixedBody();
680 solverConstraint.m_solverBodyB = rb1? rb1 : &getFixedBody();
681 solverConstraint.m_originalContactPoint = &cp;
683 setupContactConstraint(solverConstraint, colObj0, colObj1, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
685 // const btVector3& pos1 = cp.getPositionWorldOnA();
686 // const btVector3& pos2 = cp.getPositionWorldOnB();
688 /////setup the friction constraints
690 solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
692 if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized)
694 cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
695 btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
696 if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
698 cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel);
699 if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
701 cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
702 cp.m_lateralFrictionDir2.normalize();//??
703 applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2);
704 applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2);
705 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
708 applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1);
709 applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1);
710 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
711 cp.m_lateralFrictionInitialized = true;
714 //re-calculate friction direction every frame, todo: check if this is really needed
715 btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
716 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
718 applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2);
719 applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2);
720 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
723 applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1);
724 applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1);
725 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
727 cp.m_lateralFrictionInitialized = true;
732 addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1);
733 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
734 addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
737 setFrictionConstraintImpulse( solverConstraint, rb0, rb1, cp, infoGlobal);
743 btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
745 BT_PROFILE("solveGroupCacheFriendlySetup");
749 m_maxOverrideNumSolverIterations = 0;
751 if (!(numConstraints + numManifolds))
753 // printf("empty\n");
757 if (infoGlobal.m_splitImpulse)
759 for (int i = 0; i < numBodies; i++)
761 btRigidBody* body = btRigidBody::upcast(bodies[i]);
764 body->internalGetDeltaLinearVelocity().setZero();
765 body->internalGetDeltaAngularVelocity().setZero();
766 body->internalGetPushVelocity().setZero();
767 body->internalGetTurnVelocity().setZero();
773 for (int i = 0; i < numBodies; i++)
775 btRigidBody* body = btRigidBody::upcast(bodies[i]);
778 body->internalGetDeltaLinearVelocity().setZero();
779 body->internalGetDeltaAngularVelocity().setZero();
787 for (j=0;j<numConstraints;j++)
789 btTypedConstraint* constraint = constraints[j];
790 constraint->buildJacobian();
791 constraint->internalSetAppliedImpulse(0.0f);
794 //btRigidBody* rb0=0,*rb1=0;
800 int totalNumRows = 0;
803 m_tmpConstraintSizesPool.resize(numConstraints);
804 //calculate the total number of contraint rows
805 for (i=0;i<numConstraints;i++)
807 btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
808 if (constraints[i]->isEnabled())
810 constraints[i]->getInfo1(&info1);
813 info1.m_numConstraintRows = 0;
816 totalNumRows += info1.m_numConstraintRows;
818 m_tmpSolverNonContactConstraintPool.resize(totalNumRows);
821 ///setup the btSolverConstraints
824 for (i=0;i<numConstraints;i++)
826 const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
828 if (info1.m_numConstraintRows)
830 btAssert(currentRow<totalNumRows);
832 btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
833 btTypedConstraint* constraint = constraints[i];
834 btRigidBody& rbA = constraint->getRigidBodyA();
835 btRigidBody& rbB = constraint->getRigidBodyB();
838 int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
839 if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
840 m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
844 for ( j=0;j<info1.m_numConstraintRows;j++)
846 memset(¤tConstraintRow[j],0,sizeof(btSolverConstraint));
847 currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
848 currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
849 currentConstraintRow[j].m_appliedImpulse = 0.f;
850 currentConstraintRow[j].m_appliedPushImpulse = 0.f;
851 currentConstraintRow[j].m_solverBodyA = &rbA;
852 currentConstraintRow[j].m_solverBodyB = &rbB;
853 currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
856 rbA.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
857 rbA.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
858 rbB.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
859 rbB.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
863 btTypedConstraint::btConstraintInfo2 info2;
864 info2.fps = 1.f/infoGlobal.m_timeStep;
865 info2.erp = infoGlobal.m_erp;
866 info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
867 info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
868 info2.m_J2linearAxis = 0;
869 info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
870 info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
871 ///the size of btSolverConstraint needs be a multiple of btScalar
872 btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
873 info2.m_constraintError = ¤tConstraintRow->m_rhs;
874 currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
875 info2.m_damping = infoGlobal.m_damping;
876 info2.cfm = ¤tConstraintRow->m_cfm;
877 info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit;
878 info2.m_upperLimit = ¤tConstraintRow->m_upperLimit;
879 info2.m_numIterations = infoGlobal.m_numIterations;
880 constraints[i]->getInfo2(&info2);
882 ///finalize the constraint setup
883 for ( j=0;j<info1.m_numConstraintRows;j++)
885 btSolverConstraint& solverConstraint = currentConstraintRow[j];
887 if (solverConstraint.m_upperLimit>=constraints[i]->getBreakingImpulseThreshold())
889 solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
892 if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold())
894 solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
897 solverConstraint.m_originalContactPoint = constraint;
900 const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
901 solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
904 const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
905 solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
909 btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass();
910 btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
911 btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal?
912 btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
914 btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
915 sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
916 sum += iMJlB.dot(solverConstraint.m_contactNormal);
917 sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
919 solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
924 ///todo: add force/torque accelerators
927 btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity());
928 btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity());
930 rel_vel = vel1Dotn+vel2Dotn;
932 btScalar restitution = 0.f;
933 btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
934 btScalar velocityError = restitution - rel_vel * info2.m_damping;
935 btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
936 btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
937 solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
938 solverConstraint.m_appliedImpulse = 0.f;
943 currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
949 btPersistentManifold* manifold = 0;
950 // btCollisionObject* colObj0=0,*colObj1=0;
953 for (i=0;i<numManifolds;i++)
955 manifold = manifoldPtr[i];
956 convertContact(manifold,infoGlobal);
961 btContactSolverInfo info = infoGlobal;
964 int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
965 int numConstraintPool = m_tmpSolverContactConstraintPool.size();
966 int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
968 ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
969 m_orderNonContactConstraintPool.resize(numNonContactPool);
970 m_orderTmpConstraintPool.resize(numConstraintPool);
971 m_orderFrictionConstraintPool.resize(numFrictionPool);
974 for (i=0;i<numNonContactPool;i++)
976 m_orderNonContactConstraintPool[i] = i;
978 for (i=0;i<numConstraintPool;i++)
980 m_orderTmpConstraintPool[i] = i;
982 for (i=0;i<numFrictionPool;i++)
984 m_orderFrictionConstraintPool[i] = i;
992 btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/,btStackAlloc* /*stackAlloc*/)
995 int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
996 int numConstraintPool = m_tmpSolverContactConstraintPool.size();
997 int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
1001 if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
1003 if ((iteration & 7) == 0) {
1004 for (j=0; j<numNonContactPool; ++j) {
1005 int tmp = m_orderNonContactConstraintPool[j];
1006 int swapi = btRandInt2(j+1);
1007 m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
1008 m_orderNonContactConstraintPool[swapi] = tmp;
1011 //contact/friction constraints are not solved more than
1012 if (iteration< infoGlobal.m_numIterations)
1014 for (j=0; j<numConstraintPool; ++j) {
1015 int tmp = m_orderTmpConstraintPool[j];
1016 int swapi = btRandInt2(j+1);
1017 m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
1018 m_orderTmpConstraintPool[swapi] = tmp;
1021 for (j=0; j<numFrictionPool; ++j) {
1022 int tmp = m_orderFrictionConstraintPool[j];
1023 int swapi = btRandInt2(j+1);
1024 m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
1025 m_orderFrictionConstraintPool[swapi] = tmp;
1031 if (infoGlobal.m_solverMode & SOLVER_SIMD)
1033 ///solve all joint constraints, using SIMD, if available
1034 for (j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
1036 btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
1037 if (iteration < constraint.m_overrideNumSolverIterations)
1038 resolveSingleConstraintRowGenericSIMD(*constraint.m_solverBodyA,*constraint.m_solverBodyB,constraint);
1041 if (iteration< infoGlobal.m_numIterations)
1043 for (j=0;j<numConstraints;j++)
1045 constraints[j]->solveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
1048 ///solve all contact constraints using SIMD, if available
1049 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1050 for (j=0;j<numPoolConstraints;j++)
1052 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
1053 resolveSingleConstraintRowLowerLimitSIMD(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
1057 ///solve all friction constraints, using SIMD, if available
1058 int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
1059 for (j=0;j<numFrictionPoolConstraints;j++)
1061 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
1062 btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
1064 if (totalImpulse>btScalar(0))
1066 solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
1067 solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
1069 resolveSingleConstraintRowGenericSIMD(*solveManifold.m_solverBodyA, *solveManifold.m_solverBodyB,solveManifold);
1076 ///solve all joint constraints
1077 for (j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
1079 btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
1080 if (iteration < constraint.m_overrideNumSolverIterations)
1081 resolveSingleConstraintRowGeneric(*constraint.m_solverBodyA,*constraint.m_solverBodyB,constraint);
1084 if (iteration< infoGlobal.m_numIterations)
1086 for (j=0;j<numConstraints;j++)
1088 constraints[j]->solveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
1090 ///solve all contact constraints
1091 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1092 for (j=0;j<numPoolConstraints;j++)
1094 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
1095 resolveSingleConstraintRowLowerLimit(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
1097 ///solve all friction constraints
1098 int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
1099 for (j=0;j<numFrictionPoolConstraints;j++)
1101 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
1102 btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
1104 if (totalImpulse>btScalar(0))
1106 solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
1107 solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
1109 resolveSingleConstraintRowGeneric(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
1118 void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
1121 if (infoGlobal.m_splitImpulse)
1123 if (infoGlobal.m_solverMode & SOLVER_SIMD)
1125 for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
1128 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1130 for (j=0;j<numPoolConstraints;j++)
1132 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
1134 resolveSplitPenetrationSIMD(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
1141 for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
1144 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1146 for (j=0;j<numPoolConstraints;j++)
1148 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
1150 resolveSplitPenetrationImpulseCacheFriendly(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
1158 btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
1160 BT_PROFILE("solveGroupCacheFriendlyIterations");
1163 ///this is a special step to resolve penetrations (just for contacts)
1164 solveGroupCacheFriendlySplitImpulseIterations(bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc);
1166 int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
1168 for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
1169 //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
1171 solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc);
1178 btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies ,int numBodies,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** /*constraints*/,int /* numConstraints*/,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/,btStackAlloc* /*stackAlloc*/)
1180 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1183 for (j=0;j<numPoolConstraints;j++)
1186 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
1187 btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint;
1189 pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
1190 if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING)
1192 pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
1193 pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
1196 //do a callback here?
1199 numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
1200 for (j=0;j<numPoolConstraints;j++)
1202 const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
1203 btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
1204 constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
1205 if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
1207 constr->setEnabled(false);
1212 if (infoGlobal.m_splitImpulse)
1214 for ( i=0;i<numBodies;i++)
1216 btRigidBody* body = btRigidBody::upcast(bodies[i]);
1218 body->internalWritebackVelocity(infoGlobal.m_timeStep);
1222 for ( i=0;i<numBodies;i++)
1224 btRigidBody* body = btRigidBody::upcast(bodies[i]);
1226 body->internalWritebackVelocity();
1231 m_tmpSolverContactConstraintPool.resize(0);
1232 m_tmpSolverNonContactConstraintPool.resize(0);
1233 m_tmpSolverContactFrictionConstraintPool.resize(0);
1240 /// btSequentialImpulseConstraintSolver Sequentially applies impulses
1241 btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* /*dispatcher*/)
1244 BT_PROFILE("solveGroup");
1245 //you need to provide at least some bodies
1247 btAssert(numBodies);
1249 solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
1251 solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
1253 solveGroupCacheFriendlyFinish(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
1258 void btSequentialImpulseConstraintSolver::reset()
1263 btRigidBody& btSequentialImpulseConstraintSolver::getFixedBody()
1265 static btRigidBody s_fixed(0, 0,0);
1266 s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));