Popularny post Adder Napisano Maj 2, 2021 Popularny post Udostępnij Napisano Maj 2, 2021 Wstęp W artykule przedstawione zostały wybrane, podstawowe metody operowania obiektami trójwymiarowymi w środowisku Processing 4.0 alpha 3 (rel. 17.01.2021). Pomimo, że zapoznanie się z tematem nie wymaga wcześniejszego doświadczenia z Processing, wskazana jest znajomość fundamentów programowania oraz pewien stopień swobody w budowaniu skryptów. Niekoniecznie w tym środowisku. Prawie wszystkie poruszane tematy uzupełnione są praktycznymi przykładami, składającymi się na kompletny, działający i jednocześnie nieduży program, który następnie może podlegać dalszym modyfikacjom. Co budujemy? W roku 1543 Mikołaj Kopernik opublikował w Norymberdze dzieło, które na zawsze zmieniło postrzeganie Wszechświata. Dzisiaj nie wyobrażamy sobie Układu Słonecznego inaczej niż grupy planet okrążających Słońce. Jednak ujęcie geocentryczne obecne jest w języku potocznym, sztuce, a nawet astronawigacji. Nasz program będzie próbą prezentacji układu Ziemia-Słońce tak, jakby to Ziemia znajdowała się w jego centrum, a nie odwrotnie. Zadaniem programu będzie modelowanie wzajemnego położenia nieruchomej Ziemi (EARTH) i krążącego wokół niej Słońca (SUN). Na koniec dla uatrakcyjnienia całości wprowadzony zostanie również trzeci obiekt: Sfera Niebieska (CELESTIAL_SPHERE). Na potrzeby budowy modelu przyjęto, że zarówno Ziemia jak i Słońce są idealnymi kulami. Założono również, że centrum trójwymiarowego układu współrzędnych, względem którego dokonywane będą przekształcenia, znajduje się w geometrycznym środku Ziemi. Dokonano także uproszczeń mechaniki ruchu Słońca. PShape i translate() Ponieważ program będzie wykorzystywał obiekty i przekształcenia dostępne jedynie w trzech wymiarach naszym pierwszym krokiem będzie ustawienie jednego z 5 dostępnych trybów renderingu na „P3D”. Należy tego dokonać podając trzeci parametr funkcji size() odpowiedzialnej za określenie rozmiarów okna, w którym wykonywany będzie program: size(1800,1000,P3D); // Rozmiar okna 1800/1000 pikseli. Rendering trójwymiarowy Program będzie dokonywał animacji ruchu Słońca wokół Ziemi, czyli sekwencyjnego wyświetlania klatek (frames) zawierających kolejne przekształcenia wzajemnej pozycji tych obiektów. Dlatego zawsze warto mieć na uwadze szybkość z jaką klatki są odtwarzane. Parametrem tym można sterować za pomocą funkcji frameRate(), przy czym domyślną wartością jest 60 fps/s. Na potrzeby programu w zupełności wystarczy 30 fps/s: frameRate(30); // Ilość klatek na sekundę(ftp/s) Ustawienia podstawowych parametrów programu kończą się wyborem koloru tła w skali odcieni szarości: Background(22); // Tło Processing oferuje szereg metod pozwalających na rysowanie obiektów trójwymiarowych. Jednym z wygodniejszych sposobów jest wykorzystanie typu danych PShape pozwalającego na przechowywanie kształtów, w tym kształtów trójwymiarowych. Użycie obiektu przechowującego kształt wymaga jego zadeklarowania: PShape EARTH; // Deklaracja obiektu przechowującego informacje o kształcie Ziemi Od momentu zadeklarowania EARTH jako obiektu typu PShape możliwe będzie wykorzystanie w stosunku do niego wszystkich metod przypisanych do typu PShape. Należy pamiętać, że przed użyciem obiektu musi być on przypisany do kształtu, który z kolei może być wczytany za pomocą funkcji loadShape() lub stworzony funkcją createShape(). Processing oferuje wiele sposobów zastosowania funkcji createShape() oraz zestaw predefiniowanych kształtów wybieranych za pośrednictwem parametrów funkcji. Możliwe jest również grupowanie wielu kształtów oraz wykorzystanie funkcji bez parametrów i zdefiniowanie kształtu później, w trakcie działania programu. W przypadku podania jako parametru kształtu predefiniowanego możliwe jest wykorzystanie w stosunku do niego parametrów kształtu podstawowego. Na przykład w stosunku do predefiniowanego kształtu SPHERE możliwe jest zastosowanie parametrów funkcji sphere(). Aby użyć obiektu EARTH w naszym programie przypisywany jest do niego nowy kształt będący sferą (predefiniowany kształt SPHERE - co zasadniczo odpowiada kształtowi Ziemi) z jednym parametrem określającym jej promień (EARTH_RADIUS). EARTH=createShape(SPHERE,EARTH_RADIUS); // Przypisanie do obiektu EARTH typu PShape predefiniowanego kształtu sfery o zadanym promieniu (jeden z dozwolonych parametrów funkcji podstawowej sphere()) Oczywiście parametr EARTH_RADIUS wymaga wcześniejszego zadeklarowania: int EARTH_RADIUS=150; // Promień Ziemi Samo zadeklarowanie obiektu EARTH i przypisanie do niego zadanego kształtu nie jest wystarczające do jego wyświetlenia. W tym celu konieczne jest użycie dodatkowo funkcji shape(). W programie zastosowano najprostsze jej wywołanie: shape(EARTH); // Rysunek Ziemi Podsumowując, prawidłowe wyświetlenie obiektu typu PShape wymaga: Deklaracji obiektu: PShape Przypisania do obiektu zadanego kształtu: (createShape() lub loadShape()) Wyświetlenia obiektu (wywołania): shape() Sfera w środowisku Processing jest obiektem szczególnym. Ponieważ jej wyświetlenie wymaga narysowania zbioru płaszczyzn, często konieczne jest podjęcie decyzji co do ich liczby, zapewniającej oczekiwane przybliżenie kształtu sfery. Określenie liczby wierzchołków siatki wykorzystywanej do rysowania sfery realizowane jest przez funkcję sphereDetail(). Rozdzielczość domyślna to 30, co pozwala na narysowanie stosunkowo precyzyjnej figury. Przy podejmowaniu decyzji o szczegółowości odtworzenia kształtu należy mieć jednak na uwadze ile sfer będzie rysowanych w tym samym czasie. Im większa liczba użytych płaszczyzn tym mniejsza liczba sfer będzie wyświetlana bez opóźnień wpływających na płynność działania programu. Ponieważ w naszym programie wykorzystywane są tylko 3 sfery możliwe jest ustawienie wysokiego poziomu szczegółowości: sphereDetail(120); // Określenie szczegółowości rysowania sfer Warto pamiętać, aby wywołanie funkcji sphereDetail() odbywało się przed wywołaniem createShape() oraz shape(). Na podstawie zdobytej wiedzy można pokusić się na zbudowanie pierwszej wersji programu, którego zadaniem będzie wyświetlenie sfery o promieniu 150 i szczegółowości 120. Miejsca w których umieszczone są poszczególne komendy nie są przypadkowe! int EARTH_RADIUS=150; // Promień Ziemi PShape EARTH; // Deklaracja kształtu przechowującego informacje o kształcie Ziemii void setup() { // Część programu wykonywana raz size(1800,1000,P3D); // Rozmiar okna 1800/1000 pixeli. Rendering trójwymiarowy frameRate(30); // Ilość klatek na sekundę(ftp/s) background(22); // Tło sphereDetail(120); // Szczegółowość rysowania sfer EARTH=createShape(SPHERE,EARTH_RADIUS); } void draw() { // Część program wykonywana w pętli shape(EARTH); // Rysunek Ziemi } Otrzymujemy widok sfery zniekształconej przez perspektywę, której centrum zlokalizowane jest w lewym górnym rogu ekranu. Ponadto, na jej powierzchni widoczne są linie płaszczyzn, z których została zbudowana, a jej kolor daleki jest od koloru Ziemi. Sam rysunek jest też trochę chropowaty. Zacznijmy od naprawienia mankamentów jakimi są kolor i linie na powierzchni obiektu. Jak już wcześniej wspomniano do rysunku Ziemi możliwe będzie wykorzystanie metod przypisanych do typu PShape. Za określenie sposobu wyświetlania koloru obrysu obiektu typu PShape odpowiada metoda setStroke(), natomiast za kolor i wypełnienie kształtu metoda setFill(). W naszym programie określamy je za pośrednictwem dwóch komend: EARTH.setStroke(false); // Ustawienie braku wyświetlania obrysu EARTH.setFill(#0D8FBC); // Kolor wypełnienia #0D8FBC (błękitny) Processing udostępnia wiele sposobów reprezentacji kolorów, które nie zostaną tutaj omówione. Zarówno do prostych jak i zaawansowanych projektów wystarczające jest używanie reprezentacji heksadecymalnej. Wybór żądanego koloru umożliwia wbudowane proste narzędzie „Color Selector” dostępne w menu „Tools”. Dla bardziej wymagających przedsięwzięć wygodniejsze jest jednak korzystanie z zewnętrznych narzędzi wyboru koloru. Za „chropowatość” linii odpowiada zjawisko aliasingu. Standardowo w trybie renderingu P3D anty-aliasing ustawiony jest na poziom 2x. W zależności od wydajności sprzętu możliwe jest zastosowanie wygładzania z poziomem 4x lub 8x. W programie zastosowano poziom 4, czyli czterokrotny poziom nadmiaru próbkowania bufora grafiki. smooth(4); // Ustawienie poziomu anty-aliasingu Ponieważ Ziemia znajduje się w centrum uwagi naszego programu konieczne jest na koniec nadanie należnego jej miejsca. W tym celu można, choć nie jest to jedyny sposób, wykorzystać niezwykle potężną funkcję translate(). W środowisku 3D translację można wyobrazić sobie jako przesunięcie środka układu współrzędnych x,y,z o zadaną wartość wzdłuż poszczególnych osi. Z funkcji należy korzystać bardzo ostrożnie. Przekształcenia geometryczne są wrażliwe na kolejność w jakiej wywoływane będą poszczególne funkcje. W konsekwencji narysowanie obiektu np. w środku układu współrzędnych, a następnie zastosowanie funkcji translate() nie spowoduje jego przesunięcia. Pozostanie on tam gdzie został pierwotnie narysowany, przesunie się natomiast sam układ współrzędnych. Przy okazji należy pamiętać, że w środowisku trójwymiarowym Processing, układ współrzędnych jest lewoskrętnym układem kartezjańskim, którego środek umiejscowiony jest w lewym górnym rogu ekranu. Wartości Y rosną w kierunku dołu ekranu, wartości X w kierunku prawej strony ekranu, natomiast wartości Z zwiększają się w kierunku ruchu do powierzchni ekranu i zmniejszają w kierunku w „głąb” ekranu. Do tej pory nie wskazano gdzie dokładnie ma zostać wyświetlona Ziemia. W konsekwencji została ona umieszczona przez program w środku układu współrzędnych, który znajduje się jak wspomniano w lewym górnym rogu ekranu. Aby przesunąć ją w docelowe miejsce konieczne jest przesunięcie środka układu współrzędnych do centrum okna programu. translate(width/2,height/2,0); // Przesunięcie środka układu współrzędnych do centrum ekranu/okna programu W tym konkretnym przypadku zamiast bezpośredniego podania przesunięcia wzdłuż osi X oraz osi Y wykorzystano zmienne systemowe height oraz width przechowujące rozmiary okna programu zdefiniowane na poziomie funkcji size(). W konsekwencji środek układu współrzędnych przesunął się o połowę szerokości okna wzdłuż osi X oraz połowę wysokości okna wzdłuż osi Y, nie zmieniając swojego położenia na osi Z. Po dokonaniu powyższych modyfikacji program przyjął następującą formę: int EARTH_RADIUS=150; // Promień Ziemi PShape EARTH; // Deklaracja kształtu przechowującego informacje o kształcie Ziemii 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 sphereDetail(120); // Szczegółowość rysowania sfer EARTH=createShape(SPHERE,EARTH_RADIUS); smooth(4); // Ustawienie poziomu anty-aliasingu EARTH.setStroke(false); // Brak wyświetlania obrysu EARTH.setFill(#0D8FBC); // Kolor wypełnienia #0D8FBC (błękitny) } void draw() { translate(width/2,height/2,0); // Przesunięcie środka układu współrzędnych do centrum ekranu/okna programu – kolejność jest ważna! shape(EARTH); // Rysunek Ziemi } W centrum okna wyświetlana jest gładka, niebieska sfera: W tym miejscu kończy się Część Pierwsza. Przed sięgnięciem do Części Drugiej, gdzie do programu dodamy funkcje odpowiedzialne za Słońce oraz jego obrót wokół Ziemi, a obrazy sfer zostaną nieco bardziej urealnione, zachęcam do eksperymentów z różnymi obiektami typu PShape i funkcją translate(). 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!