2012-02-16 11 views
8

Mam prostą grę, która używa 3D reprezentacji siatki, coś jak:3D Gra Geometria

Blocks grid[10][10][10]; 

Osoba w grze jest reprezentowana przez punkt i wektor widok:

double x,y,z, dx,dy,dz; 

narysować siatkę z 3 zagnieżdżonej pętli:

for(...) for(...) for(...) 
    draw(grid[i][j][k]); 

oczywistym problem polega na tym, gdy rozmiar siatki rośnie w hun dreds, fps dramatycznie spada. Z pewną intuicję, zdałem sobie sprawę, że:

  • bloków, które zostały ukryte przez inne bloki w sieci nie muszą być świadczone
  • bloków, które nie były w polu wizyjnym osoby również nie muszą być świadczone (np. bloki, które były za osobę)

Moje pytanie jest, biorąc pod uwagę grid[][][], osoby x,y,z, a wzrok wektor dx,dy,dz, w jaki sposób mogę dowiedzieć się, które potrzebują bloki mają być świadczone, a które don” t?

+1

Jest to dość ogromny temat, objęty również [Wykrywaniem ukrytych powierzchni] (http : //en.wikipedia.org/wiki/Hidden_surface_determination). –

+4

Jeśli używasz biblioteki OpenGL lub dowolnej innej biblioteki 3D, robi to automatycznie _culling_ w ostatecznym renderowaniu. – toto2

+0

Więc jeśli używam OpenGL, to dodanie optymalizacji geometrycznej nie wpłynie na ogólną wydajność? –

Odpowiedz

7

Przyjrzałem się korzystaniu z silnika gier 3D JMonkeyEngine i przyglądałem się niektórym technikom, które stosują. Z tego co pamiętam, używają czegoś, co nazywa się ubojem. Budują strukturę drzewa wszystkiego, co istnieje w "świecie". Pomysł polega na tym, że masz podzbiór tego drzewa, który reprezentuje widoczne obiekty w danym momencie. Innymi słowy, są to rzeczy, które należy oddać. Powiedzmy na przykład, że mam pokój z przedmiotami w pokoju. Pokój jest na drzewie, a przedmioty w pokoju są dziećmi drzewa. Jeśli jestem poza pokojem, to przycinam (usuwam) tę gałąź drzewa, co oznacza, że ​​jej nie renderuję. Powodem, dla którego to działa tak dobrze, jest to, że nie muszę oceniać KAŻDEGO obiektu na świecie, aby zobaczyć, czy powinien on być renderowany, ale zamiast tego szybko przycinam całe części świata, o których wiem, że nie powinny być renderowane.

Jeszcze lepiej, gdy wchodzę do pokoju, przycinam całą resztę świata z drzewa, a następnie oddaję pokój i wszystkich jego potomków.

Myślę, że wiele decyzji projektowych, które zespół JMonkeyEngine stworzył, było oparte na książce Davida Eberly'ego, 3D Game Engine Design. Nie znam szczegółów technicznych, jak wdrożyć takie podejście, ale założę się, że ta książka byłaby dla ciebie świetnym punktem wyjścia.

Oto ciekawy article na kilku różnych algorytmów uboju:

  • Zobacz ściętego uboju
  • Back-face ubojów sanitarnych
  • opartych na komórkach okluzji uboju
  • PVS oparte dowolna geometria okluzji uboju
  • Inne
+0

"W naiwnej wersji tego algorytmu każdy obiekt na świecie jest testowany pod kątem sześciu płaszczyzn." Jak mam wdrożyć coś takiego? Nie jestem szczególnie zainteresowany złożonymi strukturami ósemkowymi itp. –

+3

Jeśli nie jesteś zainteresowany wdrożeniem tego, co jest uważane za standardowe podejście do problemu opisanego w pytaniu, możesz chcieć dostosować swoje wysiłki. Zamiast próbować zrobić to sam, użyj biblioteki. Jest mnóstwo w C++ i wiem, że jednym z najlepszych Javy jest JMonkeyEngine (który mam powyżej). – jbranchaud

1

Najpierw potrzebujesz przestrzennej struktury partycjonowania, jeśli używasz jednolitych rozmiarów bloków, prawdopodobnie najbardziej efektywną strukturą będzie octree. Następnie musisz napisać algorytm, który może obliczyć, czy pole znajduje się po określonej stronie (lub przecina) płaszczyzny.Kiedy już to zrobisz, możesz dowiedzieć się, które węzły liści ośmiornicy znajdują się w sześciu bokach twojego widoku - to jest , widok odstający. Korzystając z ósemki, możesz określić, które bloki blokują inne (czasami nazywane frustum maskujące), ale pierwsza część działa pierwsza.

1

Wygląda na to, że wybierasz się na coś typu minecraft-y. Spójrz na this android minecraft level renderer. Należy zwrócić uwagę na następujące elementy:

  • Trzeba tylko rysować ściany bloków, które są współużytkowane z przezroczystymi blokami. np .: nie przejmuj się rysowaniem twarzy pomiędzy dwoma nieprzezroczystymi blokami - gracz nigdy ich nie zobaczy.
  • Prawdopodobnie zechcesz podzielić widoczną geometrię bloku na fragmenty (i wstawić ją do VBO) i określić widoczność dla poszczególnych porcji. Odszukanie dokładnie, które bloki można zobaczyć, zajmie prawdopodobnie więcej czasu niż rzucenie VBO na GPU i zaakceptowanie przekroczenia.
  • Wypełnienie dobrze sprawdza się, aby określić, które kawałki są widoczne - ograniczyć wypełnienie za pomocą widoku punktu ścięcia, kierunku widoku (jeśli masz do czynienia w kierunku + ve x, nie zalewaj w kierunku -ve) i proste analizy danych porcji (np. jeśli cała twarz porcji jest nieprzezroczysta, nie przelewaj przez tę twarz)
+0

Dzięki, wypełnienie powodzi działa niesamowicie dobrze! –