X. ELEMENTY GRAFIKI ANIMOWANEJ 10.1. Wprowadzenie Przekształcenia i algorytmy przedstawione w poprzednich rozdziałach dotyczyły obiektów pozostających w spoczynku, a więc ich obrazy na ekranie były nieruchome. Wprawienie ich w ruch nazywa się animacją. Nie trzeba chyba dodawać, że tworzenie obiektów ruchomych na ekranie i sterowanie nimi ma liczne zastosowania praktyczne (gry komputerowe, edukacja, symulatory lotów, wizualizacja naukowa procesów fizycznych, chemicznych itp.). Przy tworzeniu animacji należy pamiętać o tym, aby ruchomy element nie zmieniał się zbyt szybko w stosunku do liczby ramek, tj. pojedynczych obrazów statycznych składających się na animację, gdyż oko ludzkie ma ograniczone możliwości percepcyjne w tym zakresie (zakłócenia takie nazywamy zakłóceniami czasowymi). Ponadto należy uwzględnić czas potrzebny na narysowanie elementu. W wielu zastosowaniach proces ten nie powinien być zauważalny, co wymusza maksymalne upraszczanie ruchomego elementu obrazu. 10.2. Symulacja ruchu w przestrzeni dwuwymiarowej W przestrzeni dwuwymiarowej ruch może odbywać się wzdłuż linii prostej lub linii krzywej. Ruch może być przy tym jednostajny, jednostajnie lub niejednostajnie przyspieszony lub opóźniony, okresowy itp. Przez takie ruchy można symulować wiele zjawisk fizycznych, na przykład ruch wahadła, lot pocisku, poruszanie się satelity po orbicie itp. Także w wielu grach komputerowych ruch płaski jest całkowicie wystarczający. 10.2.1. Ruch wzdłuż linii prostej Najprostszą animacją ekranową jest ruch jednostajny pojedynczego punktu (piksela) wzdłuż linii prostej. Animację taką uzyskuje się za pomocą sukcesywnych przesunięć piksela, wygaszając przy tym jego poprzednie położenie. Jak wiadomo, w ruchu jednostajnym prostoliniowym droga s przebyta przez ciało w czasie t dana jest wzorem (10.1) gdzie v oznacza stałą prędkość. Jeśli w chwili początkowej ciało znajduje się w punkcie P 1 o współrzędnych (x 1, y 1 ) i po upływie czasu t ma znaleźć się w punkcie P 2 o współrzędnych (x 2, y 2 ), to zgodnie ze wzorem (10.1) powinno poruszać się z prędkością
180 X. Elementy grafiki animowanej (10.2) W praktyce problem prędkości przesuwania się punktu na ekranie rozwiązujemy przez użycie jakiejś funkcji standardowej 1), która określa zatrzymanie wykonywania programu na wyspecyfikowaną liczbę milisekund. Zatrzymanie to powinno wystąpić pomiędzy wyświetleniem piksela w określonym miejscu i jego usunięciem w tym miejscu. Usunięcie (wygaszenie) piksela realizujemy przez wyświetlenie w danym miejscu piksela w kolorze zapamiętanym przed wyświetleniem piksela przesuwającego się. Niech )x ' x 2 & x 1, )y ' y 2 &y 1, a )t oznacza liczbę milisekund zatrzymania programu po zaświeceniu piksela. Jeśli )x 0 lub )y 0, to algorytm przesuwania piksela w kolorze c od punktu P 1 do punktu P 2 ruchem jednostajnym prostoliniowym możemy opisać następująco:! wykonaj operacje wstępne: s x :' sgn()x), s y :' sgn()y), c 1 :' kolor piksela w punkcie P 1, zaświeć w punkcie P 1 piksel w kolorze c, zatrzymaj wykonywanie programu na czas )t,! jeśli )x ' 0, to dla i ' 1, 2,..., *)y*: zaświeć w punkcie (x 1, y 1 %s y (i&1)) piksel w kolorze c 1, c 1 :' kolor piksela w punkcie (x 1, y 1 %s y i), zaświeć w punkcie (x 1, y 1 %s y i) piksel w kolorze c, zatrzymaj wykonanie programu na czas )t, w przeciwnym przypadku, gdy )y ' 0, to dla i ' 1, 2,..., *)y*: zaświeć w punkcie (x 1 %s x (i&1), y 1 ) piksel w kolorze c 1, c 1 :' kolor piksela w punkcie (x 1 %s x i, y 1 ), zaświeć w punkcie (x 1 %s x i, y 1 ) piksel w kolorze c, zatrzymaj wykonanie programu na czas )t, w przeciwnym przypadku, gdy *)y*>*)x*, to dla i ' 1, 2,..., *)y*: zaświeć w punkcie (x 1 % s y (i&1))x/)y, y 1 %s y (i&1)) piksel w kolorze c 1, c 1 :' kolor piksela w punkcie (x 1 % s y i)x/)y, y 1 %s y i) zaświeć w punkcie (x 1 % s y i)x/)y, y 1 %s y i) piksel w kolorze c, zatrzymaj wykonanie programu na czas )t, w przeciwnym przypadku dla i ' 1, 2,..., *)x*: zaświeć w punkcie (x 1 %s x (i&1), y 1 %s x (i&1))y/)x) piksel w kolorze c 1, c 1 :' kolor piksela w punkcie (x 1 %s x i, y 1 %s x i)y/)x), zaświeć w punkcie (x 1 %s x i, y 1 %s x i)y/)x) piksel w kolorze c, zatrzymaj wykonanie programu na czas )t. 1) Odpowiednie funkcje lub procedury standardowe są dostępne w każdym języku programowania wysokiego poziomu.
10.2. Symulacja ruchu w przestrzeni dwuwymiarowej 181 Ponieważ współrzędne ekranu są liczbami całkowitymi, w podanym algorytmie tam, gdzie niezbędne, należy wykonać odpowiednie zaokrąglenia. W ruchu prostoliniowym jednostajnie przyspieszonym lub opóźnionym droga s przebyta przez ciało od punktu P 1 do punktu P 2 dana jest, przy braku prędkości początkowej, wzorem (10.3) przy czym a > 0 w ruchu jednostajnie przyspieszonym i a < 0 w ruchu jednostajnie opóźnionym (nie ma to wpływu na przebytą drogę). Przyspieszenie lub opóźnienie piksela poruszającego się na ekranie można symulować przez sukcesywne zmniejszanie lub zwiększanie odstępu czasu pomiędzy wyświetleniem piksela w bieżącym położeniu i jego wygaszeniem w miejscu poprzedniej lokalizacji. Algorytm przesuwania piksela w ruchu jednostajnie przyspieszonym lub opóźnionym będzie różnić się od algorytmu podanego dla ruchu jednostajnego tylko wyznaczaniem czasu zatrzymania programu. Rozważmy najpierw ruch jednostajnie przyspieszony i załóżmy w nim jednostkowe przyspieszenie. Wówczas pierwsze przesunięcie o jeden piksel (wszystko jedno w którą stronę), czyli przebycie jednostkowego odcinka drogi, nastąpi w czasie. Oznacza to, że po zaświeceniu piksela w punkcie P 1 powinniśmy zatrzymać wykonanie programu na czas t 0. Drugie przesunięcie o jeden piksel będzie wymagać krótszego czasu, trzecie przesunięcie czasu itd. Ogólnie możemy zapisać, że Oznaczmy przez )t czas przesunięcia ostatniego piksela na drodze od punktu P 1 do punktu P 2 i zastanówmy się, w jakim czasie, w stosunku do )t, powinniśmy przesuwać kolejne piksele. Ponieważ na podstawie podanego bliżej algorytmu liczba wyświetlanych pikseli wynosi 2@max{)x, )y}%1, więc zgodnie z powyższymi rozważaniami po wyświetleniu ostatniego piksela program powinien zostać zatrzymany na czas skąd otrzymujemy Czas zatrzymania programu po wyświetleniu k-tego piksela wynosi zatem Oczywiście czas ten nie uwzględnia czasu wykonywania instrukcji programu. W przypadku ruchu jednostajnie opóźnionego przez )t oznaczamy czas zatrzymania programu po wyświetleniu piksela w punkcie P 1, czyli dla k ' 0. Wykonując podobną analizę, jak
182 X. Elementy grafiki animowanej dla ruchu jednostajnie przyspieszonego, znajdziemy, że czas zatrzymania programu po wyświetleniu k tego piksela powinien wynosić Dotychczas rozważaliśmy tylko ruch punktu. Zaprogramowanie ruchu dowolnych obiektów po linii prostej w przestrzeni dwuwymiarowej może być już bardziej skomplikowane. Podstawowa trudność polega na konieczności zapamiętania wycinku tła i jego odtworzeniu po wykonaniu ruchu. Jeśli przesuwane obiekty mają małe rozmiary i dają się opisać za pomocą standardowych funkcji lub procedur graficznych dostępnych w danym języku programowania, a tło ekranu w obszarze ruchu ma jeden kolor, to do zaprogramowania ruchu można posłużyć się techniką podaną dla punktu, tj. wyświetlać obiekt w kolejnym położeniu i wygaszać, czyli wyświetlać w kolorze tła, w miejscu poprzednim. 10.2.2. Ruch wzdłuż linii krzywej Symulację ruchu punktu wzdłuż linii krzywej uzyskuje się w podobny sposób, jak wzdłuż linii prostej, z tym że kolejne położenia punktu wyznacza się z równania krzywej. Krzywą przedstawiamy jako funkcję zmiennej x lub y: (11.4) W symulacji ruchu wzdłuż linii krzywych obiektów reprezentowanych na ekranie przez odcinki lub wielokąty należy dodatkowo wziąć pod uwagę zmianę ich orientacji (obroty). Zmianę orientacji poruszającego się odcinka lub wielokąta uzyskuje się przez odniesienie położenia względem stycznej do krzywej. Dla krzywej o równaniu danym w postaci wyraźnej: równanie stycznej w punkcie (x 0, y 0 ) ma postać: a dla krzywej o równaniu danym w postaci uwikłanej: równanie stycznej jest następujące: (11.5) Zastosowanie powyższych wzorów zilustrujemy na przykładzie ruchu odcinka wzdłuż elipsy. Przykład 10.1 Równanie elipsy o środku w punkcie (x 0, y 0 ), półosi wielkiej a (równoległej do osi x) i półosi małej b (równoległej do osi y) ma postać
10.3. Symulacja ruchu w przestrzeni trójwymiarowej 183 (11.6) skąd Na podstawie wzoru (11.5) możemy obliczyć równanie stycznej do okręgu (11.6) w punkcie. Równanie to jest następujące: (11.7) Końce odcinka o długości 2d położone na stycznej symetrycznie względem punktu styczności posiadają współrzędne (x 1, y 1 ) i (x 2, y 2 ), przy czym (11.8) Zależności te wynikają z równania stycznej (11.7) oraz z faktu, że 11.3. Symulacja ruchu w przestrzeni trójwymiarowej Animacja w przestrzeni trójwymiarowej wymaga dodatkowego uwzględnienia perspektywy (zob. p. 4.2) i wynikających stąd przeliczeń rozmiarów poruszającego się obiektu. Jeśli ruch odbywa się po niepłaskiej linii krzywej, to trzeba także uwzględnić niewidoczne rzutowanie perspektywiczne samej krzywej i wykonywanie względem stycznej do niej obrotów obiektu. Przekształcenia te mogą spowodować duże zakłócenia czasowe i dlatego należy dążyć do zminimalizowania liczby wykonywanych operacji arytmetycznych. Torem ruchu obiektu w przestrzeni trójwymiarowej może być linia prosta lub krzywa (płaska lub nie). Prostą w przestrzeni określa się jako linię przecięcia dwóch płaszczyzn i wyznacza się ją analitycznie za pomocą układu dwóch równań liniowych. Poniżej podajemy cztery postacie równań prostej w przestrzeni (niektóre z nich były już przez nas używane) najczęściej stosowane przy określaniu toru ruchu. 1) Równanie ogólne prostej: przy czym i
184 X. Elementy grafiki animowanej 2) Równanie prostej przechodzącej przez punkt P 1 o współrzędnych (x 1, y 1, z 1 ) i równoległej do wektora r ' r x i % r y j % r z k (i, j oraz k oznaczają wektory jednostkowe w kierunkach osi odpowiednio x, y oraz z): 3) Równanie parametryczne prostej: 4) Równanie prostej przechodzącej przez dane dwa punkty P 1 i P 2 o współrzędnych odpowiednio (x 1, y 1, z 1 ) i (x 2, y 2, z 2 ): Jeśli ruch w przestrzeni odbywa się po linii krzywej, to najczęściej określamy ją trzema równaniami parametrycznymi postaci (11.9) Podobnie jak w przypadku dwuwymiarowym, zmianę orientacji poruszającego się wzdłuż krzywej odcinka lub wielokąta uzyskuje się przez odniesienie położenia względem stycznej do tej krzywej. Równanie stycznej do krzywej opisanej równaniami (11.9) jest określone zależnościami (11.10) gdzie (n 1 (t 0 ), n 2 (t 0 ), n 3 (t 0 )) oznaczają współrzędne punktu styczności. Nie wdając się w dalsze szczegóły związane z opisem ruchu w przestrzeni trójwymiarowej, podamy przykład jego symulacji. Przykład 10.2 Załóżmy, że ruch odbywa się po linii śrubowej, tj. linii określonej równaniami (11.11) gdzie a > 0 oraz b 0. Z zależności (11.10) wynika, że równania stycznej do krzywej (11.11) w punkcie (x 0, y 0, z 0 ) ' (acost 0, asint 0, bt 0 ) mają postać (11.12) Na podstawie równań (11.12) możemy obliczyć współrzędne końców odcinka o długości 2d położone na stycznej symetrycznie względem punktu styczności. Otrzymamy
10.3. Symulacja ruchu w przestrzeni trójwymiarowej 185 Poruszając w różny sposób poszczególne elementy obrazu uzyskuje się ruch złożony. W tworzeniu ruchu złożonego często wykorzystuje się ruch tła. Na przykład dobrą symulację ruchu samochodu można uzyskać (przy nieruchomym samochodzie) przez przesuwanie linii środkowej jezdni. W podobny sposób symulację ruchu pociągu uzyskamy przez przesuwanie słupów telefonicznych lub trakcji elektrycznej.
XI. GRAFIKA RASTROWA A GRAFIKA WEKTOROWA Przedstawiony w poprzednich rozdziałach materiał dotyczył w zasadzie wyłącznie tzw. grafiki rastrowej. Drugim rodzajem grafiki komputerowej jest grafika wektorowa. W grafice rastrowej obraz jest budowany z siatki punktów (pikseli). Obrazy są przechowywane w plikach o odpowiednich formatach, z których najważniejsze to: Bitmap, OpenRaster i ICO. Do przechowywania obrazów rastrowych służą także pliki o formatach JPEG, TIFF, PNG i GIF, tyle że w plikach tych dodatkowo stosuje się kompresje danych. Najpopularniejszymi edytorami graficznymi do wykonywania obrazów rastrowych są Photoshop, MS Paint, GIMP oraz Corel Photo-Paint. W grafice wektorowej stosuje się tzw. prymitywy graficzne, do których zalicza się punkty, linie, różne kształty i wieloboki. Wszystkie prymitywy graficzne są przedstawiane za pomocą równań matematycznych. Podstawowym standardem grafiki wektorowej jest SVG (skr. ang. scalable vector graphics). Najpopularniejszymi edytorami graficznymi są CorelDRAW, Adobe Illustrator i Inkscape. Najczęściej w grafice wektorowej używa się następujących prymitywów:! odcinki i łamane,! wielokąty,! okręgi i elipsy,! krzywe Béziera,! wielokąty Béziera,! litery (np. w formacie TrueType każda litera jest utworzona w oparciu o krzywe Béziera). Grafika wektorowa ma pewną przewagę nad grafiką rastrową. Przede wszystkim, obraz wektorowy wymaga bardzo małej ilości informacji, co przekłada się na mały rozmiar plików przechowujących obrazy wektorowe. Z drugiej jednak strony jest potrzebny potężny procesor do wygenerowania obrazu w oparciu o algorytm (równania matematyczne). Druga zaleta polega na tym, że parametry wizualizowanych obiektów są pamiętane i mogą być modyfikowane. Oznacza to, że przekształcenia, takie jak translacja, skalowanie, obrót itp. nie wpływają na jakość obrazu. Ponadto przybliżanie krzywych nie zwiększa proporcjonalnie ich grubości jako linii.