5

私は物理エンジンを構築していて、ある種の「疑似ベレ」を実行していて、それを「実際の」ベレにアップグレードしたかったのです。だから私は記事を見つけて仕事に取り掛かりました。良い近似だと思うものを追加した後、エンジンは動作しなくなりました。誰かが私が間違っていることを理解するのを手伝ってもらえますか?

私の主な物理ボディクラスの更新、力の適用、およびインパルスシステムの適用:

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

編集: 私はそれを修正しました、そしてそれは魅力のように働きます、しかし私は次のコードについて2つの質問があります:

  • インパルスアプリケーションコードは正しいですか?そうでない場合はどうあるべきですか?
  • 体の現在の速度を維持するように位置プロパティを変更するにはどうすればよいですか?

コードは次のとおりです。

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

他の人への参照として...あなたがおそらく参照しているベレの紙はこれです:ヒットマンを作成し、ラグドールベースの物理学を最初に持ったチームの1つによって作られた高度なキャラクター物理学

とにかく...彼らが使用した元のコードは次のとおりです。

 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))、変動しません。もしそうなら、これを説明する時間修正されたベレ統合を使用する必要があります

編集:

質問2への回答:(速度/加速度を変更せずに)位置を移動するには、位置を新しい位置に更新し、追加の手順として、この移動のデルタ(つまりnewPosition-oldPosition)をoldpossに追加して、これが更新されるようにしますによると。

質問1への回答:インパルスは、ある期間にわたってオブジェクトに加えられる力です。したがって、あなたの解決策は正しくありません。衝動は、Xタイムステップ(またはフレーム)にわたって、固定の力でapplyForce関数を呼び出すことです。

于 2009-10-21T09:04:35.750 に答える