pRoGraMerZ


Forum pRoGraMerZ Strona Główna -> OpenGL -> Fizyka w grach
Napisz nowy temat  Odpowiedz do tematu Zobacz poprzedni temat :: Zobacz następny temat 
Fizyka w grach
PostWysłany: Czw 14:20, 09 Mar 2006
Popiol
Poison Headcrab

 
Dołączył: 02 Lis 2005
Posty: 16
Przeczytał: 0 tematów

Ostrzeżeń: 0/5
Skąd: Wygiełzów





Opracowałem pewien model matematyczny jazdy samochodem. Wiem, że temat jest troche oderwany od tematu tego działu, ale wszakże samo zaprojektowanie samochodu 3D jest mało ciekawe dopóki ten samochód nie może jeździć. Dlatego przedstawie swój pomysł na wyliczanie położenia samochodu w czasie jazdy.

Samochód utożsamiamy w moim modelu z dwoma punktami (przód i tył samochodu) połączonymi krawędzią. Zakładam, że napęd jest na przednie koła, a więc na przód działa siła przyśpieszająca, potrzebna do uzyskania następującego przyśpieszenia:
Kod:
ax = vk*sin(kat+skret) - vx;
ay = vk*cos(kat+skret) - vy;

gdzie vk to prędkość kół, kat to kąt pomiędzy osią x w układzie współrzędnych a krawędzią łączącą przód i tył samochodu, skret to kąt o jaki są skręcone koła, a (vx,vy) to aktualny wektor prędkości przodu samochodu. Takie przyśpieszenie będzie miał samochód, jeśli nie wpadnie w poślizg.

Generalnie zakładam, że samochód porusza się po płaszczyźnie, dlatego wektory prędkości i przyśpieszenia dzielę na składowe x i y. Co prawda samochód może jechać pod górę, ale w tym przypadku wystarczy uwzględnić dodatkową siłę, ściągającą samochód w dół.

Jeśli chodzi o tył samochodu to trzeba uwzględnić siłę tarcia, która sprawia, że koła nie przesuwają się w bok, tylko kręcą się do przodu, albo do tyłu (o ile nie wpadną w poślizg, ale o tym później). Przyśpieszenie powodowane tą siłą wyliczam następująco:
Kod:
dx = tg(kat);
dy = 1;
b = (vy*dx-vx*dy)/(dy^2+dx^2);
ax = b * dy;
ay = -b * dx;

Co innego jeśli zaciągniemy ręczny, wtedy w każdym kierunku tarcie jest takie samo:
Kod:
ax = -vx;
ay = -vy;

Trzeba zadbać także o to, aby siła działająca na jeden punkt oddziaływała również na drugi punkt. Realizuje to następująca funkcja:
Kod:
dx = x2 - x1;
dy = y2 - y1;
b = (dy*ay1+dx*ax1)/(dy^2+dx^2);
dax2 += b * dx;
day2 += b * dy;

gdzie x1,y1 - położenie pierwszego punktu, ax1,ay1 - przyśpieszenie pierwszego punktu, dax2,day2 - zmiana przyśpieszenia drugiego punktu, x2,y2 - wiadomo, reszta to zmienne pomocnicze. Trzeba ten kod wykonać dwa razy: gdy przód jest pierwszym punktem, a tył drugim i na odwrót. Następnie trzeba dodać do wektorów przyśpieszenia wektory zmiany przyśpieszenia.

A teraz zajmiemy się wpadaniem w poślizg. Sprawa okazuje się całkiem prosta, trzeba sprawdzić czy siła tarcia działająca na przód i tył samochodu nie jest zbyt duża i jeśli jest to ją zmniejszyć. Wygląda to tak:
Kod:
if ( abs(ax) > us*g ) {
    ax = sign(ax)*uk*g;
}
if ( abs(ay) > us*g ) {
    ay = sign(ay)*uk*g;
}

W całym modelu siła jest reprezentowana przez przyśpieszenie, które ta siła nadaje, na podstawie wzoru f = a*m. W powyższym kodzie występują dwa współczynniki tarcia: us (tarcie satyczne) i uk (tarcie kinetyczne). Współczynnik tarcia kinetycznego jest mniejszy od współczynnika tarcia statycznego, z regóły zachodzi mniej więcej zależność us = 1.25 * uk. Parametr g to przyśpieszenie ziemskie. Nie należy jednak przywiązywać zbyt dużej wagi do jednostek, a więc g nie musi wcale wynosić 9.81. W praktyce w moim modelu poślizg wygląda w miarę sensownie dla parametrów: g = 0.1, us = 0.5, uk = 0.4.

Mając tak wyliczone przyśpieszenie dodajemy je do aktualnych wektorów prędkości. Ostatnim etapem jest "poprawienie" wektorów prędkości tak, by przód i tył znjdowały się nadal w tej samej odległości. Realizuje to następujący kod:
Kod:
  dx = x2 - x1;
  dy = y2 - y1;
  xv1 = x1 + vx1; yv1 = y1 + vy1;
  xv2 = x2 + vx2; yv2 = y2 + vy2;
  a = (m1+m2)*(m1+m2)*(dx*dx+dy*dy);
  b = 2*(m1+m2)*((xv1-xv2)*dx+(yv1-yv2)*dy);
  c = (xv1-xv2)*(xv1-xv2)+(yv1-yv2)*(yv1-yv2)-dx*dx-dy*dy;
  delta = b*b-4*a*c;
  if (delta < 0) w = 0;
  else w = (-sqrt(delta)-b)/(2*a);
  vx1 += w*m2*dx; vy1 += w*m2*dy;
  vx2 -= w*m1*dx; vy2 -= w*m1*dy;

x1,y1 - położenie pierwszego punktu, vx1,vy1 - prędkość pierwszego punktu, m1 - masa pierwszego punktu, analogicznie dla drugiego punktu, reszta to zmienne pomocnicze.

To jeszcze nie jest pełny model, bo trzeba jakoś wyliczać prędkość kół i kąt skręcenia kół. Jeśli chodzi o skręcanie kół to doszedłem do wniosku, że jadąc szybciej powinno się skręcać wolniej, bo po pierwsze gwałtowny ruch kierownicą przy dużej prędkości może spowodować wpadnięcie w poślizg, a po drugie siła odśrodkowa sprawia, że trudniej jest skręcić kierownicę (tak mi się wydaje). Dlatego wymyśliłem taki model skręcania kół:
Kod:
void skrec(float kierunek) {
  if (sign(kierunek)*sign(skret) < 0) skret += kierunek*dodkret;
  else skret += kierunek*dskret/(abs(vk)+1);
  if (skret > max) skret = max;
  else if (skret < -max) skret = -max;
}

Pierwszy warunek sprawdza czy skręcamy czy odkręcamy kierownicę. Parametry dodkret i dskret określają jak szybko to robimy. Ustawiłem dla nich wartości: dodkret = 0.1, dskret = 0.05. Nie wiem czy mam rację, ale wydaje mi się, że skręcić koła jest trudniej niż odkręcić. Parametr max określa maksymalny kąt skręcenia kół. U mnie to 45 stopni.

Jeśli chodzi o wyliczanie prędkości kół to tego jeszcze dokładnie nie opracowałem. W najprostszej wersji przyśpiesza się i hamuje jednostanie, bez uwzględnienia biegów, ale to jest oczywiście kiepski model.


Post został pochwalony 0 razy
Zobacz profil autora
PostWysłany: Nie 1:16, 25 Lut 2007
Erten6
Poison Headcrab

 
Dołączył: 25 Lut 2007
Posty: 17
Przeczytał: 0 tematów

Ostrzeżeń: 0/5





Carmen Electra Giving A Head And Taking A Load!
[link widoczny dla zalogowanych]


Post został pochwalony 0 razy
Zobacz profil autora
Fizyka w grach
Forum pRoGraMerZ Strona Główna -> OpenGL
Możesz pisać nowe tematy
Możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Wszystkie czasy w strefie EET (Europa)  
Strona 1 z 1  

  
  
 Napisz nowy temat  Odpowiedz do tematu  


fora.pl - załóż własne forum dyskusyjne za darmo
Powered by phpBB © 2001-2003 phpBB Group
Theme created by Vjacheslav Trushkin
Regulamin