2009-10-21 5 views
5

Je construis un moteur de physique et j'ai eu une sorte de pseudo-verlet et je voulais le mettre à niveau vers un verlet "réel". J'ai donc trouvé un article et je me suis mis au travail. Après avoir ajouté ce que je pense être une bonne approximation, le moteur ne fonctionne plus. Quelqu'un peut-il m'aider à comprendre ce que je fais mal?L'intégration de Verlet fait exploser mon moteur physique

Ma principale mise à jour de classe du corps physique, appliquer une force, et appliquer les systèmes d'impulsion:

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: je l'ai fixé et il fonctionne comme un charme, mais j'ai deux questions sur la Le code suivant est-il:

  • Le code d'application d'impulsion est-il correct, et si ce n'est pas le cas, que devrait-il être?
  • Comment modifier la propriété de position de sorte que le réglage préserve la vitesse actuelle du corps?

Voici le code:

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

Pourquoi? ? –

+0

Actualy n'a pas pensé à ça ... Merci! – RCIX

Répondre

3

comme référence à d'autres ... le papier verlet vous référenceurs probablement à ceci: advanced character physics réalisé par l'équipe qui a créé tueur à gages et était l'un des premier à avoir ragdoll basé sur la physique

en tout cas ... le code original qu'ils ont utilisé était:

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

et vous êtes r que votre code fasse une chose semblable.

La seule chose qui a toujours fait sauter mes simulations était l'utilisation d'un pas trop long. De plus, avec cette intégration de verlet, assurez-vous que le pas de temps que vous utilisez est constant tout au long de la partie. (par exemple 30 images/s par exemple (donc timestep est 1/30)) et ne fluctue pas. Si elle ne vous devez utiliser le time corrected verlet integration qui représente cette

EDIT:

réponse à question2: pour déplacer votre position (sans changer de vitesse/accélération) actualisateurs la position de la nouvelle position, puis en tant step supplémentaire ajoute le delta de ce mouvement (donc newPosition-oldPosition) aux oldposs, donc ceci est mis à jour en conséquence.

réponse à la question 1: L'impulsion est la force appliquée à un objet sur une période de temps. Donc, votre solution n'est pas correcte. L'impulsion serait que plus de X timesteps (ou frames), vous appelez votre fonction applyForce avec une force fixe. Pourquoi pas: _acceleration - = impulse

+0

J'utilise en fait http://www.gamedev.net/reference/programming/features/verlet/ comme base. Qu'est-ce qui se passe est que la particule ne bouge pas du tout (sous une force de gravité linéaire), et si je remplace la ligne '_acceleration = Vector2.Zero;' avec _acceleration = Vector2.Multiply (_acceleration, 1 - _linearDrag); il agit de manière très inhabituelle (les particules commencent à bouger puis quand elles heurtent une contrainte qui les lie à une zone qu'elles font disparaître de l'écran, je soupçonne que leurs valeurs sont réglées sur NaN peu de temps après). – RCIX

+0

J'utilise le temps corrigé verlet BTW. – RCIX

+0

Ok maintenant j'ai mis à jour mon code et mes questions. – RCIX