Grafika 3D w Visual Basic'u

   Opiszę tutaj, jak w Visual Basic'u tworzyć grafikę 3D z wykorzystaniem gotowego enginu. Bez niego byłoby to bardzo trudne, a tak możemy łatwo i stosunkowo szybko zrobić np. grę FPP. W Sieci można znaleźć parę dobrych enginów 3D do VB w postaci kontrolek, ale najbardziej spodobała mi się kontrolka TrueVision3D. Można ją ściągnąć ze strony http://www.truevision3dsdk.com. Oprócz samego enginu na stronie jest też m.in. engin do dźwięku, a także mnóstwo sampli, tutoriali i narzędzi. Kontrolka jest szybko rozwijana i często wychodzą nowe wersje. W chwili pisania artu była dostępna wersja 4.9b, ale to co tu opiszę będzie działało i na starszych wersjach, np. 3.7. Kontrolka wymaga zainstalowanego DirectX 8. Żeby skorzystać ze strony trzeba się najpierw zarejestrować. Jest to darmowe i sprowadza się do wypełnienia formularza. Możemy też wybrać płatną rejestrację otrzymując m.in. dostęp do pomocy technicznej. Kontrolkę można też ściągnąć ze strony http://www.grzegorz.net. Po ściągnięciu ZIP-a z kontrolką trzeba go rozpakować do jakiegoś foldera. Lepiej sobie zrobić nowy folder specjalnie dla kontrolki, w którym będziemy też trzymać sample, tutoriale i dokumentacje. Teraz trzeba zarejestrować kontrolkę. Jest do tego specjalny plik. W wersji 4.9 nazywa się on Register Engine.bat. Po uruchomieniu go kontrolka zostaje zarejestrowana w systemie i możemy odpalić VB. Po utworzeniu nowego projektu udajemy się do menu Project i wybieramy References... Z listy wybieramy TrueVision 3D DX8 v4.9b engine for Visual Basic. Teraz możemy zacząć pisać kod. Opiszę tutaj jak zrobić powierzchnię, po której można chodzić i niebo. Kontrolka zawiera kilka obiektów, których zmienne musimy zadeklarować. W sekcji General formy deklarujemy zmienne:

Public TV As TrueVision8
Public Scene As Scene8
Public Land As Landscape8
Public Inp As InputEngine8
Public Scr As Screen8
Public TexFactory As New TextureFactory8
Public PosX As Single, PosY As Single, PosZ As Single, Ang As Single, AngY As Single, MX As Long, MY As Long
Public Camera As New Camera8
Dim GCamera(2) As CameraGravity
Public Effects As New GraphicEffect8
Dim blnKoniec As Boolean
Dim blnRender As Boolean
Dim b1 As Integer
Dim b2 As Integer

Teraz przenosimy się do kodu formy, do zdarzenia Form_Load(). Tworzymy nowe obiekty:

Set TV = New TrueVision8
Set Scene = New Scene8
Set Land = New Landscape8
Set Scr = New Screen8

Wyłączamy konsolę

TV.Console = False

Ustawiamy tytuł okna

TV.SetWindowTitle "Aplikacja 3D"

Wyświetlenie okienka, w którym można wybrać mi.in. rozdzielczość. Jjeśli klikniemy na Cancel, to program zakańcza się.

If TV.ShowDriverDialog = False Then End

Inicjalizacia i tworzenie obiektów

TV.Initialize
Set Inp = New InputEngine8

Wszystkie tekstury i inne pliki będą wczytywane z jednego foldera. Ustawiamy go np tak:

TV.SetSearchDirectory App.Path & "\pliki"

Teraz wczytujemy tekstury:

TexFactory.LoadTexture "powierzchnia.jpg", "Powierzchnia"
TexFactory.LoadTexture "szczeg.jpg", "Szczegoly"
TexFactory.LoadTexture "niebo1.jpg", "Niebo1"
TexFactory.LoadTexture "niebo2.jpg", "Niebo2"
TexFactory.LoadTexture "niebo3.jpg", "Niebo3"
TexFactory.LoadTexture "niebo4.jpg", "Niebo4"
TexFactory.LoadTexture "niebo5.jpg", "Niebo5"
TexFactory.LoadTexture "dolne.jpg", "Dolne"

Czyścimy ekran.

TV.Clear

Teraz tworzymy powierzchnię. Może być ona płaska lub pagórkowata. Jeśli ma być płaska, jako pierwszy parametr podajemy pusty ciąg. Jeśli pagórkowata, pdajemy nazwę pliku z mapą wysokości. A skąd wziąć taki plik? Bierzemy po prostu dowolny JPEG, ale nie kolorowy, tylko czarno-biały. Jaśniejsze miejsca są wyższe, a ciemniejsze niższe. Stąd wniosek, że do zmian ukształtowania terenu będziemy używać dowolnego edytora grafiki. W przykładzie teren jest pagórkowaty i wysokość jest wczytywana z pliku:

Land.GenerateHugeTerrain "wysokosc.jpg", TV_PRECISION_LOW, 1, 1, 0, 0, True

Drugi parametr określa precyzję. Prawie wszystko co wyświetla kontrolka, tworzy ona z trójkątów. Im większa jest precyzja, tym mniejsze są trójkąty. Obraz jest dokładniejszy (pagórki są bardziej zaokrąglone), ale karta graficzna ma więcej do liczenia i spada liczba klatek na sekundę (FPS). Następne 2 parametry określają wielkość powierzchni, póżniej są 2 określające przesunięcie powierzchni względem układu współrzędnych. Nie wiem dokładnie, jaka jest rola ostatniego parametru, ale ustawienie go na False powoduje wygładzanie szczytów niektórych pagórków i powstawanie ścian na 2 brzegach powierzchni.
Teraz wczytujemy teksturę dla powierzchni. Zawiera ona jednak tylko kolory większych obaszarów powierzchni.

Land.SetTexture GetTex("Powierzchnia")

Ustawiamy ile tekstur w jednym i drugim wymiarze ma przypadać na płaszczyznę.

Land.SetTextureScale 1, 1 'skala tekstury

Teraz pora na teksturę szczegółów, dla której też ustawiamy skalę.

Land.SetDetailTexture GetTex("Szczegoly")
Land.SetDetailTextureScale 15, 15

Teraz pora na niebo. Jak ono jest zrobione? Jest to 6 tekstur tworzących sześcian. Gdy kamera się porusza, to tak naprawdę porusza się powierzchnia, a kamera stoi w miejscu. Dzięki temu niebo pozostaje nieruchome. Szósta dolna tekstura widoczna jest wtedy, gdy wyjdziemy poza powierzchnię i popatrzymy w dół. Ostatni parametr określa odległość od nieba.

Scene.SetSkyTexture GetTex("Niebo1"), GetTex("Niebo2"), GetTex("Niebo3"), GetTex("NIebo4"), GetTex("Niebo5"), GetTex("Dolne"), 1500

Tą linijkę warto dodać, aby choć trochę "podkręcić" liczbę FPS.

Land.Optimize

Teraz ustawiamy początkowe współrzędne kamery i kąt patrzenia góra/dół. A co to jest -1.57? To jest w przybliżeniu -Pi/2, czyli -90 stopni.

GCamera(0).X = 50
GCamera(0).z = 50
AngY = -1.57

Włączamy wyświetlanie ilości klatek na sekundę.

TV.DisplayFPS = True

Rozjaśnianie widoku przez 2 sekundy

Effects.FadeIn 2000

A teraz wreszcie pętla wyświetlająca obraz:

Do
   ChangePos
   TV.Clear
   Scene.RenderSky
   Land.Render False, False
   TV.RenderToScreen
   If Inp.IsKeyPressed(TV_KEY_ESCAPE) = True Then
      Scene.SetRenderMode TV_SOLID
      blnKoniec = True
      Effects.FadeOut 2500
   End If
Loop Until Effects.FadeFinished = True And blnKoniec = True
Set TV = Nothing
End

Najpierw wywoływana jest procedura odpowiedzialna za przemieszczanie kamery i reakcję na naciskanie klawiszy. Zostanie ona omówiona w drugiej części arta. Następnie czyszczony jest ekran, wyświetlane niebo i powierzchnia. Dzieje się to tylko w pamięci karty graficznej i dopiero następna linijka powoduje faktyczne wyświetlenie obrazu. Pętla jest zakańczana po naciśnięciu Esc. Wcześniej następuje ściemnianie obrazu.Po ściemnieniu program zakańcza się.
To tyle w tym odcinku. Źródło omawianej tu prostej aplikacji wykorzystujące kontrolkę TrueVision3D jest dołączone do VBM. Jeśli źródło nie będzie chciało się uruchomić(będzie wyskakiwał błąd), to prawdopodobnie trzeba zaznaczyć kontrolkę w Project|References i odznaczyć pozycję rozpoczynającą się do MISSING. Kontrolka może też nie działać, jeśli nie ma zainstalowanego DirectX 8. Kto chce, może przeanalizować całe źródło i spróbować je modyfikować. Warto wcisnąć F2 w VB i obejrzeć dostępne właściwości, metody, zdarzenia i funkcje kontrolki. W drugiej części omówię wyświetlanie ścian innych podobnych elementów.

Grzegorz Niemirowski
grzegorz@grzegorz.net
www.grzegorz.net