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 #include "btNNCGConstraintSolver.h"
18 btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
20 btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
22 m_pNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
23 m_pC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
24 m_pCF.resizeNoInitialize(m_tmpSolverContactFrictionConstraintPool.size());
25 m_pCRF.resizeNoInitialize(m_tmpSolverContactRollingFrictionConstraintPool.size());
27 m_deltafNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
28 m_deltafC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
29 m_deltafCF.resizeNoInitialize(m_tmpSolverContactFrictionConstraintPool.size());
30 m_deltafCRF.resizeNoInitialize(m_tmpSolverContactRollingFrictionConstraintPool.size());
35 btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
37 int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
38 int numConstraintPool = m_tmpSolverContactConstraintPool.size();
39 int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
41 if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
43 if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
45 for (int j = 0; j < numNonContactPool; ++j)
47 int tmp = m_orderNonContactConstraintPool[j];
48 int swapi = btRandInt2(j + 1);
49 m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
50 m_orderNonContactConstraintPool[swapi] = tmp;
53 //contact/friction constraints are not solved more than
54 if (iteration < infoGlobal.m_numIterations)
56 for (int j = 0; j < numConstraintPool; ++j)
58 int tmp = m_orderTmpConstraintPool[j];
59 int swapi = btRandInt2(j + 1);
60 m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
61 m_orderTmpConstraintPool[swapi] = tmp;
64 for (int j = 0; j < numFrictionPool; ++j)
66 int tmp = m_orderFrictionConstraintPool[j];
67 int swapi = btRandInt2(j + 1);
68 m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
69 m_orderFrictionConstraintPool[swapi] = tmp;
75 btScalar deltaflengthsqr = 0;
77 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
79 btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
80 if (iteration < constraint.m_overrideNumSolverIterations)
82 btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
83 m_deltafNC[j] = deltaf;
84 deltaflengthsqr += deltaf * deltaf;
89 if (m_onlyForNoneContact)
93 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j];
97 // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
98 btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
101 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0;
105 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
107 btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
108 if (iteration < constraint.m_overrideNumSolverIterations)
110 btScalar additionaldeltaimpulse = beta * m_pNC[j];
111 constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
112 m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
113 btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
114 btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
115 const btSolverConstraint& c = constraint;
116 body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
117 body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
122 m_deltafLengthSqrPrev = deltaflengthsqr;
126 if (iteration < infoGlobal.m_numIterations)
128 for (int j = 0; j < numConstraints; j++)
130 if (constraints[j]->isEnabled())
132 int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
133 int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
134 btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
135 btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
136 constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
140 ///solve all contact constraints
141 if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
143 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
144 int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
146 for (int c = 0; c < numPoolConstraints; c++)
148 btScalar totalImpulse = 0;
151 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
152 btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
153 m_deltafC[c] = deltaf;
154 deltaflengthsqr += deltaf * deltaf;
155 totalImpulse = solveManifold.m_appliedImpulse;
157 bool applyFriction = true;
161 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
163 if (totalImpulse > btScalar(0))
165 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
166 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
167 btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
168 m_deltafCF[c * multiplier] = deltaf;
169 deltaflengthsqr += deltaf * deltaf;
173 m_deltafCF[c * multiplier] = 0;
177 if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
179 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
181 if (totalImpulse > btScalar(0))
183 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
184 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
185 btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
186 m_deltafCF[c * multiplier + 1] = deltaf;
187 deltaflengthsqr += deltaf * deltaf;
191 m_deltafCF[c * multiplier + 1] = 0;
197 else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
199 //solve the friction constraints after all contact constraints, don't interleave them
200 int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
203 for (j = 0; j < numPoolConstraints; j++)
205 const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
206 btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
207 m_deltafC[j] = deltaf;
208 deltaflengthsqr += deltaf * deltaf;
211 ///solve all friction constraints
213 int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
214 for (j = 0; j < numFrictionPoolConstraints; j++)
216 btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
217 btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
219 if (totalImpulse > btScalar(0))
221 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
222 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
224 btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
225 m_deltafCF[j] = deltaf;
226 deltaflengthsqr += deltaf * deltaf;
236 int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
237 for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
239 btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
240 btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
241 if (totalImpulse > btScalar(0))
243 btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
244 if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
245 rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
247 rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
248 rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
250 btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
251 m_deltafCRF[j] = deltaf;
252 deltaflengthsqr += deltaf * deltaf;
263 if (!m_onlyForNoneContact)
267 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j];
268 for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = m_deltafC[j];
269 for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = m_deltafCF[j];
270 for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = m_deltafCRF[j];
274 // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
275 btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
278 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0;
279 for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = 0;
280 for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = 0;
281 for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = 0;
285 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
287 btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
288 if (iteration < constraint.m_overrideNumSolverIterations)
290 btScalar additionaldeltaimpulse = beta * m_pNC[j];
291 constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
292 m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
293 btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
294 btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
295 const btSolverConstraint& c = constraint;
296 body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
297 body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
300 for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++)
302 btSolverConstraint& constraint = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
303 if (iteration < infoGlobal.m_numIterations)
305 btScalar additionaldeltaimpulse = beta * m_pC[j];
306 constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
307 m_pC[j] = beta * m_pC[j] + m_deltafC[j];
308 btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
309 btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
310 const btSolverConstraint& c = constraint;
311 body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
312 body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
315 for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++)
317 btSolverConstraint& constraint = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
318 if (iteration < infoGlobal.m_numIterations)
320 btScalar additionaldeltaimpulse = beta * m_pCF[j];
321 constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
322 m_pCF[j] = beta * m_pCF[j] + m_deltafCF[j];
323 btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
324 btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
325 const btSolverConstraint& c = constraint;
326 body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
327 body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
331 for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++)
333 btSolverConstraint& constraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
334 if (iteration < infoGlobal.m_numIterations)
336 btScalar additionaldeltaimpulse = beta * m_pCRF[j];
337 constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
338 m_pCRF[j] = beta * m_pCRF[j] + m_deltafCRF[j];
339 btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
340 btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
341 const btSolverConstraint& c = constraint;
342 body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
343 body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
349 m_deltafLengthSqrPrev = deltaflengthsqr;
352 return deltaflengthsqr;
355 btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
357 m_pNC.resizeNoInitialize(0);
358 m_pC.resizeNoInitialize(0);
359 m_pCF.resizeNoInitialize(0);
360 m_pCRF.resizeNoInitialize(0);
362 m_deltafNC.resizeNoInitialize(0);
363 m_deltafC.resizeNoInitialize(0);
364 m_deltafCF.resizeNoInitialize(0);
365 m_deltafCRF.resizeNoInitialize(0);
367 return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);