2009-10-21 9 views
5

Buduję silnik fizyki i miałem coś w rodzaju "pseudo-verlet" i chcę go ulepszyć do "prawdziwego" verleta. Więc znalazłem artykuł i gotowe do pracy. Po dodaniu tego, co uważam za dobre przybliżenie, silnik przestał działać. Czy ktoś może mi pomóc zrozumieć, co robię źle? AktualizacjaVerlet Integration wysadza mój silnik fizyki

mojego główne klasy body fizyki za zastosować siłę i zastosować układy impulsowe:

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: Naprawiłem go i działa jak czar, ale mam dwa pytania o następujący kod:

  • Czy kod aplikacji impulsu jest poprawny, a jeśli nie, jaki powinien być?
  • Jak zmienić właściwość pozycji, aby ustawienie zachowywało bieżącą prędkość ciała?

Oto kod:

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

Dlaczego nie: _acceleration - = impuls; ? –

+0

Actualy nie pomyślał o tym ... Dzięki! – RCIX

Odpowiedz

3

jako odniesienie do innych ... The Verlet papieru, prawdopodobnie refering to: advanced character physics wykonana przez zespół, który stworzył hitman i był jednym z pierwszy opiera się ragdoll physics

... zresztą oryginalny kod kiedyś było:

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

i jesteś R Cześć, że twój kod robi coś podobnego.

Jedną rzeczą, która zawsze wysadzała moje symulacje, było użycie zbyt dużego czasu. Ponadto, z tą integracją verlet, upewnij się, że używany czas jest stały przez całą grę. (np. 30 klatek/s na przykład (więc taktowanie to 1/30)) i nie podlega fluktuacjom. Jeśli tak się stanie należy użyć time corrected verlet integration co stanowi tym

EDIT:

odpowiedzi do question2: aby przenieść swoją pozycję (bez zmiany prędkości/przyspieszenia) po prostu zaktualizować pozycję do nowej pozycji, a następnie jako dodatkowy krok dodaje deltę tego ruchu (tak newPosition-oldPosition) do oldpossa, więc to zostanie odpowiednio zaktualizowane.

odpowiedź na pytanie1: Impuls to siła przykładana do obiektu przez pewien czas. Twoje rozwiązanie nie jest poprawne. Impuls byłby taki, że ponad X timesteps (lub ramek), nazywasz swoją funkcję applyForce ze stałą siłą.

+0

Używam http://www.gamedev.net/reference/programming/features/verlet/ jako bazy. Co się dzieje, to, że cząstka naprawdę nie porusza się wcale (pod liniową siłą grawitacji) i jeśli zastąpię linię '_acceleration = Vector2.Zero;' z _acceleration = Vector2.Multiply (_acceleration, 1 - _linearDrag); działa bardzo nietypowo (cząsteczki zaczynają się poruszać, a kiedy uderzą w wiązanie, które wiąże je z obszarem, który znikają z ekranu, podejrzewam, że ich wartości zostaną wkrótce ustawione na NaN). – RCIX

+0

Używam poprawionego czasu verlet BTW. – RCIX

+0

Ok, teraz zaktualizowałem swój kod i moje pytania. – RCIX