Processing Podstawy Processingu Processing jest darmowym językiem i środowiskiem, opartym na języku Java, służącym do tworzenia interaktywnych aplikacji graficznych. Został on stworzony w MIT (Massachusetts Institute of Technology) przez Casey a Reasa i Bena Fry a w 2000 roku. Processing można pobrać ze strony: http://processing.org/ Na stronie domowej Processingu znajduje się również dokładny opis wszystkich funkcji, o których będzie mowa w dalszej części. Rysunek 1 przedstawia główne okno Processingu. Widzimy w nim menu, pasek z przyciskami służącymi do kompilacji, uruchamiania, eksportowania itp., edytorem kodu źródłowego oraz konsoli, na której będą wyświetlane wszelkie komunikaty. Programy napisane w Processingu mogą zostać wyeksportowane do apletu Javy lub samodzielnej aplikacji dla systemów Windows, Linux oraz Mac OS. Wszystkie programy są aplikacjami okienkowymi o domyślnym rozmiarze okna 100 100 pikseli. Do zmiany wielkości okna służy funkcja size, która przyjmuje dwa parametry szerokość i wysokość okna w pikselach. Podstawowymi graficznymi prymitywami 2D w Processingu są: punkt funkcja point, linia funkcja line, trójkąt funkcja triangle, elipsa funkcja ellipse, 1
2 Rysunek 1: Processing. prostokąt funkcja rect, czworokąt funkcja quad, łuk funkcja arc, krzywa Béziera funkcja bezier, krzywa Catmulla-Roma funkcja curve. Oprócz wymienionych prymitywów istnieją funkcje beginshape, endshape pomiędzy, którymi definiujemy wierzchołki (funkcja vertex) kształtu. W zależności od wybranego trybu wierzchołki kształtu będą inaczej interpretowane. Do zmiany koloru: tła służy funkcja background, wypełnienia służy funkcja fill, linii obramowania służy funkcja stroke. Możemy wyłączyć wypełnienie funkcją nofill, a linię obramowania funkcją nostroke. W przypadku linii możemy zmienić niektóre jej własności: grubość (funkcja strokeweight), sposób zakończenia linii (funkcja strokecap), styl łączenia linii (funkcja strokejoin). Ponadto możemy włączyć lub wyłączyć antialiasing (funkcje smooth, nosmooth).
3 Oprócz czysto graficznych funkcji Processing dostarcza standardowe możliwości, które dostępne są w każdym języku programowania tzn. komentarze: //, /... / pętle: for, while, instrukcje warunkowe: if, if...else, instrukcję wyboru: switch, operatory porównania: <, <=, >, >=, ==,!=, operatory logiczne:, &&,!, operatory arytmetyczne: +,,, /, %, ++,. Typy wbudowane: char, float, int, byte, boolean. Klasy wbudowane: String, PImage, PFont, BufferedReader, PrintWriter. Oprócz wymienionych typów i klas można definiować własne typy poprzez napisanie odpowiednich klas. Literatura dodatkowa na temat Processingu: [1] Fry B., Visualizing Data, O Reilly, 2008. [2] Greenberg I., Processing: Creative Coding and Computational Art, Friendsofted, 2007. [3] Noble J., Programming Interactivity: A Designer s Guide to Processing, Ardunio, and openframeworks, O Reilly, 2009. [4] Reas C., Fry B., Processing: A Programming Handbook for Visual Designers and Artists, MIT Press, 2007. [5] Rocchesso D., Media Processing in Processing, http://cnx.org/content/col10268/latest (dostępna wrzesień 2009). [6] Shiffman D., Learning Processing: A Beginner s Guide to Programming Images, Animation, and Interaction, Morgan Kaufman, 2008. [7] Terzidis K., Algorithms for Visual Design using the Processing Language, Wiley Publishing Inc., 2009.
4 Czcionki, obrazy, animacja i interakcja w Processingu W Processingu istnieje możliwość tworzenia i wyświetlania napisów. Zanim będziemy mogli używać napisów musimy stworzyć odpowiednią czcionkę w formacie vlw, który jest formatem rastrowym, a nie wektorowym. Żeby utworzyć czcionkę wybieramy menu Tools Create Font, zobaczymy okno, w którym możemy wybrać jedną z czcionek zainstalowanych w systemie, ustalić jej wielkość oraz nadać jej nazwę za pomocą, której będziemy mogli ją wczytać w programie. Mając utworzoną plik z czcionką musimy go wczytać i wybrać jako bieżącą czcionkę. Robimy to następująco: PFont f o n t = loadfont ( nazwa. vlw ) ; textfont ( f o n t ) ; Kiedy ustawimy już czcionkę możemy wyświetlać tekst za pomocą funkcji text, która przyjmuje trzy argumenty: tekst, współrzędne x i y punktu, w którym tekst ma zostać wyświetlony. Kolor czcionki zmieniamy za pomocą funkcji fill. Inne własności jakie możemy zmienić są następujące: wielkość (funkcja textsize), wyrównanie (funkcja textalign), odstęp między wierszami (funkcja textleading). Przydatną funkcją jest funkcja textwidth, która oblicza szerokość podanego napisu w pikselach dla aktualnie ustawionej czcionki. Klasa PImage służy w Processingu do przechowywania obrazów rastrowych: gif, jpg, tga i png. Zanim będziemy mogli skorzystać z obrazu musimy go najpierw wczytać (funkcja loadimage) lub stworzyć (funkcja createimage). Następnie żeby wyświetlić wczytany lub stworzony obraz korzystamy z funkcji image, która ma dwie wersje. Pierwsza przyjmuje obraz oraz współrzędne punktu, w którym ma znaleźć się lewy górny róg obrazu. Druga wersja dodatkowo przyjmuje jeszcze szerokość i wysokość z jaką obraz ma być wyświetlony. W klasie PImage dostępnych jest kilka funkcji, które służą do przekształcania obrazu: mask maskuje część obrazu za pomocą innego obrazu lub tablicy liczb, filter dokonuje filtracji na obrazie (binaryzacja, konwersja do odcieni szarości, negatyw, redukcja liczby kolorów, rozmycie, przeźroczystość), blend miesza region obrazu z innym obrazem (liniowa interpolacja, dodawanie, odejmowanie, rozjaśnianie, przyciemnianie, itp.).
5 Jeśli chcemy dokonać innych bardziej skomplikowanych operacji na obrazach, to musimy napisać własne funkcje, które będą to robiły. W tym przypadku potrzebne będą nam funkcje pobierające i ustawiające pojedynczy piksel obrazu. Do tego celu służą funkcje get i set. W przypadku wielu operacji pobierania i ustawiania piksela wymienione funkcje są nieefektywne. Bardziej efektywnym sposobem jest skorzystanie z jednowymiarowej tablicy pikseli będącej składową klasy PImage i mająca nazwę pixels. Jeśli chcemy zmieniać piksele okna aplikacji, to zanim odwołamy się do tablicy pixels musimy ją wczytać funkcją loadpixels, a po dokonaniu zmian musimy odświeżyć zawartość aplikacji funkcją updatepixels. Processing pozwala w bardzo prosty sposób tworzyć animację. W tym celu należy napisać dwie funkcje: setup, draw. Funkcja setup służy do zainicjowania zmiennych globalnych (zmienne znajdujące się poza funkcjami setup, draw), wczytania zasobów potrzebnych później w programie itp. Funkcja draw jest funkcją, która wykonywana jest w pętli i odpowiada za wyświetlanie poszczególnych klatek animacji. Nie musimy się martwić o efekt migotania podczas animacji ponieważ twórcy Processingu przy obsłudze funkcji draw wykorzystali tzw. podwójne buforowanie, które eliminuje ten efekt. Istnieje możliwość zmiany liczby klatek wyświetlanych na sekundę. Do tego celu służy funkcja framerate. Istnieje również zmienna o tej samej nazwie przechowująca aktualną liczbę klatek na sekundę. Do przerwania pętli wywołującej funkcję draw służy funkcja noloop, do wznowienia funkcja loop. Ponadto mamy funkcję redraw, która wymusza odrysowanie okna aplikacji. Processing umożliwia tworzenie aplikacji interaktywnych. Do interakcji wykorzystywane są: myszka, klawiatura. Dla myszki istnieją zmienne przechowujące współrzędne kursora: mousex, mousey współrzędne aktualnej pozycji kursora, pmousex, pmousey współrzędne poprzedniej pozycji kursora. Do sprawdzenia czy został naciśnięty jakikolwiek przycisk myszki służy zmienna boolowska mousepressed. Żeby sprawdzić, który przycisk został naciśnięty służy zmienna mousebutton, która przyjmuje wartości: LEFT, RIGHT, CENTER. Do obsługi zdarzeń związanych z myszką służą funkcje: mousepressed naciśnięcie przycisku myszki,
6 mousereleased zwolnienie przycisku myszki, mouseclicked kliknięcie, mousemoved ruch myszką, mousedragged ruch myszka z naciśniętym przyciskiem. W przypadku klawiatury istnieje zmienna boolowska keypressed, która służy do sprawdzenia czy został naciśnięty klawisz na klawiaturze. Zmienna key przechowuje ostatnio naciśnięty klawisz. W przypadku klawiszy specjalnych tj. Alt, Control, Shift, strzałki najpierw sprawdzamy czy wartość zmiennej key jest równa CODED, a następnie za pomocą zmiennej keycode sprawdzamy, który klawisz specjalny został naciśnięty. Do obsługi zdarzeń związanych z klawiaturą służą funkcje: keypressed naciśnięcie klawisza, keyreleased zwolnienie klawisza, keytyped naciśniecie klawisza, ale ignorowany jest klawisz specjalny np. po naciśnięciu Shift+a otrzymujemy a. Podstawy grafiki 3D w Processingu Oprócz grafiki 2D w Processingu istnieje możliwość tworzenia grafiki 3D. Żeby móc korzystać z grafiki 3D jako trzeci parametr funkcji size musimy podać jedną z dwóch wartości: P3D renderer grafiki 3D będący częścią Processingu, OPENGL renderer grafiki 3D korzystający z biblioteki OpenGL. W przypadku korzystania z OpenGL-a oprócz przekazania odpowiedniej wartości do funkcji size musimy na początku pliku zaimportować bibliotekę OpenGL: import p r o c e s s i n g. opengl. ; Podobnie jak w przypadku grafiki 2D Processing udostępnia prymitywy 3D: box prostopadłościan, sphere sfera.
7 Ponieważ prymitywy 3D nie posiadają argumentów odpowiedzialnych za ich położenie na scenie, więc do ich pozycjonowania używana jest funkcja translate (translacja obiektu o podany wektor). Oprócz translacji obiekty możemy skalować (funkcja scale) oraz obracać wokół osi OX, OY, OZ (funkcje rotatex, rotatey, rotatez). Dodatkowo możemy dokonać własnego przekształcenia podanego za pomocą macierzy. Służy do tego funkcja applymatrix. Oprócz funkcji applymatrix w Processingu istnieją inne funkcje dotyczące macierzy przekształcenia. Są to: pushmatrix zrzuca bieżącą macierz przekształcenia na stos, popmatrix ściąga macierz ze stosu zastępując nią bieżąca macierz, printmatrix wypisuje na konsoli zawartość bieżącej macierzy, resetmatrix zastępuje bieżąca macierz przekształcenia macierzą jednostkową. Wszystkie prymitywy 2D działają również w trybie 3D z tą różnicą, że musimy podać o jedną współrzędną więcej przy określaniu współrzędnych. Podobnie tworzenie dowolnych kształtów za pomocą funkcji beginshape, endshape i vertex działa w trybie 3D tylko do funkcji vertex należy przekazać trzy współrzędne wierzchołka. Ponieważ scenę 3D oglądamy na ekranie, który jest dwuwymiarowy dużą rolę w tym jak widzimy obiekty odgrywa kamera i to w jakim trybie ona pracuje. W Processingu istnieje kilka funkcji umożliwiających manipulację kamerą: camera ustawia pozycję kamery na podstawie pozycji oka, środka sceny oraz osi, która skierowana jest do góry, begincamera zaczyna zaawansowane ustawienie kamery, endcamera kończy zaawansowane ustawianie kamery, ortho ustawia rzutowanie prostopadłe, perspective ustawia rzutowanie perspektywiczne, frustum ustawia macierz perspektywy za pomocą podanych parametrów. Kolejnym ważnym czynnikiem w naszym postrzeganiu sceny 3D na dwuwymiarowym ekranie jest światło. Do obsługi światła w Processingu udostępniono kilka funkcji:
8 lights włącza domyślne oświetlenie sceny, nolights wyłącza oświetlenie sceny, ambientlight dodaje do sceny światło otoczenia, directionallight dodaje do sceny światło kierunkowe, pointlight dodaje do sceny światło punktowe, spotlight dodaje do sceny światło miejscowe, normal ustawia wektor normalny w bieżącym punkcie. Oprócz ustawień kamery czy światła Processing daje możliwość ustawienia własności materiału (funkcje: ambient, emissive, shininess, specular) oraz ustawienia tekstury (funkcja texture). Processing udostępnia jedynie część funkcji jakie są dostępne w bibliotece OpenGL. Nic nie stoi na przeszkodzie żeby skorzystać z tych funkcji, wystarczy odwoływać się do nich bezpośrednio. To w jaki sposób można tego dokonać można znaleźć między innymi na stronie domowej Processingu.