2009-10-21 10 views
5

Sto costruendo un motore fisico e ho avuto una sorta di "pseudo-verlet" che sta succedendo e volevo aggiornarlo a verlet "reale". Così ho trovato un articolo e mi sono messo al lavoro. Dopo aver aggiunto quello che penso sia una buona approssimazione, il motore non funziona più. Qualcuno può aiutarmi a capire cosa sto facendo male? aggiornamentoVerlet Integration sta facendo esplodere il mio motore fisico

La mia principale di classe corpo di fisica, applicare la forza, e applicare sistemi di impulso:

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

Edit: Ho risolto e funziona come un fascino, ma ho due domande circa la codice seguente:

  • Il codice dell'applicazione degli impulsi è corretto e, in caso contrario, quale dovrebbe essere?
  • Come si modifica la proprietà della posizione in modo che l'impostazione mantenga la velocità corrente del corpo?

Ecco il codice:

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

Perché no: _accelerazione - = impulso; ? –

+0

A dire il vero non ci pensavo ... Grazie! – RCIX

risposta

3

come riferimento per gli altri ... la carta Verlet probabilmente stai riferendo a è questa: advanced character physics realizzato dal team che ha creato killer ed è stato uno dei prima di aver ragdoll basato fisica

tant'è ... il codice originale hanno usato era:

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

e si sono r ight che il tuo codice faccia una cosa simile

L'unica cosa che ha sempre fatto esplodere le mie simulazioni era l'uso di un timestep troppo grande. Inoltre, con questa integrazione di verlet, assicurati che il timestep che usi sia costante durante il gioco. (ad esempio 30 fotogrammi/sec per esempio (quindi timestep è 1/30)) e non fluttua. Se è così si dovrebbe usare il time corrected verlet integration che rappresenta per questo

EDIT:

risposta a question2: per spostare la vostra posizione (senza cambiare la velocità/accelerazione) solo aggiornare la posizione nella nuova posizione, e poi come passo extra aggiungi il delta di questo movimento (quindi newPosition-oldPosition) al oldposs, quindi questo viene aggiornato di conseguenza.

risposta alla domanda 1: Impulso è la forza applicata a un oggetto per un periodo di tempo. Quindi la tua soluzione non è corretta. L'impulso sarebbe che oltre X timesteps (o frame), si chiama la funzione applyForce con una forza fissa.

+0

Attualmente sto usando http://www.gamedev.net/reference/programming/features/verlet/ come base. Quello che succede è che la particella non si muove affatto (sotto una forza di gravità lineare), e se sostituisco la '_acceleration = Vector2.Zero;' linea con _acceleration = Vector2.Multiply (_acceleration, 1 - _linearDrag); agisce in modo molto insolito (le particelle iniziano a muoversi e quando colpiscono un vincolo che le lega ad un'area che vanno a carreggiarsi dallo schermo, sospetto che i loro valori siano impostati su NaN poco dopo). – RCIX

+0

Sto utilizzando il BTW corretto per il tempo corretto. – RCIX

+0

Ok ora ho aggiornato il mio codice e le mie domande. – RCIX