Bullet Collision Detection & Physics Library
btSequentialImpulseConstraintSolver.cpp
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16//#define COMPUTE_IMPULSE_DENOM 1
17#ifdef BT_DEBUG
18# define BT_ADDITIONAL_DEBUG
19#endif
20
21//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
22
25
28
29//#include "btJacobianEntry.h"
30#include "LinearMath/btMinMax.h"
32#include <new>
35//#include "btSolverBody.h"
36//#include "btSolverConstraint.h"
38#include <string.h> //for memset
39
41
43
44//#define VERBOSE_RESIDUAL_PRINTF 1
48{
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());
52
53 // const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
56
58 if (sum < c.m_lowerLimit)
59 {
62 }
63 else if (sum > c.m_upperLimit)
64 {
67 }
68 else
69 {
71 }
72
73 bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
74 bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
75
76 return deltaImpulse * (1. / c.m_jacDiagABInv);
77}
78
80{
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());
84
88 if (sum < c.m_lowerLimit)
89 {
92 }
93 else
94 {
96 }
97 bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
98 bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
99
100 return deltaImpulse * (1. / c.m_jacDiagABInv);
101}
102
103#ifdef USE_SIMD
104#include <emmintrin.h>
105
106#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e))
107static inline __m128 btSimdDot3(__m128 vec0, __m128 vec1)
108{
111}
112
113#if defined(BT_ALLOW_SSE4)
114#include <intrin.h>
115
116#define USE_FMA 1
117#define USE_FMA3_INSTEAD_FMA4 1
118#define USE_SSE4_DOT 1
119
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))
122
123#if USE_SSE4_DOT
124#define DOT_PRODUCT(a, b) SSE4_DP(a, b)
125#else
126#define DOT_PRODUCT(a, b) btSimdDot3(a, b)
127#endif
128
129#if USE_FMA
130#if USE_FMA3_INSTEAD_FMA4
131// a*b + c
132#define FMADD(a, b, c) _mm_fmadd_ps(a, b, c)
133// -(a*b) + c
134#define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c)
135#else // USE_FMA3
136// a*b + c
137#define FMADD(a, b, c) _mm_macc_ps(a, b, c)
138// -(a*b) + c
139#define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c)
140#endif
141#else // USE_FMA
142// c + a*b
143#define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b))
144// c - a*b
145#define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b))
146#endif
147#endif
148
149// Project Gauss Seidel or the equivalent Sequential Impulse
151{
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));
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);
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;
178}
179
180// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
182{
183#if defined(BT_ALLOW_SSE4)
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));
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);
202 return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
203#else
205#endif
206}
207
209{
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));
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);
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;
233}
234
235// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
237{
238#ifdef BT_ALLOW_SSE4
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));
247 const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit);
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);
255 return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
256#else
258#endif //BT_ALLOW_SSE4
259}
260
261#endif //USE_SIMD
262
264{
266}
267
268// Project Gauss Seidel or the equivalent Sequential Impulse
270{
272}
273
275{
277}
278
280{
282}
283
287 const btSolverConstraint& c)
288{
290
291 if (c.m_rhsPenetration)
292 {
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());
297
301 if (sum < c.m_lowerLimit)
302 {
305 }
306 else
307 {
309 }
310 bodyA.internalApplyPushImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
311 bodyB.internalApplyPushImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
312 }
313 return deltaImpulse * (1. / c.m_jacDiagABInv);
314}
315
317{
318#ifdef USE_SIMD
319 if (!c.m_rhsPenetration)
320 return 0.f;
321
323
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));
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);
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));
347 return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
348#else
350#endif
351}
352
354{
355 m_btSeed2 = 0;
358}
359
361{
365
366 if (useSimd)
367 {
368#ifdef USE_SIMD
372
373#ifdef BT_ALLOW_SSE4
376 {
379 }
380#endif //BT_ALLOW_SSE4
381#endif //USE_SIMD
382 }
383}
384
386{
387}
388
390{
392}
393
395{
397}
398
399#ifdef USE_SIMD
401{
403}
405{
407}
408#ifdef BT_ALLOW_SSE4
410{
412}
414{
416}
417#endif //BT_ALLOW_SSE4
418#endif //USE_SIMD
419
421{
422 m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff;
423 return m_btSeed2;
424}
425
426//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
428{
429 // seems good; xor-fold and modulus
430 const unsigned long un = static_cast<unsigned long>(n);
431 unsigned long r = btRand2();
432
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)
436 {
437 r ^= (r >> 16);
438 if (un <= 0x00000100UL)
439 {
440 r ^= (r >> 8);
441 if (un <= 0x00000010UL)
442 {
443 r ^= (r >> 4);
444 if (un <= 0x00000004UL)
445 {
446 r ^= (r >> 2);
447 if (un <= 0x00000002UL)
448 {
449 r ^= (r >> 1);
450 }
451 }
452 }
453 }
454 }
455
456 return (int)(r % un);
457}
458
460{
462
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);
467
468 if (rb)
469 {
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;
479 }
480 else
481 {
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);
491 }
492 }
493
495{
496 //printf("rel_vel =%f\n", rel_vel);
498 return 0.;
499
501 return rest;
502}
503
505{
506 if (colObj && colObj->hasAnisotropicFriction(frictionMode))
507 {
508 // transform to local coordinates
509 btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
510 const btVector3& friction_scaling = colObj->getAnisotropicFriction();
511 //apply anisotropic friction
513 // ... and transform it back to global coordinates
514 frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
515 }
516}
517
519{
522
525
526 solverConstraint.m_solverBodyIdA = solverBodyIdA;
527 solverConstraint.m_solverBodyIdB = solverBodyIdB;
528
529 solverConstraint.m_friction = cp.m_combinedFriction;
530 solverConstraint.m_originalContactPoint = 0;
531
532 solverConstraint.m_appliedImpulse = 0.f;
533 solverConstraint.m_appliedPushImpulse = 0.f;
534
535 if (body0)
536 {
537 solverConstraint.m_contactNormal1 = normalAxis;
539 solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
540 solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor();
541 }
542 else
543 {
544 solverConstraint.m_contactNormal1.setZero();
545 solverConstraint.m_relpos1CrossNormal.setZero();
546 solverConstraint.m_angularComponentA.setZero();
547 }
548
549 if (bodyA)
550 {
551 solverConstraint.m_contactNormal2 = -normalAxis;
553 solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
554 solverConstraint.m_angularComponentB = bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor();
555 }
556 else
557 {
558 solverConstraint.m_contactNormal2.setZero();
559 solverConstraint.m_relpos2CrossNormal.setZero();
560 solverConstraint.m_angularComponentB.setZero();
561 }
562
563 {
565 btScalar denom0 = 0.f;
566 btScalar denom1 = 0.f;
567 if (body0)
568 {
569 vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
570 denom0 = body0->getInvMass() + normalAxis.dot(vec);
571 }
572 if (bodyA)
573 {
574 vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
575 denom1 = bodyA->getInvMass() + normalAxis.dot(vec);
576 }
578 solverConstraint.m_jacDiagABInv = denom;
579 }
580
581 {
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));
585
587
588 // btScalar positionalError = 0.f;
589
592
594
595 if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
596 {
597 btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis);
598 btScalar positionalError = -distance * infoGlobal.m_frictionERP / infoGlobal.m_timeStep;
600 }
601
603 solverConstraint.m_rhsPenetration = 0.f;
605 solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
606 solverConstraint.m_upperLimit = solverConstraint.m_friction;
607 }
608}
609
611{
616 return solverConstraint;
617}
618
623
624{
625 btVector3 normalAxis(0, 0, 0);
626
627 solverConstraint.m_contactNormal1 = normalAxis;
628 solverConstraint.m_contactNormal2 = -normalAxis;
631
634
635 solverConstraint.m_solverBodyIdA = solverBodyIdA;
636 solverConstraint.m_solverBodyIdB = solverBodyIdB;
637
639 solverConstraint.m_originalContactPoint = 0;
640
641 solverConstraint.m_appliedImpulse = 0.f;
642 solverConstraint.m_appliedPushImpulse = 0.f;
643
644 {
646 solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
647 solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor() : btVector3(0, 0, 0);
648 }
649 {
651 solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
652 solverConstraint.m_angularComponentB = bodyA ? bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor() : btVector3(0, 0, 0);
653 }
654
655 {
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);
658 btScalar sum = 0;
659 sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
660 sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
661 solverConstraint.m_jacDiagABInv = btScalar(1.) / sum;
662 }
663
664 {
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));
668
670
671 // btScalar positionalError = 0.f;
672
677 solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
678 solverConstraint.m_upperLimit = solverConstraint.m_friction;
679 }
680}
681
683{
688 return solverConstraint;
689}
690
692{
693#if BT_THREADSAFE
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)
699 {
700 // dynamic body
701 // Dynamic bodies can only be in one island, so it's safe to write to the companionId
703 if (solverBodyId < 0)
704 {
707 initSolverBody(&solverBody, &body, timeStep);
709 }
710 }
711 else if (isRigidBodyType && isKinematic)
712 {
713 //
714 // NOTE: must test for kinematic before static because some kinematic objects also
715 // identify as "static"
716 //
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;
723 {
725 }
727 // if no table entry yet,
729 {
730 // create a table entry for this body
733 initSolverBody(&solverBody, &body, timeStep);
735 }
736 }
737 else
738 {
740 // Incorrectly set collision object flags can degrade performance in various ways.
741 if (!isMultiBodyType)
742 {
744 }
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)
748 {
751 initSolverBody(&fixedBody, 0, timeStep);
752 }
754 }
756 return solverBodyId;
757#else // BT_THREADSAFE
758
759 int solverBodyIdA = -1;
760
761 if (body.getCompanionId() >= 0)
762 {
763 //body has already been converted
766 }
767 else
768 {
770 //convert both active and kinematic objects (for their velocity)
771 if (rb && (rb->getInvMass() || rb->isKinematicObject()))
772 {
775 initSolverBody(&solverBody, &body, timeStep);
777 }
778 else
779 {
780 if (m_fixedBodyId < 0)
781 {
784 initSolverBody(&fixedBody, 0, timeStep);
785 }
786 return m_fixedBodyId;
787 // return 0;//assume first one is a fixed solver body
788 }
789 }
790
791 return solverBodyIdA;
792#endif // BT_THREADSAFE
793}
794#include <stdio.h>
795
800 const btVector3& rel_pos1, const btVector3& rel_pos2)
801{
802 // const btVector3& pos1 = cp.getPositionWorldOnA();
803 // const btVector3& pos2 = cp.getPositionWorldOnB();
804
807
808 btRigidBody* rb0 = bodyA->m_originalBody;
809 btRigidBody* rb1 = bodyB->m_originalBody;
810
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();
815
816 relaxation = infoGlobal.m_sor;
817 btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
818
819 //cfm = 1 / ( dt * kp + kd )
820 //erp = dt * kp / ( dt * kp + kd )
821
822 btScalar cfm = infoGlobal.m_globalCfm;
823 btScalar erp = infoGlobal.m_erp2;
824
825 if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
826 {
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;
831 }
832 else
833 {
834 if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
835 {
836 btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
837 if (denom < SIMD_EPSILON)
838 {
840 }
841 cfm = btScalar(1) / denom;
842 erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
843 }
844 }
845
846 cfm *= invTimeStep;
847
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);
852
853 {
854#ifdef COMPUTE_IMPULSE_DENOM
855 btScalar denom0 = rb0->computeImpulseDenominator(pos1, cp.m_normalWorldOnB);
856 btScalar denom1 = rb1->computeImpulseDenominator(pos2, cp.m_normalWorldOnB);
857#else
859 btScalar denom0 = 0.f;
860 btScalar denom1 = 0.f;
861 if (rb0)
862 {
863 vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
864 denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
865 }
866 if (rb1)
867 {
868 vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
869 denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
870 }
871#endif //COMPUTE_IMPULSE_DENOM
872
873 btScalar denom = relaxation / (denom0 + denom1 + cfm);
874 solverConstraint.m_jacDiagABInv = denom;
875 }
876
877 if (rb0)
878 {
879 solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
880 solverConstraint.m_relpos1CrossNormal = torqueAxis0;
881 }
882 else
883 {
884 solverConstraint.m_contactNormal1.setZero();
885 solverConstraint.m_relpos1CrossNormal.setZero();
886 }
887 if (rb1)
888 {
889 solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
890 solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
891 }
892 else
893 {
894 solverConstraint.m_contactNormal2.setZero();
895 solverConstraint.m_relpos2CrossNormal.setZero();
896 }
897
898 btScalar restitution = 0.f;
899 btScalar penetration = cp.getDistance() + infoGlobal.m_linearSlop;
900
901 {
903
904 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0, 0, 0);
905 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0);
906
907 // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
909 btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
910
911 solverConstraint.m_friction = cp.m_combinedFriction;
912
913 restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
914 if (restitution <= btScalar(0.))
915 {
916 restitution = 0.f;
917 };
918 }
919
921 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
922 {
923 solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
924 if (rb0)
925 bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
926 if (rb1)
927 bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
928 }
929 else
930 {
931 solverConstraint.m_appliedImpulse = 0.f;
932 }
933
934 solverConstraint.m_appliedPushImpulse = 0.f;
935
936 {
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);
941
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);
945
947 btScalar velocityError = restitution - rel_vel; // * damping;
948
949 if (penetration > 0)
950 {
951 positionalError = 0;
952
954 }
955 else
956 {
958 }
959
962
963 if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
964 {
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;
968 }
969 else
970 {
971 //split position and velocity into rhs and m_rhsPenetration
973 solverConstraint.m_rhsPenetration = penetrationImpulse;
974 }
975 solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
976 solverConstraint.m_lowerLimit = 0;
977 solverConstraint.m_upperLimit = 1e10f;
978 }
979}
980
984{
985 {
987
988 frictionConstraint1.m_appliedImpulse = 0.f;
989 }
990
991 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
992 {
994
995 frictionConstraint2.m_appliedImpulse = 0.f;
996 }
997}
998
1000{
1002
1003 colObj0 = (btCollisionObject*)manifold->getBody0();
1004 colObj1 = (btCollisionObject*)manifold->getBody1();
1005
1008
1009 // btRigidBody* bodyA = btRigidBody::upcast(colObj0);
1010 // btRigidBody* bodyB = btRigidBody::upcast(colObj1);
1011
1014
1016 if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
1017 return;
1018
1019 int rollingFriction = 1;
1020 for (int j = 0; j < manifold->getNumContacts(); j++)
1021 {
1022 btManifoldPoint& cp = manifold->getContactPoint(j);
1023
1024 if (cp.getDistance() <= manifold->getContactProcessingThreshold())
1025 {
1029
1033 solverConstraint.m_solverBodyIdB = solverBodyIdB;
1034
1035 solverConstraint.m_originalContactPoint = &cp;
1036
1037 const btVector3& pos1 = cp.getPositionWorldOnA();
1038 const btVector3& pos2 = cp.getPositionWorldOnB();
1039
1040 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
1041 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
1042
1045
1046 solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
1047 solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
1048
1049 btVector3 vel = vel1 - vel2;
1050 btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
1051
1053
1055
1057
1058 if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
1059 {
1060 {
1063 btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
1064 axis0.normalize();
1065 axis1.normalize();
1066
1071 if (axis0.length() > 0.001)
1073 cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
1074 if (axis1.length() > 0.001)
1076 cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
1077 }
1078 }
1079
1084
1095
1097 {
1098 cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
1099 btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
1101 {
1102 cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
1106
1107 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1108 {
1109 cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
1110 cp.m_lateralFrictionDir2.normalize(); //??
1114 }
1115 }
1116 else
1117 {
1118 btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
1119
1123
1124 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1125 {
1129 }
1130
1132 {
1133 cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
1134 }
1135 }
1136 }
1137 else
1138 {
1139 addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
1140
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);
1143 }
1145 }
1146 }
1147 }
1148
1150{
1151 int i;
1153 // btCollisionObject* colObj0=0,*colObj1=0;
1154
1155 for (i = 0; i < numManifolds; i++)
1156 {
1157 manifold = manifoldPtr[i];
1159 }
1160}
1161
1165 int solverBodyIdA,
1166 int solverBodyIdB,
1168{
1169 const btRigidBody& rbA = constraint->getRigidBodyA();
1170 const btRigidBody& rbB = constraint->getRigidBodyB();
1171
1174
1175 int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
1178
1179 for (int j = 0; j < info1.m_numConstraintRows; j++)
1180 {
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;
1189 }
1190
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);
1208
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
1218 btAssert(info2.rowskip * sizeof(btScalar) == sizeof(btSolverConstraint));
1219 info2.m_constraintError = &currentConstraintRow->m_rhs;
1220 currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
1221 info2.m_damping = infoGlobal.m_damping;
1222 info2.cfm = &currentConstraintRow->m_cfm;
1223 info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
1224 info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
1225 info2.m_numIterations = infoGlobal.m_numIterations;
1226 constraint->getInfo2(&info2);
1227
1229 for (int j = 0; j < info1.m_numConstraintRows; j++)
1230 {
1232
1233 if (solverConstraint.m_upperLimit >= constraint->getBreakingImpulseThreshold())
1234 {
1235 solverConstraint.m_upperLimit = constraint->getBreakingImpulseThreshold();
1236 }
1237
1238 if (solverConstraint.m_lowerLimit <= -constraint->getBreakingImpulseThreshold())
1239 {
1240 solverConstraint.m_lowerLimit = -constraint->getBreakingImpulseThreshold();
1241 }
1242
1243 solverConstraint.m_originalContactPoint = constraint;
1244
1245 {
1246 const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
1247 solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld() * ftorqueAxis1 * constraint->getRigidBodyA().getAngularFactor();
1248 }
1249 {
1250 const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
1251 solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld() * ftorqueAxis2 * constraint->getRigidBodyB().getAngularFactor();
1252 }
1253
1254 {
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;
1259
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);
1266 btScalar sorRelaxation = 1.f; //todo: get from globalInfo?
1267 solverConstraint.m_jacDiagABInv = fsum > SIMD_EPSILON ? sorRelaxation / sum : 0.f;
1268 }
1269
1270 {
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);
1274
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);
1277
1278 btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity() + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity() + externalTorqueImpulseA);
1279
1280 btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity() + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity() + externalTorqueImpulseB);
1281
1283 btScalar restitution = 0.f;
1284 btScalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
1289 solverConstraint.m_appliedImpulse = 0.f;
1290 }
1291 }
1292}
1293
1295{
1296 BT_PROFILE("convertJoints");
1297 for (int j = 0; j < numConstraints; j++)
1298 {
1301 constraint->internalSetAppliedImpulse(0.0f);
1302 }
1303
1304 int totalNumRows = 0;
1305
1307 //calculate the total number of contraint rows
1308 for (int i = 0; i < numConstraints; i++)
1309 {
1311 btJointFeedback* fb = constraints[i]->getJointFeedback();
1312 if (fb)
1313 {
1315 fb->m_appliedTorqueBodyA.setZero();
1316 fb->m_appliedForceBodyB.setZero();
1317 fb->m_appliedTorqueBodyB.setZero();
1318 }
1319
1320 if (constraints[i]->isEnabled())
1321 {
1322 constraints[i]->getInfo1(&info1);
1323 }
1324 else
1325 {
1326 info1.m_numConstraintRows = 0;
1327 info1.nub = 0;
1328 }
1329 totalNumRows += info1.m_numConstraintRows;
1330 }
1332
1334 int currentRow = 0;
1335
1336 for (int i = 0; i < numConstraints; i++)
1337 {
1339
1340 if (info1.m_numConstraintRows)
1341 {
1343
1346 btRigidBody& rbA = constraint->getRigidBodyA();
1347 btRigidBody& rbB = constraint->getRigidBodyB();
1348
1351
1353 }
1354 currentRow += info1.m_numConstraintRows;
1355 }
1356}
1357
1359{
1360 BT_PROFILE("convertBodies");
1361 for (int i = 0; i < numBodies; i++)
1362 {
1363 bodies[i]->setCompanionId(-1);
1364 }
1365#if BT_THREADSAFE
1367#endif // BT_THREADSAFE
1368
1369 m_tmpSolverBodyPool.reserve(numBodies + 1);
1371
1372 //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
1373 //initSolverBody(&fixedBody,0);
1374
1375 for (int i = 0; i < numBodies; i++)
1376 {
1377 int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
1378
1379 btRigidBody* body = btRigidBody::upcast(bodies[i]);
1380 if (body && body->getInvMass())
1381 {
1383 btVector3 gyroForce(0, 0, 0);
1385 {
1386 gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
1387 solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
1388 }
1390 {
1392 solverBody.m_externalTorqueImpulse += gyroForce;
1393 }
1395 {
1397 solverBody.m_externalTorqueImpulse += gyroForce;
1398 }
1399 }
1400 }
1401}
1402
1404{
1405 m_fixedBodyId = -1;
1406 BT_PROFILE("solveGroupCacheFriendlySetup");
1408
1409 // if solver mode has changed,
1410 if (infoGlobal.m_solverMode != m_cachedSolverMode)
1411 {
1412 // update solver functions to use SIMD or non-SIMD
1413 bool useSimd = !!(infoGlobal.m_solverMode & SOLVER_SIMD);
1415 m_cachedSolverMode = infoGlobal.m_solverMode;
1416 }
1418
1419#ifdef BT_ADDITIONAL_DEBUG
1420 //make sure that dynamic bodies exist for all (enabled) constraints
1421 for (int i = 0; i < numConstraints; i++)
1422 {
1424 if (constraint->isEnabled())
1425 {
1426 if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
1427 {
1428 bool found = false;
1429 for (int b = 0; b < numBodies; b++)
1430 {
1431 if (&constraint->getRigidBodyA() == bodies[b])
1432 {
1433 found = true;
1434 break;
1435 }
1436 }
1437 btAssert(found);
1438 }
1439 if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
1440 {
1441 bool found = false;
1442 for (int b = 0; b < numBodies; b++)
1443 {
1444 if (&constraint->getRigidBodyB() == bodies[b])
1445 {
1446 found = true;
1447 break;
1448 }
1449 }
1450 btAssert(found);
1451 }
1452 }
1453 }
1454 //make sure that dynamic bodies exist for all contact manifolds
1455 for (int i = 0; i < numManifolds; i++)
1456 {
1457 if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
1458 {
1459 bool found = false;
1460 for (int b = 0; b < numBodies; b++)
1461 {
1462 if (manifoldPtr[i]->getBody0() == bodies[b])
1463 {
1464 found = true;
1465 break;
1466 }
1467 }
1468 btAssert(found);
1469 }
1470 if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
1471 {
1472 bool found = false;
1473 for (int b = 0; b < numBodies; b++)
1474 {
1475 if (manifoldPtr[i]->getBody1() == bodies[b])
1476 {
1477 found = true;
1478 break;
1479 }
1480 }
1481 btAssert(found);
1482 }
1483 }
1484#endif //BT_ADDITIONAL_DEBUG
1485
1486 //convert all bodies
1487 convertBodies(bodies, numBodies, infoGlobal);
1488
1489 convertJoints(constraints, numConstraints, infoGlobal);
1490
1492
1493 // btContactSolverInfo info = infoGlobal;
1494
1498
1501 if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
1503 else
1505
1507 {
1508 int i;
1509 for (i = 0; i < numNonContactPool; i++)
1510 {
1512 }
1513 for (i = 0; i < numConstraintPool; i++)
1514 {
1516 }
1517 for (i = 0; i < numFrictionPool; i++)
1518 {
1520 }
1521 }
1522
1523 return 0.f;
1524}
1525
1526btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
1527{
1528 BT_PROFILE("solveSingleIteration");
1530
1534
1535 if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
1536 {
1537 if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
1538 {
1539 for (int j = 0; j < numNonContactPool; ++j)
1540 {
1542 int swapi = btRandInt2(j + 1);
1545 }
1546
1547 //contact/friction constraints are not solved more than
1548 if (iteration < infoGlobal.m_numIterations)
1549 {
1550 for (int j = 0; j < numConstraintPool; ++j)
1551 {
1553 int swapi = btRandInt2(j + 1);
1556 }
1557
1558 for (int j = 0; j < numFrictionPool; ++j)
1559 {
1561 int swapi = btRandInt2(j + 1);
1564 }
1565 }
1566 }
1567 }
1568
1570 for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
1571 {
1573 if (iteration < constraint.m_overrideNumSolverIterations)
1574 {
1577 }
1578 }
1579
1580 if (iteration < infoGlobal.m_numIterations)
1581 {
1582 for (int j = 0; j < numConstraints; j++)
1583 {
1584 if (constraints[j]->isEnabled())
1585 {
1586 int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
1587 int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
1590 constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
1591 }
1592 }
1593
1596 {
1598 int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
1599
1600 for (int c = 0; c < numPoolConstraints; c++)
1601 {
1603
1604 {
1608
1609 totalImpulse = solveManifold.m_appliedImpulse;
1610 }
1611 bool applyFriction = true;
1612 if (applyFriction)
1613 {
1614 {
1616
1617 if (totalImpulse > btScalar(0))
1618 {
1619 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
1620 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
1621
1624 }
1625 }
1626
1628 {
1630
1631 if (totalImpulse > btScalar(0))
1632 {
1633 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
1634 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
1635
1638 }
1639 }
1640 }
1641 }
1642 }
1643 else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
1644 {
1645 //solve the friction constraints after all contact constraints, don't interleave them
1647 int j;
1648
1649 for (j = 0; j < numPoolConstraints; j++)
1650 {
1654 }
1655
1657
1659 for (j = 0; j < numFrictionPoolConstraints; j++)
1660 {
1662 btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
1663
1664 if (totalImpulse > btScalar(0))
1665 {
1666 solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
1667 solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
1668
1671 }
1672 }
1673 }
1674
1676 for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
1677 {
1680 if (totalImpulse > btScalar(0))
1681 {
1685
1688
1691 }
1692 }
1693 }
1694 return leastSquaresResidual;
1695}
1696
1698{
1699 BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
1700 int iteration;
1701 if (infoGlobal.m_splitImpulse)
1702 {
1703 {
1704 for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
1705 {
1707 {
1709 int j;
1710 for (j = 0; j < numPoolConstraints; j++)
1711 {
1713
1716 }
1717 }
1719 {
1720#ifdef VERBOSE_RESIDUAL_PRINTF
1721 printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
1722#endif
1723 break;
1724 }
1725 }
1726 }
1727 }
1728}
1729
1731{
1732 BT_PROFILE("solveGroupCacheFriendlyIterations");
1733
1734 {
1737
1738 int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
1739
1740 for (int iteration = 0; iteration < maxIterations; iteration++)
1741 //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
1742 {
1744
1745 if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
1746 {
1747#ifdef VERBOSE_RESIDUAL_PRINTF
1748 printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
1749#endif
1753 if (numBodies>0)
1755 m_analyticsData.m_numBodies = numBodies;
1758 break;
1759 }
1760 }
1761 }
1762 return 0.f;
1763}
1764
1766{
1767 for (int j = iBegin; j < iEnd; j++)
1768 {
1770 btManifoldPoint* pt = (btManifoldPoint*)solveManifold.m_originalContactPoint;
1771 btAssert(pt);
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))
1778 {
1779 pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
1780 }
1781 //do a callback here?
1782 }
1783}
1784
1786{
1787 for (int j = iBegin; j < iEnd; j++)
1788 {
1790 btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
1791 btJointFeedback* fb = constr->getJointFeedback();
1792 if (fb)
1793 {
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 ???? */
1798 }
1799
1800 constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
1801 if (btFabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold())
1802 {
1803 constr->setEnabled(false);
1804 }
1805 }
1806}
1807
1809{
1810 for (int i = iBegin; i < iEnd; i++)
1811 {
1812 btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
1813 if (body)
1814 {
1815 if (infoGlobal.m_splitImpulse)
1816 m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
1817 else
1818 m_tmpSolverBodyPool[i].writebackVelocity();
1819
1820 m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
1821 m_tmpSolverBodyPool[i].m_linearVelocity +
1822 m_tmpSolverBodyPool[i].m_externalForceImpulse);
1823
1824 m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
1825 m_tmpSolverBodyPool[i].m_angularVelocity +
1826 m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
1827
1828 if (infoGlobal.m_splitImpulse)
1829 m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
1830
1831 m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
1832 }
1833 }
1834}
1835
1837{
1838 BT_PROFILE("solveGroupCacheFriendlyFinish");
1839
1840 if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
1841 {
1843 }
1844
1847
1852
1854 return 0.f;
1855}
1856
1859{
1860 BT_PROFILE("solveGroup");
1861 //you need to provide at least some bodies
1862
1864
1866
1867 solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
1868
1869 return 0.f;
1870}
1871
1873{
1874 m_btSeed2 = 0;
1875}
@ SOLVER_SIMD
@ SOLVER_ENABLE_FRICTION_DIRECTION_CACHING
@ SOLVER_USE_WARMSTARTING
@ SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
@ SOLVER_RANDMIZE_ORDER
@ SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION
@ SOLVER_USE_2_FRICTION_DIRECTIONS
@ BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED
@ BT_CONTACT_FLAG_HAS_CONTACT_ERP
@ BT_CONTACT_FLAG_HAS_CONTACT_CFM
@ BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING
@ BT_CONTACT_FLAG_FRICTION_ANCHOR
const T & btMax(const T &a, const T &b)
Definition btMinMax.h:27
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
#define BT_PROFILE(name)
static int uniqueId
@ BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY
Definition btRigidBody.h:47
@ BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT
BT_ENABLE_GYROPSCOPIC_FORCE flags is enabled by default in Bullet 2.83 and onwards.
Definition btRigidBody.h:45
@ BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD
Definition btRigidBody.h:46
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition btScalar.h:314
btScalar btSqrt(btScalar y)
Definition btScalar.h:466
btScalar btFabs(btScalar x)
Definition btScalar.h:497
#define SIMD_INFINITY
Definition btScalar.h:544
#define SIMD_EPSILON
Definition btScalar.h:543
#define btAssert(x)
Definition btScalar.h:153
static btScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &c)
This is the scalar reference implementation of solving a single constraint row, the innerloop of the ...
static btScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &c)
static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &c)
static btScalar gResolveSplitPenetrationImpulse_scalar_reference(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &c)
btScalar(* btSingleConstraintRowSolver)(btSolverBody &, btSolverBody &, const btSolverConstraint &)
static T sum(const btAlignedObjectArray< T > &items)
#define btSimdScalar
Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later,...
void btPlaneSpace1(const T &n, T &p, T &q)
Definition btVector3.h:1251
void resizeNoInitialize(int newsize)
resize changes the number of elements in the array.
int size() const
return the number of elements in the array
void resize(int newsize, const T &fillData=T())
T & expand(const T &fillValue=T())
btCollisionObject can be used to manage collision detection objects.
bool isStaticOrKinematicObject() const
int getInternalType() const
reserved for Bullet internal usage
int getWorldArrayIndex() const
void setCompanionId(int id)
bool isKinematicObject() const
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
ManifoldContactPoint collects and maintains persistent contactpoints.
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
The btRigidBody is the main class for rigid body objects.
Definition btRigidBody.h:60
int getFlags() const
btScalar getInvMass() const
btVector3 computeGyroscopicImpulseImplicit_World(btScalar dt) const
perform implicit force computation in world space
btVector3 computeGyroscopicImpulseImplicit_Body(btScalar step) const
perform implicit force computation in body space (inertial frame)
static const btRigidBody * upcast(const btCollisionObject *colObj)
to keep collision detection and dynamics separate we don't store a rigidbody pointer but a rigidbody ...
const btMatrix3x3 & getInvInertiaTensorWorld() const
btVector3 computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const
explicit version is best avoided, it gains energy
btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit()
Various implementations of solving a single constraint row using an inequality (lower limit) constrai...
void initSolverBody(btSolverBody *solverBody, btCollisionObject *collisionObject, btScalar timeStep)
btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric()
virtual void convertBodies(btCollisionObject **bodies, int numBodies, const btContactSolverInfo &infoGlobal)
btSolverConstraint & 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=0., btScalar cfmSlip=0.)
void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo &infoGlobal)
virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject **bodies, int numBodies, const btContactSolverInfo &infoGlobal)
virtual void convertJoints(btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal)
void convertJoint(btSolverConstraint *currentConstraintRow, btTypedConstraint *constraint, const btTypedConstraint::btConstraintInfo1 &info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo &infoGlobal)
virtual btScalar solveGroup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifold, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &info, btIDebugDraw *debugDrawer, btDispatcher *dispatcher)
btSequentialImpulseConstraintSolver Sequentially applies impulses
btSolverConstraint & addTorsionalFrictionConstraint(const btVector3 &normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint &cp, btScalar torsionalFriction, const btVector3 &rel_pos1, const btVector3 &rel_pos2, btCollisionObject *colObj0, btCollisionObject *colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f)
virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
unsigned long m_btSeed2
m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
virtual void reset()
clear internal cached data and reset random seed
virtual void convertContacts(btPersistentManifold **manifoldPtr, int numManifolds, const btContactSolverInfo &infoGlobal)
btScalar resolveSingleConstraintRowLowerLimit(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &contactConstraint)
static void applyAnisotropicFriction(btCollisionObject *colObj, btVector3 &frictionDirection, int frictionMode)
btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit()
btScalar resolveSingleConstraintRowGeneric(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &contactConstraint)
void setupTorsionalFrictionConstraint(btSolverConstraint &solverConstraint, const btVector3 &normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint &cp, btScalar combinedTorsionalFriction, const btVector3 &rel_pos1, const btVector3 &rel_pos2, btCollisionObject *colObj0, btCollisionObject *colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.)
void convertContact(btPersistentManifold *manifold, const btContactSolverInfo &infoGlobal)
btAlignedObjectArray< btSolverBody > m_tmpSolverBodyPool
btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit
btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric()
Various implementations of solving a single constraint row using a generic equality constraint,...
btAlignedObjectArray< btTypedConstraint::btConstraintInfo1 > m_tmpConstraintSizesPool
btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric()
void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo &infoGlobal)
btAlignedObjectArray< int > m_kinematicBodyUniqueIdToSolverBodyTable
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
void 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=0., btScalar cfmSlip=0.)
void setFrictionConstraintImpulse(btSolverConstraint &solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint &cp, const btContactSolverInfo &infoGlobal)
btScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &contactConstraint)
int getOrInitSolverBody(btCollisionObject &body, btScalar timeStep)
btScalar restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
btScalar resolveSingleConstraintRowGenericSIMD(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &contactConstraint)
btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit()
void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo &infoGlobal)
virtual btScalar solveSingleIteration(int iteration, btCollisionObject **bodies, int numBodies, btPersistentManifold **manifoldPtr, int numManifolds, btTypedConstraint **constraints, int numConstraints, const btContactSolverInfo &infoGlobal, btIDebugDraw *debugDrawer)
btScalar resolveSplitPenetrationImpulse(btSolverBody &bodyA, btSolverBody &bodyB, const btSolverConstraint &contactConstraint)
void setupContactConstraint(btSolverConstraint &solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint &cp, const btContactSolverInfo &infoGlobal, btScalar &relaxation, const btVector3 &rel_pos1, const btVector3 &rel_pos2)
TypedConstraint is the baseclass for Bullet constraints and vehicles.
virtual void buildJacobian()
internal method used by the constraint solver, don't use them directly
btVector3 can be used to represent 3D points and vectors.
Definition btVector3.h:82
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition btVector3.h:380
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition btVector3.h:229
void setZero()
Definition btVector3.h:671
btVector3 m_appliedForceBodyA
The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packe...
1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and fr...
btSimdScalar m_appliedImpulse
btSimdScalar m_appliedPushImpulse