Wokselowe szczyty

Nie wiem czy długo oczekiwany, ale na pewno kolejny post na temat mojego projektu jakim jest generator światów z wokseli.

07.05.2018 23:00 WorldGen

No, a przynajmniej jej niewielka część. Wprawdzie do przeżycia pełnej wokselowej przygody, takiej podobnej do tej, którą możesz "przeżyć" w Minecrafcie jest jeszcze daleko, ale przynajmniej podziwianie wokselowego terenu w mojej aplikacji jest już możliwe.

Bardzo dużo czasu minęło od kiedy napisałem poprzedni post na temat mojego generatora. Byłem dosyć zajęty, dodatkowo jeszcze były te problemy ze stroną, przez co nie miałem za bardzo nawet jak napisać kolejnego postu. Od tamtego momentu w sumie wiele zmieniło się już w moim programie. Dodałem bardzo dużo funkcji, a wiele już istniejących rzeczy uległo znacznej zmianie.

Ja sam jestem zdania, że ten projekt jest już praktycznie gotowy, ponieważ spełnia funkcje, które założyłem i działa dostatecznie stabilnie. Nie chcę jednak jeszcze dodawać go jako gotowy projekt tutaj na moją stronę, ponieważ być może będą konieczne jeszcze jakieś drobne zmiany, które pewnie nie wpłyną za bardzo na ogólne działanie projektu, ale jednak to nadal jakieś dodatkowe zmiany. Jeśli nie możesz się już doczekać tego, żeby pobrać i zobaczyć mój program, to niestety będziesz musiał na to jeszcze trochę poczekać XD

Jak już napisałem projekt został znacznie zmieniony od czasu kiedy prezentowałem go po raz ostatni. W tym poście chciałbym napisać co nowego zostało dodane oraz co zostało zmienione. Tak więc usiądź wygodnie i przygotuj się na zaawansowane zmiany :P

Chyba pierwszą i od razu widoczną nowością w stosunku do poprzedniej wersji jest dodanie graficznego interfejsu. Być może na pierwszy rzut oka interfejs nie wydaje się bardzo zaawansowany, ale tak naprawdę napisałem solidną podstawę, aby mógł zostać w przyszłości rozszerzony. Swoją drogą, w późniejszym etapie, mam zamiar wyodrębnić ten interfejs jako niezależną bibliotekę. W podobny sposób powstał mój projekt ConfigLib (chociaż nie do końca identyczny, tamten projekt był już samodzielny, napisany na zajęcia na studiach), który całkiem fajnie się rozwinął, a może rozwinę go jeszcze bardziej.

Następną zmianą jest ogólna metoda generowania świata. W jednym z poprzednich postów na temat mojego generatora wyjaśniałem w jaki sposób różne parametry szumu wpływają na wygenerowaną rzeźbę terenu. Wszystkie tamte spostrzeżenia były jak najbardziej trafne, natomiast generowany w ten sposób teren był bardzo monotonny. Kiedy generowane były góry, ciągnęły się one aż po horyzont i tak naprawdę jeszcze dalej. To oczywiście nie było zbytnio pożądane, tak więc trzeba było znaleźć sposób na połączenie różnych typów szumu w teren. Nie było to jednak takie łatwe, ponieważ trzeba było mieć na uwadze to, że teren powinien być także ciągły i nie mogłem dopuścić do tego, aby zaraz za wysokimi górami nagle teren zapadał się bardzo głęboko tworząc wielką pionową ścianę. Dlatego właśnie musiałem wymyślić trochę inny sposób w jaki ostateczny teren byłby generowany. Z pomocą przyszedł mi jeden artykuł z czasopisma Programista (haha, ten o silniku wokselowym oczywiście). Wprawdzie przedstawiony tam algorytm nie był zbyt wydajny i nie nadawał się na rzecz mojego generatora w czasie rzeczywistym, ale dał mi pewien pomysł w jaki sposób można wygenerować w miarę ciekawy i zróżnicowany teren, bez dziwnych łączeń na krawędziach.

Kolejną zmianą, może mało widoczną, ponieważ za mało regularnie publikowałem moje postępy, było zgłaszanie postępu przez wątki. W poprzedniej wersji nie było to zbyt dobrze dopracowane co skutkowało dziwnymi zachowaniami, takimi jak cofanie się postępu (tak, też nie mam pojęcia jakim cudem...), albo mała stabilność programu (czasem przestawał działać, chociaż działo się to rzadko). Dzięki nowemu rozwiązaniu program działa dużo stabilniej i bardziej przewidywalnie, a dodatkowo dodałem jeszcze możliwość anulowania generacji świata. Ta możliwość była już wcześniej przewidziana, ale jakoś nie miałem weny, żeby ją ostatecznie zaimplementować, a jako, że przerabiałem akurat postęp wczytywania, tak więc była to dobra okazja, żeby zaimplementować także tą funkcję. A jest ona całkiem przydatna, szczególnie kiedy przez przypadek ustalimy rozmiar kawałka świata na 256 i zasięg widzenia na 10 :D

Ostatnią nową funkcją, o której chciałbym jeszcze wspomnieć, jest możliwość edycji niektórych opcji z poziomu graficznego interfejsu i dużo nowych opcji w pliku konfiguracyjnym.

Tak naprawdę dokonałem bardzo wielu zmian w międzyczasie, ale nie o wszystkich jest po co pisać (bo np. są bardzo niewielkie), a dodatkowo nie miałbym tyle czasu żeby je wszystkie opisać. Być może nie wiecie, ale takie pisanie postów trochę jednak zajmuje, a patrząc na to, że mam jeszcze sporo innych rzeczy do zrobienia, nie zawsze (czytaj, rzadko kiedy) znajduję czas, żeby napisać coś nowego. W wolnym czasie lubię się dużo ruszać, chodzę na rower, albo na rolki no i jeszcze codziennie ćwiczę, więc niestety już to ogranicza znacznie moje zasoby czasowe. Niemniej jednak postaram się znaleźć trochę czasu na napisanie czegoś nowego.

Tak jak napisałem jedną z łatwych do zauważenia nowości jest graficzny interfejs użytkownika (GUI od angielskiego Graphics User Interface). Interfejs który napisałem jest na razie bardzo prosty, praktycznie składa się jedynie z podstawowych kształtów wypełnionych jednolitym kolorem. To, że wygląda tak, a nie inaczej ma jednak swoje plusy, np. taki interfejs jest bardzo czysty i przejrzysty.

W rzeczywistości jednak napisałem bardzo solidną podstawę pod bardziej zaawansowany interfejs użytkownika. Cały silnik, który zarządza interfejsem jest skonstruowany tak, aby mógł radzić sobie nawet z bardzo bogatym interfejsem. Obsługiwane jest przycinanie kontrolek do określonych rozmiarów, przewijanie obszaru kontrolki (aby można było np. wpisać więcej tekstu niż mieści się w jednej linijce pola tekstowego), a także zastosowane są optymalizacje rysowania kontrolek. Optymalizacje te polegają na tym, że zamiast odrysowywać cały interfejs gdy jakaś kontrolka zmienia stan, odrysowywany jest tylko ten fragment w którym zaszła zmiana. W przypadku symulacji w której i tak interfejs musi być rysowany za każdym razem na nowo nie daje to wielkich korzyści, ale silnik interfejsu graficznego pozwala także rysować go na teksturę, którą później można wykorzystać rysując ją na ekranie wielokrotnie.

Jeśli rozbudziłem waszą ciekawość opisując te wszystkie super funkcje interfejsu, to teraz przydałoby się coś zaprezentować. No i oczywiście zaprezentuję, ale pewnie nie będziecie zbytnio zachwyceni jako, że tak jak napisałem kontrolki są w miarę proste więc efekt nie jest powalający, jednak zawsze lepiej prezentuje się aplikacji ze swoim własnym interfejsem niż bez. Oto interfejs graficzny jakim dysponuje mój generator aktualnie:

Kolejną wymienioną zmianą było generowanie świata. Poprzednio świat był generowany z pojedynczego szumu, ewentualnie ze zsumowanych wielu jego oktaw. Tamto rozwiązanie w pewien sposób przetrwało, ale jednak ostatecznie teren generowany jest trochę inaczej.

Główna różnica polega na tym, że zamiast generować od razu ostatecznego terenu z szumu, tak naprawdę generuje kilka różnych szumów, które następnie są składane w ostateczny teren. Każdy z wygenerowanych szumów odpowiada za coś innego. Jedne szum odpowiada np. za ogólną bazową wysokość terenu. Inny odpowiada za ilość szczegółów jakie otrzyma teren, a jeszcze kolejny jest generowany, aby użyć go jako szczegóły dodawane do terenu. Dzięki zastosowaniu takiej metody teren staje się dużo bardziej atrakcyjniejszy, a dodatkowo nie jest już taki monotonny. Dzięki temu, że o ilości szczegółów decyduje także wartość szumu, nie występują już problemy na łączeniach różnych obszarów, ponieważ wartości szumu zmieniają się płynnie. Tutaj możecie zobaczyć część świata wygenerowanego przy użyciu nowego algorytmu:

Ostatnią nowością, którą opiszę trochę szerzej są jeszcze opcje programu. Wraz z graficznym interfejsem pojawiła się możliwość dodania opcji do zmieniania z poziomu programu (wcześniej opcje też były, ale jedynie w pliku konfiguracyjnym). Niestety interfejs graficzny nie ma zaimplementowanych bardziej wymyślnych kontrolek, dlatego z poziomu programu można zmieniać tylko niektóre najważniejsze opcje.

Tak więc z poziomu programu można zmieniać wszystkie opcje związane z grafiką (rozdzielczość, tryb pełnoekranowy, albo nie, synchronizacja pionowa itp.). Można także zmieniać główne ustawienia wpływające na "doznania", to znaczy, rozmiar pojedynczego kawałka świata, zasięg widzenia oraz dodatkowo można także zażyczyć sobie, aby program nie dopuszczał latających wokseli.

Opisane opcje są dostępne z poziomu interfejsu w programie natomiast w pliku konfiguracyjnym jest o wiele więcej różnych opcji. Można tam zmienić takie rzeczy jak kierunek padania światła, kolor światła, kolor mgły, gęstość mgły, oraz masę dodatkowych ustawień, które kontrolują algorytm generowania świata. Ekran interfejsu opcji możecie podziwiać ;P poniżej:

Myślę, że seria postów poświęcona temu projektowi powoli dobiega końca. Projekt uznaję już praktycznie za gotowy i ewentualnie wprowadzę do niego jeszcze kilka niewielkich modyfikacji.

Wydaje mi się także, że nie będę już dalej rozwijał tego projektu samego w sobie. Na początku miałem duże plany związane z tym projektem, ale niestety trochę zmieniłem podejście i chyba nie będę mógł go wykorzystać. Głównie wynika to z faktu iż sam w sobie generator jest całkiem dobry, ale niestety jego struktura mało pasuje do silnika gry. Ciężko byłoby wszystko odpowiednio połączyć i dlatego i tak musiałbym pewnie sporą część pisać od nowa. Tak czy inaczej napisanie takiego generatora dało mi dużo bardzo ważnego doświadczenia. Zaznajomiłem się z wieloma różnymi podejściami oraz popracowałem z wielowątkową aplikacją, wszystko to pozwoli mi napisać o wiele lepszą wersję takiego silnika kiedy będę tego potrzebował, albo po prostu miał na to ochotę ;)

Postaram się jeszcze w miarę możliwości pisać więcej postów na różne inne tematy, ale niestety wszystko zależy od mojego czasu i nastroju. O moim nastroju mógłbym napisać cały oddzielny dział, ale nie wiem czy byłoby to takie dobre pisać to tutaj, a poza tym to raczej osobiste i mało obchodzące kogokolwiek. Na dzisiaj to tyle, ponieważ i tak zeszło mi się już bardzo długo, a muszę jeszcze przecież poćwiczyć :)