计算和应用摩擦力

时间:2011-12-09 03:01:33

标签: algorithm physics game-engine game-physics

我一直在研究如何施加摩擦力,并且有一部分我被困住,这就是如何将摩擦力应用于速度(如果实际上我正在计算正确的摩擦力)。

当我在表面上有一个球,法线为(0,1,0),当前速度为(2,0,0)时,我会将我的摩擦力计算为(0,-0.3, 0)。但是,我不明白的是如何正确地将其应用于我的速度。如果我简单地减去它,那么我的速度将是(2,-0.3,0),但是,摩擦是否应该导致x分量更小?

这是我目前的代码,如果有人可以请一看,我会非常感激。有一些优化要做,我知道这一点。

mTotalForces = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

D3DXVECTOR3 vSurfaceNormalized;
D3DXVec3Normalize(&vSurfaceNormalized, &vSurfaceNormal);
D3DXVECTOR3 vFrictionForce(0.0f, 0.0f, 0.0f);

D3DXVECTOR3 forceAndVelocity = mTotalForces + m_vVelocity;
float fVelocityMagnitude = sqrt((forceAndVelocity.x * forceAndVelocity.x) + (forceAndVelocity.y * forceAndVelocity.y) + forceAndVelocity.z * (forceAndVelocity.z));
float fFrictionForceMagnitude = 0.0f;
float fFrictionForce = 0.0f;

if(fVelocityMagnitude == 0.0f)
{
    fFrictionForce = m_fStaticFrictionCoefficient;

    D3DXVECTOR3 vStaticFriction = -m_fStaticFrictionCoefficient * vSurfaceNormalized;
    vFrictionForce = vStaticFriction;
}
else if(fVelocityMagnitude > 0.0f)
{
    fFrictionForce = m_fKineticFrictionCoefficient;

    D3DXVECTOR3 vKineticFriction = -m_fKineticFrictionCoefficient * vSurfaceNormalized;
    vFrictionForce = vKineticFriction;
}


{
    float fFrictionForceMagnitude = abs(fFrictionForce * D3DXVec3Dot(&vSurfaceNormalized, &forceAndVelocity));

    if(fFrictionForceMagnitude > fVelocityMagnitude)
    {
        fFrictionForceMagnitude = 0.0f;
        m_vVelocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    }
    else
    {
        m_vVelocity -= vFrictionForce;
    }
}

我在此摩擦函数开始时使总力为零,因为如果存在摩擦,则之前的力(重力)不应该影响以后的速度。 (...对吧?)

3 个答案:

答案 0 :(得分:4)

您的代码存在许多问题。所以,除了回答你的实际问题之外,我还要介绍它们。首先,

D3DXVECTOR3 forceAndVelocity = mTotalForces + m_vVelocity;

是不正确的,因为力和速度在概念上非常不同。这体现在他们的不同单位,因此无法添加。从下一行开始,

float fVelocityMagnitude = sqrt((forceAndVelocity.x * forceAndVelocity.x) + ...

我相信你希望forceAndVelocity严格要求速度。

我将重做第一个if语句,如下所示,

float fFrictionCoefficient = 0.0f;
if(fVelocityMagnitude == 0.0f)
{
    float fFrictionCoefficient = m_fStaticFrictionCoefficient;
}
else if(fVelocityMagnitude > 0.0f)
{
    float fFrictionCoefficient = m_fKineticFrictionCoefficient;
}

我放弃了矢量计算,因为它们与法线不垂直平行。

摩擦力的大小是摩擦系数乘以法向力的大小,所以

float fFrictionForceMagnitude = fFrictionCoefficient 
                        * sqrt(D3DXVec3Dot(&vSurfaceNormal, &vSurfaceNormal));

在第二个if声明中,您再次比较力和速度,您要做的是确定何时可以克服静摩擦力。基本上,您需要确定所有其他力是否超过摩擦力,因此您需要将无摩擦力的总力量与摩擦力的大小进行比较。所以,我会将if块重做为

float fForceMagnitude = sqrt(D3DXVec3Dot(&mTotalForces, &mTotalForces));

if(fFrictionForceMagnitude > fForceMagnitude)
{
    float m_vVelocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
}
else
{
    float mTotalForces -= fFrictionForceMagnitude * m_vVelocity / fVelocityMagnitude;
}

最后一行是您问题的答案。摩擦力与速度相反,因此它与速度方向相反,其中m_vVelocity / fVelocityMagnitude是标准化速度。注意,这不会直接影响速度,而是你的速度

D3DXVECTOR3 m_vVelocity = mTotalForces * time / mass;

其中mass是对象的质量;

答案 1 :(得分:1)

首先,您的摩擦力应与表面相切,并与速度矢量方向一致。所以在你的情况下,你的力矢量将是(-0.3,0,0)。然后你的摩擦是一种力量,所以你不能将它添加到这样的速度。你的力量会影响速度。这项工作随着时间而变化,实际上可能与你的速度成正比。

答案 2 :(得分:0)

动态摩擦总是平行于接触表面施加,即垂直于法线,而不是垂直于正常。