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