2009-10-21 3 views
5

私は物理エンジンを構築していますが、私はある種の "疑似バレット"を使っていました。だから私は記事を見つけ、働くことになった。私は良い近似だと思うものを追加した後、エンジンはもう動作しません。誰かが私が間違っていることを理解するのを助けることができますか?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; 
} 

編集: が、私はそれを修正しましたし、それは魔法のように動作しますが、私は約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; 
} 
+0

なぜではないか:_加速 - =衝動; ? –

+0

Actualy didntはそれを考える...ありがとう! – RCIX

答えて

3

...あなたはおそらくこれをあるために参照のうえいるverlet紙:ヒットマンを作成したとの一つであったチームによって作られた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; 
     } 
} 

、あなたは、rですあなたのコードも同様のことをしています。

私のシミュレーションを常に爆破させたのは、大きすぎるタイムステップの使用でした。 また、このverletの統合では、使用するタイムステップがゲーム中常に一定であることを確認してください。 (例えば、30フレーム/秒(例えば、タイムステップは1/30))変動しない。 question2へ

答え:ちょうど新しい位置に位置を更新し、次にとして(速度/加速を変更せずに)自分の位置を移動することがない場合は、この

EDITを占めtime corrected verlet integrationを使用する必要があります余分なステップは、このmovmentのデルタ(oldPosition)をoldpossに追加するので、それに応じて更新されます。

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

+0

私は実際にhttp://www.gamedev.net/reference/programming/features/verlet/をベースとして使用しています。何が起こるかは、パーティクルが本当に(線形重力の下で)動かないということです。もし、_acceleration = Vector2.Zero;行を_acceleration = Vector2.Multiply(_acceleration、1 - _linearDrag)に置き換えれば、それは非常に異常に機能します(パーティクルが動いてから、画面から離れたところに拘束されている制約に当たったとき、その値は直ちにNaNに設定されます)。 – RCIX

+0

私は時間修正された小児BTWを使用しています。 – RCIX

+0

今、コードと質問を更新しました。 – RCIX

関連する問題