Autor Wątek: [3D] Ślizganie sie po nierównościach ...  (Przeczytany 1231 razy)

Offline Chemik

  • Użytkownik

# Kwiecień 02, 2009, 00:53:38
Witam, na wstępie uprzedzam że dopiero od niedawna robię co nie co w OpenGL - i w ogóle w 3D ;)

Mam problem ze sprawieniem aby kamera (FPS - brak modelu postaci - reprezentowana jako Sfera)
płynnie ślizgała się po bardzo nierównej powierzchni (zbudowanej z trójkątów, przechowywanej w tablicy).

Poniższa procedura jest wykonywana przed rysowaniem :
void Fizyka(void)
{
 oldCAM.x=CAM.x;
 oldCAM.y=CAM.y;
 oldCAM.z=CAM.z;

 CAM.y+=GRAV;
 KeyPressed();

XYZ punkt;
punkt.x=-CAM.x;
punkt.y=-CAM.y;
punkt.z=-CAM.z;

for(int i=0; i<100;i++)
{
for(int j=0; j<100;j++)
{
if (StPcoll(MaP1[i][j].trj,punkt,3,5)) kolizja=true;   
if (StPcoll(MaP1[i][j].tra,punkt,3,5)) kolizja=true;   
}
}

if ((kolizja)) {
CAM.x=oldCAM.x;
CAM.y=oldCAM.y;
CAM.z=oldCAM.z;
kolizja=false;
                };
}
1.Zapis starej pozycji kamery
2.ściągnięcie camery w dół przez grawitacje & przesunięcie "z klawisza"
3.odwrócenie pozycji kamery (potem to poprawie - mapa jest rysowana w przeciwą stronę ;p )
4.wykonanie testu kolizji Sfera z Płaszczyzną - zwraca Prawdę jeżeli zajdzie (potem zoptymalizuje - na razie test wykonywany jest z każdym trójkątem mapy - raptem z 20k ;p ) & ustawienie Flagi kolizji.
5 Jeżeli kolizja - wracamy na starą pozycję
6. Renderowanie Obrazu

w.w. sposób powoduje ze "zastygam" w miejscu na dobre tak więc
CAM.y=oldCAM.y-GRAV;i wszystko OK - ślizgam się - tylko ze mam piękny Efekt skakania kamery ;/ zmniejszenie wartości wznoszenia powoduje niemożliwosć wspięcia sie na wzniesienia ...
próbowałem już sprawdzać z wyprzedzeniem ale ten sam efekt ..
ogólnie pomogłoby renderowanie co 2giej klatki - ale to raczej bez sensu ;/
wszystkie inne metody jakie powymyślałem powodowały że wypadałem z mapy przy każdym większym wzniesieniu ...

podrzuci ktoś jakiś pomysł ? będę wdzięczny ;)

ps - przejrzałem już kilka tematów z podobnymi problemami ale tam "podłoga" była raczej płaska - ja się wspinam po górach :p
« Ostatnia zmiana: Kwiecień 02, 2009, 00:59:10 wysłana przez Chemik »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline _OskaR

  • Użytkownik

# Kwiecień 02, 2009, 01:07:13
Dla obiektu, mającego znajdować się w określonej wysokości nad heightmapą, wystarczy zrobić rzutowanie punktu, w którym się on znajduje, na powierzchnię i sprawdzić wysokość. Nie trzeba przeglądać też całej tablicy. Skoro kamera sobie skacze, może nie obliczasz wysokości punktu wewnątrz trójkąta, tylko podajesz od razu wysokość jednego z wierzchołków? Albo zamiast float funkcja(..), masz int funkcja (...)?

Offline Angru

  • Użytkownik

# Kwiecień 02, 2009, 10:47:16
Najlepiej, żebyś dysponował kodem intersekcji sfery lub elipsoidy z trójkątem, lub innym prymitywem. Wtedy po pierwsze taką kamerę, albo jakikolwiek inny obiekt zamykasz w taką elipsoidę. Przed wykonaniem kroku testujesz kolizje (to niestety dość sporo roboty), w przypadku kolizji wyznaczasz wektor penetracji. Potem korzystając z elipsoidy w pozycji w momencie zderzenia i punktu kolizji na jej powierzchni wyznaczasz płaszczyznę ślizgania na którą rzutujesz wektor penetracji. Skracasz jego długość o wartość tarcia i powtarzasz.

Niestety test elipsoidy, lub dla uproszczenia sfery z trójkątem to trochę pracy. Będzie ci potrzebne napisać intersekcje promienia z płaszczyzną, trójkątem i sferą/elisoidą. Następnie samej sfery/elipsoidy z płaszczyzną i trójkątem. Do tego wszystkiego przyda ci się parę innych obliczeń geometrycznych.

Alternatywnie jak ktoś już proponował, możesz skorzystać z gotowego kodu w stylu Open Dynamics Engine (ODE).

W każdym razie takie rozwiązanie pozwoli ci "ślizgać się" nie tylko po mapie wysokości, ale praktycznie każdej geometrii którą wyznaczysz jako przeszkodę. Oczywiście jest to znacznie bardziej kosztowna metoda. Wyznaczanie małej części geometrii z którą najprawdopodobniej nastąpi kolizja to inny temat.

Offline Chemik

  • Użytkownik

# Kwiecień 02, 2009, 16:47:10
Cytuj
intersekcje promienia z płaszczyzną, trójkątem i sferą/elisoidą. Następnie samej sfery/elipsoidy z płaszczyzną i trójkątem.
wszystko mam i wykonuje test kolizji sfera(kamera) - płaszczyzna(trójkąty mapy) ;)
problem polega na tym ze nie wiem o jaką wartość unieść kamerę po kolizji żebym mógł się poruszać i coby nie było tego paskudnego telepania  .. (grav mnie ściaga -> test kolizji ==true-> przywracam stara pozycję kamery i unoszę ją o X ->grav ściaga ..  )

http://www.sendspace.com/file/wtbr64  - 256kB - w celu lepszej ilustracji problemu.
sterowanie - WSAD & R(up) F(down) & P(zwiekszenie predkosci)

ps : teraz wykonuje test kolizji tylko na 2 trójkąty od pozycji kamery - nie dla całej mapy ;]
« Ostatnia zmiana: Kwiecień 02, 2009, 17:15:50 wysłana przez Chemik »

Offline counterClockWise

  • Użytkownik

# Kwiecień 02, 2009, 17:19:21
http://www.sendspace.com/file/wtbr64  - 256kB - w celu lepszej ilustracji problemu.
sterowanie - WSAD & R(up) F(down) & P(zwiększenie predkosci)

Ściągnąłem. Na pierwszy rzut oka wygląda to jakbyś odbijał się doskonale bez wytłumienia (strat energii). Nie dziwne więc, że protagonista;) się ciągle odbija jak perpetum-mobile.
Wprowadź jakieś stopniowe tłumienie = zmniejszanie amplitudy tego odbijania np. np. każde odbicie jest maksymalnie na wysokość 0.7 * pierwotnej wysokości i jeżeli wysokość, z której spadamy jest < Epsilon to nie ma odbicia (żeby niepotrzebnie nie było setek obliczeń na pomijalnie małych wartościach).

...albo jakiś inny mniej lub bardziej zaawansowany model.

Offline Angru

  • Użytkownik

# Kwiecień 02, 2009, 17:58:19
Na pewno chcesz odbijać? Zrób jak pisałem, to działa całkiem fajnie. Cofnij się w kierunku odwrotnym do wektora penetracji na odległość, dajmy 0.0001f i wyznacz płaszczyznę ślizgu (punkt kolizji i normalna w kierunku promienia skierowana do centrum sfery) i rzutuj na nią wektor penetracji. Zastosuj tarcie. Tak wyznaczasz nową pozycję po wykonaniu ruchu. Powtarzasz to rekurencyjnie (żeby nie wyskoczyć za róg w kącie ściany na przykład) do czasu aż nie będzie kolizji.