2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 //#define COMPUTE_IMPULSE_DENOM 1
18 # define BT_ADDITIONAL_DEBUG
21 //It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
23 #include "btSequentialImpulseConstraintSolver.h"
24 #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
26 #include "LinearMath/btIDebugDraw.h"
27 #include "LinearMath/btCpuFeatureUtility.h"
29 //#include "btJacobianEntry.h"
30 #include "LinearMath/btMinMax.h"
31 #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
33 #include "LinearMath/btStackAlloc.h"
34 #include "LinearMath/btQuickprof.h"
35 //#include "btSolverBody.h"
36 //#include "btSolverConstraint.h"
37 #include "LinearMath/btAlignedObjectArray.h"
38 #include <string.h> //for memset
40 int gNumSplitImpulseRecoveries = 0;
42 #include "BulletDynamics/Dynamics/btRigidBody.h"
44 //#define VERBOSE_RESIDUAL_PRINTF 1
45 ///This is the scalar reference implementation of solving a single constraint row, the innerloop of the Projected Gauss Seidel/Sequential Impulse constraint solver
46 ///Below are optional SSE2 and SSE4/FMA3 versions. We assume most hardware has SSE2. For SSE4/FMA3 we perform a CPU feature check.
47 static btScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
49 btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
50 const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity());
51 const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity());
53 // const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
54 deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
55 deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
57 const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
58 if (sum < c.m_lowerLimit)
60 deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
61 c.m_appliedImpulse = c.m_lowerLimit;
63 else if (sum > c.m_upperLimit)
65 deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
66 c.m_appliedImpulse = c.m_upperLimit;
70 c.m_appliedImpulse = sum;
73 bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
74 bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
76 return deltaImpulse * (1. / c.m_jacDiagABInv);
79 static btScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
81 btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
82 const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity());
83 const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity());
85 deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
86 deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
87 const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
88 if (sum < c.m_lowerLimit)
90 deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
91 c.m_appliedImpulse = c.m_lowerLimit;
95 c.m_appliedImpulse = sum;
97 bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
98 bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
100 return deltaImpulse * (1. / c.m_jacDiagABInv);
104 #include <emmintrin.h>
106 #define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e))
107 static inline __m128 btSimdDot3(__m128 vec0, __m128 vec1)
109 __m128 result = _mm_mul_ps(vec0, vec1);
110 return _mm_add_ps(btVecSplat(result, 0), _mm_add_ps(btVecSplat(result, 1), btVecSplat(result, 2)));
113 #if defined(BT_ALLOW_SSE4)
117 #define USE_FMA3_INSTEAD_FMA4 1
118 #define USE_SSE4_DOT 1
120 #define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f)
121 #define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f))
124 #define DOT_PRODUCT(a, b) SSE4_DP(a, b)
126 #define DOT_PRODUCT(a, b) btSimdDot3(a, b)
130 #if USE_FMA3_INSTEAD_FMA4
132 #define FMADD(a, b, c) _mm_fmadd_ps(a, b, c)
134 #define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c)
137 #define FMADD(a, b, c) _mm_macc_ps(a, b, c)
139 #define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c)
143 #define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b))
145 #define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b))
149 // Project Gauss Seidel or the equivalent Sequential Impulse
150 static btScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
152 __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
153 __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
154 __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
155 btSimdScalar 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)));
156 __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
157 __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
158 deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
159 deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
160 btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
161 btSimdScalar resultLowerLess, resultUpperLess;
162 resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
163 resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
164 __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
165 deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
166 c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
167 __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
168 deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
169 c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
170 __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
171 __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, bodyB.internalGetInvMass().mVec128);
172 __m128 impulseMagnitude = deltaImpulse;
173 bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
174 bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
175 bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
176 bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
177 return deltaImpulse.m_floats[0] / c.m_jacDiagABInv;
180 // Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
181 static btScalar gResolveSingleConstraintRowGeneric_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
183 #if defined(BT_ALLOW_SSE4)
184 __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
185 __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm);
186 const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
187 const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit);
188 const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
189 const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
190 deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
191 deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
192 tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); // sum
193 const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit);
194 const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp);
195 deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower);
196 c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower);
197 bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
198 bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128);
199 bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
200 bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128);
201 btSimdScalar deltaImp = deltaImpulse;
202 return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
204 return gResolveSingleConstraintRowGeneric_sse2(bodyA, bodyB, c);
208 static btScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
210 __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
211 __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
212 __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
213 btSimdScalar 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)));
214 __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
215 __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
216 deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
217 deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
218 btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
219 btSimdScalar resultLowerLess, resultUpperLess;
220 resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
221 resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
222 __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
223 deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
224 c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
225 __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
226 __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
227 __m128 impulseMagnitude = deltaImpulse;
228 bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
229 bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
230 bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
231 bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
232 return deltaImpulse.m_floats[0] / c.m_jacDiagABInv;
235 // Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
236 static btScalar gResolveSingleConstraintRowLowerLimit_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
239 __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
240 __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm);
241 const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
242 const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
243 const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
244 deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
245 deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
246 tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse);
247 const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit);
248 deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask);
249 c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask);
250 bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
251 bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128);
252 bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
253 bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128);
254 btSimdScalar deltaImp = deltaImpulse;
255 return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
257 return gResolveSingleConstraintRowLowerLimit_sse2(bodyA, bodyB, c);
258 #endif //BT_ALLOW_SSE4
263 btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
265 return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c);
268 // Project Gauss Seidel or the equivalent Sequential Impulse
269 btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
271 return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c);
274 btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
276 return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c);
279 btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
281 return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c);
284 static btScalar gResolveSplitPenetrationImpulse_scalar_reference(
287 const btSolverConstraint& c)
289 btScalar deltaImpulse = 0.f;
291 if (c.m_rhsPenetration)
293 gNumSplitImpulseRecoveries++;
294 deltaImpulse = c.m_rhsPenetration - btScalar(c.m_appliedPushImpulse) * c.m_cfm;
295 const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetTurnVelocity());
296 const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetTurnVelocity());
298 deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
299 deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
300 const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
301 if (sum < c.m_lowerLimit)
303 deltaImpulse = c.m_lowerLimit - c.m_appliedPushImpulse;
304 c.m_appliedPushImpulse = c.m_lowerLimit;
308 c.m_appliedPushImpulse = sum;
310 bodyA.internalApplyPushImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
311 bodyB.internalApplyPushImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
313 return deltaImpulse * (1. / c.m_jacDiagABInv);
316 static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
319 if (!c.m_rhsPenetration)
322 gNumSplitImpulseRecoveries++;
324 __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
325 __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
326 __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
327 __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)));
328 __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetTurnVelocity().mVec128));
329 __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetTurnVelocity().mVec128));
330 deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
331 deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
332 btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
333 btSimdScalar resultLowerLess, resultUpperLess;
334 resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
335 resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
336 __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
337 deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
338 c.m_appliedPushImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
339 __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
340 __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
341 __m128 impulseMagnitude = deltaImpulse;
342 bodyA.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyA.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
343 bodyA.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyA.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
344 bodyB.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyB.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
345 bodyB.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyB.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
346 btSimdScalar deltaImp = deltaImpulse;
347 return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
349 return gResolveSplitPenetrationImpulse_scalar_reference(bodyA, bodyB, c);
353 btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
356 m_cachedSolverMode = 0;
357 setupSolverFunctions(false);
360 void btSequentialImpulseConstraintSolver::setupSolverFunctions(bool useSimd)
362 m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference;
363 m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference;
364 m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference;
369 m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
370 m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2;
371 m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2;
374 int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
375 if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
377 m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
378 m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
380 #endif //BT_ALLOW_SSE4
385 btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
389 btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric()
391 return gResolveSingleConstraintRowGeneric_scalar_reference;
394 btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit()
396 return gResolveSingleConstraintRowLowerLimit_scalar_reference;
400 btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
402 return gResolveSingleConstraintRowGeneric_sse2;
404 btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
406 return gResolveSingleConstraintRowLowerLimit_sse2;
409 btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
411 return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
413 btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
415 return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
417 #endif //BT_ALLOW_SSE4
420 unsigned long btSequentialImpulseConstraintSolver::btRand2()
422 m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff;
426 //See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
427 int btSequentialImpulseConstraintSolver::btRandInt2(int n)
429 // seems good; xor-fold and modulus
430 const unsigned long un = static_cast<unsigned long>(n);
431 unsigned long r = btRand2();
433 // note: probably more aggressive than it needs to be -- might be
434 // able to get away without one or two of the innermost branches.
435 if (un <= 0x00010000UL)
438 if (un <= 0x00000100UL)
441 if (un <= 0x00000010UL)
444 if (un <= 0x00000004UL)
447 if (un <= 0x00000002UL)
456 return (int)(r % un);
459 void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
461 btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
463 solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
464 solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
465 solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
466 solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
470 solverBody->m_worldTransform = rb->getWorldTransform();
471 solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
472 solverBody->m_originalBody = rb;
473 solverBody->m_angularFactor = rb->getAngularFactor();
474 solverBody->m_linearFactor = rb->getLinearFactor();
475 solverBody->m_linearVelocity = rb->getLinearVelocity();
476 solverBody->m_angularVelocity = rb->getAngularVelocity();
477 solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
478 solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
482 solverBody->m_worldTransform.setIdentity();
483 solverBody->internalSetInvMass(btVector3(0, 0, 0));
484 solverBody->m_originalBody = 0;
485 solverBody->m_angularFactor.setValue(1, 1, 1);
486 solverBody->m_linearFactor.setValue(1, 1, 1);
487 solverBody->m_linearVelocity.setValue(0, 0, 0);
488 solverBody->m_angularVelocity.setValue(0, 0, 0);
489 solverBody->m_externalForceImpulse.setValue(0, 0, 0);
490 solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
494 btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
496 //printf("rel_vel =%f\n", rel_vel);
497 if (btFabs(rel_vel) < velocityThreshold)
500 btScalar rest = restitution * -rel_vel;
504 void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj, btVector3& frictionDirection, int frictionMode)
506 if (colObj && colObj->hasAnisotropicFriction(frictionMode))
508 // transform to local coordinates
509 btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
510 const btVector3& friction_scaling = colObj->getAnisotropicFriction();
511 //apply anisotropic friction
512 loc_lateral *= friction_scaling;
513 // ... and transform it back to global coordinates
514 frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
518 void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
520 btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
521 btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
523 btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
524 btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
526 solverConstraint.m_solverBodyIdA = solverBodyIdA;
527 solverConstraint.m_solverBodyIdB = solverBodyIdB;
529 solverConstraint.m_friction = cp.m_combinedFriction;
530 solverConstraint.m_originalContactPoint = 0;
532 solverConstraint.m_appliedImpulse = 0.f;
533 solverConstraint.m_appliedPushImpulse = 0.f;
537 solverConstraint.m_contactNormal1 = normalAxis;
538 btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1);
539 solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
540 solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor();
544 solverConstraint.m_contactNormal1.setZero();
545 solverConstraint.m_relpos1CrossNormal.setZero();
546 solverConstraint.m_angularComponentA.setZero();
551 solverConstraint.m_contactNormal2 = -normalAxis;
552 btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2);
553 solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
554 solverConstraint.m_angularComponentB = bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor();
558 solverConstraint.m_contactNormal2.setZero();
559 solverConstraint.m_relpos2CrossNormal.setZero();
560 solverConstraint.m_angularComponentB.setZero();
565 btScalar denom0 = 0.f;
566 btScalar denom1 = 0.f;
569 vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
570 denom0 = body0->getInvMass() + normalAxis.dot(vec);
574 vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
575 denom1 = bodyA->getInvMass() + normalAxis.dot(vec);
577 btScalar denom = relaxation / (denom0 + denom1);
578 solverConstraint.m_jacDiagABInv = denom;
583 btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0));
584 btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0));
586 rel_vel = vel1Dotn + vel2Dotn;
588 // btScalar positionalError = 0.f;
590 btScalar velocityError = desiredVelocity - rel_vel;
591 btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
593 btScalar penetrationImpulse = btScalar(0);
595 if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
597 btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis);
598 btScalar positionalError = -distance * infoGlobal.m_frictionERP / infoGlobal.m_timeStep;
599 penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
602 solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
603 solverConstraint.m_rhsPenetration = 0.f;
604 solverConstraint.m_cfm = cfmSlip;
605 solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
606 solverConstraint.m_upperLimit = solverConstraint.m_friction;
610 btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
612 btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
613 solverConstraint.m_frictionIndex = frictionIndex;
614 setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
615 colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
616 return solverConstraint;
619 void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
620 btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
621 btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
622 btScalar desiredVelocity, btScalar cfmSlip)
625 btVector3 normalAxis(0, 0, 0);
627 solverConstraint.m_contactNormal1 = normalAxis;
628 solverConstraint.m_contactNormal2 = -normalAxis;
629 btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
630 btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
632 btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
633 btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
635 solverConstraint.m_solverBodyIdA = solverBodyIdA;
636 solverConstraint.m_solverBodyIdB = solverBodyIdB;
638 solverConstraint.m_friction = combinedTorsionalFriction;
639 solverConstraint.m_originalContactPoint = 0;
641 solverConstraint.m_appliedImpulse = 0.f;
642 solverConstraint.m_appliedPushImpulse = 0.f;
645 btVector3 ftorqueAxis1 = -normalAxis1;
646 solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
647 solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor() : btVector3(0, 0, 0);
650 btVector3 ftorqueAxis1 = normalAxis1;
651 solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
652 solverConstraint.m_angularComponentB = bodyA ? bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor() : btVector3(0, 0, 0);
656 btVector3 iMJaA = body0 ? body0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0);
657 btVector3 iMJaB = bodyA ? bodyA->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0);
659 sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
660 sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
661 solverConstraint.m_jacDiagABInv = btScalar(1.) / sum;
666 btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0));
667 btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0));
669 rel_vel = vel1Dotn + vel2Dotn;
671 // btScalar positionalError = 0.f;
673 btSimdScalar velocityError = desiredVelocity - rel_vel;
674 btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
675 solverConstraint.m_rhs = velocityImpulse;
676 solverConstraint.m_cfm = cfmSlip;
677 solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
678 solverConstraint.m_upperLimit = solverConstraint.m_friction;
682 btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
684 btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
685 solverConstraint.m_frictionIndex = frictionIndex;
686 setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
687 colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
688 return solverConstraint;
691 int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body, btScalar timeStep)
694 int solverBodyId = -1;
695 const bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
696 const bool isStaticOrKinematic = body.isStaticOrKinematicObject();
697 const bool isKinematic = body.isKinematicObject();
698 if (isRigidBodyType && !isStaticOrKinematic)
701 // Dynamic bodies can only be in one island, so it's safe to write to the companionId
702 solverBodyId = body.getCompanionId();
703 if (solverBodyId < 0)
705 solverBodyId = m_tmpSolverBodyPool.size();
706 btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
707 initSolverBody(&solverBody, &body, timeStep);
708 body.setCompanionId(solverBodyId);
711 else if (isRigidBodyType && isKinematic)
714 // NOTE: must test for kinematic before static because some kinematic objects also
715 // identify as "static"
717 // Kinematic bodies can be in multiple islands at once, so it is a
718 // race condition to write to them, so we use an alternate method
719 // to record the solverBodyId
720 int uniqueId = body.getWorldArrayIndex();
721 const int INVALID_SOLVER_BODY_ID = -1;
722 if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
724 m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
726 solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
727 // if no table entry yet,
728 if (solverBodyId == INVALID_SOLVER_BODY_ID)
730 // create a table entry for this body
731 solverBodyId = m_tmpSolverBodyPool.size();
732 btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
733 initSolverBody(&solverBody, &body, timeStep);
734 m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
739 bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
740 // Incorrectly set collision object flags can degrade performance in various ways.
741 if (!isMultiBodyType)
743 btAssert(body.isStaticOrKinematicObject());
745 //it could be a multibody link collider
746 // all fixed bodies (inf mass) get mapped to a single solver id
747 if (m_fixedBodyId < 0)
749 m_fixedBodyId = m_tmpSolverBodyPool.size();
750 btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
751 initSolverBody(&fixedBody, 0, timeStep);
753 solverBodyId = m_fixedBodyId;
755 btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
757 #else // BT_THREADSAFE
759 int solverBodyIdA = -1;
761 if (body.getCompanionId() >= 0)
763 //body has already been converted
764 solverBodyIdA = body.getCompanionId();
765 btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
769 btRigidBody* rb = btRigidBody::upcast(&body);
770 //convert both active and kinematic objects (for their velocity)
771 if (rb && (rb->getInvMass() || rb->isKinematicObject()))
773 solverBodyIdA = m_tmpSolverBodyPool.size();
774 btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
775 initSolverBody(&solverBody, &body, timeStep);
776 body.setCompanionId(solverBodyIdA);
780 if (m_fixedBodyId < 0)
782 m_fixedBodyId = m_tmpSolverBodyPool.size();
783 btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
784 initSolverBody(&fixedBody, 0, timeStep);
786 return m_fixedBodyId;
787 // return 0;//assume first one is a fixed solver body
791 return solverBodyIdA;
792 #endif // BT_THREADSAFE
796 void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
797 int solverBodyIdA, int solverBodyIdB,
798 btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
799 btScalar& relaxation,
800 const btVector3& rel_pos1, const btVector3& rel_pos2)
802 // const btVector3& pos1 = cp.getPositionWorldOnA();
803 // const btVector3& pos2 = cp.getPositionWorldOnB();
805 btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
806 btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
808 btRigidBody* rb0 = bodyA->m_originalBody;
809 btRigidBody* rb1 = bodyB->m_originalBody;
811 // btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
812 // btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
813 //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
814 //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
816 relaxation = infoGlobal.m_sor;
817 btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
819 //cfm = 1 / ( dt * kp + kd )
820 //erp = dt * kp / ( dt * kp + kd )
822 btScalar cfm = infoGlobal.m_globalCfm;
823 btScalar erp = infoGlobal.m_erp2;
825 if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
827 if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM)
828 cfm = cp.m_contactCFM;
829 if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)
830 erp = cp.m_contactERP;
834 if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
836 btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
837 if (denom < SIMD_EPSILON)
839 denom = SIMD_EPSILON;
841 cfm = btScalar(1) / denom;
842 erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
848 btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
849 solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
850 btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
851 solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
854 #ifdef COMPUTE_IMPULSE_DENOM
855 btScalar denom0 = rb0->computeImpulseDenominator(pos1, cp.m_normalWorldOnB);
856 btScalar denom1 = rb1->computeImpulseDenominator(pos2, cp.m_normalWorldOnB);
859 btScalar denom0 = 0.f;
860 btScalar denom1 = 0.f;
863 vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
864 denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
868 vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
869 denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
871 #endif //COMPUTE_IMPULSE_DENOM
873 btScalar denom = relaxation / (denom0 + denom1 + cfm);
874 solverConstraint.m_jacDiagABInv = denom;
879 solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
880 solverConstraint.m_relpos1CrossNormal = torqueAxis0;
884 solverConstraint.m_contactNormal1.setZero();
885 solverConstraint.m_relpos1CrossNormal.setZero();
889 solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
890 solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
894 solverConstraint.m_contactNormal2.setZero();
895 solverConstraint.m_relpos2CrossNormal.setZero();
898 btScalar restitution = 0.f;
899 btScalar penetration = cp.getDistance() + infoGlobal.m_linearSlop;
902 btVector3 vel1, vel2;
904 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0, 0, 0);
905 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0);
907 // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
908 btVector3 vel = vel1 - vel2;
909 btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
911 solverConstraint.m_friction = cp.m_combinedFriction;
913 restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
914 if (restitution <= btScalar(0.))
920 ///warm starting (or zero if disabled)
921 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
923 solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
925 bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
927 bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
931 solverConstraint.m_appliedImpulse = 0.f;
934 solverConstraint.m_appliedPushImpulse = 0.f;
937 btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse : btVector3(0, 0, 0);
938 btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse : btVector3(0, 0, 0);
939 btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse : btVector3(0, 0, 0);
940 btVector3 externalTorqueImpulseB = bodyB->m_originalBody ? bodyB->m_externalTorqueImpulse : btVector3(0, 0, 0);
942 btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity + externalTorqueImpulseA);
943 btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity + externalTorqueImpulseB);
944 btScalar rel_vel = vel1Dotn + vel2Dotn;
946 btScalar positionalError = 0.f;
947 btScalar velocityError = restitution - rel_vel; // * damping;
953 velocityError -= penetration * invTimeStep;
957 positionalError = -penetration * erp * invTimeStep;
960 btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
961 btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
963 if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
965 //combine position and velocity into rhs
966 solverConstraint.m_rhs = penetrationImpulse + velocityImpulse; //-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv;
967 solverConstraint.m_rhsPenetration = 0.f;
971 //split position and velocity into rhs and m_rhsPenetration
972 solverConstraint.m_rhs = velocityImpulse;
973 solverConstraint.m_rhsPenetration = penetrationImpulse;
975 solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
976 solverConstraint.m_lowerLimit = 0;
977 solverConstraint.m_upperLimit = 1e10f;
981 void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
982 int solverBodyIdA, int solverBodyIdB,
983 btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
986 btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
988 frictionConstraint1.m_appliedImpulse = 0.f;
991 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
993 btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
995 frictionConstraint2.m_appliedImpulse = 0.f;
999 void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
1001 btCollisionObject *colObj0 = 0, *colObj1 = 0;
1003 colObj0 = (btCollisionObject*)manifold->getBody0();
1004 colObj1 = (btCollisionObject*)manifold->getBody1();
1006 int solverBodyIdA = getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
1007 int solverBodyIdB = getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
1009 // btRigidBody* bodyA = btRigidBody::upcast(colObj0);
1010 // btRigidBody* bodyB = btRigidBody::upcast(colObj1);
1012 btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
1013 btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
1015 ///avoid collision response between two static objects
1016 if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
1019 int rollingFriction = 1;
1020 for (int j = 0; j < manifold->getNumContacts(); j++)
1022 btManifoldPoint& cp = manifold->getContactPoint(j);
1024 if (cp.getDistance() <= manifold->getContactProcessingThreshold())
1028 btScalar relaxation;
1030 int frictionIndex = m_tmpSolverContactConstraintPool.size();
1031 btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
1032 solverConstraint.m_solverBodyIdA = solverBodyIdA;
1033 solverConstraint.m_solverBodyIdB = solverBodyIdB;
1035 solverConstraint.m_originalContactPoint = &cp;
1037 const btVector3& pos1 = cp.getPositionWorldOnA();
1038 const btVector3& pos2 = cp.getPositionWorldOnB();
1040 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
1041 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
1046 solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
1047 solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
1049 btVector3 vel = vel1 - vel2;
1050 btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
1052 setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
1054 /////setup the friction constraints
1056 solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
1058 if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
1061 addTorsionalFrictionConstraint(cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
1062 btVector3 axis0, axis1;
1063 btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
1067 applyAnisotropicFriction(colObj0, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
1068 applyAnisotropicFriction(colObj1, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
1069 applyAnisotropicFriction(colObj0, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
1070 applyAnisotropicFriction(colObj1, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
1071 if (axis0.length() > 0.001)
1072 addTorsionalFrictionConstraint(axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
1073 cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
1074 if (axis1.length() > 0.001)
1075 addTorsionalFrictionConstraint(axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
1076 cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
1080 ///Bullet has several options to set the friction directions
1081 ///By default, each contact has only a single friction direction that is recomputed automatically very frame
1082 ///based on the relative linear velocity.
1083 ///If the relative velocity it zero, it will automatically compute a friction direction.
1085 ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
1086 ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
1088 ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
1090 ///The user can manually override the friction directions for certain contacts using a contact callback,
1091 ///and use contactPoint.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED
1092 ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
1093 ///this will give a conveyor belt effect
1096 if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
1098 cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
1099 btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
1100 if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
1102 cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
1103 applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
1104 applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
1105 addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
1107 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1109 cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
1110 cp.m_lateralFrictionDir2.normalize(); //??
1111 applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
1112 applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
1113 addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
1118 btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
1120 applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
1121 applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
1122 addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
1124 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1126 applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
1127 applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
1128 addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
1131 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
1133 cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
1139 addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
1141 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1142 addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
1144 setFrictionConstraintImpulse(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
1149 void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
1152 btPersistentManifold* manifold = 0;
1153 // btCollisionObject* colObj0=0,*colObj1=0;
1155 for (i = 0; i < numManifolds; i++)
1157 manifold = manifoldPtr[i];
1158 convertContact(manifold, infoGlobal);
1162 void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
1163 btTypedConstraint* constraint,
1164 const btTypedConstraint::btConstraintInfo1& info1,
1167 const btContactSolverInfo& infoGlobal)
1169 const btRigidBody& rbA = constraint->getRigidBodyA();
1170 const btRigidBody& rbB = constraint->getRigidBodyB();
1172 const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
1173 const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
1175 int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
1176 if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
1177 m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
1179 for (int j = 0; j < info1.m_numConstraintRows; j++)
1181 memset(¤tConstraintRow[j], 0, sizeof(btSolverConstraint));
1182 currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
1183 currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
1184 currentConstraintRow[j].m_appliedImpulse = 0.f;
1185 currentConstraintRow[j].m_appliedPushImpulse = 0.f;
1186 currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
1187 currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
1188 currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
1191 // these vectors are already cleared in initSolverBody, no need to redundantly clear again
1192 btAssert(bodyAPtr->getDeltaLinearVelocity().isZero());
1193 btAssert(bodyAPtr->getDeltaAngularVelocity().isZero());
1194 btAssert(bodyAPtr->getPushVelocity().isZero());
1195 btAssert(bodyAPtr->getTurnVelocity().isZero());
1196 btAssert(bodyBPtr->getDeltaLinearVelocity().isZero());
1197 btAssert(bodyBPtr->getDeltaAngularVelocity().isZero());
1198 btAssert(bodyBPtr->getPushVelocity().isZero());
1199 btAssert(bodyBPtr->getTurnVelocity().isZero());
1200 //bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
1201 //bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
1202 //bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
1203 //bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
1204 //bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
1205 //bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
1206 //bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
1207 //bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
1209 btTypedConstraint::btConstraintInfo2 info2;
1210 info2.fps = 1.f / infoGlobal.m_timeStep;
1211 info2.erp = infoGlobal.m_erp;
1212 info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
1213 info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
1214 info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
1215 info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
1216 info2.rowskip = sizeof(btSolverConstraint) / sizeof(btScalar); //check this
1217 ///the size of btSolverConstraint needs be a multiple of btScalar
1218 btAssert(info2.rowskip * sizeof(btScalar) == sizeof(btSolverConstraint));
1219 info2.m_constraintError = ¤tConstraintRow->m_rhs;
1220 currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
1221 info2.m_damping = infoGlobal.m_damping;
1222 info2.cfm = ¤tConstraintRow->m_cfm;
1223 info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit;
1224 info2.m_upperLimit = ¤tConstraintRow->m_upperLimit;
1225 info2.m_numIterations = infoGlobal.m_numIterations;
1226 constraint->getInfo2(&info2);
1228 ///finalize the constraint setup
1229 for (int j = 0; j < info1.m_numConstraintRows; j++)
1231 btSolverConstraint& solverConstraint = currentConstraintRow[j];
1233 if (solverConstraint.m_upperLimit >= constraint->getBreakingImpulseThreshold())
1235 solverConstraint.m_upperLimit = constraint->getBreakingImpulseThreshold();
1238 if (solverConstraint.m_lowerLimit <= -constraint->getBreakingImpulseThreshold())
1240 solverConstraint.m_lowerLimit = -constraint->getBreakingImpulseThreshold();
1243 solverConstraint.m_originalContactPoint = constraint;
1246 const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
1247 solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld() * ftorqueAxis1 * constraint->getRigidBodyA().getAngularFactor();
1250 const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
1251 solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld() * ftorqueAxis2 * constraint->getRigidBodyB().getAngularFactor();
1255 btVector3 iMJlA = solverConstraint.m_contactNormal1 * rbA.getInvMass();
1256 btVector3 iMJaA = rbA.getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal;
1257 btVector3 iMJlB = solverConstraint.m_contactNormal2 * rbB.getInvMass(); //sign of normal?
1258 btVector3 iMJaB = rbB.getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal;
1260 btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
1261 sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
1262 sum += iMJlB.dot(solverConstraint.m_contactNormal2);
1263 sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
1264 btScalar fsum = btFabs(sum);
1265 btAssert(fsum > SIMD_EPSILON);
1266 btScalar sorRelaxation = 1.f; //todo: get from globalInfo?
1267 solverConstraint.m_jacDiagABInv = fsum > SIMD_EPSILON ? sorRelaxation / sum : 0.f;
1272 btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0, 0, 0);
1273 btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0, 0, 0);
1275 btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0, 0, 0);
1276 btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalTorqueImpulse : btVector3(0, 0, 0);
1278 btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity() + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity() + externalTorqueImpulseA);
1280 btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity() + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity() + externalTorqueImpulseB);
1282 rel_vel = vel1Dotn + vel2Dotn;
1283 btScalar restitution = 0.f;
1284 btScalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
1285 btScalar velocityError = restitution - rel_vel * info2.m_damping;
1286 btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
1287 btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
1288 solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
1289 solverConstraint.m_appliedImpulse = 0.f;
1294 void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
1296 BT_PROFILE("convertJoints");
1297 for (int j = 0; j < numConstraints; j++)
1299 btTypedConstraint* constraint = constraints[j];
1300 constraint->buildJacobian();
1301 constraint->internalSetAppliedImpulse(0.0f);
1304 int totalNumRows = 0;
1306 m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
1307 //calculate the total number of contraint rows
1308 for (int i = 0; i < numConstraints; i++)
1310 btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
1311 btJointFeedback* fb = constraints[i]->getJointFeedback();
1314 fb->m_appliedForceBodyA.setZero();
1315 fb->m_appliedTorqueBodyA.setZero();
1316 fb->m_appliedForceBodyB.setZero();
1317 fb->m_appliedTorqueBodyB.setZero();
1320 if (constraints[i]->isEnabled())
1322 constraints[i]->getInfo1(&info1);
1326 info1.m_numConstraintRows = 0;
1329 totalNumRows += info1.m_numConstraintRows;
1331 m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
1333 ///setup the btSolverConstraints
1336 for (int i = 0; i < numConstraints; i++)
1338 const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
1340 if (info1.m_numConstraintRows)
1342 btAssert(currentRow < totalNumRows);
1344 btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
1345 btTypedConstraint* constraint = constraints[i];
1346 btRigidBody& rbA = constraint->getRigidBodyA();
1347 btRigidBody& rbB = constraint->getRigidBodyB();
1349 int solverBodyIdA = getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
1350 int solverBodyIdB = getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
1352 convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
1354 currentRow += info1.m_numConstraintRows;
1358 void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
1360 BT_PROFILE("convertBodies");
1361 for (int i = 0; i < numBodies; i++)
1363 bodies[i]->setCompanionId(-1);
1366 m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
1367 #endif // BT_THREADSAFE
1369 m_tmpSolverBodyPool.reserve(numBodies + 1);
1370 m_tmpSolverBodyPool.resize(0);
1372 //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
1373 //initSolverBody(&fixedBody,0);
1375 for (int i = 0; i < numBodies; i++)
1377 int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
1379 btRigidBody* body = btRigidBody::upcast(bodies[i]);
1380 if (body && body->getInvMass())
1382 btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
1383 btVector3 gyroForce(0, 0, 0);
1384 if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
1386 gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
1387 solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
1389 if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
1391 gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
1392 solverBody.m_externalTorqueImpulse += gyroForce;
1394 if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
1396 gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
1397 solverBody.m_externalTorqueImpulse += gyroForce;
1403 btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
1406 BT_PROFILE("solveGroupCacheFriendlySetup");
1409 // if solver mode has changed,
1410 if (infoGlobal.m_solverMode != m_cachedSolverMode)
1412 // update solver functions to use SIMD or non-SIMD
1413 bool useSimd = !!(infoGlobal.m_solverMode & SOLVER_SIMD);
1414 setupSolverFunctions(useSimd);
1415 m_cachedSolverMode = infoGlobal.m_solverMode;
1417 m_maxOverrideNumSolverIterations = 0;
1419 #ifdef BT_ADDITIONAL_DEBUG
1420 //make sure that dynamic bodies exist for all (enabled) constraints
1421 for (int i = 0; i < numConstraints; i++)
1423 btTypedConstraint* constraint = constraints[i];
1424 if (constraint->isEnabled())
1426 if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
1429 for (int b = 0; b < numBodies; b++)
1431 if (&constraint->getRigidBodyA() == bodies[b])
1439 if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
1442 for (int b = 0; b < numBodies; b++)
1444 if (&constraint->getRigidBodyB() == bodies[b])
1454 //make sure that dynamic bodies exist for all contact manifolds
1455 for (int i = 0; i < numManifolds; i++)
1457 if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
1460 for (int b = 0; b < numBodies; b++)
1462 if (manifoldPtr[i]->getBody0() == bodies[b])
1470 if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
1473 for (int b = 0; b < numBodies; b++)
1475 if (manifoldPtr[i]->getBody1() == bodies[b])
1484 #endif //BT_ADDITIONAL_DEBUG
1486 //convert all bodies
1487 convertBodies(bodies, numBodies, infoGlobal);
1489 convertJoints(constraints, numConstraints, infoGlobal);
1491 convertContacts(manifoldPtr, numManifolds, infoGlobal);
1493 // btContactSolverInfo info = infoGlobal;
1495 int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
1496 int numConstraintPool = m_tmpSolverContactConstraintPool.size();
1497 int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
1499 ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
1500 m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
1501 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1502 m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool * 2);
1504 m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
1506 m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
1509 for (i = 0; i < numNonContactPool; i++)
1511 m_orderNonContactConstraintPool[i] = i;
1513 for (i = 0; i < numConstraintPool; i++)
1515 m_orderTmpConstraintPool[i] = i;
1517 for (i = 0; i < numFrictionPool; i++)
1519 m_orderFrictionConstraintPool[i] = i;
1526 btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
1528 BT_PROFILE("solveSingleIteration");
1529 btScalar leastSquaresResidual = 0.f;
1531 int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
1532 int numConstraintPool = m_tmpSolverContactConstraintPool.size();
1533 int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
1535 if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
1537 if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
1539 for (int j = 0; j < numNonContactPool; ++j)
1541 int tmp = m_orderNonContactConstraintPool[j];
1542 int swapi = btRandInt2(j + 1);
1543 m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
1544 m_orderNonContactConstraintPool[swapi] = tmp;
1547 //contact/friction constraints are not solved more than
1548 if (iteration < infoGlobal.m_numIterations)
1550 for (int j = 0; j < numConstraintPool; ++j)
1552 int tmp = m_orderTmpConstraintPool[j];
1553 int swapi = btRandInt2(j + 1);
1554 m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
1555 m_orderTmpConstraintPool[swapi] = tmp;
1558 for (int j = 0; j < numFrictionPool; ++j)
1560 int tmp = m_orderFrictionConstraintPool[j];
1561 int swapi = btRandInt2(j + 1);
1562 m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
1563 m_orderFrictionConstraintPool[swapi] = tmp;
1569 ///solve all joint constraints
1570 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
1572 btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
1573 if (iteration < constraint.m_overrideNumSolverIterations)
1575 btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
1576 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
1580 if (iteration < infoGlobal.m_numIterations)
1582 for (int j = 0; j < numConstraints; j++)
1584 if (constraints[j]->isEnabled())
1586 int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
1587 int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
1588 btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
1589 btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
1590 constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
1594 ///solve all contact constraints
1595 if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
1597 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1598 int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
1600 for (int c = 0; c < numPoolConstraints; c++)
1602 btScalar totalImpulse = 0;
1605 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
1606 btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
1607 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
1609 totalImpulse = solveManifold.m_appliedImpulse;
1611 bool applyFriction = true;
1615 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
1617 if (totalImpulse > btScalar(0))
1619 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
1620 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
1622 btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
1623 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
1627 if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
1629 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
1631 if (totalImpulse > btScalar(0))
1633 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
1634 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
1636 btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
1637 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
1643 else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
1645 //solve the friction constraints after all contact constraints, don't interleave them
1646 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1649 for (j = 0; j < numPoolConstraints; j++)
1651 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
1652 btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
1653 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
1656 ///solve all friction constraints
1658 int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
1659 for (j = 0; j < numFrictionPoolConstraints; j++)
1661 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
1662 btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
1664 if (totalImpulse > btScalar(0))
1666 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
1667 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
1669 btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
1670 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
1675 int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
1676 for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
1678 btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
1679 btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
1680 if (totalImpulse > btScalar(0))
1682 btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
1683 if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
1684 rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
1686 rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
1687 rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
1689 btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
1690 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
1694 return leastSquaresResidual;
1697 void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
1699 BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
1701 if (infoGlobal.m_splitImpulse)
1704 for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
1706 btScalar leastSquaresResidual = 0.f;
1708 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
1710 for (j = 0; j < numPoolConstraints; j++)
1712 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
1714 btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
1715 leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
1718 if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
1720 #ifdef VERBOSE_RESIDUAL_PRINTF
1721 printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
1730 btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
1732 BT_PROFILE("solveGroupCacheFriendlyIterations");
1735 ///this is a special step to resolve penetrations (just for contacts)
1736 solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
1738 int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
1740 for (int iteration = 0; iteration < maxIterations; iteration++)
1741 //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
1743 m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
1745 if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
1747 #ifdef VERBOSE_RESIDUAL_PRINTF
1748 printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
1750 m_analyticsData.m_numSolverCalls++;
1751 m_analyticsData.m_numIterationsUsed = iteration+1;
1752 m_analyticsData.m_islandId = -2;
1754 m_analyticsData.m_islandId = bodies[0]->getCompanionId();
1755 m_analyticsData.m_numBodies = numBodies;
1756 m_analyticsData.m_numContactManifolds = numManifolds;
1757 m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
1765 void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
1767 for (int j = iBegin; j < iEnd; j++)
1769 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
1770 btManifoldPoint* pt = (btManifoldPoint*)solveManifold.m_originalContactPoint;
1772 pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
1773 // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
1774 // printf("pt->m_appliedImpulseLateral1 = %f\n", f);
1775 pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
1776 //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
1777 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1779 pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
1781 //do a callback here?
1785 void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
1787 for (int j = iBegin; j < iEnd; j++)
1789 const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
1790 btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
1791 btJointFeedback* fb = constr->getJointFeedback();
1794 fb->m_appliedForceBodyA += solverConstr.m_contactNormal1 * solverConstr.m_appliedImpulse * constr->getRigidBodyA().getLinearFactor() / infoGlobal.m_timeStep;
1795 fb->m_appliedForceBodyB += solverConstr.m_contactNormal2 * solverConstr.m_appliedImpulse * constr->getRigidBodyB().getLinearFactor() / infoGlobal.m_timeStep;
1796 fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal * constr->getRigidBodyA().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
1797 fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal * constr->getRigidBodyB().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep; /*RGM ???? */
1800 constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
1801 if (btFabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold())
1803 constr->setEnabled(false);
1808 void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
1810 for (int i = iBegin; i < iEnd; i++)
1812 btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
1815 if (infoGlobal.m_splitImpulse)
1816 m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
1818 m_tmpSolverBodyPool[i].writebackVelocity();
1820 m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
1821 m_tmpSolverBodyPool[i].m_linearVelocity +
1822 m_tmpSolverBodyPool[i].m_externalForceImpulse);
1824 m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
1825 m_tmpSolverBodyPool[i].m_angularVelocity +
1826 m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
1828 if (infoGlobal.m_splitImpulse)
1829 m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
1831 m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
1836 btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
1838 BT_PROFILE("solveGroupCacheFriendlyFinish");
1840 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
1842 writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal);
1845 writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
1846 writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal);
1848 m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
1849 m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
1850 m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
1851 m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
1853 m_tmpSolverBodyPool.resizeNoInitialize(0);
1857 /// btSequentialImpulseConstraintSolver Sequentially applies impulses
1858 btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btDispatcher* /*dispatcher*/)
1860 BT_PROFILE("solveGroup");
1861 //you need to provide at least some bodies
1863 solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
1865 solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
1867 solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
1872 void btSequentialImpulseConstraintSolver::reset()