|
|
|
|
@@ -39,7 +39,7 @@ 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)
|
|
|
|
|
@@ -298,15 +298,17 @@ btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowe
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly(
|
|
|
|
|
btScalar btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly(
|
|
|
|
|
btSolverBody& body1,
|
|
|
|
|
btSolverBody& body2,
|
|
|
|
|
const btSolverConstraint& c)
|
|
|
|
|
{
|
|
|
|
|
btScalar deltaImpulse = 0.f;
|
|
|
|
|
|
|
|
|
|
if (c.m_rhsPenetration)
|
|
|
|
|
{
|
|
|
|
|
gNumSplitImpulseRecoveries++;
|
|
|
|
|
btScalar deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm;
|
|
|
|
|
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());
|
|
|
|
|
|
|
|
|
|
@@ -325,9 +327,10 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri
|
|
|
|
|
body1.internalApplyPushImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
|
|
|
|
|
body2.internalApplyPushImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
|
|
|
|
|
}
|
|
|
|
|
return deltaImpulse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
|
|
|
|
|
btScalar btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
|
|
|
|
|
{
|
|
|
|
|
#ifdef USE_SIMD
|
|
|
|
|
if (!c.m_rhsPenetration)
|
|
|
|
|
@@ -357,8 +360,9 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri
|
|
|
|
|
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
|
|
|
|
|
resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c);
|
|
|
|
|
return resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1601,6 +1605,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
@@ -1645,7 +1650,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
{
|
|
|
|
|
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
|
|
|
|
|
if (iteration < constraint.m_overrideNumSolverIterations)
|
|
|
|
|
resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
|
|
|
|
|
{
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (iteration< infoGlobal.m_numIterations)
|
|
|
|
|
@@ -1674,7 +1682,9 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
|
|
|
|
|
resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
|
|
|
|
|
totalImpulse = solveManifold.m_appliedImpulse;
|
|
|
|
|
}
|
|
|
|
|
bool applyFriction = true;
|
|
|
|
|
@@ -1689,7 +1699,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
|
|
|
|
|
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
|
|
|
|
|
|
|
|
|
|
resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1703,7 +1714,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
|
|
|
|
|
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
|
|
|
|
|
|
|
|
|
|
resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1719,8 +1731,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
for (j=0;j<numPoolConstraints;j++)
|
|
|
|
|
{
|
|
|
|
|
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
|
|
|
|
|
resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1738,7 +1750,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
|
|
|
|
|
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
|
|
|
|
|
|
|
|
|
|
resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1758,7 +1771,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
|
|
|
|
|
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
|
|
|
|
|
|
|
|
|
|
resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1773,7 +1787,10 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
{
|
|
|
|
|
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
|
|
|
|
|
if (iteration < constraint.m_overrideNumSolverIterations)
|
|
|
|
|
resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
|
|
|
|
|
{
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (iteration< infoGlobal.m_numIterations)
|
|
|
|
|
@@ -1794,7 +1811,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
for (int j=0;j<numPoolConstraints;j++)
|
|
|
|
|
{
|
|
|
|
|
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
|
|
|
|
|
resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
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();
|
|
|
|
|
@@ -1808,7 +1826,8 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
|
|
|
|
|
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
|
|
|
|
|
|
|
|
|
|
resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1826,12 +1845,13 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
|
|
|
|
|
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
|
|
|
|
|
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
|
|
|
|
|
|
|
|
|
|
resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
|
|
|
|
|
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
|
|
|
|
|
leastSquaresResidual += residual*residual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0.f;
|
|
|
|
|
return leastSquaresResidual;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1844,6 +1864,7 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
|
|
|
|
|
{
|
|
|
|
|
for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
|
|
|
|
|
{
|
|
|
|
|
btScalar leastSquaresResidual =0.f;
|
|
|
|
|
{
|
|
|
|
|
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
|
|
|
|
|
int j;
|
|
|
|
|
@@ -1851,15 +1872,24 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
|
|
|
|
|
{
|
|
|
|
|
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
|
|
|
|
|
|
|
|
|
|
resolveSplitPenetrationSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
btScalar residual = resolveSplitPenetrationSIMD(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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
|
|
|
|
|
{
|
|
|
|
|
btScalar leastSquaresResidual = 0.f;
|
|
|
|
|
{
|
|
|
|
|
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
|
|
|
|
|
int j;
|
|
|
|
|
@@ -1867,7 +1897,15 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
|
|
|
|
|
{
|
|
|
|
|
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
|
|
|
|
|
|
|
|
|
|
resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
|
|
|
|
|
btScalar residual = resolveSplitPenetrationImpulseCacheFriendly(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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1888,7 +1926,15 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
|
|
|
|
|
for ( int iteration = 0 ; iteration< maxIterations ; iteration++)
|
|
|
|
|
//for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
|
|
|
|
|
{
|
|
|
|
|
solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|