Ruchoma kamera w OpenGL

Zapewne nie raz widząc grę w której gracz wciela się w rolę bohatera biegającego po trójwymiarowej mapie zastanawiałeś(-łaś) się w jaki sposób komputer sobie radzi z wyświetlaniem tej całej grafiki, zmienianiem położenia kamery i tak dalej… Tym razem zająłem się zagadnieniem czym jest ruchoma kamera w OpenGL.

W tym artykule chciałbym zająć się uproszczoną wersją tego problemu czyli skupić się na kamerze (poruszaniem obiektów w czasie rzeczywistym zajmę się w niedalekiej przyszłości przy okazji pisząc większy projekt). Aby niepotrzebnie nie komplikować sprawy kamera będzie poruszać się w jednej płaszczyźnie – w prawo i w lewo, tak aby móc swobodnie oglądać wygenerowaną trójwymiarową planszę, oraz do przodu i do tyłu w zależności od naciśniętego klawisza (w – ruch do przodu, s – ruch do tyłu).

W pierwszej kolejności zajmiemy się wygenerowaniem mapy po której będzie się poruszać kamera. Stworzyłem do tego celu klasę Terrain przy użyciu szumu Perlina z biblioteki libnoise. Teren jest rozłożony na płaszczyźnie wyznaczonej przez osie x i y układu współrzędnych składowa z jest generowana przez wspomnianą bibliotekę. Klasa posiada jedną metodę draw() do rysowania wygenerowanych punktów wykorzystywanej podczas wywoływania funkcji renderującej scenę.

Kamerę obsługujemy przy użyciu funkcji gluLookAt() podając jej nowe parametry podczas zaprowadzania jakiejkolwiek zmiany (obrót lub poruszenie). Położenie kamery zaczynamy renderować od początku układu współrzędnych. Jedyną wartością, która jest odchyleniem to stała jej wysokość na osi z wynosząca 2, która nie będzie modyfikowana. Gdy zachodzi obrót kamery (po naciśnięciu lewego przycisku myszki i wykonaniu przesunięcia) zmieniana jest wartość kąta (zmienna angle) o ilość pikseli pomnożonej przez dobrany empirycznie współczynik obrotu. Następnie są obliczane wartości nowego punktu (aim[0] i aim[1]) na który ma być zwrócona kamera i z nowymi wartościami wywoływana jest funkcja gluLookAt(). W przypadku gdy dokonywany jest ruch przy użyciu klawiatury – brany jest pod uwagę kierunek kamery i obliczane są nowe współrzędne jej położenia (eye[0] i eye[1]) i dodawane są do obecnego położenia, po czym wywoływana jest funkcja gluLookAt() z nowymi współrzędnymi.

Od tego wpisu nie będę już umieszczał kodu w bloczku, który był w dwóch poprzednich postach. Za to umieszczę bezpośredni link do projektu w serwisie github.com, który nieco ułatwi mi pracę nad ewentualnymi nowszymi wersjami, a skąd można go sobie łatwo pobrać.

https://github.com/lnkoc/terrain_demo

Jeśli się rozejrzysz, z pewnością zauważysz, że również znajdują się tam pozostałe projekty.

PS. Jeśli chcesz skorzystać z biblioteki libnoise proponuję jej forka, zaktualizowanego pod współczesne systemy linux (wymaga zainstalowanego cmake): https://github.com/qknight/libnoise

Model jajka w OpenGL

egg multicolor

W niniejszym wpisie przedstawię jak można stworzyć model jajka w OpenGL, naturalnie językiem, w którym jest napisany poniższy kod jest c++.

Kod zawiera klasę Egg, w której konstruktor tworzy dwuwymiarową tablicę dwu-punktów n na n w przedziale od 0 do 1. Oraz tablicę kolorów wypełnioną pseudolosowymi wartościami. Następnie jest tworzona tablica położeń trój-punktów (każda współrzędna – kolejno x, y, z) przy użyciu przekształceń matematycznych (słowem kilka ciekawych wzorów) z każdego elementu tablicy dwu-punktów.

Jeśli już przeglądałeś(-łaś) kod zapewne zauważyłeś(-łaś), że jest w nim wiele zmiennych globalnych, wszystkie oczywiście są używane, a na chwilę obecną uwagę skupmy na jednej z nich mianowicie – model. Zmienna ta jest odpowiedzialna za rodzaj obrazu, jaki będzie finalnie rysowany. Sam obiekt Egg zawiera tylko listę punktów, a to co zostanie wyświetlone zależy właśnie od tej zmiennej. Do wyboru mamy kilka opcji, mianowicie: zbiór punktów, siatkę trójkątów, siatkę wypełnionych trójkątów z wektorami normalnymi (dla niewtajemniczonych wektor normalny to w skrócie wektor prostopadły o długości równej 1 do tzw. powierzchni, w tym przypadku jest to zbiór wektorów prostopadłych do naszego jajka w każdym z punktów, który jest rysowany, po co nam to, napiszę za chwilę), oraz siatkę wypełnionych trójkątów z nałożoną teksturą i obliczonymi wektorami normalnymi.

Program po skompilowaniu i uruchomieniu ma kilka ciekawych efektów dostępnych w OpenGL.  Jednym z nich jest obsługa klawiatury (wybranych przycisków zmieniających parametry wyświetlanego obrazu) oraz obsługa myszki. A jeśli nic nie jest w danym momencie wykonywane jajko obraca się wokół własnej osi (a konkretnie osi y). Teraz może wspomnę o klawiaturze, obsługiwane przyciski to:

  • p – wyświetlenie punktów z których składa się jajko
  • w – wyświetlenie jajka jako siatki trójkątów (połączone przy użyciu linii)
  • t – wypełnienie białymi trójkątami siatki trójkątów
  • s – wyświetlenie wypełnionych, kolorowanych trójkątów
  • i – włączenie/wyłączenie wyświetlania tekstury na jajku wraz z włączeniem światła białego
  • l – włączenie/wyłączenie oświetlenia białego
  • 1 (jeśli włączone jest światło białe lub niebieskie) – przełączenie źródła światła na czerwone lub wyłączenie
  • 2 (jeśli włączone jest światło białe lub czerwone) – przełączenie źródła światła na niebieskie lub wyłączenie

Teraz może wspomnę o obsłudze myszki. Jeśli naciśniemy lewy przycisk i przesuniemy urządzenie możemy obracać kamerą wokół. Wymaga to nieco wprawy ponieważ zastosowałem tutaj sferyczny układ odniesienia (zmianie ulegają kąty theta i fi), tak aby można było zobaczyć jajko z każdej strony. W zasadzie to jest wszystko co miałbym do napisania, na ten temat, ale zostawiłem jeszcze małą niespodziankę na koniec. Obsługa prawego przycisku myszki pozwala na poruszanie źródłem światła (ostatnio włączonym) po całej sferze wokół obiektu. Można zatem włączyć światło niebieskie i ustawić jego położenie, a następnie włączyć światło czerwone i również ustawić jego położenie.

A tutaj zamieszczam kod:

Ostatnia rzecz, o której chciałem wspomnieć to model oświetlenia jaki został wybrany nazwany jest modelem oświetlenia Phonga. Wybrałem go ponieważ daje on możliwie najbardziej zbliżone efekty do zwykłego oświetlenia.

egg points

egg textured

egg lights

Dywan Sierpińskiego w c++ OpenGL

Poniższy kod w języku c++ umożliwia wygenerowanie dywanu Sierpińskiego trzeciego stopnia przy użyciu biblioteki OpenGL. Oczywiście, jak po analizie kodu będzie można łatwo zauważyć, owy stopień można niemal dowolnie zmodyfikować.

Przed kompilacją należy pamiętać o dodaniu bibliotek glut (The OpenGL Utility Toolkit). U mnie wymagało to dodania wpisów „-lGL -lGLU -lglut” przy wywoływaniu g++ w środowisku programistycznym.

Powyższy kod nie jest powalająco złożony. W skrócie tworzenie dywanu polega na podzieleniu każdego kwadratu na dziewięć części i usunięcie środkowego elementu w każdej iteracji. Można zatem swobodnie ustawić liczbę iteracji na np. sześć i podziwiać uzyskany efekt.

Sierpinski carpet

Witaj, świecie!

Witajcie w WordPressie.

I stało się. Postanowiłem stworzyć bloga o moich pomysłach i potyczkach z szeroko rozumianym programowaniem. Na chwilę pisania tego tekstu tworzę co nieco w c++ i OpenGL’u (z rozszerzeniem GLUT) na platformie Linux. W najbliższych dniach postaram się zamieścić nieco więcej i konkretniej (czytaj z kodem źródłowym), a na chwilę obecną zajmę się początkami konfiguracji WordPress’a.