12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 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.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- //#define COMPUTE_IMPULSE_DENOM 1
- //#define BT_ADDITIONAL_DEBUG
- //It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
- #include "btSequentialImpulseConstraintSolver.h"
- #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
- #include "LinearMath/btIDebugDraw.h"
- #include "LinearMath/btCpuFeatureUtility.h"
- //#include "btJacobianEntry.h"
- #include "LinearMath/btMinMax.h"
- #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
- #include <new>
- #include "LinearMath/btStackAlloc.h"
- #include "LinearMath/btQuickprof.h"
- //#include "btSolverBody.h"
- //#include "btSolverConstraint.h"
- #include "LinearMath/btAlignedObjectArray.h"
- #include <string.h> //for memset
- int gNumSplitImpulseRecoveries = 0;
- #include "BulletDynamics/Dynamics/btRigidBody.h"
- //#define VERBOSE_RESIDUAL_PRINTF 1
- ///This is the scalar reference implementation of solving a single constraint row, the innerloop of the Projected Gauss Seidel/Sequential Impulse constraint solver
- ///Below are optional SSE2 and SSE4/FMA3 versions. We assume most hardware has SSE2. For SSE4/FMA3 we perform a CPU feature check.
- static btSimdScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
- {
- btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
- const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
- // const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
- const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_lowerLimit;
- }
- else if (sum > c.m_upperLimit)
- {
- deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_upperLimit;
- }
- else
- {
- c.m_appliedImpulse = sum;
- }
- body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- return deltaImpulse;
- }
- static btSimdScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
- {
- btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
- const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
- const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_lowerLimit;
- }
- else
- {
- c.m_appliedImpulse = sum;
- }
- body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- return deltaImpulse;
- }
- #ifdef USE_SIMD
- #include <emmintrin.h>
- #define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
- static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
- {
- __m128 result = _mm_mul_ps( vec0, vec1);
- return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) );
- }
- #if defined (BT_ALLOW_SSE4)
- #include <intrin.h>
- #define USE_FMA 1
- #define USE_FMA3_INSTEAD_FMA4 1
- #define USE_SSE4_DOT 1
- #define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f)
- #define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f))
- #if USE_SSE4_DOT
- #define DOT_PRODUCT(a, b) SSE4_DP(a, b)
- #else
- #define DOT_PRODUCT(a, b) btSimdDot3(a, b)
- #endif
- #if USE_FMA
- #if USE_FMA3_INSTEAD_FMA4
- // a*b + c
- #define FMADD(a, b, c) _mm_fmadd_ps(a, b, c)
- // -(a*b) + c
- #define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c)
- #else // USE_FMA3
- // a*b + c
- #define FMADD(a, b, c) _mm_macc_ps(a, b, c)
- // -(a*b) + c
- #define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c)
- #endif
- #else // USE_FMA
- // c + a*b
- #define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b))
- // c - a*b
- #define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b))
- #endif
- #endif
- // Project Gauss Seidel or the equivalent Sequential Impulse
- static btSimdScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
- {
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- 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)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, body2.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
- btSimdScalar resultLowerLess, resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, body2.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
- body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
- body2.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
- body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
- return deltaImpulse;
- }
- // Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
- static btSimdScalar gResolveSingleConstraintRowGeneric_sse4_1_fma3(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
- {
- #if defined (BT_ALLOW_SSE4)
- __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
- __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm);
- const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
- const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit);
- const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
- const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, body2.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
- deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
- tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); // sum
- const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit);
- const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp);
- deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower);
- c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower);
- body1.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, body1.internalGetInvMass().mVec128), deltaImpulse, body1.internalGetDeltaLinearVelocity().mVec128);
- body1.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, body1.internalGetDeltaAngularVelocity().mVec128);
- body2.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, body2.internalGetInvMass().mVec128), deltaImpulse, body2.internalGetDeltaLinearVelocity().mVec128);
- body2.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, body2.internalGetDeltaAngularVelocity().mVec128);
- return deltaImpulse;
- #else
- return gResolveSingleConstraintRowGeneric_sse2(body1,body2,c);
- #endif
- }
- static btSimdScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
- {
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- 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)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, body2.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
- btSimdScalar resultLowerLess, resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, body2.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
- body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
- body2.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
- body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
- return deltaImpulse;
- }
- // Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
- static btSimdScalar gResolveSingleConstraintRowLowerLimit_sse4_1_fma3(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
- {
- #ifdef BT_ALLOW_SSE4
- __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
- __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse)*c.m_cfm);
- const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
- const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
- const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, body2.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
- deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
- tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse);
- const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit);
- deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask);
- c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask);
- body1.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, body1.internalGetInvMass().mVec128), deltaImpulse, body1.internalGetDeltaLinearVelocity().mVec128);
- body1.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, body1.internalGetDeltaAngularVelocity().mVec128);
- body2.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, body2.internalGetInvMass().mVec128), deltaImpulse, body2.internalGetDeltaLinearVelocity().mVec128);
- body2.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, body2.internalGetDeltaAngularVelocity().mVec128);
- return deltaImpulse;
- #else
- return gResolveSingleConstraintRowLowerLimit_sse2(body1,body2,c);
- #endif //BT_ALLOW_SSE4
- }
- #endif //USE_SIMD
- btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
- {
- return m_resolveSingleConstraintRowGeneric(body1, body2, c);
- }
- // Project Gauss Seidel or the equivalent Sequential Impulse
- btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
- {
- return m_resolveSingleConstraintRowGeneric(body1, body2, c);
- }
- btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
- {
- return m_resolveSingleConstraintRowLowerLimit(body1, body2, c);
- }
- btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
- {
- return m_resolveSingleConstraintRowLowerLimit(body1, body2, c);
- }
- static btSimdScalar gResolveSplitPenetrationImpulse_scalar_reference(
- btSolverBody& body1,
- btSolverBody& body2,
- const btSolverConstraint& c)
- {
- btScalar deltaImpulse = 0.f;
- if (c.m_rhsPenetration)
- {
- gNumSplitImpulseRecoveries++;
- deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
- const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
- deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
- const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse;
- c.m_appliedPushImpulse = c.m_lowerLimit;
- }
- else
- {
- c.m_appliedPushImpulse = sum;
- }
- body1.internalApplyPushImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- body2.internalApplyPushImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
- }
- return deltaImpulse;
- }
- static btSimdScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
- {
- #ifdef USE_SIMD
- if (!c.m_rhsPenetration)
- return 0.f;
- gNumSplitImpulseRecoveries++;
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __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)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,body1.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,body2.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
- btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
- btSimdScalar resultLowerLess,resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
- deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
- c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128,body2.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
- body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
- body2.internalGetPushVelocity().mVec128 = _mm_add_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
- body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
- return deltaImpulse;
- #else
- return gResolveSplitPenetrationImpulse_scalar_reference(body1,body2,c);
- #endif
- }
- btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
- {
- m_btSeed2 = 0;
- m_cachedSolverMode = 0;
- setupSolverFunctions( false );
- }
- void btSequentialImpulseConstraintSolver::setupSolverFunctions( bool useSimd )
- {
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference;
- m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference;
- if ( useSimd )
- {
- #ifdef USE_SIMD
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2;
- m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2;
- #ifdef BT_ALLOW_SSE4
- int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
- if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
- {
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
- }
- #endif//BT_ALLOW_SSE4
- #endif //USE_SIMD
- }
- }
- btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
- {
- }
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric()
- {
- return gResolveSingleConstraintRowGeneric_scalar_reference;
- }
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit()
- {
- return gResolveSingleConstraintRowLowerLimit_scalar_reference;
- }
- #ifdef USE_SIMD
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
- {
- return gResolveSingleConstraintRowGeneric_sse2;
- }
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
- {
- return gResolveSingleConstraintRowLowerLimit_sse2;
- }
- #ifdef BT_ALLOW_SSE4
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
- {
- return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
- }
- btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
- {
- return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
- }
- #endif //BT_ALLOW_SSE4
- #endif //USE_SIMD
- unsigned long btSequentialImpulseConstraintSolver::btRand2()
- {
- m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff;
- return m_btSeed2;
- }
- //See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
- int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
- {
- // seems good; xor-fold and modulus
- const unsigned long un = static_cast<unsigned long>(n);
- unsigned long r = btRand2();
- // note: probably more aggressive than it needs to be -- might be
- // able to get away without one or two of the innermost branches.
- if (un <= 0x00010000UL) {
- r ^= (r >> 16);
- if (un <= 0x00000100UL) {
- r ^= (r >> 8);
- if (un <= 0x00000010UL) {
- r ^= (r >> 4);
- if (un <= 0x00000004UL) {
- r ^= (r >> 2);
- if (un <= 0x00000002UL) {
- r ^= (r >> 1);
- }
- }
- }
- }
- }
- return (int) (r % un);
- }
- void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
- {
- btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0;
- solverBody->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- solverBody->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
- if (rb)
- {
- solverBody->m_worldTransform = rb->getWorldTransform();
- solverBody->internalSetInvMass(btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor());
- solverBody->m_originalBody = rb;
- solverBody->m_angularFactor = rb->getAngularFactor();
- solverBody->m_linearFactor = rb->getLinearFactor();
- solverBody->m_linearVelocity = rb->getLinearVelocity();
- solverBody->m_angularVelocity = rb->getAngularVelocity();
- solverBody->m_externalForceImpulse = rb->getTotalForce()*rb->getInvMass()*timeStep;
- solverBody->m_externalTorqueImpulse = rb->getTotalTorque()*rb->getInvInertiaTensorWorld()*timeStep ;
- } else
- {
- solverBody->m_worldTransform.setIdentity();
- solverBody->internalSetInvMass(btVector3(0,0,0));
- solverBody->m_originalBody = 0;
- solverBody->m_angularFactor.setValue(1,1,1);
- solverBody->m_linearFactor.setValue(1,1,1);
- solverBody->m_linearVelocity.setValue(0,0,0);
- solverBody->m_angularVelocity.setValue(0,0,0);
- solverBody->m_externalForceImpulse.setValue(0,0,0);
- solverBody->m_externalTorqueImpulse.setValue(0,0,0);
- }
- }
- btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
- {
- //printf("rel_vel =%f\n", rel_vel);
- if (btFabs(rel_vel)<velocityThreshold)
- return 0.;
- btScalar rest = restitution * -rel_vel;
- return rest;
- }
- void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode)
- {
- if (colObj && colObj->hasAnisotropicFriction(frictionMode))
- {
- // transform to local coordinates
- btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
- const btVector3& friction_scaling = colObj->getAnisotropicFriction();
- //apply anisotropic friction
- loc_lateral *= friction_scaling;
- // ... and transform it back to global coordinates
- frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
- }
- }
- 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)
- {
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* body1 = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_friction = cp.m_combinedFriction;
- solverConstraint.m_originalContactPoint = 0;
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
- if (body0)
- {
- solverConstraint.m_contactNormal1 = normalAxis;
- btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1);
- solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor();
- }else
- {
- solverConstraint.m_contactNormal1.setZero();
- solverConstraint.m_relpos1CrossNormal.setZero();
- solverConstraint.m_angularComponentA .setZero();
- }
- if (body1)
- {
- solverConstraint.m_contactNormal2 = -normalAxis;
- btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2);
- solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor();
- } else
- {
- solverConstraint.m_contactNormal2.setZero();
- solverConstraint.m_relpos2CrossNormal.setZero();
- solverConstraint.m_angularComponentB.setZero();
- }
- {
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- if (body0)
- {
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = body0->getInvMass() + normalAxis.dot(vec);
- }
- if (body1)
- {
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = body1->getInvMass() + normalAxis.dot(vec);
- }
- btScalar denom = relaxation/(denom0+denom1);
- solverConstraint.m_jacDiagABInv = denom;
- }
- {
- btScalar rel_vel;
- 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));
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(body1?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:btVector3(0,0,0));
- rel_vel = vel1Dotn+vel2Dotn;
- // btScalar positionalError = 0.f;
- btScalar velocityError = desiredVelocity - rel_vel;
- btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
- btScalar penetrationImpulse = btScalar(0);
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
- {
- btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis);
- btScalar positionalError = -distance * infoGlobal.m_frictionERP/infoGlobal.m_timeStep;
- penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- }
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
- solverConstraint.m_cfm = cfmSlip;
- solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
- solverConstraint.m_upperLimit = solverConstraint.m_friction;
- }
- }
- 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)
- {
- btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
- return solverConstraint;
- }
- void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis1,int solverBodyIdA,int solverBodyIdB,
- btManifoldPoint& cp,btScalar combinedTorsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,
- btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity, btScalar cfmSlip)
- {
- btVector3 normalAxis(0,0,0);
- solverConstraint.m_contactNormal1 = normalAxis;
- solverConstraint.m_contactNormal2 = -normalAxis;
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* body1 = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_friction = combinedTorsionalFriction;
- solverConstraint.m_originalContactPoint = 0;
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
- {
- btVector3 ftorqueAxis1 = -normalAxis1;
- solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0);
- }
- {
- btVector3 ftorqueAxis1 = normalAxis1;
- solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0);
- }
- {
- btVector3 iMJaA = body0?body0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0);
- btVector3 iMJaB = body1?body1->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0);
- btScalar sum = 0;
- sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
- }
- {
- btScalar rel_vel;
- 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));
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(body1?solverBodyB.m_linearVelocity+solverBodyB.m_externalForceImpulse:btVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:btVector3(0,0,0));
- rel_vel = vel1Dotn+vel2Dotn;
- // btScalar positionalError = 0.f;
- btSimdScalar velocityError = desiredVelocity - rel_vel;
- btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_cfm = cfmSlip;
- solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
- solverConstraint.m_upperLimit = solverConstraint.m_friction;
- }
- }
- 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)
- {
- btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction,rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
- return solverConstraint;
- }
- int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body,btScalar timeStep)
- {
- #if BT_THREADSAFE
- int solverBodyId = -1;
- if ( !body.isStaticOrKinematicObject() )
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- if ( solverBodyId < 0 )
- {
- if ( btRigidBody* rb = btRigidBody::upcast( &body ) )
- {
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &solverBody, &body, timeStep );
- body.setCompanionId( solverBodyId );
- }
- }
- }
- else if (body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ];
- // if no table entry yet,
- if ( solverBodyId == INVALID_SOLVER_BODY_ID )
- {
- // create a table entry for this body
- btRigidBody* rb = btRigidBody::upcast( &body );
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &solverBody, &body, timeStep );
- m_kinematicBodyUniqueIdToSolverBodyTable[ uniqueId ] = solverBodyId;
- }
- }
- else
- {
- // all fixed bodies (inf mass) get mapped to a single solver id
- if ( m_fixedBodyId < 0 )
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody( &fixedBody, 0, timeStep );
- }
- solverBodyId = m_fixedBodyId;
- }
- btAssert( solverBodyId < m_tmpSolverBodyPool.size() );
- return solverBodyId;
- #else // BT_THREADSAFE
- int solverBodyIdA = -1;
- if (body.getCompanionId() >= 0)
- {
- //body has already been converted
- solverBodyIdA = body.getCompanionId();
- btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
- } else
- {
- btRigidBody* rb = btRigidBody::upcast(&body);
- //convert both active and kinematic objects (for their velocity)
- if (rb && (rb->getInvMass() || rb->isKinematicObject()))
- {
- solverBodyIdA = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody,&body,timeStep);
- body.setCompanionId(solverBodyIdA);
- } else
- {
- if (m_fixedBodyId<0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody,0,timeStep);
- }
- return m_fixedBodyId;
- // return 0;//assume first one is a fixed solver body
- }
- }
- return solverBodyIdA;
- #endif // BT_THREADSAFE
- }
- #include <stdio.h>
- void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- const btVector3& rel_pos1, const btVector3& rel_pos2)
- {
- // const btVector3& pos1 = cp.getPositionWorldOnA();
- // const btVector3& pos2 = cp.getPositionWorldOnB();
- btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* rb0 = bodyA->m_originalBody;
- btRigidBody* rb1 = bodyB->m_originalBody;
- // btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
- // btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
- //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
- //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
- relaxation = infoGlobal.m_sor;
- btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
- //cfm = 1 / ( dt * kp + kd )
- //erp = dt * kp / ( dt * kp + kd )
-
- btScalar cfm = infoGlobal.m_globalCfm;
- btScalar erp = infoGlobal.m_erp2;
- if ((cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP))
- {
- if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_CFM)
- cfm = cp.m_contactCFM;
- if (cp.m_contactPointFlags&BT_CONTACT_FLAG_HAS_CONTACT_ERP)
- erp = cp.m_contactERP;
- } else
- {
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
- {
- btScalar denom = ( infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1 );
- if (denom < SIMD_EPSILON)
- {
- denom = SIMD_EPSILON;
- }
- cfm = btScalar(1) / denom;
- erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
- }
- }
-
- cfm *= invTimeStep;
-
- btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
- btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
- {
- #ifdef COMPUTE_IMPULSE_DENOM
- btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
- btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
- #else
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- if (rb0)
- {
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
- }
- if (rb1)
- {
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
- }
- #endif //COMPUTE_IMPULSE_DENOM
- btScalar denom = relaxation/(denom0+denom1+cfm);
- solverConstraint.m_jacDiagABInv = denom;
- }
- if (rb0)
- {
- solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- } else
- {
- solverConstraint.m_contactNormal1.setZero();
- solverConstraint.m_relpos1CrossNormal.setZero();
- }
- if (rb1)
- {
- solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- }else
- {
- solverConstraint.m_contactNormal2.setZero();
- solverConstraint.m_relpos2CrossNormal.setZero();
- }
- btScalar restitution = 0.f;
- btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
- {
- btVector3 vel1,vel2;
- vel1 = rb0? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
- vel2 = rb1? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
- // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
- solverConstraint.m_friction = cp.m_combinedFriction;
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
- if (restitution <= btScalar(0.))
- {
- restitution = 0.f;
- };
- }
- ///warm starting (or zero if disabled)
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
- } else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- }
- solverConstraint.m_appliedPushImpulse = 0.f;
- {
- btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse: btVector3(0,0,0);
- btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse: btVector3(0,0,0);
- btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse: btVector3(0,0,0);
- btVector3 externalTorqueImpulseB = bodyB->m_originalBody ?bodyB->m_externalTorqueImpulse : btVector3(0,0,0);
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity+externalForceImpulseA)
- + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity+externalTorqueImpulseA);
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity+externalForceImpulseB)
- + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity+externalTorqueImpulseB);
- btScalar rel_vel = vel1Dotn+vel2Dotn;
- btScalar positionalError = 0.f;
- btScalar velocityError = restitution - rel_vel;// * damping;
-
- if (penetration>0)
- {
- positionalError = 0;
- velocityError -= penetration *invTimeStep;
- } else
- {
- positionalError = -penetration * erp*invTimeStep;
- }
- btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;//-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhsPenetration = 0.f;
- } else
- {
- //split position and velocity into rhs and m_rhsPenetration
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = penetrationImpulse;
- }
- solverConstraint.m_cfm = cfm*solverConstraint.m_jacDiagABInv;
- solverConstraint.m_lowerLimit = 0;
- solverConstraint.m_upperLimit = 1e10f;
- }
- }
- void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
- {
- btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
- btRigidBody* rb0 = bodyA->m_originalBody;
- btRigidBody* rb1 = bodyB->m_originalBody;
- {
- btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse);
- } else
- {
- frictionConstraint1.m_appliedImpulse = 0.f;
- }
- }
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse);
- } else
- {
- frictionConstraint2.m_appliedImpulse = 0.f;
- }
- }
- }
- void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal)
- {
- btCollisionObject* colObj0=0,*colObj1=0;
- colObj0 = (btCollisionObject*)manifold->getBody0();
- colObj1 = (btCollisionObject*)manifold->getBody1();
- int solverBodyIdA = getOrInitSolverBody(*colObj0,infoGlobal.m_timeStep);
- int solverBodyIdB = getOrInitSolverBody(*colObj1,infoGlobal.m_timeStep);
- // btRigidBody* bodyA = btRigidBody::upcast(colObj0);
- // btRigidBody* bodyB = btRigidBody::upcast(colObj1);
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
- ///avoid collision response between two static objects
- if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
- return;
- int rollingFriction=1;
- for (int j=0;j<manifold->getNumContacts();j++)
- {
- btManifoldPoint& cp = manifold->getContactPoint(j);
- if (cp.getDistance() <= manifold->getContactProcessingThreshold())
- {
- btVector3 rel_pos1;
- btVector3 rel_pos2;
- btScalar relaxation;
- int frictionIndex = m_tmpSolverContactConstraintPool.size();
- btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_originalContactPoint = &cp;
- const btVector3& pos1 = cp.getPositionWorldOnA();
- const btVector3& pos2 = cp.getPositionWorldOnB();
- rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
- rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
- btVector3 vel1;
- btVector3 vel2;
-
- solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1,vel1);
- solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2,vel2 );
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
- setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
- /////setup the friction constraints
- solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
- if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0))
- {
-
- {
- addTorsionalFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,cp.m_combinedSpinningFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- btVector3 axis0,axis1;
- btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1);
- axis0.normalize();
- axis1.normalize();
-
- applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- if (axis0.length()>0.001)
- addTorsionalFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,
- cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- if (axis1.length()>0.001)
- addTorsionalFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,
- cp.m_combinedRollingFriction, rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- }
- }
- ///Bullet has several options to set the friction directions
- ///By default, each contact has only a single friction direction that is recomputed automatically very frame
- ///based on the relative linear velocity.
- ///If the relative velocity it zero, it will automatically compute a friction direction.
- ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
- ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
- ///
- ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
- ///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
- ///and set the cp.m_lateralFrictionInitialized to true
- ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
- ///this will give a conveyor belt effect
- ///
-
- if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
- {
- cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
- btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
- if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
- {
- cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,infoGlobal);
- if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
- cp.m_lateralFrictionDir2.normalize();//??
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
- }
- } else
- {
- btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
- }
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
- {
- cp.m_contactPointFlags|=BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
- }
- }
- } else
- {
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
- }
- setFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
- }
- }
- }
- void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr,int numManifolds, const btContactSolverInfo& infoGlobal)
- {
- int i;
- btPersistentManifold* manifold = 0;
- // btCollisionObject* colObj0=0,*colObj1=0;
- for (i=0;i<numManifolds;i++)
- {
- manifold = manifoldPtr[i];
- convertContact(manifold,infoGlobal);
- }
- }
- btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
- {
- m_fixedBodyId = -1;
- BT_PROFILE("solveGroupCacheFriendlySetup");
- (void)debugDrawer;
- // if solver mode has changed,
- if ( infoGlobal.m_solverMode != m_cachedSolverMode )
- {
- // update solver functions to use SIMD or non-SIMD
- bool useSimd = !!( infoGlobal.m_solverMode & SOLVER_SIMD );
- setupSolverFunctions( useSimd );
- m_cachedSolverMode = infoGlobal.m_solverMode;
- }
- m_maxOverrideNumSolverIterations = 0;
- #ifdef BT_ADDITIONAL_DEBUG
- //make sure that dynamic bodies exist for all (enabled) constraints
- for (int i=0;i<numConstraints;i++)
- {
- btTypedConstraint* constraint = constraints[i];
- if (constraint->isEnabled())
- {
- if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
- {
- bool found=false;
- for (int b=0;b<numBodies;b++)
- {
- if (&constraint->getRigidBodyA()==bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
- {
- bool found=false;
- for (int b=0;b<numBodies;b++)
- {
- if (&constraint->getRigidBodyB()==bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- }
- }
- //make sure that dynamic bodies exist for all contact manifolds
- for (int i=0;i<numManifolds;i++)
- {
- if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
- {
- bool found=false;
- for (int b=0;b<numBodies;b++)
- {
- if (manifoldPtr[i]->getBody0()==bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
- {
- bool found=false;
- for (int b=0;b<numBodies;b++)
- {
- if (manifoldPtr[i]->getBody1()==bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- }
- #endif //BT_ADDITIONAL_DEBUG
- for (int i = 0; i < numBodies; i++)
- {
- bodies[i]->setCompanionId(-1);
- }
- #if BT_THREADSAFE
- m_kinematicBodyUniqueIdToSolverBodyTable.resize( 0 );
- #endif // BT_THREADSAFE
- m_tmpSolverBodyPool.reserve(numBodies+1);
- m_tmpSolverBodyPool.resize(0);
- //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- //initSolverBody(&fixedBody,0);
- //convert all bodies
- for (int i=0;i<numBodies;i++)
- {
- int bodyId = getOrInitSolverBody(*bodies[i],infoGlobal.m_timeStep);
- btRigidBody* body = btRigidBody::upcast(bodies[i]);
- if (body && body->getInvMass())
- {
- btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
- btVector3 gyroForce (0,0,0);
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
- {
- gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
- solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
- }
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
- {
- gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
- solverBody.m_externalTorqueImpulse += gyroForce;
- }
- if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
- {
- gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
- solverBody.m_externalTorqueImpulse += gyroForce;
- }
-
- }
- }
- if (1)
- {
- int j;
- for (j=0;j<numConstraints;j++)
- {
- btTypedConstraint* constraint = constraints[j];
- constraint->buildJacobian();
- constraint->internalSetAppliedImpulse(0.0f);
- }
- }
- //btRigidBody* rb0=0,*rb1=0;
- //if (1)
- {
- {
- int totalNumRows = 0;
- int i;
- m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
- //calculate the total number of contraint rows
- for (i=0;i<numConstraints;i++)
- {
- btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- btJointFeedback* fb = constraints[i]->getJointFeedback();
- if (fb)
- {
- fb->m_appliedForceBodyA.setZero();
- fb->m_appliedTorqueBodyA.setZero();
- fb->m_appliedForceBodyB.setZero();
- fb->m_appliedTorqueBodyB.setZero();
- }
- if (constraints[i]->isEnabled())
- {
- }
- if (constraints[i]->isEnabled())
- {
- constraints[i]->getInfo1(&info1);
- } else
- {
- info1.m_numConstraintRows = 0;
- info1.nub = 0;
- }
- totalNumRows += info1.m_numConstraintRows;
- }
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
- ///setup the btSolverConstraints
- int currentRow = 0;
- for (i=0;i<numConstraints;i++)
- {
- const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- if (info1.m_numConstraintRows)
- {
- btAssert(currentRow<totalNumRows);
- btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
- btTypedConstraint* constraint = constraints[i];
- btRigidBody& rbA = constraint->getRigidBodyA();
- btRigidBody& rbB = constraint->getRigidBodyB();
- int solverBodyIdA = getOrInitSolverBody(rbA,infoGlobal.m_timeStep);
- int solverBodyIdB = getOrInitSolverBody(rbB,infoGlobal.m_timeStep);
- btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
- int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
- m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
- int j;
- for ( j=0;j<info1.m_numConstraintRows;j++)
- {
- memset(¤tConstraintRow[j],0,sizeof(btSolverConstraint));
- currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
- currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
- currentConstraintRow[j].m_appliedImpulse = 0.f;
- currentConstraintRow[j].m_appliedPushImpulse = 0.f;
- currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
- currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
- currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
- }
- bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
- btTypedConstraint::btConstraintInfo2 info2;
- info2.fps = 1.f/infoGlobal.m_timeStep;
- info2.erp = infoGlobal.m_erp;
- info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
- info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
- info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
- info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
- info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
- ///the size of btSolverConstraint needs be a multiple of btScalar
- btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
- info2.m_constraintError = ¤tConstraintRow->m_rhs;
- currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
- info2.m_damping = infoGlobal.m_damping;
- info2.cfm = ¤tConstraintRow->m_cfm;
- info2.m_lowerLimit = ¤tConstraintRow->m_lowerLimit;
- info2.m_upperLimit = ¤tConstraintRow->m_upperLimit;
- info2.m_numIterations = infoGlobal.m_numIterations;
- constraints[i]->getInfo2(&info2);
- ///finalize the constraint setup
- for ( j=0;j<info1.m_numConstraintRows;j++)
- {
- btSolverConstraint& solverConstraint = currentConstraintRow[j];
- if (solverConstraint.m_upperLimit>=constraints[i]->getBreakingImpulseThreshold())
- {
- solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
- }
- if (solverConstraint.m_lowerLimit<=-constraints[i]->getBreakingImpulseThreshold())
- {
- solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
- }
- solverConstraint.m_originalContactPoint = constraint;
- {
- const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
- solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
- }
- {
- const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
- solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
- }
- {
- btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass();
- btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
- btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal?
- btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
- btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
- sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- sum += iMJlB.dot(solverConstraint.m_contactNormal2);
- sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- btScalar fsum = btFabs(sum);
- btAssert(fsum > SIMD_EPSILON);
- btScalar sorRelaxation = 1.f;//todo: get from globalInfo?
- solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?sorRelaxation/sum : 0.f;
- }
- {
- btScalar rel_vel;
- btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0,0,0);
- btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0,0,0);
- btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0,0,0);
- btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ?bodyBPtr->m_externalTorqueImpulse : btVector3(0,0,0);
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()+externalForceImpulseA)
- + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity()+externalTorqueImpulseA);
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()+externalForceImpulseB)
- + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity()+externalTorqueImpulseB);
- rel_vel = vel1Dotn+vel2Dotn;
- btScalar restitution = 0.f;
- btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
- btScalar velocityError = restitution - rel_vel * info2.m_damping;
- btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
- solverConstraint.m_appliedImpulse = 0.f;
- }
- }
- }
- currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
- }
- }
- convertContacts(manifoldPtr,numManifolds,infoGlobal);
- }
- // btContactSolverInfo info = infoGlobal;
- int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
- ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
- m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2);
- else
- m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
- m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
- {
- int i;
- for (i=0;i<numNonContactPool;i++)
- {
- m_orderNonContactConstraintPool[i] = i;
- }
- for (i=0;i<numConstraintPool;i++)
- {
- m_orderTmpConstraintPool[i] = i;
- }
- for (i=0;i<numFrictionPool;i++)
- {
- m_orderFrictionConstraintPool[i] = i;
- }
- }
- return 0.f;
- }
- btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/)
- {
- btScalar leastSquaresResidual = 0.f;
- int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
- if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
- {
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
- {
- for (int j=0; j<numNonContactPool; ++j) {
- int tmp = m_orderNonContactConstraintPool[j];
- int swapi = btRandInt2(j+1);
- m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
- m_orderNonContactConstraintPool[swapi] = tmp;
- }
- //contact/friction constraints are not solved more than
- if (iteration< infoGlobal.m_numIterations)
- {
- for (int j=0; j<numConstraintPool; ++j) {
- int tmp = m_orderTmpConstraintPool[j];
- int swapi = btRandInt2(j+1);
- m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
- m_orderTmpConstraintPool[swapi] = tmp;
- }
- for (int j=0; j<numFrictionPool; ++j) {
- int tmp = m_orderFrictionConstraintPool[j];
- int swapi = btRandInt2(j+1);
- m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
- m_orderFrictionConstraintPool[swapi] = tmp;
- }
- }
- }
- }
- ///solve all joint constraints
- for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
- {
- btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
- {
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
- leastSquaresResidual += residual*residual;
- }
- }
- if (iteration< infoGlobal.m_numIterations)
- {
- for (int j=0;j<numConstraints;j++)
- {
- if (constraints[j]->isEnabled())
- {
- int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep);
- int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
- btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
- btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
- constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep);
- }
- }
- ///solve all contact constraints
- if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
- for (int c=0;c<numPoolConstraints;c++)
- {
- btScalar totalImpulse =0;
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
- btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual += residual*residual;
- totalImpulse = solveManifold.m_appliedImpulse;
- }
- bool applyFriction = true;
- if (applyFriction)
- {
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]];
- if (totalImpulse>btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual += residual*residual;
- }
- }
- if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]];
- if (totalImpulse>btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual += residual*residual;
- }
- }
- }
- }
- }
- else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
- {
- //solve the friction constraints after all contact constraints, don't interleave them
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
- for (j=0;j<numPoolConstraints;j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual += residual*residual;
- }
- ///solve all friction constraints
- int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j=0;j<numFrictionPoolConstraints;j++)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual += residual*residual;
- }
- }
- }
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (int j=0;j<numRollingFrictionPoolConstraints;j++)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse>btScalar(0))
- {
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
- if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
- leastSquaresResidual += residual*residual;
- }
- }
- }
- return leastSquaresResidual;
- }
- void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
- {
- int iteration;
- if (infoGlobal.m_splitImpulse)
- {
- {
- for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
- {
- btScalar leastSquaresResidual =0.f;
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
- for (j=0;j<numPoolConstraints;j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- leastSquaresResidual += residual*residual;
- }
- }
- if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration>=(infoGlobal.m_numIterations-1))
- {
- #ifdef VERBOSE_RESIDUAL_PRINTF
- printf("residual = %f at iteration #%d\n",leastSquaresResidual,iteration);
- #endif
- break;
- }
- }
- }
- }
- }
- btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer)
- {
- BT_PROFILE("solveGroupCacheFriendlyIterations");
- {
- ///this is a special step to resolve penetrations (just for contacts)
- solveGroupCacheFriendlySplitImpulseIterations(bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
- int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
- for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
- //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
- {
- m_leastSquaresResidual = solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
- if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration>= (maxIterations-1)))
- {
- #ifdef VERBOSE_RESIDUAL_PRINTF
- printf("residual = %f at iteration #%d\n",m_leastSquaresResidual,iteration);
- #endif
- break;
- }
- }
- }
- return 0.f;
- }
- btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal)
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int i,j;
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- for (j=0;j<numPoolConstraints;j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
- btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint;
- btAssert(pt);
- pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
- // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- // printf("pt->m_appliedImpulseLateral1 = %f\n", f);
- pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
- }
- //do a callback here?
- }
- }
- numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
- for (j=0;j<numPoolConstraints;j++)
- {
- const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
- btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
- btJointFeedback* fb = constr->getJointFeedback();
- if (fb)
- {
- fb->m_appliedForceBodyA += solverConstr.m_contactNormal1*solverConstr.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep;
- fb->m_appliedForceBodyB += solverConstr.m_contactNormal2*solverConstr.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
- }
- constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
- if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
- {
- constr->setEnabled(false);
- }
- }
- for ( i=0;i<m_tmpSolverBodyPool.size();i++)
- {
- btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
- if (body)
- {
- if (infoGlobal.m_splitImpulse)
- m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
- else
- m_tmpSolverBodyPool[i].writebackVelocity();
- m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
- m_tmpSolverBodyPool[i].m_linearVelocity+
- m_tmpSolverBodyPool[i].m_externalForceImpulse);
- m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
- m_tmpSolverBodyPool[i].m_angularVelocity+
- m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
- if (infoGlobal.m_splitImpulse)
- m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
- m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
- }
- }
- m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverBodyPool.resizeNoInitialize(0);
- return 0.f;
- }
- /// btSequentialImpulseConstraintSolver Sequentially applies impulses
- btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btDispatcher* /*dispatcher*/)
- {
- BT_PROFILE("solveGroup");
- //you need to provide at least some bodies
- solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer);
- solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer);
- solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
- return 0.f;
- }
- void btSequentialImpulseConstraintSolver::reset()
- {
- m_btSeed2 = 0;
- }
|