Popularny post Adder Napisano Maj 3, 2021 Popularny post Udostępnij Napisano Maj 3, 2021 pushMatrix(), popMatrix() Czas na dodanie do programu obrazu Słońca. W poprzedniej części artykułu przedstawione zostały zasady tworzenia obiektów typu PShape. Tworzenie obrazu Słońca dokonywane będzie dokładnie w ten sam sposób co tworzenie obrazu Ziemi. Jedyna różnica polegała będzie na różnicach położenia tych obiektów w układzie współrzędnych. Co więcej, o ile położenie Ziemi będzie stałe, o tyle położenie Słońca będzie się zmieniało w czasie, ponieważ będzie ono krążyło bezustannie wokół Ziemi, a w naszym programie w każdej klatce wyświetlane w nieco innym miejscu. Oczywiście istnieje wiele metod umożliwiających realizację tego zadania, jednak Processing oferuje niezwykle wygodną funkcję pushMatrix(), która w połączeniu ze znanym już translate() znacznie je ułatwia. pushMatrix() zapisuje bieżącą macierz transformacji na stosie danych, a popMatrix() ponownie go stamtąd wydobywa. Transformacje wykonane pomiędzy pushMatrix() a popMatrix() będą dotyczyły układu znajdującego się na stosie. Upraszczając, działanie funkcji pushMatrix() możemy wyobrazić sobie jako wciśnięcie układu współrzędnych razem ze znajdującymi się w nim obiektami w inną rzeczywistość, niż ta która dokonuje się na ekranie. W trakcie przebywania w tej innej rzeczywistości możliwe jest wykonywanie translacji układu współrzędnych oraz operacji na „wciśniętych” razem z nim obiektach. Wywołanie popMatrix() powoduje powrót do poprzedniego układu jednak obiekty pojawiają się w miejscach w jakich znalazły się po dokonaniu translacji poza układem. Dla przykładu narysowanie sfery, a następnie wywołanie funkcji pushMatrix() oraz przesunięcie sfery o 10 jednostek zakończone wywołaniem popMatrix() spowoduje pojawienie się na ekranie obrazu dwóch sfer przesuniętych względem siebie o 10 jednostek, pomimo, że obrazy dotyczą tej samej sfery. Potęga i jednocześnie prostota pushMatrix() jest porównywalna do translate(). Połączenie ich razem jest nieocenionym narzędziem programistycznym. Pojawia się pytanie, gdzie zostanie wyświetlone „Słońce” jeśli nie zostanie przesunięte w odpowiednie miejsce? Oczywiście wewnątrz „Ziemi”, tj. w środku układu współrzędnych. Ponieważ jego promień będzie mniejszy od ziemskiego, nie będzie nawet widoczne. Konieczne jest zatem jego przesunięcie w stosunku do środka współrzędnych oraz wprawienie w ruch wokół Ziemi. Zanim program zostanie odpowiednio zmodyfikowany warto rzucić okiem na stan aktualny, czyli z obrazem Słońca: int EARTH_RADIUS=150; // Promień Ziemi int SUN_RADIUS=10; // Promień Słońca PShape EARTH; // Deklaracja kształtu przechowującego informacje o kształcie Ziemii PShape SUN; // Deklaracja kształtu przechowującego informacje o kształcie Słońca void setup() { size(1800,1000,P3D); // Rozmiar okna 1800/1000 pixeli. Rendering trójwymiarowy frameRate(30); // Ilość klatek na sekundę(ftp/s) background(22); // Tło smooth(4); // Ustawienie poziomu anty-aliasingu sphereDetail(120); // Szczegółowość rysowania sfer EARTH=createShape(SPHERE,EARTH_RADIUS); SUN=createShape(SPHERE, SUN_RADIUS); EARTH.setStroke(false); // Brak wyświetlania obrysu EARTH.setFill(#0D8FBC); // Kolor wypełnienia #0D8FBC (błękitny) SUN.setStroke(false); // Brak wyświetlania obrysu SUN.setFill(#F5E20A); // Kolor wypełnienia #F5E20A (żółty) } void draw() { translate(width/2,height/2,0); // Przesunięcie środka układu współrzędnych do centrum ekranu/okna programu shape(EARTH); // Rysunek Ziemi shape(SUN); // Rysunek Słońca } Z punktu widzenia obserwatora na Ziemi Słońce porusza się po nieboskłonie idealnym ruchem okrężnym. Peryhelium i aphelium orbity widoczne może być jako pozorne zmniejszenie lub zwiększenie promienia Słońca, co gołym okiem jest jednak praktycznie niemożliwe. Dlatego w programie przyjęto, że ruch Słońca wokół Ziemi odbywa się po okręgu i nie jest dokonywana korekta promienia gwiazdy. Związane jest to również z faktem, że skala i cykl tej korekty wymaga dość skomplikowanych obliczeń oraz wprowadzania pojęć, które zamieniłyby ten artykuł (i program) w rozprawkę z dziedziny astronomii i astronawigacji. Uwzględniając powyższe ograniczenia, do określenia pozycji słońca względem Ziemi potrzebne będą następujące zmienne: float xSol=0; // Chwilowa współrzędna x środka Słońca float ySol=0; // Chwilowa współrzędna y środka Słońca float zSol=0; // Chwilowa współrzędna z środka Słońca float tSol=0; // Chwilowy azymut Słońca liczony od południka 0 w stopniach int SUN_ORBIT=600; // Promień orbity Słońca Przez chwilowe współrzędne środka słońca należy rozumieć położenie obrazu Słońca w oknie programu w trakcie wyświetlania kolejnych klatek. Chwilowy azymut określa miejsce w jakim znajduje się obraz Słońca względem obrazu ziemskich południków. Współrzędne środka Słońca wyliczane są na podstawie równania okręgu zgodnie z następującym algorytmem: xSol=SUN_ORBIT*cos(tSol); // wyliczenie pozycji x Słońca ySol=SUN_ORBIT*sin(tSol); // wyliczenie pozycji y Słońca tSol+=TWO_PI/360; // inkrementacja azymutu o 1 stopień na klatkę if (tSol>TWO_PI) tSol=0; // reset azymutu po zakreśleniu przez Słońce całej orbity Mając wszystkie niezbędne dane możliwe jest dokonanie odpowiednich przekształceń wykorzystując funkcje popMatrix() oraz translate() pushMatrix(); // wepchnięcie macierzy współrzędnych translate(xSol,ySol,zSol); // przesunięcie środka układu shape(SUN); // wyświetlenie obrazu Słońca popMatrix(); // wypchnięcie macierzy Jak łatwo zauważyć nie została obliczona wartość zmiennej zSol. Nie jest to na tym etapie niezbędne. Ruch Słońca względem osi Z w układzie geocentrycznym wywoływany jest przez nachylenie ekliptyki. Jego określenie wymaga odrębnych, dość zawiłych obliczeń, które nie wnoszą jednak niczego nowego w zakresie opisywanych funkcji, zmniejszając jednocześnie przejrzystość kodu. Tym samym w naszym programie Słońce okrąża Ziemię idealnie w płaszczyźnie równika. Działanie programu uwzględniającego nachylenie ekliptyki zostanie przedstawione na końcu artykułu jako dodatek. Po uzupełnieniu programu o komendy definiujące pozycję Słońca oraz zasady jego wyświetlania pełny kod będzie wyglądał następująco: int EARTH_RADIUS=150; // Promień Ziemi int SUN_RADIUS=10; // Promień Słońca int SUN_ORBIT=300; // Promień orbity Słońca; float xSol=0; // Chwilowa współrzędna x środka Śłońca float ySol=0; // Chwilowa współrzędna y środka Śłońca float zSol=0; // Chwilowa współrzędna z środka Śłońca float tSol=0; // Chwilowy azymut Słońca liczony od południka 0 w radianach float tSolFromSeasonStart=0; // Suma azymutów Słońca w sezonie w okresie obserwacji w radianach PShape EARTH; // Deklaracja kształtu przechowującego informacje o kształcie Ziemii PShape SUN; // Deklaracja kształtu przechowującego informacje o kształcie Słońca void setup() { size(1800,1000,P3D); // Rozmiar okna 1800/1000 pixeli. Rendering trójwymiarowy frameRate(30); // Ilość klatek na sekundę(ftp/s) background(22); // Tło smooth(4); // Ustawienie poziomu anty-aliasingu sphereDetail(120); // Szczegółowość rysowania sfer EARTH=createShape(SPHERE,EARTH_RADIUS); SUN=createShape(SPHERE, SUN_RADIUS); EARTH.setStroke(false); // Brak wyświetlania obrysu EARTH.setFill(#0D8FBC); // Kolor wypełnienia #0D8FBC (błękitny) SUN.setStroke(false); // Brak wyświetlania obrysu SUN.setFill(#F5E20A); // Kolor wypełnienia #F5E20A (żółty) } void draw() { background(22); // Wymazanie obrazu klatki translate(width/2,height/2,0); // Przesunięcie środka układu współrzędnych do centrum ekranu/okna programu shape(EARTH); // Rysunek Ziemi xSol=SUN_ORBIT*cos(tSol); ySol=SUN_ORBIT*sin(tSol); tSol+=TWO_PI/360; if (tSol>TWO_PI) tSol=0; pushMatrix(); translate(xSol,ySol,zSol); shape(SUN); popMatrix(); } Po uruchomieniu programu w tej formie otrzymamy następujący obraz: Efekt niesie niemiłą niespodziankę! Słońce zamiast okrążać Ziemię rysuje wokół niej okrąg. Jak już wspomniano, spowodowane jest to faktem, że wpychanie i wypychanie macierzy nie powoduje przesunięcia lub wymazania obrazu obiektów sprzed tej operacji. Widzimy po prostu kolejne obrazy tego samego obiektu, którego przesunięcia odbywają się poza wyświetlaną macierzą współrzędnych. Jedyny sposób, aby temu zaradzić to wyczyszczenie klatki i przerysowanie jej na nowo. Z pomocą przychodzi tu funkcja background(). Jej zastosowanie w pętli draw() będzie powodowało wymazywanie zawartości każdej kolejnej wyświetlanej klatki i rozwiąże problem. background(22); // Wymazanie obrazu klatki Po uzupełnieniu programu o powyższą komendę działa on już zgodnie z oczekiwaniami: Ostatecznie kod przyjmuje postać: int EARTH_RADIUS=150; // Promień Ziemi int SUN_RADIUS=10; // Promień Słońca int SUN_ORBIT=300; // Promień orbity Słońca; float xSol=0; // Chwilowa współrzędna x środka Śłońca float ySol=0; // Chwilowa współrzędna y środka Śłońca float zSol=0; // Chwilowa współrzędna z środka Śłońca float tSol=0; // Chwilowy azymut Słońca liczony od południka 0 w radianach float tSolFromSeasonStart=0; // Suma azymutów Słońca w sezonie w okresie obserwacji w radianach PShape EARTH; // Deklaracja kształtu przechowującego informacje o kształcie Ziemii PShape SUN; // Deklaracja kształtu przechowującego informacje o kształcie Słońca void setup() { size(1800,1000,P3D); // Rozmiar okna 1800/1000 pixeli. Rendering trójwymiarowy frameRate(30); // Ilość klatek na sekundę(ftp/s) background(22); // Tło smooth(4); // Ustawienie poziomu anty-aliasingu sphereDetail(120); // Szczegółowość rysowania sfer EARTH=createShape(SPHERE,EARTH_RADIUS); SUN=createShape(SPHERE, SUN_RADIUS); EARTH.setStroke(false); // Brak wyświetlania obrysu EARTH.setFill(#0D8FBC); // Kolor wypełnienia #0D8FBC (błękitny) SUN.setStroke(false); // Brak wyświetlania obrysu SUN.setFill(#F5E20A); // Kolor wypełnienia #F5E20A (żółty) } void draw() { background(22); // Wymazanie obrazu klatki translate(width/2,height/2,0); // Przesunięcie środka układu współrzędnych do centrum ekranu/okna programu shape(EARTH); // Rysunek Ziemi xSol=SUN_ORBIT*cos(tSol); ySol=SUN_ORBIT*sin(tSol); tSol+=TWO_PI/360; if (tSol>TWO_PI) tSol=0; pushMatrix(); translate(xSol,ySol,zSol); shape(SUN); popMatrix(); } W kolejnej, trzeciej części artykułu zajmiemy się światłem i ruchem obserwatora układu (do tej pory układ obserwowany jest z jednego miejsca), a Słońce i Ziemia uzyskają inny, atrakcyjniejszy wygląd. Do tego czasu warto poćwiczyć wykorzystanie funkcji pushMatrix() i popMatrix(). Przy pewnej wprawie stają się one nadzwyczaj użytecznym narzędziem. 4 Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Maj 3, 2021 Udostępnij Maj 3, 2021 @Adder Twój artykuł został właśnie opublikowany i jest już dostępny publicznie. Dzięki za ciekawy wpis 🚀 Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!