Autor Wątek: Dynamiczne ładowanie świata  (Przeczytany 4763 razy)

Offline kacperz1

  • Użytkownik

# Kwiecień 19, 2008, 12:07:21
Witam,

Chciałbym dynamicznie ładować teren/świat tylko nie wiem zbytnio jak to zrobić. Chodzi o to że cały świat jest ogromny i dlatego chciałbym tylko ładować i renderować kawałek świata tak aby pamięć nie była by zbędnie zaśmiecana. Tak jak w grze World of Warcraft.

Offline Mr. Spam

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

Offline yarpen

  • Użytkownik

# Kwiecień 19, 2008, 12:23:43
Oj.... To nie jest temat na wyjasnienie w jednym poscie. Najczesciej jest tak, iz swiat podzielony jest na chunki (gracz tego nie widzi) i renderujac jeden chunk jednoczesnie w tle ladujesz drugi. To oczywiscie uproszczenie bo dochodza kwestie logiki pomiedzy chunkami, przewidywania, ktore chunki ladowac, ile trzymac w pamieci, co robic kiedy dojdziemy do miejsca, ktore nie zdazylo sie zaladowac itd. Calkiem niezle wprowadzenie masz np. w prezentacji Volition z GDC o Saints Row: https://www.cmpevents.com/sessions/GD/S3741i1.pdf

Offline Reg

  • Administrator
    • Adam Sawicki - Home Page

# Kwiecień 19, 2008, 12:37:30
Ja tam nie wiem, ale podejrzewam, że zacząć trzeba od tego:

1. Podzielić świat na kawałki.

2. Zapewnić sobie możliwość wczytywania kawałków w tle, w osobnym wątku, żeby wczytywanie nie zawieszało na chwilę całej gry.

Offline Hans

  • Użytkownik

# Kwiecień 19, 2008, 12:40:21
yo

WoW'a wprawdzie na oczy nie widziałem, za to grałem byłem w obliviona

w skrócie aby ładować świat 'dynamicznie' trzeba ładować go jakimiś kawałkami, więc pierwsza rzecz do zrobienia to wprowadzenie jakiegoś sensownego podziału na, nazwijmy to, komórki. najprościej można pociąć świat na kwadraty o zadanym rozmiarze albo lepiej (i trudniej) podzielić zgodnie z ukształtowaniem/zagospodarowaniem terenu (tak żeby np jakaś wioska nie wypadła na łączeniu komórek tylko stanowiła całą oddzielną)

potem czas na ładowanie :) wczytujesz komórke w której jest gracz/kamera oraz sąsiednie, jeżeli gracz wlezie na komórke obok to wtedy dla niej wczytujesz sąsiedzie, a wywalasz te które są za daleko. ważne jest aby granice wczytywania komórki i wywalania jej były różne (czyli wczytujesz wcześniej/bliżej, zwalniasz dalej). w przeciwnym wypadku idąc wzdłuż takiej granicy (i co chwile ją przekraczając) cały czas by 'mieliło'

(aa w zależności od typu gry/terenu/sprzętu/etc wyświetlać można oczywiści wiecej komórek jednocześnie, można też zrobić kilka LOD dla komórek i ładować je kolejno w miarę zbliżania się)

z aspektów technicznych.. potrzebna jest wielowątkowość tutaj. czyli do standardowego wątku (albo wątków) głównego dorzucasz wątek zajmujący się tylko ładowaniem map/zasobów (może być ich więcej niż jeden), najlepiej o mniejszym priorytecie żeby działał 'w tle' nie przeszkadzając zbytnio w rozgrywce

//edit.. za długo to pisałem hehe

Offline kacperz1

  • Użytkownik

# Kwiecień 19, 2008, 12:54:00
Dziękuję za odpowiedzi i na pewno pomoże mi to bardzo w dalszym rozwoju gry, lecz nie ma mowy o wątkach. Znaczy się że ja kiedyś z nimi pracowałem i pracowało mi się okropnie.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Kwiecień 19, 2008, 13:01:53
Dziękuję za odpowiedzi i na pewno pomoże mi to bardzo w dalszym rozwoju gry, lecz nie ma mowy o wątkach. Znaczy się że ja kiedyś z nimi pracowałem i pracowało mi się okropnie.
W takim razie polecam lekturę tego: http://msdn2.microsoft.com/en-us/library/aa365683(VS.85).aspx
Mniej więcej działa to tak, że prosisz Windowsa, żeby Ci coś załadował, a on Ci grzecznie mówi, kiedy skończy. :)

Offline yarpen

  • Użytkownik

# Kwiecień 19, 2008, 13:09:37
To przy zalozeniu, ze dane nie wymagaja zadnego postprocessingu.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Kwiecień 19, 2008, 13:24:19
To przy zalozeniu, ze dane nie wymagaja zadnego postprocessingu.
Zawsze można procesować w wątku głównym, chociaż fakt, że w ten sposób traci się dosyć łatwą okazję skorzystania z drugiego rdzenia.

Offline kacperz1

  • Użytkownik

# Kwiecień 19, 2008, 14:12:11
Jaka była by najlepsza metoda poinformowania programu jakie mapy znajdują sie obok mapy na której aktualnie znajduje sie gracz. Myślałem o odczytywaniu tych informacji z pliku tekstowego. Informacja wyglądały by tak:
Mapa_5: Mapa_4 & Mapa_6 // co znaczy że mapa_5 sąsiaduje z mapa 4 i 6

Offline Esidar

  • Użytkownik

# Kwiecień 19, 2008, 15:20:26
Dziękuję za odpowiedzi i na pewno pomoże mi to bardzo w dalszym rozwoju gry, lecz nie ma mowy o wątkach. Znaczy się że ja kiedyś z nimi pracowałem i pracowało mi się okropnie.

Bez wątków i procesora z co najmniej dwoma rdzeniami nie dasz rady. A przynajmniej nie będzie płynnie bez tego. Podczas wczytywania danych musisz wykonywać dość kosztowne operacje takie jak tworzenie vertexbuffers, indexbuffers, textures, shaders. Niestety PC nadal nie radzi sobie z tym dobrze bo w zależności od drivera i systemu stworzenie każdego z tych zasobów może mocno zablokować rendering.

Cytuj
Jaka była by najlepsza metoda poinformowania programu jakie mapy znajdują sie obok mapy na której aktualnie znajduje sie gracz
Najpierw pomyśl jak będzie tworzona (przygotuj sobie miasto w jakimś programie 3D), dzielona (algorytm, wielkość bloków) i wczytywana geometria świata (algorytm określający który blok jest widoczny a który wczytywany) a dopiero na końcu sposób zapisu o którym mówisz. Właściwie ten sposób sam Ci się określi, jak już przebrniesz przez wcześniejsze punkty.

Cytuj
Mapa_5: Mapa_4 & Mapa_6 // co znaczy że mapa_5 sąsiaduje z mapa 4 i 6
Jeśli podzielisz świat na szachownicę, to Mapa_5 będzie zawsze sąsiadować z 4 i 6. Nie musisz tego wczytywać :)

Jeśli masz szachownicę 8x8 a gracz stoi w polu x:3 y:4 to na lewo będzie x-1 y+0, na prawo x+1 y+0, na górze x+0 y-1, a na dole x+0 y+1.

« Ostatnia zmiana: Kwiecień 19, 2008, 15:23:22 wysłana przez Esidar »

Offline Kos

  • Użytkownik
    • kos.gd

# Kwiecień 19, 2008, 15:35:10
Btw, w quakach było coś takiego, jak portale - działało to tak, że w miejscu np. drzwi była jakaś niewidzialna bryła. Jeśli ta bryła kolidowała ze ściętosłupem widzenia (czyli gracz mógł przez drzwi wyjrzeć) to wtedy był renderowany teren za nią. Mógłbyś może zrobić na podobnej zasadzie ładowanie terenu, choć tu bez liczenia widoczności - po prostu jeśli gracz jest w jakimś obszarze, to doczytujesz obszary które są za portalami znajdującymi się w tym obszarze, a zapominasz pozostałe.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Kwiecień 19, 2008, 15:41:37
Cytuj
Bez wątków i procesora z co najmniej dwoma rdzeniami nie dasz rady. A przynajmniej nie będzie płynnie bez tego. Podczas wczytywania danych musisz wykonywać dość kosztowne operacje takie jak tworzenie vertexbuffers, indexbuffers, textures, shaders. Niestety PC nadal nie radzi sobie z tym dobrze bo w zależności od drivera i systemu stworzenie każdego z tych zasobów może mocno zablokować rendering.
Myślę, że tutaj nie jest aż tak tragicznie. W jednym ze swoich programów przez przypadek co klatkę tworzyłem i ładowałem na kartę od nowa teksturę 512x512 i przez sporo czasu nawet tego nie zauważyłem (chociaż 512x512 to nie są ogromne ilości danych). Samo tworzenie zasobów można obejść tworząc ich pewną pulę i uploadując do nich nowe dane w razie potrzeby. Poza tym na procesorach jednordzeniowych tworzenie drugiego wątku i tak za wiele nie przyspieszy, więc odpowiednia implementacja powinna się obejść bez wątków i nie ucierpieć na tym zbyt wiele. :)

Cytuj
Jeśli podzielisz świat na szachownicę, to Mapa_5 będzie zawsze sąsiadować z 4 i 6. Nie musisz tego wczytywać :)
Nie zawsze jest tak prosto. Przykładowo, na kaflu Mapa_5 mogą znajdować się wejścia do innych lokacji, które wypadało by zacząć wczytywać jak nie ma nic innego do wczytywania, bo jak gracz będzie chciał wejść do danej lokacji, to może być już za późno na płynne wczytanie (przykład: Wiedźmin). ;)

Offline kacperz1

  • Użytkownik

# Kwiecień 19, 2008, 16:45:58
Wykonałem podane punkty (pisemnie bo nie modelowałem na razie terenu bo to już nie moja działka) ale nadal nie wiem jak wykonać odczytywanie sąsiednich kafli. Zastanawiam się czy zrobić to w pliku tekstowym czy może w tablicach.

Jak będzie stworzona mapa?
Naturalne proporcja w stylu trawa, człowiek, drzewo, budynek.

Jak będzie dzielona?
Dzielona na kafle o rozmiarach 100 na 100.
Jeżeli przy dzieleniu problemem będzie obiekt który stanie na drodze to zwiększamy rozmiar mapy do dzielenia.

Jak będzie wczytywana?
Pobieranie pozycji gracza i nazwę kafla na którym sie znajduje z bazy danych.
Wczytywane będą kafle map sąsiadujących z tą na której znajduje sie grac.
Stare kafle nie sąsiadujące już z aktualnym kaflem na którym jest gracz zostaną usunięte
z pamięci.

Offline SauRooN

  • Użytkownik

# Kwiecień 19, 2008, 17:10:50
Wczytywane będą kafle map sąsiadujących z tą na której znajduje sie grac.
Stare kafle nie sąsiadujące już z aktualnym kaflem na którym jest gracz zostaną usunięte
z pamięci.
Możesz bardzo zwiększyć wydajność systemu implementując wczytywanie kafli z predykcją (przewidując, które kafle prawdopodobnie będzie trzeba niedługo wczytać), a do wyładowywania wykorzystać histerezę (nie wyładowywać kafli natychmiast po stwierdzeniu, że są niepotrzebne (niewidoczne), tylko np. po odejściu od nich na jakąś większą odległość).

Offline Syriusz

  • Użytkownik

# Kwiecień 19, 2008, 17:23:10
Cytuj
Dzielona na kafle o rozmiarach 100 na 100.
To będzie gra 2D ???