5

我正在构建一个物理引擎,并且我有某种“伪verlet”的东西,我想将它升级为“真正的”verlet。所以我找到了一篇文章并开始工作。在我添加了我认为很好的近似值之后,引擎不再工作了。有人可以帮我理解我做错了什么吗?

我的主要物理体类的更新、应用力和应用脉冲系统:

public void Update(float timestepLength)
{
    if (!this._isStatic)
    {
        Vector2 velocity =  Vector2.Subtract(_position, _lastPosition);
        Vector2 nextPos = _position + (_position - _lastPosition) + _acceleration * (timestepLength * timestepLength);
        _lastPosition = _position;
        _position = nextPos;
        _acceleration = Vector2.Zero;
    }
}

public void ApplyForce(Vector2 accelerationValue)
{
    if (!this._isStatic)
        _acceleration += (accelerationValue) * _mass;
}
public void ApplyImpulse(Vector2 impulse)
{
    if (!this._isStatic)
        _acceleration +=-1 * impulse;
}

编辑: 我已经修复了它,它就像一个魅力,但我对以下代码有两个问题:

  • 脉冲应用程序代码是否正确,如果不正确,应该是什么?
  • 如何更改位置属性以使其设置保留身体的当前速度?

这是代码:

public Vector2 Position
{
    get { return _position; }
    set { _position = value;}
}
public void Update(float timestepLength)
{
    if (!this._isStatic)
    {
        Vector2 velocity =  Vector2.Subtract(_position, _lastPosition);
        Vector2 velocityChange = Vector2.Subtract(velocity, Vector2.Subtract(_lastPosition, _twoStepsAgoPosition));
        Vector2 nextPos = _position + (_position - _lastPosition) + _acceleration * (timestepLength * timestepLength);
        _twoStepsAgoPosition = _lastPosition;
        _lastPosition = _position;
        _position = nextPos;
        _acceleration = Vector2.Multiply(velocityChange, timestepLength);
    }
}

public void ApplyForce(Vector2 force)
{
    if (!this._isStatic)
        _lastPosition -= force;
}
public void ApplyImpulse(Vector2 impulse)
{
    if (!this._isStatic)
        _acceleration +=-1 * impulse;
}
4

1 回答 1

3

作为对其他人的参考...您可能指的是 Verlet 论文:由创建杀手的团队制作的高级角色物理,并且是第一个拥有基于布娃娃的物理的团队之一

无论如何......他们使用的原始代码是:

 void ParticleSystem::Verlet() {
       for(int i=0; i<NUM_PARTICLES; i++) {
             Vector3& x = m_x[i];
             Vector3 temp = x;
             Vector3& oldx = m_oldx[i];
             Vector3& a = m_a[i];
             x += x-oldx+a*fTimeStep*fTimeStep;
             oldx = temp;
       }
 }

你是对的,你的代码做了类似的事情。

总是让我的模拟崩溃的一件事是使用了太大的时间步长。此外,通过这个 verlet 集成,确保您使用的时间步长在整个游戏中保持不变。(例如,例如 30 帧/秒(因此时间步长为 1/30))并且不会波动。如果是这样,您应该使用时间更正的 verlet 集成来解释这一点

编辑:

对问题2的回答:移动你的位置(不改变速度/加速度)只需将位置更新到新位置,然后作为额外的步骤将这个运动的增量(所以 newPosition-oldPosition)添加到 oldposs,所以这个得到更新因此。

对问题 1 的回答:冲动是在一段时间内施加在物体上的力。所以你的解决方案不正确。冲动将是在 X 时间步(或帧)上,您以固定的力调用您的 applyForce 函数。

于 2009-10-21T09:04:35.750 回答