|
|
|
@@ -22,6 +22,8 @@ subject to the following restrictions:
|
|
|
|
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
|
|
|
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "LinearMath/btIDebugDraw.h"
|
|
|
|
#include "LinearMath/btIDebugDraw.h"
|
|
|
|
|
|
|
|
#include "LinearMath/btCpuFeatureUtility.h"
|
|
|
|
|
|
|
|
|
|
|
|
//#include "btJacobianEntry.h"
|
|
|
|
//#include "btJacobianEntry.h"
|
|
|
|
#include "LinearMath/btMinMax.h"
|
|
|
|
#include "LinearMath/btMinMax.h"
|
|
|
|
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
|
|
|
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
|
|
|
@@ -38,11 +40,70 @@ int gNumSplitImpulseRecoveries = 0;
|
|
|
|
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
|
|
|
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///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
|
|
|
|
#ifdef USE_SIMD
|
|
|
|
#include <emmintrin.h>
|
|
|
|
#include <emmintrin.h>
|
|
|
|
|
|
|
|
|
|
|
|
//#include <intrin.h>//is it safe to include this header?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
|
|
|
|
#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
|
|
|
|
static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
|
|
|
|
static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
|
|
|
|
@@ -51,12 +112,12 @@ static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
|
|
|
|
return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) );
|
|
|
|
return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined (BT_USE_SSE4)
|
|
|
|
#if defined (BT_ALLOW_SSE4)
|
|
|
|
#include <intrin.h>
|
|
|
|
#include <intrin.h>
|
|
|
|
|
|
|
|
|
|
|
|
#define USE_FMA 1
|
|
|
|
#define USE_FMA 1
|
|
|
|
#define USE_FMA3_INSTEAD_FMA4 1
|
|
|
|
#define USE_FMA3_INSTEAD_FMA4 1
|
|
|
|
#define USE_SSE4_DOT 0
|
|
|
|
#define USE_SSE4_DOT 1
|
|
|
|
|
|
|
|
|
|
|
|
#define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f)
|
|
|
|
#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))
|
|
|
|
#define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f))
|
|
|
|
@@ -147,6 +208,7 @@ static btSimdScalar gResolveSingleConstraintRowGeneric_sse4_1_fma3(btSolverBody&
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static btSimdScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
|
|
|
|
static btSimdScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& body1, btSolverBody& body2, const btSolverConstraint& c)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
|
|
|
|
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
|
|
|
|
@@ -217,34 +279,7 @@ btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGene
|
|
|
|
// Project Gauss Seidel or the equivalent Sequential Impulse
|
|
|
|
// Project Gauss Seidel or the equivalent Sequential Impulse
|
|
|
|
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
|
|
|
|
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
|
|
|
|
return gResolveSingleConstraintRowGeneric_scalar_reference(body1, body2, c);
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
|
|
|
|
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
|
|
|
|
@@ -259,26 +294,7 @@ btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowe
|
|
|
|
|
|
|
|
|
|
|
|
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
|
|
|
|
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
|
|
|
|
return gResolveSingleConstraintRowLowerLimit_scalar_reference(body1,body2,c);
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -349,34 +365,61 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri
|
|
|
|
|
|
|
|
|
|
|
|
btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
|
|
|
|
btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
|
|
|
|
:m_btSeed2(0),
|
|
|
|
:m_btSeed2(0),
|
|
|
|
m_resolveSingleConstraintRowGeneric(gResolveSingleConstraintRowGeneric_sse2),
|
|
|
|
m_resolveSingleConstraintRowGeneric(gResolveSingleConstraintRowGeneric_scalar_reference),
|
|
|
|
m_resolveSingleConstraintRowLowerLimit(gResolveSingleConstraintRowLowerLimit_sse2)
|
|
|
|
m_resolveSingleConstraintRowLowerLimit(gResolveSingleConstraintRowLowerLimit_scalar_reference)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_SIMD
|
|
|
|
|
|
|
|
m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
|
|
|
|
|
|
|
|
m_resolveSingleConstraintRowLowerLimit=gResolveSingleConstraintRowLowerLimit_sse2;
|
|
|
|
|
|
|
|
#endif //USE_SIMD
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
|
|
|
|
btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return gResolveSingleConstraintRowGeneric_scalar_reference;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return gResolveSingleConstraintRowLowerLimit_scalar_reference;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_SIMD
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return gResolveSingleConstraintRowGeneric_sse2;
|
|
|
|
return gResolveSingleConstraintRowGeneric_sse2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return gResolveSingleConstraintRowLowerLimit_sse2;
|
|
|
|
return gResolveSingleConstraintRowLowerLimit_sse2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef BT_ALLOW_SSE4
|
|
|
|
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
|
|
|
|
|
|
|
|
}
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
|
|
|
|
btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
|
|
|
|
return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //BT_ALLOW_SSE4
|
|
|
|
|
|
|
|
#endif //USE_SIMD
|
|
|
|
|
|
|
|
|
|
|
|
unsigned long btSequentialImpulseConstraintSolver::btRand2()
|
|
|
|
unsigned long btSequentialImpulseConstraintSolver::btRand2()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|