improve rolling friction using anisotropic direction, to avoid resting in an instable position
(for implicit capsule, cylinder and cone shape) See Bullet/Demos/RollingFrictionDemo for an example
This commit is contained in:
@@ -138,6 +138,13 @@ public:
|
||||
CO_USER_TYPE=32
|
||||
};
|
||||
|
||||
enum AnisotropicFrictionFlags
|
||||
{
|
||||
CF_ANISOTROPIC_FRICTION_DISABLED=0,
|
||||
CF_ANISOTROPIC_FRICTION = 1,
|
||||
CF_ANISOTROPIC_ROLLING_FRICTION = 2
|
||||
};
|
||||
|
||||
SIMD_FORCE_INLINE bool mergesSimulationIslands() const
|
||||
{
|
||||
///static objects, kinematic and object without contact response don't merge islands
|
||||
@@ -148,14 +155,15 @@ public:
|
||||
{
|
||||
return m_anisotropicFriction;
|
||||
}
|
||||
void setAnisotropicFriction(const btVector3& anisotropicFriction)
|
||||
void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
|
||||
{
|
||||
m_anisotropicFriction = anisotropicFriction;
|
||||
m_hasAnisotropicFriction = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
|
||||
bool isUnity = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
|
||||
m_hasAnisotropicFriction = isUnity?frictionMode : 0;
|
||||
}
|
||||
bool hasAnisotropicFriction() const
|
||||
bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
|
||||
{
|
||||
return m_hasAnisotropicFriction!=0;
|
||||
return (m_hasAnisotropicFriction&frictionMode)!=0;
|
||||
}
|
||||
|
||||
///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
|
||||
|
||||
@@ -104,6 +104,14 @@ public:
|
||||
|
||||
}
|
||||
|
||||
virtual btVector3 getAnisotropicRollingFrictionDirection() const
|
||||
{
|
||||
btVector3 aniDir(0,0,0);
|
||||
aniDir[getUpAxis()]=1;
|
||||
return aniDir;
|
||||
}
|
||||
|
||||
|
||||
virtual int calculateSerializeBufferSize() const;
|
||||
|
||||
///fills the dataBuffer and returns the struct name (and 0 on failure)
|
||||
|
||||
@@ -109,6 +109,13 @@ public:
|
||||
|
||||
|
||||
int getShapeType() const { return m_shapeType; }
|
||||
|
||||
///the getAnisotropicRollingFrictionDirection can be used in combination with setAnisotropicFriction
|
||||
///See Bullet/Demos/RollingFrictionDemo for an example
|
||||
virtual btVector3 getAnisotropicRollingFrictionDirection() const
|
||||
{
|
||||
return btVector3(1,1,1);
|
||||
}
|
||||
virtual void setMargin(btScalar margin) = 0;
|
||||
virtual btScalar getMargin() const = 0;
|
||||
|
||||
|
||||
@@ -84,6 +84,11 @@ public:
|
||||
return m_coneIndices[1];
|
||||
}
|
||||
|
||||
virtual btVector3 getAnisotropicRollingFrictionDirection() const
|
||||
{
|
||||
return btVector3 (0,1,0);
|
||||
}
|
||||
|
||||
virtual void setLocalScaling(const btVector3& scaling);
|
||||
|
||||
};
|
||||
@@ -93,6 +98,12 @@ class btConeShapeX : public btConeShape
|
||||
{
|
||||
public:
|
||||
btConeShapeX(btScalar radius,btScalar height);
|
||||
|
||||
virtual btVector3 getAnisotropicRollingFrictionDirection() const
|
||||
{
|
||||
return btVector3 (1,0,0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
///btConeShapeZ implements a Cone shape, around the Z axis
|
||||
@@ -100,6 +111,12 @@ class btConeShapeZ : public btConeShape
|
||||
{
|
||||
public:
|
||||
btConeShapeZ(btScalar radius,btScalar height);
|
||||
|
||||
virtual btVector3 getAnisotropicRollingFrictionDirection() const
|
||||
{
|
||||
return btVector3 (0,0,1);
|
||||
}
|
||||
|
||||
};
|
||||
#endif //BT_CONE_MINKOWSKI_H
|
||||
|
||||
|
||||
@@ -97,6 +97,13 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
return m_upAxis;
|
||||
}
|
||||
|
||||
virtual btVector3 getAnisotropicRollingFrictionDirection() const
|
||||
{
|
||||
btVector3 aniDir(0,0,0);
|
||||
aniDir[getUpAxis()]=1;
|
||||
return aniDir;
|
||||
}
|
||||
|
||||
virtual btScalar getRadius() const
|
||||
{
|
||||
return getHalfExtentsWithMargin().getX();
|
||||
|
||||
@@ -324,12 +324,12 @@ btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel,
|
||||
|
||||
|
||||
|
||||
static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection);
|
||||
static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection)
|
||||
static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode);
|
||||
static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode)
|
||||
{
|
||||
|
||||
|
||||
if (colObj && colObj->hasAnisotropicFriction())
|
||||
if (colObj && colObj->hasAnisotropicFriction(frictionMode))
|
||||
{
|
||||
// transform to local coordinates
|
||||
btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
|
||||
@@ -807,15 +807,24 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
|
||||
if (relAngVel.length()>infoGlobal.m_singleAxisRollingFrictionThreshold)
|
||||
{
|
||||
relAngVel.normalize();
|
||||
addRollingFrictionConstraint(relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||
applyAnisotropicFriction(colObj0,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
|
||||
applyAnisotropicFriction(colObj1,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
|
||||
if (relAngVel.length()>0.001)
|
||||
addRollingFrictionConstraint(relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||
|
||||
} else
|
||||
{
|
||||
addRollingFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||
btVector3 axis0,axis1;
|
||||
btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1);
|
||||
addRollingFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||
addRollingFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||
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)
|
||||
addRollingFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||
if (axis1.length()>0.001)
|
||||
addRollingFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -834,14 +843,14 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
|
||||
{
|
||||
cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
|
||||
cp.m_lateralFrictionDir2.normalize();//??
|
||||
applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2);
|
||||
applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2);
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1);
|
||||
applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1);
|
||||
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);
|
||||
|
||||
|
||||
@@ -853,13 +862,13 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
|
||||
|
||||
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
|
||||
{
|
||||
applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2);
|
||||
applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2);
|
||||
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);
|
||||
}
|
||||
|
||||
applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1);
|
||||
applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1);
|
||||
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);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user