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

我主要的物理 body 课的更新,施加力和施加脉冲系统:

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;
}

编辑:
我已经对其进行了修复,并且它的工作原理很吸引人,但是我对以下代码有两个疑问:
  • 脉冲应用程序代码正确吗?如果不正确,应该是什么?
  • 如何更改position属性,以便对其进行设置以保留 body 的当前速度?

  • 这是代码:
    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;
    }
    

    最佳答案

    作为对他人的引用...您可能要引用的普通论文是:advanced character physics,由创造杀手的团队制作,是最早基于布娃娃的物理学之一

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

     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;
           }
     }
    

    您说对了,您的代码做了类似的事情,这是对的。

    总是让我的模拟震惊的一件事是使用了太大的时间步长。
    另外,通过这种垂直整合,请确保您在整个游戏中使用的时间步长是恒定的。 (例如30帧/秒(因此时间步长是1/30))并且不会波动。如果是这样,您应该使用time corrected verlet integration来解决这个问题

    编辑:

    问题2的答案:要移动您的位置(不改变速度/加速度),只需将位置更新到新位置,然后作为额外步骤,将此运动的增量(即newPosition-oldPosition)添加到oldposs中,以便对此进行更新因此。

    问题1的答案:冲动是一段时间内施加到对象上的力。因此,您的解决方案不正确。这种冲动可能是在X个时间步长(或帧)上,您以固定的力调用了applyForce函数。

    关于c# - Verlet集成使我的物理引擎崩溃了,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1599376/

    10-10 07:46