Doc. dr inż. Jacek Jarnicki Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej jacek.jarnicki@pwr.wroc.pl Techniki wizualizacji Ćwiczenie 9 System POV-ray - wprowadzenie Celem ćwiczenia jest zapoznanie się z technologią generacji obrazów scen 3-D metodą śledzenia promieni (ray-tracing) w programie POV-ray (www.povray.org): Rozważane będą następujące zagadnienia: układ współrzędnych 3-D, orientacja osi układu, obroty wokół osi transformacje elementarne, translacja, skalowanie, obrót wokół osi składanie transformacji inicjalizacja zmiennych i realizacji pętli programowej budowa modeli złożonych obiektów geometrycznych przy pomocy konstrukcyjnej geometrii bryłowej (CSG) definiowania własnych obiektów geometrycznych 1. Uruchomienie programu POV-ray, pierwszy przykład generacji obrazu sceny 3-D Skopiować do utworzonego wcześniej folderu roboczego plik Scena_1.pov Uruchomić program POV-ray. Przy pomocy polecenia File > Open File >.../Scena_1.pov wczytać opis tekstowy sceny (jest to pewien program napisany w specyficznym języku opisu sceny) do pola edytora programu POV-ray. Obejrzeć (bez zbytniego zwracania uwagi na zrozumienie tekstu) treść wczytanego opisu sceny (programu). Wykonać polecenie Render > Start Rendering lub nacisnąć przycisk Run (oznaczony biegnącym człowieczkiem). Zaobserwować efekt wykonanego polecenia i spróbować skojarzyć wygląd wygenerowanego obrazu z tekstem opisu sceny umieszczonym w polu edytora. Zmienić w treści opisu sceny (edytując tekst przy pomocy typowych poleceń edycyjnych) linię pigment {color Red} na pigment {color Yellow}.
Ponownie nacisnąć przycisk Run i zaobserwować efekt. Zapisać wynik zmiany przy pomocy polecenia File > Save. W okienku z napisem 320x240, No AA (co oznacza, że generowany obraz ma rozmiar 320 na 240 pikseli i jest uzyskiwany bez zastosowania mechanizmu antyaliasingu), zmienić selekcję na 640 x 480, No AA i nacisnąć przycisk Run (rozdzielczość można zmienić również przez wykonanie polecenia Reneder > Edit Setings/Render i wpisanie w okienko Section odpowiednich parametrów rozdzielczości). Kolejny raz zmienić selekcję tym razem na 640 x 480, AA 0.3, nacisnąć przycisk Run i porównać uzyskany obraz z poprzednim. 2. Analiza treści opisu sceny Plik Scena_1.pov zawierający opis sceny, której obraz wygenerowano w poprzednim punkcie ma następującą treść i dla większej przejrzystości podzielony został na fragmenty, oznaczone różnymi kolorami. Funkcje jakie pełnią poszczególne fragmenty zostały opisane w formie komentarzy. #include "colors.inc" /* włączenie pliku zawierającego */ /* predefiniowane elementy sceny */ background { color Cyan } /* określenie koloru tła */ camera /* określenie pozycji obserwatora */ /* i sposobu patrzenia na obiekt */ { location <0, 2, -3> look_at <0, 1, 2> } sphere /* definicja obiektu */ { <0, 1, 2>, 1.5 texture{pigment { color Red }} } light_source { <2, 4, -3> color White} /* definicja oświetlenia sceny */ Dalsza analiza treści pliku z opisem sceny zostanie przeprowadzona w kolejnych punktach.
3. Włączanie do opisu sceny obiektów predefiniowanych Podany program zawiera komendę #include powodującą włączenie do treści opisu sceny elementów zdefiniowanych wcześniej i zapisanych w pliku z rozszerzeniem.inc. W tym przypadku jest to plik o nazwie colors.inc, w którym umieszczone zostały definicje różnych kolorów (wyrażone w modelu barw RGB). Niewielki fragment pliku colors.inc pokazano poniżej.... #declare Copper = color red 0.72 green 0.45 blue 0.20; #declare Bronze = color red 0.55 green 0.47 blue 0.14; #declare Bronze2 = color red 0.65 green 0.49 blue 0.24; #declare Silver = color red 0.90 green 0.91 blue 0.98; #declare BrightGold = color red 0.85 green 0.85 blue 0.10; #declare OldGold = color red 0.81 green 0.71 blue 0.23; #declare Feldspar = color red 0.82 green 0.57 blue 0.46; #declare Quartz = color red 0.85 green 0.85 blue 0.95; #declare Mica = color Black; // needed in textures.inc #declare NeonPink = color red 1.00 green 0.43 blue 0.78; #declare DarkPurple = color red 0.53 green 0.12 blue 0.47; #declare NeonBlue = color red 0.30 green 0.30 blue 1.00; #declare CoolCopper = color red 0.85 green 0.53 blue 0.10; #declare MandarinOrange = color red 0.89 green 0.47 blue 0.20;... Kolejne linie pliku są definicjami kolorów o podanych nazwach. Podane liczby oznaczają zawartości składowych R, G, B i są liczbami z przedziału [0, 1]. Jeśli plik colors.inc zostanie włączony do treści opisu sceny przy pomocy komendy #include "plik", to dalej zastosowanie danego koloru wymaga jedynie podania jego nazwy. Zmniejszyć rozdzielczość generowanego obrazu sceny, powracając do ustawienia 320 x 240, No AA. Zmienić w treści opisu sceny linię pigment {color...} wpisując nazwy kolorów podane w pokazanym wyżej fragmencie pliku colors.inc (np. Copper, Silver itd) i generować obrazy sceny obserwując jak zmienia się wygląd kuli. Obejrzeć zawartość pliku colors.inc 4. Określenie tła Tło zdefiniowane zostało w opisie przykładowej sceny przy pomocy komendy background {color Cyan}. Tło nie jest obiektem geometrycznym, lecz kolorem, którym wypełniane są punkty obrazu sceny nie związane z żadnym obiektem. Domyślny kolor tła jest kolorem czarnym. Zmienić w komendzie opisującej tło kolor na inny i zaobserwować efekt. Ustawić tło jako czarne (kolor domyślny) przez wstawienie znaków komentarza. Można to zrobić na dwa sposoby:
// background { color color} lub /* background { color color} */ Komentarz jest to fragment pliku opisu sceny (programu), który nie będzie miał żadnego wpływu na treść generowanego obrazu. W procesie generacji obrazu będzie on ignorowany. W pierwszym przypadku jako komentarz traktowany jest tekst od znaków // do końca danej linii. W drugim, tekst umieszczony pomiędzy sekwencją znaków /*...*/. W tym przypadku tekst komentarza może się składać z wielu linii. Komentarze służą do umieszczania w treści programu informacji zwiększających jego czytelność i powinny być często stosowane. W większych programach brak komentarzy jest dowodem niechlujstwa programisty, a nie jak się sądzi w niektórych kręgach tzw. informatyków przejawem profesjonalizmu. Wypróbować efekt działania komentarzy, zauważyć, że fragment, który jest komentarzem wyświetlany jest dla większej czytelności innym kolorem. 5. Określenie układu współrzędnych i sposobu patrzenia na scenę Układ współrzędnych używany w programie POV-Ray jest tzw. układem lewoskrętnym. Rys. 1. Lewoskrętny układ współrzędnych Orientację osi układu można wyobrazić sobie posługując się następującym przykładem. Jeśli na płaszczyźnie wyznaczonej przez osie x-y zostanie umieszczony ekran monitora, to oś z będzie swoim grotem wbijała się w ekran, czyli punkt o większej wartości współrzędnej z będzie położony dalej od ekranu. W układzie zdefiniowanym powyżej, opisywane będą dalej wszystkie obiekty geometryczne umieszczane na modelowanej scenie. Generacja obrazu
sceny 3-D wymaga prócz opisania samej sceny określenia sposobu jej obserwacji. Formalnie sprowadza się to do określenia sposoby rzutowania punktów z przestrzeni trójwymiarowej na płaszczyznę. W programie POV-Ray do określenia sposobu rzutowania służy komenda camera użyta w pokazanym wyżej, przykładowym programie w postaci: camera { } location <0, 2, -3> /* określenie pozycji obserwatora */ look_at <0, 1, 2> /* określenie sposobu patrzenia na obiekt */ Funkcje jakie pełnią opcje location i look_at wyjaśnia rysunek: Rys. 2. Parametry ustawienia kamery Opcja location< x, y, z > definiuje położenie w przestrzeni trójwymiarowej, punktu, w którym umieszczone jest ognisko obiektywu fikcyjnego aparatu fotograficznego mającego wykonać zdjęcie sceny. Opcja look_at< x, y, z > ustala natomiast punkt przez, który przechodzi oś obiektywu. Inaczej mówiąc location określa punkt, z którego obserwator patrzy na scenę a look_at punkt, na który patrzy. Wiedząc, że rysowanym obiektem jest kula o promieniu r = 1,5 i środku umieszczonym w punkcie (x, y, z) = (0, 1, 2) (patrz następna komenda opisu sceny) zmienić w kilkakrotnie parametry opcji location i look_at tak, aby nabrać pewnej wprawy w manipulowaniu położeniem kamery. Przećwiczyć takie umieszczanie kamery aby można było w sposób kontrolowany oddalać się od pokazywanej na rysunku kuli.
Sprawdzić co stanie się gdy kamera zostanie umieszczona wewnątrz kuli i na jej powierzchni. 6. Opis obiektu na scenie W przykładowym programie opisującym scenę pokazanym w punkcie 2 występuje tylko jeden obiekt. Jest nim sfera (powierzchnia kuli) o promieniu r = 1,5 i środku umieszczonym w punkcie (x, y, z) = (0, 1, 2). Komenda definiująca sferę ma następującą postać: sphere /* nazwa obiektu */ { <0, 1, 2>, 1.5 /* współrzędne środka i promień */ texture{ pigment { color Red }} } /* powierzchnia obiektu jest czerwona */ Współrzędne środka i promień opisują geometrię obiektu, natomiast komenda texture zawarta wewnątrz komendy sphere pozwala na opisanie charakterystyki powierzchni obiektu. W tym przypadku opis jest bardzo prosty, mówi jedynie, że powierzchnia sfery jest czerwona. Możliwe są oczywiście do zdefiniowania bardziej subtelne charakterystyki powierzchni obiektu. Powyższy fragment programu definiujący sferę jest w pełni równoważny tekstowi: sphere { <0, 1, 2>, 1.5 texture { pigment { color Red } } } bowiem przy generowaniu obrazu sceny spacje, nowe linie i komentarze są ignorowane. Zmienić kilkakrotnie położenie środka i promień sfery, generując za każdym razem obraz i obserwując efekty zmian. W oknie edytora programu POV-Ray zaznaczyć definicję sfery i przy pomocy poleceń Edit > Copy i Edit > Paste skopiować treść komendy opisującej sferę, aby w ten sposób uzyskać definicję drugiej sfery (umieszczając je jedna za drugą). Zmienić parametry i kolor drugiej sfery a następnie wygenerować obraz sceny. Zaznaczyć definicję drugiej sfery i skasować ją przy pomocy polecenia Edit > Delete. Dodać do opisu sceny drugi obiekt (płaszczyznę pokrytą wzorem szachownicy) przez dopisanie po fragmencie z definicją sfery następujących linii.
plane /* nazwa obiektu */ { <0, 1, 0>, -1 /* parametry opisujące płaszczyznę */ } pigment {checker color Red,color Blue } /*(czerwono - niebieska szachownica) */ Parametry opisujące płaszczyznę to: współrzędne wektora normalnego < nx, ny, nz > (wektora prostopadłego do płaszczyzny) i odległość od środka układu współrzędnych, liczona wzdłuż kierunku wyznaczonego przez wektor normalny. W powyższym przykładzie opisana została płaszczyzna równoległa do płaszczyzny wyznaczonej przez osie x i z układu współrzędnych i przesunięta o jedną jednostkę w dół, licząc wzdłuż osi y. Wprowadzenie płaszczyzny pozwoli na lepszą orientację obserwatora obrazu w przestrzeni. 7. Opis sposobu oświetlenia sceny Aby po wygenerowaniu obrazu zdefiniowany w opisie sceny obiekt był widoczny, na scenie musi znajdować się przynajmniej jedno źródło światła. W analizowanym opisie sceny z punktu 2 żródło światła opisuje fragment: light_source { <2, 4, -3> color White} /* definicja źródła światła */ Określono w ten sposób źródło punktowe, umieszczone w punkcie (x, y, z) = (2, 4, -3), świecące światłem białym. Możliwe jest określeni wielu źródeł i uzyskanie znacznie bardziej subtelnych charakterystyk świecenia. Zmienić kolor sfery na biały. Zmienić kilkakrotnie położenie źródła (przesuwając je w prawo, w lewo a także poza obiekt ) i obserwować efekty zmian. Zmienić kolor światła np. na czerwony, zielony itd. i obserwować jak wygląda obraz białej kuli. Zmienić kolor kuli i obserwować jak wygląda jej obraz przy oświetlaniu kolorowym światłem. Skopiować linię opisującą źródło, wprowadzając w ten sposób nowe źródło światła. Oświetlać kulę kilkoma źródłami świecącymi różnymi kolorami. 8. Transformacje obiektów geometrycznych Napisać prosty program rysujący stożek ( cone ) przy następujących założeniach: stożek umieszczony jest w środku układu współrzędnych (czyli tak, że środek podstawy znajduje się w punkcie (0, 0, 0) a wierzchołek w punkcie (0, d, 0)), stożek obserwowany jest z kamery znajdującej się na ujemnej części półosi osi z ( location <0, a,- b>, look_at <0,0,0> ). Uzyskany obraz powinien wyglądać mniej więcej tak:
Rys. 3. Stożek, którego środek podstawy znajduje się w punkcie (0, 0, 0) Zapisać scenę pod nazwą program1. Otworzyć nowy plik opisu sceny, zapisać go pod nazwą program2, zdefiniować drugi stożek (innego koloru) i zaobserwować działanie odpowiednio użytych (patrz plik pomocy) komend o translate, o scale, o rogate. Zbadać wpływ kolejności wykonywania transformacji na wynik końcowy. Rysunek pokazuje efekt uzyskany po skopiowaniu opisu stożka zielonego, zmianie koloru na czerwony i zastosowaniu w jego opisie komendy translate <0, 0, c>. Po zakończeniu zapisać plik z definicją sceny.
Rys. 4. Czerwony stożek powstał przez przesunięcie zielonego stożka wzdłuż osi z 8. Podstawowe konstrukcje programowe języka opisu sceny, deklarowanie zmiennych, pętla Deklaracja zmiennej w języku opisu sceny stosowanym w programie POV-Ray wygląda następująco: #declare Count = 0; /* zdefiniowana została zmienna Count i przypisano jej wartość 0*/ W linii deklaracji zmiennej można stosować operacje arytmetyczne +, -, *, / np : #declare Ang = 360/Number; /* zdefiniowana została zmienna Ang i przypisano jej wartość wyliczoną na podstawie wartości zmiennej Number */ Struktura pętli programowej (liczby 1 i 64 są przykładowe) wygląda natomiast tak:
#declare Number = 64; /* Deklaracja i ustawienie wartości liczby przebiegów pętli*/ #while (Count < Number+1) /* Sprawdzenie warunku końca pętli*/ (komendy do wykonania wewnątrz pętli ) #declare Count= Count+1; /* Zwiększenie licznika petli*/ #end /* Koniec pętli*/ Wykorzystując program z poprzedniego punktu oraz używając komendy translacji i pętli opisać scenę, na której prócz zielonego stożka znajdzie się jeszcze dziesięć czerwonych stożków oddalonych równo od siebie. Przykład obrazu takiej sceny pokazano na rysunku. Program zapisać pod nazwą program3. Rys. 4. 10 czerwonych stożków jako efekt wykonania pętli (w stosunku do poprzednich obrazów punkt usytuowania obserwatora został nieznacznie zmieniony) Używając jako obiektu elementarnego sfery, trzech poznanych wcześniej transformacji i konstrukcji pętli napisać program generujący obraz obiektu podobny do obiektu na rysunku 5. Zapisać program pod nazwą program4.
Rys. 5. Obiekt, który powstał z jednej sfery po jej przesunięciu, przeskalowaniu i 64 krotnym obróceniu wokół osi y. 9. Podstawy konstrukcyjnej geometrii bryłowej (Constructive Solid Geometry) Utworzyć plik z opisem sceny i nazwać go program5. Skopiować zawartość pliku o nazwie program1 (pojedynczy zielony stożek). Wprowadzić do opisu sceny drugi stożek tak aby, otrzymać obraz podobny do pokazanego na rysunku. Rys. 6. Dwa stożki
9. Definiowanie własnych obiektów Utworzyć plik z opisem sceny i nazwać go program6. Skopiować treść pliku o nazwie program4 (zielony pierścień). Wprowadzić do opisu sceny ("obejmując" jej zakresem opis pierścienia) następującą konstrukcję: # declare My_object = union {( dowolny ciąg komend opisujących obiekt )} można w ten sposób zdefiniować nowy obiekt o nazwie My_object. W deklaracji opisu obiektu użyto komendy union w ogólności może być tu użyta inna komenda (np. merge, intersection, itd. ). Wygenerować obraz sceny. Jeśli nie ma błędów w tresci opisu obiekt powinien zniknąć. Po deklaracji obiektu My_object dodać linię wywołania obiektu przy pomocy komendy object: object { My_object translate <0, 0, 0> } po wygenerowaniu obrazu pierścień powinien pojawić się ponownie w tym samym miejscu gdzie był poprzednio. Przedstawiona powyżej konstrukcja pozwala na operowanie jedynie nazwą obiektu i stosowanie do jego przemieszczania dowolnych transformacji. Posługując się definicją pierścienia, komendą object i pętlą programową, zmodyfikować program opisujący scenę tak, aby uzyskać obraz podobny do pokazanego na rysunku.
Rys. 7. Scena zawiera 36 pierścieni a każdy z nich zbudowany jest z 64 sfer. Pokazane wyżej konstrukcje programowe pozwalają na dalsze zagnieżdżanie opisów obiektów.