Jak ulepszyê procedurë? ----------------------- COMANCHE: KOD Kiedy mamy juû wygenerowanâ mapë, po której moûemy sië poruszaê (pisaîem o tym w poprzednim odcinku), warto dopisaê jeszcze sam kod procedury. Zrobimy to dzisiaj... Miklesz/Damage Jak zapewne pamiëtacie, mamy póîmegowy plik, zawierajâcy 512 * 512 sîów, w którym wyûszy bajt odpowiada za wysokoôê punktu, a niûszy za jego kolor. Mapë wejôciowâ radzë trzymaê w miarë moûliwoôci w pamiëci typu Fast, gdyû odwoîywaê sië do niej bëdzie jedynie procesor. Nasz krajobraz bëdziemy tworzyê na ekranie 160 * 128 * 256. Skîadaê sië on bëdzie ze 128 przekrojów gór (kaûdy o szerokoôci 160 punktów). Pierwszy przekrój bëdzie przebiegaî bezpoôrednio przed "kamerâ", a ostatni bëdzie niknâî na horyzoncie. Jeûeli sporzâdzaliôcie kiedyô wykresy funkcji dwóch zmiennych, to zapewne juû wiecie, o co chodzi. Po narysowaniu pierwszej warstwy (najbliûszej nam), nastëpne nanosimy tylko wtedy, gdy "wystajâ" one ponad poprzednie. Tutaj jednak pojawi sië pierwszy problem. Przecieû góry, oddalajâc sië od obserwatora, stajâ sië coraz niûsze! Problem ten rozwiâzujemy, tworzâc dla kaûdego paska (warstwy) osobnâ tablicë perspektywy (w osi Y). Jej wymiary to: 128 * 256 (128 pasków, w kaûdym 256 moûliwych wysokoôci). Wysokie wzniesienia, kiedy znajdujâ sië blisko kamery (obserwatora), zajmujâ caîâ wysokoôê ekranu, natomiast na horyzoncie jedynie parë punktów. Teoretycznie warstw powinno byê nieskoïczenie wiele, a wysokoôê gór powinna zmierzaê do zera (moûna to sprawdziê, liczâc granicë standardowej funkcji perspektywy). Okazuje sië, ûe kiedy rysujemy znacznie mniej pasków (np. 64), góry albo urywajâ sië przed horyzontem, albo (kiedy trochë "podrasujemy" perspektywë) wyrastajâ nagle spod ziemi w miarë zbliûania sië do nich. Dlatego wartoôê ok. 128 przekrojów wydaje sië sensowna. Przy okazji moûemy zastosowaê ciekawy trik, polegajâcy na ôciemnianiu kolorów gór w miarë zwiëkszania sië ich odlegîoôci od obserwatora. Efekt jest bardzo ciekawy (krajobraz jest jakby "gouraudowany"), a wyglâda, jakbyômy lecieli "czymô" w nocy, oôwietlajâc sobie reflektorem kawaîek ziemi przed dziobem! Jeûeli caîy obraz mamy wyîâcznie w odcieniach jednego koloru, to radzë sobie stworzyê tablicë (z przygotowanymi wczeôniej jasnoôciami) o rozmiarach: 128 * 256 (128 pasków, w kaûdym 256 moûliwych jasnoôci). Po omówieniu zasady nanoszenia pasków i perspektywy w osi Y warto zwróciê uwagë, ûe wzniesienia, oddalajâc sië od nas, zmniejszajâ nie tylko swojâ wysokoôê, ale równieû rozmiary w dwóch pozostaîych kierunkach (X i Z). Skutkiem powyûszego jest to, ûe obserwowany przez nas obszar ma rozmiary zbliûone bardziej do trapezu niû do prostokâta. Co to oznacza? Otóû to, ûe pobierajâc z mapy dane do rysowania musimy, w wypadku punktów oddalonych od kamery, po prostu niektóre kolumny i wiersze pomijaê. Tu z pomocâ przyjdzie nam kolejna tablica, w której przeliczymy sobie, jakie wartoôci w stosunku do obserwatora naleûy nanieôê. Póúniej wystarczy zmieniaê poîoûenie kamery, a góry bëdâ sië nam przesuwaîy w ûâdanych kierunkach. Tablica bëdzie miaîa rozmiary 160 * 128 (128 pasków, kaûdy po 160 punktów szerokoôci). Ktoô moûe mi zarzuciê nadmierne tablicowanie, ale w tym wypadku wielokrotnie przyôpieszajâ one obliczenia (prawie je eliminujâc), zajmujâ natomiast jedynie: 168 KB -- sîowa, 84 KB -- bajty. Teraz parë sîów o samym przygotowaniu tablic. Wydaje sië to proste, ale przy perspektywie X-Z naleûy zauwaûyê, ûe dla "leûâcej" przed nami pîaszczyzny nie obliczamy poîoûenia jej punktów na ekranie, lecz dokonujemy przeksztaîcenia odwrotnego. Chcemy dla kaûdego punktu ekranu znaê jego odpowiednik z pîaszczyzny. W zwiâzku z tym musimy przeksztaîciê oryginalny wzór na perspektywë (2 linijki na kartce, i mamy). Ostrzegam Was dlatego, ûe sam kiedyô przesiedziaîem kawaî czasu, nim wykombinowaîem, jak zrobiê tablicë. Kiedy przygotowania mamy za sobâ, warto szczegóîowo omówiê algorytm. Nim zaczniemy, potrzebujemy zarezerwowaê sobie (i kasowaê co klatkë) 160 sîów (ew. bajtów), w których zapisana bëdzie aktualna linia horyzontu. 1. Ustalamy obserwatora na mapie (od "niego" liczyê bëdziemy wszelkie offsety). 2. Zaczynamy rysowaê pierwszy (ew. kolejny) przekrój. 3. Pobieramy punkt z mapy i sprawdzamy, czy "wystaje" ponad horyzont (w pierwszej linii zawsze "wystaje"). 4. Jeûeli "tak", to rysujemy sîupek w dóî, który poîâczy nasz nowy punkt z punktem postawionym poniûej. Kolor pobieramy z tablicy. Oprócz tego musimy teû uaktualniê wysokoôê horyzontu w tym punkcie. Jeûeli "nie", to przechodzimy tylko do 5. 5. Zwiëkszamy liczniki pëtli, jeûeli nie przeszliômy jeszcze caîej szerokoôci ekranu, to skaczemy do 3. 6. Jeûeli narysowaliômy juû wszystkie punkty warstwy, to zmieniamy minimalnie perspektywë, jasnoôê i przechodzimy do nastëpnego paska, czyli do punktu 2. 7. Kiedy narysujemy juû wszystkie paski, to mamy nowâ klatkë obrazu. Nasz "Comanche" juû lata nad górkami, ale caîâ zabawë wypadaîoby trochë urozmaiciê. Zaczniemy od obrotów, choê z góry ostrzegam, ûe szybka rotacja jest w naszym wypadku bardzo pamiëcioûerna. Jest równieû bardzo prosta. Kiedy chcemy sië obróciê, wystarczy wykonaê rotacjë wokóî obserwatora wszystkich punktów naszej tablicy perspektywy X-Z. Tutaj jednak -- wiadro zimnej wody na gîowë. Kaûda nowa pozycja kâta to dodatkowe dwadzieôcia kilobajtów tablicy (a jeûeli zaûyczymy sobie tablicy zîoûonej ze sîów, to czterdzieôci kilo). Przy okazji pragnë zauwaûyê, ûe czësto warto tworzyê tablice zîoûone z dîugich sîów, w których mamy na raz przeliczone wartoôci dla Y i X. Jak? Po prostu przy mapce o szerokoôci 512 przesuniëcie w osi Y o 1 w dóî to to samo, co przesuniëcie w osi X o 512 w prawo. Prawda, ûe proste? Wzglëdy objëtoôciowe nie pozwalajâ mi na omówienie przechyîów (na boki) i dodawania ruchomych chmur na niebie, lecz obiecujë, ûe uczynië to za miesiâc, w odcinku przeznaczonym wektorówce cieniowanej. Na dzisiaj materiaîu jest i tak sporo, jak na te 30/31 dni. Naprawdë! Pierwsze próby nad "Comanche'ami" przeprowadziîem prawie rok temu, zdâûyîem swoje wypociny umieôciê juû w dwóch demach, a mimo wszystko caîy czas dopracowujë të samâ procedurë! Zarówno w poprzednim odcinku, jak i dziô, umieôciîem kilka "shotów" krajobrazów z kilku znanych demek. Pamiëtaê jednak naleûy, ûe choê w wypadku mojego kodu jestem pewien jego realtime'owoôci, to czasami to, co widzimy, jest zwykîâ animacjâ ze Scenery'ego bâdú Visty! To juû wszystko na dzisiaj. Juû za miesiâc Gouraudy!