Symulacja samochodu z kamerą stereowizyjną
Transkrypt
Symulacja samochodu z kamerą stereowizyjną
Symulacja samochodu z kamerą stereowizyjną
Krzysztof Sykuła
15 czerwca 2007
1
1
Opis wykonanego projektu
Symulacja samochodu z kamerą stereowizyjną była pretekstem do napisania Engine’u 3D, wykorzystującego openGl przy pomocy którego w szybki i
intuicyjny sposób, można byłoby tworzyć wizualizacje rożnych problemów z
dziedziny robotyki. Engine napisany został w javie co ma swoje wady i zalety,
niewątpliwie wadą jest szybkość działania takiego Engine’u lecz gdy uznamy,
że nie chcemy stworzyć ultra realistycznej grafiki z realistycznymi cieniami
itd... to dostrzeżemy zalety w postaci wieloplatformowości takiej aplikacji.
Warunkiem uruchomienia mojej aplikacji lub tworzenia innej z wykorzystaniem mojego projektu jest posiadanie aktualnej wersji javy oraz biblioteki
jogl. Poniżej na rys1 zamieściłem screenshota stworzonej symulacji samochodu. Aby uruchomić aplikacje należy wpisać w linii komend : java -jar
symulator.jar.
Rysunek 1: Symulator samochodu.
2
2
Omowienie klas oraz etapów renderowania
obiektów 3D.
2.1
Diagram klas.
Poniżej przedstawiłem diagram ważniejszych klas oraz metod na które należy
zwrócić uwage, aby poprawnie tworzyć kolejne etapy renderowania obiektów
3D.
Transfolmowalny
Renderowalny
+renderuj()
Transformacje
GLEventListener
SterowanieMysza
AbsObiekt3D
+display()
+init()
+displayChanged()
+reshape()
AbsScena
+dodajTransformowalny()
+dodajPotomka()
+dodajObserwatora()
+renderujPotomkow()
+wlaczObserwatorow()
Obserwator
ZrodloSwiatla
Obserwowalny
Obiekt3D
+obserwuj()
Pojazd
Rysunek 2: Diagram klas.
2.2
Klasa AbsObiekt3D.
Klasa AbsObiekt3D jest klasą, po której dziedziczą wszystkie obiekty 3D,
będące elementami renderowanej sceny. Obiektem 3D jest beczka, źródło
3
światła a także kamera. Klasa AbsObiekt3D posiada wszystkie wspólne cechy obiektów 3D, a dziedzicząc po klasie Transformacje otrzymuje zestaw
metod służących do transformowania obiektu w przestrzeni 3D. We wszystkich klasach dziedziczonych po klasie AbsObiekt3D, należy przedefiniować
metode implementowaną z interfejsu Renderowalny.
2.2.1
Interfejs Renderowalny
Interfejs Renderowalny służy do implementacji rysowania danego obiektu
3D w charakterystyczny dla niego sposób. Wszystkie operacje na obiekcie 3D,
które chcemy zobaczyć na ekranie, powinny być umieszczane w metodzie
renderuj(), która jest implementowana z wyżej wspomnianym interfejsem.
Poniżej zamieszczam przykładowy kod z przedefiniowaną metodą renderuj.
public void renderuj(){
if (!niewidoczny) {
gl.glTranslatef(transX, transY, transZ);
gl.glRotatef(-rotY, 0, 1, 0);
gl.glRotatef(-rotX, 1, 0, 0);
gl.glRotatef(-rotZ, 0, 0, 1);
for (int j = 0; j ¡ model3D.pobierzIloscElementow(); j++) {
gl.glCallList(model3D.pobierzElement(j).pobierzTeksture()
.pobierzNrID());
gl.glCallList(model3D.pobierzElement(j).pobierzNrID());
}
renderujPotomkow();
gl.glRotatef(rotZ, 0, 0, 1);
gl.glRotatef(rotX, 1, 0, 0);
gl.glRotatef(rotY, 0, 1, 0);
gl.glTranslatef(-transX, -transY, -transZ);
}
}
Na początek należy zauważyć, że każdy niewidoczny obiekt nie jest renderowany w celu optymalizacji szybkości engine’u. Kolejna sprawa na którą
należy zwrócić uwagę to model3D, będący polem dziedziczonym po klasie
AbsObiekt3D. Model3D to obiekt klasy Model3D, opisujący obiekt 3D
wczytany z pliku wavefront obj. Każdy model3D składa się z elementów,
które mają przypisane listy wyświetlania openGl. Lokalny układ współrzędnych, każdego modelu 3D starałem się umieszczać w początku globalnego
4
układu współrzędnych, co ułatwia transformowanie w przestrzeni 3D. Dokładniejszy opis klasy Model3D znajduje się w dokumentacji.
Gdy już stworzymy obiekt 3D należy się zastanowić w jaki sposób chcemy
rysować jego i jego ewentualnych potomków. Można zrobić to w nastepujący
sposób:
1. Przesuwamy lokalny układ współrzędnych obiektu 3D
2. Rysujemy jego wszystkie elementy poprzez wezwanie list wyświetlania
openGl
3. Rysujemy potomków obiektu 3D względem jego obecnej pozycji
4. Przesuwamy lokalny układ współrzędenych obiektu 3D do pozycji początkowej
2.3
Klasa Obserwator
Główną klasą dziedziczoną po AbsObiekt3D jest Obserwator. Obserwator reprezentuje wirtualną kamerę, która jest skierowana na scene. Obserwator może być statyczny lub ruchomy. Wszystkie obiekty, które chcemy
narysować na scenie, łącznie ze sceną dodajemy jako potomków do obserwatora, a następnie uruchamiamy metodę renderuj(). Najważniejsze jest aby
pamiętać,o uruchomieniu obserwatora na samym początku kolejki renderowania tzn. nie możemy dodawać Obserwatora jako potomka do innego obiektu.
Obserwatora uruchamiamy tak, jak każdy inny obiekt dziedziczony po klasie
AbsObiekt3D metodą renderuj().
2.3.1
Obserwator statyczny
Prosty przykład użycia obserwatora to kamera statyczna, która jest ustawiona na stałe w dowolnym miejscu na scenie. W tej sytuacji wszystkie
obiekty łącznie ze sceną dodajemy jako potomków do obserwatora i uruchamiamy go metodą renderuj().
2.3.2
Obserwator ruchomy
Są przypadki w których chcemy aby jakiś ruchomy obiekt 3D był śledzony
przez kamerę, w takim przypadku musimy wykonać kilka operacji, które nam
to umożliwią, a są to:
1. Tworzymy nową klasę dziedziczoną po AbsObiekt3D i imlpementującą interfejs Obserwowalny którą nazwiemy SledzonyObiekt3D.
5
2. W metodzie obserwuj() implementowanej z interfejsu Obserwowalny
definiujemy sposób zachownia się obserwatora czyli to w jaki sposób
ma podążać za śledzonym obiektem 3D. W metodzie obserwuj, musi
się znajdować uruchomienie metody wlaczObserwatorow() dziedziczonej po AbsObiekt3D, która uruchomi wszystkich obserwatorów dodanych do śledzonego obiektu 3D. W tym przypadku nie używamy
metody renderuj() do uruchomienia obserwatora, jak to miało miejsce
w przypadku obserwatora statycznego.
3. Tworzymy obiekt klasy Obserwator i dodajemy go metodą dodajObserwatora() do śledzonego obiektu 3D.
4. Sledzony obiekt 3D uruchamiamy metodą obserwuj().
2.4
Klasa AbsScena
Klasa dziedziczona po AbsObiekt3D oraz implementująca interfejs GLEventListener. Klasę tą należy odziedziczyć i przedefiniować 5 metod tzn.
renderuj(), init(), display(), dispalyChanged() oraz reshape(). Należy zwrócić
szczególną uwagę na dwie metody pierwszą z nich jest init() w której inicjalizujemy wszystkie obiekty 3D oraz opcje renderowania w openGl. Druga
metodą jest display() w której uruchamiamy drzewo renderowania obiektów
3D rozpoczynając od korzenia, którym jest obiekt klasy Obserwator. Następnie obserwator uruchamia potomków lub jak kto woli liście.
2.5
Klasa ZrodloSwiatla
To klasa reprezentyjąca openGl’owe światła, obiekt tej klasy jak każdego inny
obiekt klasy AbsObiekt3D dodajemy jako potomka do sceny albo do innego
obiektu, może być to ruchomy obiekt. Opisy wszystkich metod operujących
na tej klasie znajdują się w dokumentacji.
2.6
Klasa Obiekt3D
Klasa reprezentuje dowolny statyczny obiekt 3D z typowymi własnościami
oczywiście klasa może być przedefiniowana i reprezentować jakiś charakterystyczny obiekt.
6
3
Wnioski i uwagi do projektu
Napisany przeze mnie engine 3D jest fazie rozwoju. W przyszłości chcę go
udoskanalać o takie elementy jak np. wykrywanie kolizji i realistyczne cienie.
Literatura
[1] Java. Tworzenie gier. David Brackeen, Bret Barker
[2] OpenGl. Księga eksperta. Richard S. Wright, Michael Sweet.
7