plik


ÿþUniwersytet MikoBaja Kopernika WydziaB Fizyki, Astronomii i Informatyki Stosowanej Jakub PrzewBocki nr albumu: 169422 Praca magisterska na kierunku fizyka techniczna Wizualizacja danych z u|yciem grafiki trójwymiarowej i mechanizmy interakcji z u|ytkownikiem w OpenGL Opiekun pracy dyplomowej dr Jacek Matulewski ZakBad Mechaniki Kwantowej ToruD 2008 Prac przyjmuj i akceptuj Potwierdzam zBo|enie pracy dyplomowe ............................................................. .................................................................. data i podpis opiekuna pracy data i podpis pracownika dziekanatu Dzikuj Panu doktorowi Jackowi Matulewskiemu za cierpliwo[, pomoc i opiek nad projektem 2 UMK zastrzega sobie prawo wBasno[ci niniejszej pracy magisterskiej w celu udostpniania dla potrzeb dziaBalno[ci naukowo-badawczej lub dydaktycznej 3 Spis tre[ci 1. Wstp& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & 6 2. Metody poruszania obiektami& & & & & & & & & & & & & & & & & & & & & 7 2.1. Rotacja sferyczna& & & & & & & & & & & & & & & & & & & & & & & 7 2.2 Przeciganie obiektów na scenie za pomoc myszy& & & & & & & & & & 14 3. Selekcja jako sposób zaznaczania obiektów& & & & & & & & & & & & & & & . 18 3.1. Selekcja& & & & & & & & & & & & & & & & & & & & & & & & & & .. 18 3.2. Tryby renderowania& & & & & & & & & & & & & & & & & & & & & ... 18 3.3. Stos nazw obiektów& & & & & & & & & & & & & & & & & & & & & & 20 3.4. Bufor selekcji  przetwarzanie rekordów trafieD& & & & & & & & & & & 22 3.5. Wybieranie obiektów& & & & & & & & & & & & & & & & & & & & & .. 23 4. Sprz|enie zwrotne& & & & & & & & & & & & & & & & & & & & & & & & & . 29 4.1. Tryb renderowania& & & & & & & & & & & & & & & & & & & & & & . 29 4.2. Buffor sprze|enia zwrotnego& & & & & & & & & & & & & & & & & & . 29 4.3. Dane bufora sprz|enia zwrotnego& & & & & & & & & & & & & & & & 30 4.4. Podsumowanie& & & & & & & & & & & & & & & & & & & & & & & & 31 5. GrafDyn  program do wizualizacji danych& & & & & & & & & & & & & & & 32 5.1. Instalacja& & & & & & & & & & & & & & & & & & & & & & & & & & 33 5.2. Interfejs aplikacji GrafDyn& & & & & & & & & & & & & & & & & & & 36 5.3. ModuB importu& & & & & & & & & & & & & & & & & & & & & & & .. 37 5.4. O[wietlenie& & & & & & & & & & & & & & & & & & & & & & & & & 41 5.5. WBasno[ci wykresu& & & & & & & & & & & & & & & & & & & & & & 45 4 6. Podsumowanie& & & & & & & & & & & & & & & & & & & & & & & & & & & 50 7. Literatura& & & & & & & & & & & & & & & & & & & & & & & & & & & & & 51 Dodatek A  Prymitywy& & & & & & & & & & & & & & & & & & & & & & & & 52 5 1. Wstp Moim zadaniem byBo przygotowanie programu wykorzystujcego bibliotek OpenGL do wizualizacji funkcji dwóch zmiennych z = f(x,y) zadanej przez odczytany z pliku zbiór punktów (x,y,z). Charakterystyczn cech programu ma by mo|liwo[ interakcji z u|ytkownikiem obejmujca dowolne obracania wykresu za pomoc myszki, zaznaczanie i przeciganie zródeB [wiatBa (równie| myszk) i podokna pozwalajce na wygodne ustalanie wBasno[ci wykresu oraz tworzenia i edycji zródeB [wiatBa. Wymaga to bdzie m. in. u|ycia trybu selekcji OpenGL umo|liwiajcego na interakcj u|ytkownika z zawarto[ci sceny oraz wprowadzenia do obsBugi kamery mechanizmu rotacji sferycznej. Program zawiera te| moduB importu pozwalajcy na wczytywanie plików z danymi w postaci trójek wspóBrzdnych x, y i z oraz plików zawierajcych jedynie cz[ rzeczywist i urojon funkcji zespolonej. W tym drugim przypadku parametry sieci musz by pobierane z osobnego pliku lub wpisane przez u|ytkownika w udostpnionym przez program formularzu. W pierwszych rozdziaBach pracy opisuj najciekawsze, a zarazem najtrudniejsze do zaimplementowania, techniki u|yte w programie, a wic rotacj sferyczn, mechanizm selekcji obiektów w OpenGL oraz poruszanie zródeB [wiatBa za pomoc myszki. Kolejne rozdziaBy po[wicone s zaimplementowanym w programie narzdziom takim, jak moduB do importu danych, narzdzie do definiowania i edycji wBasno[ci zródeB [wiatBa oraz narzdzia pozwalajce na modyfikowanie wygldu sceny oraz dobierania parametrów wykresu. 6 2. Metody poruszania obiektami 2.1. Rotacja sferyczna Ka|dy zaawansowany program wy[wietlajcy grafik trójwymiarow daje mo|liwo[ swobodnego obracania modelu za pomoc myszy. Na tym wBa[nie polega rotacja sferyczna. W tym rozdziale przedstawi implementacje tej techniki na przykBadzie mojego programu (Rys. 1.) oraz powody dla których watro jej u|ywa. CaBo[ oparta jest na standardowej klasie ArcBall, która zostaBa opisana w  PereBkach programowania gier [13], a tak|e w witrynie NeHe (lekcja 48)[7]. Klasa ArcBall oparta jest na kwaternionach. S to obiekty matematyczne, które sBu| programist grafiki i gier do reprezentowania rotacji i orientacji w przestrzeni 3D [17]. Ogólnie kwaterniony to struktura algebraiczna bdca rozszerzeniem ciaBa liczb zespolonych. Jedna z jego notacji reprezentowana jest w postaci pary, w której pierwsza cz[ to rzeczywista wielko[ skalarna, a druga to trójwymiarowy wektor wspóBczynników cz[ci urojonych: [w (x y z)] W grafice 3D kwaternion tworzy kt obrotu w, oraz o[ obrotu (x y z) wokóB której wykonywany jest obrót [19]. Je|eli przyjmiemy, |e mamy kt obrotu ± i n jako wektor jednostkowy opisujcy o[, to kwaternion reprezentujcy okre[lony obrót bdzie miaB posta (1): ¸ w=cos( ) 2 ¸ v=sin( )n gdzie v = (x,y ,z) (1) 2 ¸ ¸ [ cos( ) sin( )n ] 2 2 Majc te wszystkie dane mo|emy stworzy macierz (2): 7 w 2 + x 2 - y 2 - z 2 2xy + 2wz 2xz - 2wy 0 2xy - 2wz w 2 - x 2 + y 2 - z 2 2yz + 2wx 0 (2) 2xz + 2wy 2yz - 2wx w 2 - x 2 - y 2 + z 2 0 0 0 0 w 2 + x 2 + y 2 + z 2 Majc punkty i wektory mo|emy przeksztaBci je, poprzez przemno|enie ich przez powy|sz macierz (2) reprezentujc obrót [17]. Rotacja sferyczna wymaga mapowania dwuwymiarowych wspóBrzdnych miejsca, w którym znajduje si mysz w oknie w momencie kliknicia do trójwymiarowych koordynatów wirtualnej kuli[7]. Kiedy klikniemy mysz w okno tworzony jest wektor pocztkowy(ArcBall.click(&MousePt))(Listing 3.), a nastpnie podczas przecigania kursora wektor koDcowy, który modyfikowany jest przez funkcje ArcBall.drag(&MousePt, &ThisQuat). Majc oba wektory mo|emy obliczy wektor prostopadBy do wektora pocztkowego i koDcowego wokóB, którego wykonywany jest obrót. Te informacje wystarcz nam do stworzenia macierzy obrotu. Rys. 1. Program GrafDyn Obiekt implementujcy system rotacji sferycznej inicjowany jest przy pomocy nastpujcego konstruktora. 8 ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight) gdzie NewWidth i NewHeight odpowiadaj szeroko[ci i wysoko[ci obszaru roboczego okna, a dokBadniej tej cz[ci okna, która zarezerwowana jest na potrzeby OpenGL (viewport). W programie inicjuj go wprowadzajc nastpujce warto[ci: ArcBall(640.0f, 480.0f); Nie s to prawdziwe rozmiary okna (te nie s jeszcze w momencie tworzenie instancji ArcBall znane), dlatego po jego utworzeniu konieczne jest przesBanie prawdziwych danych. To samo nale|y robi za ka|dym razem, kiedy jego rozmiar si zmienia. Uaktualnienia danych dokonujemy za pomoc funkcji: void ArcBall_t::setBounds(GLfloat NewWidth, GLfloat NewHeight) Listing 1. Funkcja ReSizeGLScene  wywoBywana po zmianie rozmiarów formy void __fastcall TGLForm::ReSizeGLScene(GLsizei width, GLsizei height) { if (height==0) // zapobiegnij dzieleniu przez zero... { height=1; // ...ustawiajc liczb 1 } glViewport(0, 0, width, height); // zresetuj pole widzenia glMatrixMode(GL_PROJECTION) ; glLoadIdentity(); // zresetuj j // oblicz perspektyw dla okna gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); // wybierz macierz modeli glLoadIdentity(); // zresetuj j ArcBall.setBounds((GLfloat)width, (GLfloat)height); } 9 Metoda ArcBall::setBounds wywoBywana jest w funkcji ReSizeGLScene (Listing 1.), gdzie jako argumenty podawane s nowe rozmiary okna. Jednocze[nie w funkcji tej ustawiamy perspektyw do rozmiarów okna w momencie rozcignicia okna (perspektywa bdzie omówiona szerzej w dalszej cz[ci pracy). Znaczy to, |e to co jest dalej, jest mniejsze i jednocze[nie stworzy to realistyczn scen [7] (lekcja 1). Aby program reagowaB na ka|d zmian rozmiaru okna, musimy skojarzy okre[lone zdarzenie z odpowiednim komunikatem Windows. SBu|y do tego procedura obsBugi komunikatów nazywana zwykle WndProc. To w niej umieszczamy zbiór instrukcji wykonywanych w reakcji na odebranie komunikatu WM_SIZING (Listing 2.), który informuje o zmianie rozmiaru okna. Listing 2. Sekcja instrukcji switch w WndProc, która odpowiedzialna jest za obsBug komunikatu WM_SIZING switch(Message.Msg) { case WM_SIZING: ReSizeGLScene(ClientWidth,ClientHeight); & } Listing 3. Trzy macierze odpowiedzialne za obrót oraz funkcja UpdateTransform Matrix4fT Transform = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; Matrix3fT LastRot = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; Matrix3fT ThisRot = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; ArcBallT ArcBall(640.0f, 480.0f); Point2fT MousePt; 10 bool isClicked = false; bool isDragging = false; void UpdateTransform() { if (!isDragging) { if (isClicked) { isDragging = true; LastRot = ThisRot; ArcBall.click(&MousePt); } } else { if (isClicked) { Quat4fT ThisQuat; ArcBall.drag(&MousePt, &ThisQuat); Matrix3fSetRotationFromQuat4f(&ThisRot, &ThisQuat); Matrix3fMulMatrix3f(&ThisRot, &LastRot); Matrix4fSetRotationFromMatrix3f(&Transform, &ThisRot); } else isDragging = false; } } W programie zainicjowane s trzy macierze odpowiedzialne za nasz obrót. Transform to macierz 4x4 przechowujca informacje o obrocie ukBadu odniesienia sceny i wszelkich translacjach jakich dokonamy mysz. Druga macierz 3x3 LastRot zapamituje ostatni obrót, jaki uzyskali[my po ostatnim przeciganiu myszk. Ostatni macierz jest ThisRot przechowujca obrót podczas bie|cego przecigania. Wszystkie te macierze s inicjowane jako macierze jednostkowe. 11 WspóBrzdne punktu wskazywanego przez mysz przechowuje zmienna MousePt typu Point2fT. MousePt jest uaktualniane za ka|dym razem, gdy poruszymy mysz przy jednoczesnym przytrzymaniu jej przycisku. Do obsBugi myszki u|yjemy jeszcze dwóch dodatkowych zmiennych isClicked i isDragging. Obie inicjalizujemy warto[ciami false. Pierwsza odpowiada za to czy wcisnli[my przycisk myszki, natomiast druga sprawdza czy aktywne jest przeciganie. Kliknicie okna lewym przyciskiem rozpoczyna caBy proces. W tym momencie macierz obrotu ustawiana jest na macierz jednostkow. W trakcie zmiany pozycji kursora na bie|co obliczany jest obrót od pocztkowego punktu kliknicia do aktualnych wspóBrzdnych myszy. W metodzie ArcBall::UpdateTransform (Listing 3.), zaimplementowany jest algorytm obrotów naszego obiektu. Podczas kliknicia myszk, w LastRot zapamitywany jest wynik wszystkich obrotów, natomiast w ThisRot tylko aktualny. Podczas przecigania kursora myszki (isDragging = true), ThisRot modyfikowany jest najpierw przez oryginalny obrót, a nastpnie przez LastRot. Proces ten ilustruj poni|sze kroki: " ArcBall.drag(&MousePt, &ThisQuat) aktualizowany jest wektor koDcowy i pobierany wynikowy obrót w postaci kwaternionu, " Matrix3fSetRotationFromQuat4f(&ThisRot, &ThisQuat) konwertujemy kwaternion do Matrix3fT " Matrix3fMulMatrix3f(&ThisRot, &LastRot) dodajemy wynik ostatniego obrotu " Matrix4fSetRotationFromMatrix3f(&Transform, &ThisRot) ustawiamy nasz ostateczny obrót Kiedy koDczymy przeciganie mysz (isDragging = false), do macierzy LastRot zostaje skopiowana warto[ ThisRot. Bardzo wa|ne w caBym algorytmie rotacji sferycznej jest to, |e zapamitujemy ostatni obrót, jaki otrzymali[my pod koniec przecigania (LastRot). Gdyby[my tego nie robili, po ka|dym klikniciu model zaczynaBby obrót od wyj[ciowej pozycji. PrzykBadowo, je[li obrócimy model wokóB osi X o 50 stopni, a potem o 25 stopni w tym samym kierunku, chcieliby[my otrzyma obrót o 75 stopni, a nie o ostatnie 25. 12 Kiedy ju| mam gotowy algorytm rotacji sferycznej, nadszedB czas umiejscowi odpowiednie funkcje w kodzie programu, aby[my mogli swobodnie obraca nasz model. Na pocztku zajmiemy si zmienn isClicked. Chcemy aby program za ka|dym razem podczas poruszania myszk, sprawdzaB czy zostaB wci[nity lewy przycisk myszki i do naszej zmiennej przypisywaB odpowiedni warto[. W tym celu musimy skojarzy okre[lone zdarzenie (w naszym przypadku poruszanie myszk) z odpowiednim komunikatem Windows. Zatem w WndProc umieszczamy zbiór instrukcji wykonywanych w reakcji na odebranie komunikatu WM_MOUSEMOVE (Listing 4.), który informuje o ruchu myszy w obrbie okna. Listing 4. Sekcja instrukcji switch w WndProc, która odpowiedzialna jest za obsBug komunikatu WM_MOUSEMOVE case WM_MOUSEMOVE isClicked = (LOWORD(Message.WParam) & MK_LBUTTON) ? true : false; Aby wszystko dziaBaBo poprawnie nale|y u|y nowej macierz transformacji (przed renderowaniem wykresu). Tylko wówczas transformacja bdzie wpBywa na jego poBo|enie. W klasie GLForm implementujcej gBówne okno aplikacji zdefiniowana jest funkcja GL_RysujScene (Listing 5.), która odpowiedzialna jest za generowanie sceny. To w niej wBa[nie rysujemy nasz aktualny wykres, [wiatBa i legend. Chcemy aby rotacja obejmowaBo tylko wykres i [wiatBa, wic tu| przed nimi wywoBujemy metod ArcBall::UpdateTransform i glMultMatrixf(Transform.M). Zwrómy uwag, |e w metodzie GL_RysujScene druga funkcja umieszcza bie|c macierz model-widok na stosie macierzy (zapamituje w ten sposób jej warto[). Po zakoDczeniu renderowania modelu przywracamy zapamitany stan [cigajc go ze stosu. Listing 5. Kod programu odpowiedzialny za transformacje w funkcji GL_RysujScene void __fastcall TGLForm::GL_RysujScene() { & & & UpdateTransform() 13 glPushMatrix(); glMultMatrixf(Transform.M); & & & // renderujemy model podlegajcy rotacji glPopMatrix(); } W ten sposób zakoDczyli[my implementacj rotacji sferycznej w programie. Postpujc zgodnie z opisanymi powy|ej krokami mo|emy u|y jej tak|e w innych projektach korzystajcych z OpenGL. 2.2 Przeciganie obiektów na scenie za pomoc myszy Biblioteka OpenGL zawiera funkcje, które pozwalaj stworzy odpowiedni algorytm do przesuwania obiektów za pomoc myszy. W tym rozdziale, na przykBadzie zródeB [wiatBa jako obiektów, postaram si go dokBadnie opisa. W programie GrafDyn, ka|de nowo dodane zródBo [wiatBa posiada swoj okre[lon pozycj (x,y,z), które pocztkowo ustawione jest na (0,0,0). Mamy mo|liwo[ zmiany ustawienia poBo|enia [wiatBa za pomoc formularza umieszczonego w oknie O[wietlenie (opis w rozdziale 5.4). Wygodniejsz metod zmiany jego pozycji jest jednak przeciganie go za pomoc myszy w przestrzeni 3D. Jednak zanim przystpi do opisania algorytmu, który zaimplementowaBem w tym celu w programie GrafDyn, opisz dwie u|yte do tego funkcje udostpniane przez bibliotek GLU doBczan do OpenGL. Pierwsza z nich to: gluProject(x,y,z,model_view, projection, viewport, &winX, &winY, &winZ); SBu|y do przeliczenia wspóBrzdnych w przestrzeni widoku (x, y, z) na wspóBrzdne w przestrzeni okna (winX,winY,winZ)[14]. Wzory na podstawie którego nastpuje przeliczenie to (3): v=(x,y,z,1.0) v' = P x M x v winX = viewport(0) + viewport(2) * (v'(0) + 1) / 2 (3) winY = viewport(1) + viewport(3) * (v'(1) + 1) / 2 14 winZ = (v'(2) + 1) / 2 gdzie M to macierz widoku, a P to macierz rzutowania. PrzeciwieDstwem tej funkcji jest: gluUnProject(winX, winY, winZ, model_view, projection, viewport, &pos3D_x, &pos3D_y, &pos3D_z); SBu|y do przeliczenia wspóBrzdnych w przestrzeni okna (winX,winY,winZ) na wspóBrzdne w przestrzeni widoku (pos3D_x, pos3D_y, pos3D_z)[14]. Przeliczanie to odbywa si na podstawie wzoru (4): 2(winX - viewport[0]) ëø -1öø ìø ÷ø pos3d _ x viewport[2] ëø öø ìø ÷ø ìø ÷ø ìø ÷ø pos3d _ y÷ø ìø ìø ÷ø (4) = INV(PM)2(winY - viewport[1]) -1 ìø ÷ø viewport[3] pos3d _ z ìø ÷ø ìø ÷ø ìøW ÷ø ìø2(winZ ) -1 ÷ø íø øø ìø ÷ø ìø1 ÷ø íø øø Obie funkcje do przeliczenia wspóBrzdnych wykorzystuj macierz modelowania (parametr model_view), macierz rzutowania (parametr projection) oraz wspóBrzdne okna renderingu (parametr viewport). Macierz modelowania mówi nam jak zmieni ukBad odniesienia sceny na ukBad odniesienia kamery. Druga macierz (macierz rzutowania) wprowadza do obrazu perspektyw [16]. Algorytm przesuwania [wiateB zaszyty jest w metodzie MoveLight (Listing 6.), który jako argumenty przyjmuje bie|c pozycj myszy na ekranie. Funkcja ta wywoBywana jest w GL_RysujScene(), czyli za ka|dym razem kiedy jest generowana scena. Listing 6. Funkcja MoveLight void __fastcall TGLGraf::MoveLight(int xPos, int yPos) { int nrLight = NrLightMove-1; if(HitsMove == 1 || HitsMove == 2) { if(nrLight >= 0 && nrLight <= 6) 15 { if(clickMouseMove) { float x = tabPropertiesLight[nrLight].GetPosLight(0); float y = tabPropertiesLight[nrLight].GetPosLight(1); float z = tabPropertiesLight[nrLight].GetPosLight(2); GLdouble pos3D_x, pos3D_y, pos3D_z; GLdouble winX, winY, winZ; GLdouble model_view[16]; glGetDoublev(GL_MODELVIEW_MATRIX, model_view); GLdouble projection[16]; glGetDoublev(GL_PROJECTION_MATRIX, projection); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); //szeroko[ i wysok[ obszaru renderingu int width = viewport[2]; int height = viewport[3]; gluProject(x,y,z,model_view, projection, viewport, &winX, &winY, &winZ); winX=xPos; winY = (float)viewport[3] - (float)yPos; gluUnProject(winX, winY, winZ,model_view, projection, viewport, &pos3D_x, &pos3D_y, &pos3D_z); tabPropertiesLight[nrLight].SetPosLight(0,(float)pos3D_ x); tabPropertiesLight[nrLight].SetPosLight(1,(float)pos3D_ y); tabPropertiesLight[nrLight].SetPosLight(2,(float)pos3D_ z); 16 SetPositionLight((float)pos3D_x, (float)pos3D_y, (float)pos3D_z); } } else clickMouseMove = false; } else clickMouseMove = false; } W MoveLight pocztkowo sprawdzamy czy zostaBo wybrane które[ ze zdefiniowanych zródeB [wiatBa ( wybór czyli selekcja zródBa [wiatBa jest opisana w rozdziale 3). Gdy zaznaczyli[my jedno ze zródeB [wiatBa mysz, zmienna clickMouseMove przyjmuje warto[ true. Jednocze[nie zmienna isClicked zmienia si na false co nie pozwala na rotacj modelu (wykresu, osi itd.). Zapamitujemy bie|ce poBo|enie zródBa [wiatBa (x,y,z). Nastpnie za pomoc funkcji glGetDoublev pobieramy macierz widoku modelu (u|ywana do rozmieszczenia elementów na scenie) oraz macierz rzutowania (u|ywanego do definiowania bryBy obcinania). Metoda glGetIntegerv pomo|e nam pobra aktualne wspóBrzdne okna. Gdy wszystkie parametry s ju| gotowe, przeliczamy wspóBrzdne (x,y,z) bie|cego [wiatBa na wspóBrzdne w przestrzeni okna (winX,winY,winZ). Nastpnie przypisujemy do zmiennych winX i winY bie|c pozycje myszki. Pamita nale|y |e wspóBrzdne okna w Windows maj punkt (0,0) w górnym lewym rogu, natomiast w OpenGL ma pocztek ukBadu wspóBrzdnych jest w dolnym lewym rogu. Dlatego nale|y wykona nastpujc operacj: winY = (float)viewport[3] - (float)yPos; Kolejnym krokiem jest przeliczenie wspóBrzdnych przestrzeni okna (winX,winY,winZ) na wspóBrzdne w przestrzeni widoku (pos3D_x, pos3D_y, pos3D_z) i zapamitanie aktualnej pozycji [wiatBa. W efekcie mo|emy swobodnie ustala pozycj zródeB [wiatBa w przestrzeni 3D klikajc na wybrane zródBo i przecigajc je. 17 3. Selekcja jako sposób zaznaczania obiektów 3.1. Selekcja OpenGL pozwala programi[cie tworzy grafik trójwymiarow. Uwzgldnia równie| mo|liwo[ interakcji u|ytkownika z zawarto[ci sceny wBczajc w to zaznaczanie obiektów. Selekcja, bardzo u|yteczny element OpenGL, umo|liwia kliknicie myszk w pewne miejsce okna i wyznaczanie obiektu, w obrbie którego nastpiBo to kliknicie. Zaznaczenie konkretnego obiektu nazywamy wybraniem. Tworzona jest wtedy specjalna matryca, oparta wyBcznie na wspóBrzdnych ekranu i rozmiarach w pikselach. Za pomoc tej matrycy mo|na stworzy bryB widzenia z wierzchoBkiem w poBo|eniu kursora myszy. Nastpnie mo|na u|y selekcji do sprawdzenia, jakie obiekty nale| do owej bryBy widzenia. 3.2. Tryby renderowania Tryb selekcji jest jednym z trzech trybów renderingu dostpnych w bibliotece OpenGL. W trybie tym |adne piksele nie s kopiowane do bufora ramki. Zamiast tego tworzona jest lista prymitywów [Dodatek A] których wierzchoBki przecinaj bryB widzenia [15]. BryBa widzenia stanowi ograniczenie sceny 3D, w zwizku z tym obiekty znajdujce si poza obszarem widzenia nie s rysowane, a te które ja przecinaj s rysowane tylko cz[ciowo. Z obszarem widzenia [ci[le zwizane jest rzutowanie. Okre[lamy go jako odwzorowanie zawarto[ci trójwymiarowej sceny graficznej na pBaskim ekranie monitora [15]. Biblioteka OpenGL oferuje standardowo dwie metody rzutowania: rzutowanie prostoktne i rzutowanie perspektywiczne. W programie GrafDyn zostaBo u|yte rzutowanie perspektywiczne, które pozwala na ocen odlegBo[ci przedmiotów od kamery, a tym samym daje bardziej realistyczny efekt. BryBa odcinania w tym przypadku ma posta [citego ostrosBupa (Rys. 2.). Jej parametry ustawiamy za pomoc funkcji: void glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far) 18 Parametry left, right, bottom i top wyznaczaj rozmiary górnej podstawy bryBy odcinania, a near i far wyznaczaj poBo|enie odpowiednio górnej i dolnej [ciany ostrosBupa. Funkcja ta mno|y jednostkow macierz rzutowania przez macierz perspektywy wygenerowan na podstawie argumentów funkcji, generujc w efekcie rzut perspektywiczny[16]. Rys. 2. BryBa widzenia w rzutowaniu perspektywicznym W programie GrafDyn wykorzystuj tryb selekcji do wybrania okre[lonych obiektów (zródBa [wiatBa) rysowanych w bryle widzenia. W trybie tym wykonywane s te przeksztaBcenia sceny, które wykonuje si w trybie renderowania, aby klikajc w dany obiekt trafi w to samo miejsce, w którym zostaB on narysowany. W buforze selekcji tworzone s rekordy trafieD. Aby móc z niego korzysta nale|y wcze[niej go przygotowa i ponadawa nazwy prymitywom lub grupie prymitywów (obiektom) w celu ich identyfikacji w buforze. Czst praktyk jest okre[lanie bryBy widzenia odpowiadajc wskaznikowi myszy, a nastpnie sprawdza si, który z nazwanych obiektów jest przez ni wskazywany. Kolejnym i jednocze[nie domy[lnym trybem w bibliotece OpenGL jest tryb renderowania. W odró|nieniu od selekcji, wykonywane tu operacje graficzne pojawiaj si 19 na ekranie. Ostatnim trybem jest tryb sprz|enia zwrotnego. Ró|ni si on od selekcji tym, |e w buforze sprz|enia zwrotnego tworzone s dane o wspóBrzdnych wierzchoBków prymitywów, skBadowych kolorów oraz wspóBrzdnych tekstur. Mo|na u|y tych informacji do przesyBania rezultatów renderowania przez sie, rysowania sceny za pomoc plotera czy te| Bczenia obiektów OpenGL z grafika GDI[1]. Aby móc korzysta z selekcji obiektów w bibliotece OpenGL trzeba zmieni tryb renderingu. Do zmiany trybu sBu|y funkcja: GLint glRenderMode (GLenum mode) której parametr mode przyjmowa mo|e jedn z nastpujcych warto[ci: " GL_RENDER  tryb renderowania, " GL_SELECT  tryb selekcji, " GL_FEEDBACK  tryb sprz|enia zwrotnego Warto[ zwracana przez funkcj glRenderMode zale|y od tryby renderingu. W przypadku trybu renderowania funkcja zwraca warto[ 0, a w trybie selekcji zwraca ilo[ rekordów trafieD znajdujcych si w buforze selekcji. 3.3. Stos nazw obiektów Nazwy obiektów, które mog zosta wybrane w trakcie selekcji przechowywane s na stosie jako cyfrowe identyfikatory w postaci liczb caBkowitych bez znaku. Po zainicjowaniu stosu mo|na odkBada na niego nazwy. Gdy podczas selekcji nastpi trafienie, wszystkie nazwy ze stosu s kopiowane do bufora selekcji. W zwizku z tym pojedyncze trafienie mo|e zwróci wicej ni| jedn nazw. Funkcja: glInitNames() jest odpowiedzialna za inicjalizacje pustego stosu nazw obiektów. Nazwy poszczególnym obiektom lub grupie obiektów, które maj by narysowane, nadaje si wywoBujc funkcj: 20 glLoadName(GLuint name), gdzie parametr name jest unikatowym identyfikatorem obiektu. Jednocze[nie nazwy w postaci liczb caBkowitych bez znaku, nie s odkBadane na stos nazw, lecz zastpuj bie|c nazw na szczycie stosu. Funkcj t nale|y wywoBa tu| przed narysowaniem prymitywu, któremu wBa[nie nadajemy nazw (Listing 7.). Czasem jednak w programie chcemy mie informacje o tym |e trafiony zostaB obiekt zwizany z innym obiektem. W takim przypadku ich nazwy nale|y umie[ci na bie|cym stosie przy u|yciu funkcji: void glPushName(GLuint name), gdzie parametr name jest unikatowym identyfikatorem obiektu. W ten sposób mo|emy wykrywa selekcje obiektów o hierarchicznej strukturze, poniewa| w na stosie mamy kilka nazw, które po trafieniu zostan umieszczone w buforze ( W moim kodzie nie u|ywam tej funkcji gdy| zródBo [wiatBa skBada si z jednego elementu (kula)). Na sam koniec trzeba zdj nazw obiektu ze stosu, co wymaga u|ycia funkcji: void glPopName(); Wielko[ stosu nazw nie mo|e by mniejsza ni| 64, a niedomiar lub przepeBnienie stosu powoduje zgBoszenie bBdów GL_STACK_UNDERFLOW i GL_STACK_OVERFLOW [15]. Listing 7. Funkcja RenderLights void __fastcall TForm1::RenderLights(void) { bool enabled; // inicjalizacja stosu nazw obiektów glInitNames(); // odkBada na stos identyfikator 0 w celu wypeBnienia stosu przynajmniej jedn nazw 21 glPushName(0); for(int nrLight = 0; nrLight<lengthTabLight; nrLight++) { if(existLight[nrLight]) { enabled = glIsEnabled(tabLight[nrLight]); glPushMatrix(); if(enabled) glColor3f(1.0f,1.0f,1.0f); else glColor3f(1.0f,0.0f,0.0f); glLoadName(nrLight+1); RysujLampe(nrLight); glPopMatrix(); } } } W funkcji RenderLights(void) (Listing 7.) nadawane s nazwy tylko tym zródBom [wiatBa które s zdefiniowane . Dodatkowo wBczone [wiatBa otrzymuj kolor biaBy, a wyBczone kolor czerwony. 3.4. Bufor selekcji  przetwarzanie rekordów trafieD Podczas renderowania bufor selekcji jest wypeBniany rekordami trafieD. Rekord trafienia jest generowany za ka|dym razem, gdy renderowany prymityw przecina bryB widzenia[1]. Aby móc korzysta z selekcji obiektów nale|y ustawi odpowiednio bufor selekcji. Wymaga to wywoBania funkcji: void glSelectBuffer(GLsize size, GLuint *buffer) gdzie parametr size okre[la wielko[ bufora, do którego wskaznik zawiera parametr buffer. Bufor selekcji to tablica liczb caBkowitych bez znaku. Powinien by on na tyle du|y, aby zmie[ci informacje o wszystkich obiektach wybranych w wyniku selekcji [15]. Bardzo wa|ne jest aby ustawi bufor selekcji przed przeBczeniem biblioteki OpenGL w 22 tryb selekcji. Ka|dy rekord selekcji zajmuje przynajmniej cztery elementy tablicy (Listing 8.). Pierwsza pozycja tablicy zawiera ilo[ nazw na stosie w momencie wystpienia trafienia. Kolejne pozycje zawieraj minimaln i maksymaln warto[ wspóBrzdnych z prymitywów graficznych wchodzcych w skBad wybranego obiektu. Te warto[ci z zakresu <0 ,1>, s pomno|one prze 232  1 i zaokrglone do najbli|szej liczby caBkowitej. Listing 8. Bufor selekcji Bufor selekcji [0]  ilo[ nazw na stosie nazw w momencie trafienia Bufor selekcji [1]  minimalna warto[ wspóBrzdnych Z Bufor selekcji [2]  maksymalna warto[ci wspóBrzdnych Z Bufor selekcji [3]  najni|szy element stosu nazw obiektów . . . Bufor selekcji [n]  najwy|szy element sotsu nazw obiektów Trzeba pamita, |e z bufora selekcji nie mo|na wycign informacji o ilo[ci rekordów trafieD. Jest tak poniewa| bufor selekcji nie jest wypeBniany, a| do momentu powrotu do trybu GL_RENDER. Ilo[ wybranych obiektów zwraca funkcja glRenderMode w momencie powrotu do domy[lnego trybu renderowania, czyli po zakoDczeniu pracy w trybie selekcji. 3.5. Wybieranie obiektów W programie mo|emy stworzy siedem niezale|nych zródeB [wiatBa, ale tylko aktywne poddawane s selekcji. Wybieranie nastpuje wtedy, gdy podczas selekcji wykorzystuje si poBo|nie myszy do utworzenia bryBy obcinania. Gdy utworz mniejsz bryB widzenia znajdujc si na scenie w miejscu wskaznika myszy, generowane bd trafienia dla tych obiektów, które przecinaj bryB widzenia. Nastpnie sprawdzam zawarto[ bufora selekcji i mog prze[ledzi na których obiektach nastpiBo kliknicie mysz. Aby ograniczy bryB widzenia (Listing 9.), tak aby obejmowaBa blisk okolic punktu, w którym zostaB naci[nity przycisk myszki najlepiej wykorzysta funkcje z biblioteki GLU: 23 void gluPickMatrix( GLdouble x, GLdouble y, GLdouble width, GLdouble height, const GLint viewport[4]) Parametry x i y okre[laj wspóBrzdne [rodka nowej bryBy obcinania (wspóBrzdne okienkowe), w których wyra|ona jest pozycja myszy. Kolejne parametry width i height okre[laj szeroko[ i wysoko[ bryBy widzenia w pikselach okna [1]. Je|eli chcemy klika w pobli|u obiektu trzeba u|y wikszych warto[ci, jednak w moim przypadku kliknicia bd bezpo[rednio na obiektach, dlatego te| u|yBem mniejszych warto[ci. Tablica viewport zawiera dane opisujce aktualne rozmiary okna. Dane te najlepiej jest pobra wywoBujc funkcj glGetIntegerv z parametrem GL_VIEWPORT (glGetIntegerv(GL_VIEWPORT, viewport)). . Listing 9. Funkcja ProcessSelection void __fastcall TGLForm::ProcessSelection(int xPos, int yPos) { int hits; // buffor selekcji GLuint selectBuff[BUFFER_LENGTH]; //przygotowanie buffora selekcji glSelectBuffer(BUFFER_LENGTH, selectBuff); // pobranie obszaru renderingu // int viewport[4]; // glGetIntegerv(GL_VIEWPORT, viewport); //szeroko[ i wysok[ obszaru renderingu int width = viewport[2]; int height = viewport[3]; // wybor macierzy rzutowania glMatrixMode(GL_PROJECTION); 24 // odlozenie macierzy rzutowania na stos glPushMatrix(); // wlaczenie trybu selekcji glRenderMode(GL_SELECT); // marierz rzutowania = macierz jednostkowa glLoadIdentity(); // parametry bryly obcinania (jednostkowa kostka) gluPickMatrix(xPos,height - yPos, 2, 2, viewport); //parametyr bryly obcinania float wsp=(float)height/(float)width ; glFrustum(-0.1, 0.1, wsp*-0.1, wsp*0.1, 0.3, 1000.0); // generowanie sceny 3D GL_RysujScene(); // zliczanie ilo[ci rekordow trafien i powrot do domyslnego trybu renderowania hits = glRenderMode(GL_RENDER); // wybor macierzy rzutowania glMatrixMode(GL_PROJECTION); // zdjecie macierzy rzutowania ze stosu glPopMatrix(); glMatrixMode(GL_MODELVIEW); if(hits) MakeSelection(selectBuff, hits); } Zanim u|yjemy jednak funkcji gluPickMatrix, musimy przechowa bie|cy stan macierzy rzutowania na stosie. Nastpnie trzeba zaBadowa do macierzy rzutowania 25 macierz jednostkow poprzez wywoBanie funkcji glLoadIdentity(). Dopiero teraz mo|emy zmodyfikowa now bryB widzenia tak aby obejmowaBa jedynie obszar pod wskaznikiem myszki. Bardzo wa|ne jest aby ustawi macierz rzutowania perspektywicznego glFrustum takie jakie zostaBo u|yte w oryginalnej scenie gdy| w przeciwnym razie nie otrzymamy wBa[ciwego odwzorowania[1]. Nastpnie wywoBujemy GL_RysujScene(), gdzie wykonywany jest etap renderingu sceny. Po odrysowaniu sceny ponownie wywoBujemy funkcje glRenderMode(GL_RENDER) w celu przeBczenia OpenGL do trybu renderowania. Po powrocie do tego trybu otrzymujemy ilo[ wygenerowanych rekordów trafieD i wypeBniony bufor selekcji odpowiednimi danymi. hits = glRenderMode(GL_RENDER) Po ustaleniu ilo[ci rekordów trafieD trzeba dokona analizy zawarto[ci bufora selekcji. W tym celu do naszej funkcji MakeSelection (Listing 10.) przekazujemy tablice selectBuff oraz zmienn hits przechowujc ilo[ rekordów trafieD. Listing 10. Funkcja MakeSelection void __fastcall TGLGraf::MakeSelection(GLuint select, int hits) { NrLightMove = select; HitsMove = hits; AnsiString NrLight = IntToStr(select); if(hits == 1) { if(select >= 1 && select <= 7) { lightStr = "Swiatlo Nr "+ NrLight; GLOswietlenieForm->ChangeLight(select-1); clickMouseMove = true; } } if(hits == 2) { if(select >= 1 && select <= 7) 26 { lightStr = "Swiatlo Nr "+ NrLight; GLOswietlenieForm->ChangeLight(select-1); clickMouseMove = true; } } GL_RysujScene(); } Funkcja MakeSelection wy[wietla w prawym dolnym rogu numer [wiatBa, na które nastpiBo kliknicie, jego aktualn pozycj oraz przekazuje do programu wszystkie wBa[ciwo[ci zwizane z tym [wiatBem(Rys.3.). Rys. 3. Wykres z zaznaczonym zródBem [wiatBa numer 2 W momencie kliknicia lewym przyciskiem myszki wywoBywany jest komunikat WM_LBUTTONDOWN, który odpowiedzialny jest za przekazanie odpowiednich wspóBrzdnych myszy (przechowywanych w parametru LParam) do aplikacji. S one przekazywane dalej do funkcji ProcessSelection (Listing 11.). W programie nastpuje wówczas przetwarzanie kliknicia myszki. 27 Listing 11. Odbiór komunikatu WM_LBUTTONDOWN case WM_LBUTTONDOWN: X0=LOWORD(Message.LParam); //biezaca poz. x kursora Y0=HIWORD(Message.LParam); //biezaca poz. y kursora ProcessSelection(X0,Y0); 28 4. Sprz|enie zwrotne W tym rozdziale omówi sprz|enie zwrotne, które podobnie jak selekcja jest trybem renderowania, w którym nic faktycznie nie jest rysowane na ekranie. Sprz|enie zwrotne nie jest zaimplementowane w naszym programie, ale warto o nim wspomnie aby lepiej zrozumie sposób wybierania obiektów dostpnych i dopeBni informacje o trybach renderowania. Swoj budow bufor sprz|enia zwrotnego bardzo przypomina bufor selekcji, z t jednak ró|nic, |e zamiast tablicy liczb caBkowitych mamy do czynienia z tablic liczb zmiennoprzecinkowych typu GLfloat [15]. Wpisywane s tam informacje na temat sposobu renderowania sceny. 4.1. Tryb renderowania Aby móc skorzysta ze sprz|enia zwrotnego nale|y zmieni tryb renderowania. Podobnie jak w trybie selekcji wykonuj si to poprzez wywoBanie funkcji glRenderMode. Tym razem z parametrem GL_FEEDBACK. Aby wypeBni bufor sprz|enia zwrotnego i powróci do domy[lnego trybu renderowania nale|y wywoBa funkcj glRenederMode(GL_RENDER). 4.2. Buffor sprze|enia zwrotnego Za utworzenie bufora sprz|enia zwrotnego odpowiedzialna jest funkcja: Void glFeedbackBuffer(GLsizei size, GLenum type, GLfloat *Buffet) gdzie parametr size okre[la wielko[ tablicy wskazywanej w parametrze buffer, a rodzaj danych przekazywanych do bufora zwrotnego okre[la parametr type [15]. Dostpne warto[ci dla typu danych zostaBy okre[lone w tabeli (Tab.1.). 29 Typ WspóBrzdne SkBadowe WspóBrzdne wierzchoBka koloru tekstury GL_2D (x,y) - - GL_3D (x,y,z) - - GL_3D_COLOR (x,y,z) (R,G,B,A) - GL_3D_COLOR_TEXTURE (x,y,z) (R,G,B,A) (s,t,r,q) GL_4D_COLOR_TEXTURE (x,y,z,w) (R,G,B,A) (s,t,r,q) Tab.1. Typy danych zwracanych w buforze sprz|enia zwrotnego. W OpenGL dane zwizane z kolorem reprezentowane s przez cztery skBadowe RGBA albo pojedyncza warto[  numer indeksu koloru. WspóBrzdne x, y, z poBo|enia wierzchoBków podawane s w odniesieniu do wspóBrzdnych renderingu. 4.3. Dane bufora sprz|enia zwrotnego W buforze sprz|enia zwrotnego mieszcz si specjalne znaczniki, które oddzielaj dane. Znaczniki identyfikowane s przez nastpujce staBe[1]: " GL_POINT_TOKEN  punkty, " GL_LINE_TOKEN  linie, " GL_LINE_RESET_TOKEN  segment linii po wyzerowaniu wzorca linii " GL_POLYGON_TOKEN  wielokt, " GL_BITMAP_TOKEN  bitmapa, " GL_DRAW_PIXEL_TOKEN  mapa pikselowa " GL_COPY_PIXEL_TOKEN  kopiowanie mapy pikselowej " GL_PASS_THROUGH_TOKEN  znacznik zdefiniowany przez u|ytkownika. Po znaczniku w buforze wystpuj dane pojedynczego wierzchoBka oraz ewentualnie dane koloru i tekstury [1]. Wszystko zale|y od parametru type funkcji glFeedbackBuffer. W przypadku GL_LINE_TOKEN, GL_LINE_RESET_TOKEN zwracane s dwa zestawy danych wierzchoBków, a po GL_POLYGON_TOKEN wystpuje warto[ okre[lajca ilo[ wierzchoBków wielokta. Bezpo[rednio po GL_POINT_TOKEN, GL_BITMAP_TOKEN, GL_DRAW_PIXEL_TOKEN, GL_COPY_PIXEL_TOKEN bd to 30 dane pojedynczego wierzchoBka. Poni|ej przedstawiam przykBadow zawarto[ci bufora sprz|enia zwrotnego: Bufor sprz|enia zwrotnego: [0]  GL_POINT_TOKEN [1]  WspóBrzdna x [2]  WspóBrzdna y [3]  WspóBrzdna z [4]  GL_PASS_THROUGH_TOKEN [5]  Dowolna warto[ zdefiniowana przez u|ytkownika [6]  GL_POLYGON_TOKEN [7]  Ilo[ wierzchoBków wielkta [8]  WspóBrzdna x pierwszego wierzchoBka [9]  WspóBrzdna y pierwszego wierzchoBka [10]  WspóBrzdna z pierwszego wierzchoBka [11] - WspóBrzdna x drugiego wierzchoBka & W trybie sprz|enia zwrotnego mo|na utworzy znacznik zdefiniowany przez u|ytkownika. Aby to zrobi nale|y wywoBa funkcj: void glPassThrough(GLfloat token) Ta funkcja umieszcza element GL_PASS_THROUGH_TOKEN w buforze selekcji, a bezpo[rednio po nim warto[ podana przy wywoBaniu funkcji [1]. 4.4. Podsumowanie Sprz|enie zwrotne, tak jak selekcja, jest bardzo przydatnym elementem biblioteki OpenGL, sBu|cym do identyfikacji obiektów. Zwraca informacje dotyczce poBo|enia rysowanych prymitywów we wspóBrzdnych okna. 31 5. GrafDyn  program do wizualizacji danych Zadaniem programu GrafDyn jest wy[wietlanie funkcji dwóch zmiennych zapisanych w pliku tekstowym (raw data). Domy[lnie wczytuje on dwa rodzaje plików, cho dziki moduBowi importu mo|liwe jest w zasadzie wczytywanie danych z ka|dego rodzaju pliku tekstowego. Domy[lne formaty rekordów rozpoznawane s przez program po nastpujcych szablonach nazw plików: *.plt, plt*.dat i psi*.dat (Listing 12.). Listing 12. Plik typu plt*.dat #Funkcja falowa w t=0 (0) #Kwadrat modulu |Psi(x,y)|^2 #Parametry sieci x: 256 (-100,100), y: 256 (-100,100), t: 10 (0,0.0628319) # #x y norm(Psi(x,y)) -100 -100 1.03775e-28 -99.2157 -100 1.30337e-28 -98.4314 -100 1.63553e-28 -97.6471 -100 2.05049e-28 -96.8627 -100 2.56839e-28 Pierwszy i drugi zawiera warto[ci funkcji wraz z odpowiadajcymi jej wspóBrzdnymi x i y. W nagBówku tego pliku zawarte s parametry sieci. Nie s one jednak wykorzystywane przez program. Parametry te mog by odczytane z osobnego pliku lub wpisane w trakcie do importu danych. Drugi typ plików (psi*.dat) zawiera tylko dwie kolumny danych z cz[ci rzeczywist i urojon funkcji (bez wspóBrzdnych przestrzennych). W programie GrafDyn zostaB zaimplementowany moduB importu plików, który odczytuje funkcj z plików tekstowych i zapisuje do odpowiedniej tablicy. ModuB ten wczytuje równie| parametry sieci przestrzennej z pliku z rozszerzeniem .par. Struktura pliku parametrów opisana jest w listingu 13. Jego pierwsza linia zawiera wersj pliku. Z punktu widzenia naszego programu najwa|niejsze s linie druga i trzecia, które zawieraj informacje o wielko[ci i zakresie sieci, a mianowicie: ilo[ wzBów oraz minimaln i maksymaln warto[ wspóBrzdnych dla danej osi. 32 Listing 13. Struktura pliku z rozszerzeniem typu par Schemat: PrzykBad: wersja 1.00000000000000e+00 N , xmin, xmax 256 -1.00000000000000e+02 1.00000000000000e+02 x N , ymin, ymax 256 -1.00000000000000e+02 1.00000000000000e+02 y Nt , tmin , dt 1000 0.00000000000000e+00 6.28318530717957e-03 Po wczytaniu pliku parametrów i pliku danych w programie pojawi sie wykres, który w zale|no[ci od naszych potrzeb mo|emy obraca, skalowywa, czy dobiera sposób kolorowania. Mo|emy tak|e definiowa zródBa [wiatBa (w OpenGL jest ich maksimum osiem). 5.1. Instalacja Aby móc korzysta z programu GrafDyn, musimy go zainstalowa na naszym komputerze. Instalacja przebiega wedBug standardowego kreatora, który krok po korku prowadzi nas przez kolejne etapy pozwalajc na wybór odpowiedniej konfiguracji. W pierwszym okienku zostanie wy[wietlona informacja o tym |e przystpujemy do instalacji programu GrafDyn ver. 1.0 ( Rys. 4.). Rys. 4. Instalacja - powitanie 33 Po klikniciu klawisza Next mamy mo|liwo[ wyboru katalogu w którym zainstaluje si program. Standardowo program instalujcy proponuje C:\Program Files\GrafDyn (Rys. 5.). Rys. 5. Instalacja  wybór katalogu W kolejnym okienku instalator stworzy nam nowy folder o nazwie GrafDyn w Start Menu (Rys. 6.). Rys. 6. Instalacja  skrót start menu Po wyborze program instalacyjny zapyta nas o to, czy chcemy umie[ci skrót do programu GrafDyn na pulpicie (Rys. 7.). 34 Rys. 7. Instalacja  skrót pulpit Przed sam instalacj pojawi si jeszcze krótkie podsumowanie naszych ustawieD i je|eli wszystko si zgadza mo|emy przystpi do instalacji programu GrafDyn (Rys. 8.) klikajc przycisk Install. Rys. 8. Instalacja - podsumowanie Je|eli wszystko przebiegBo bez |adnych problemów zobaczymy okienko z informacj o poprawnym zainstalowaniu programu (Rys.9.). Po zakoDczonej instalacji mo|emy przystpi do pierwszego uruchomienia programu. 35 Rys. 9. Instalacja -koniec 5.2. Interfejs aplikacji GrafDyn Po uruchomieniu programu GrafDyn, uka|e si nam gBówny interfejs aplikacji (Rys. 10.), na którym znajduj si wszystkie wa|ne funkcje potrzebne do zaimportowania, obracania oraz przeksztaBcania naszego wykresu. Rys. 10. Program GrafDyn Interfejs skBada si z gBównego menu, informacji o pliku z danymi, który aktualnie jest wczytany oraz paska narzdzi. W tym pierwszym mamy pola takie jak: " Narzdzia  sBu|y do wybrania o[wietlenia oraz wBasno[ci wykresu, " Wykres  wBcza okno, w którym wy[wietlony jest wykres (Rys.11.), " Import - uruchamia moduB importu danych z plików, " Pomoc  wy[wietla informacje o wersji OpenGL. 36 Rys. 11. Program GrafDyn W pasku narzdzi znajduj si ikonki sBu|ce do szybkiego uruchamiania odpowiednich narzdzi (o[wietlenie, wBasno[ci wykresu, wykres i import). Po najechaniu kursorem myszki nad odpowiedni ikon, system wy[wietla peBn jego nazw. 5.3. ModuB importu ModuB importu danych jest zaprojektowany na wzór analogicznego kreatora w Excelu, cho bardziej rozbudowany. SBu|y on do tego, aby nawet niezaawansowany u|ytkownik aplikacji mógB wybierajc krok po kroku odpowiednie ustawienia wczyta dane z dowolnego pliku. Po uruchomieniu funkcji Importu wy[wietli si pierwsze okno kreatora (Rys 12.), w którym mamy mo|liwo[ wskazania pliku wpisujc jego nazw w polu tekstowym lub wybierajc go za pomoc standardowego okna dialogowego Windows. 37 Rys. 12. ModuB importu  wybieranie pliku Kliknicie przycisku Dalej, powoduje uruchomienie kolejnego kroku kreatora (Rys. 13.), w którym mamy mo|liwo[ wyboru znaku u|ywanego do oznaczenia linii komentarza. Podczas importu program bdzie omijaB te linie w pliku, które rozpoczynaj si od tego znaku. Mamy mo|liwo[ wyboru znaku z listy lub zdefiniowania wBasnego. Rys. 13. ModuB importu  znak komentarza, ilo[ wczytywanych danych 38 Mo|emy te| wybra krok, z którym program bdzie odczytywaB linie z pliku. Dziki temu mo|na wizualizowa nawet bardzo du|e pliki narzucajc uwzgldnianie np. co drugiej, co trzeciej lub co dziesitej linii. W kolejnym oknie zostaniemy poproszeni o wybór parametrów sieci oraz zakres wy[wietlanych danych (Rys. 14.). Jak wspomniaBem wcze[niej, parametry sieci mo|emy wczyta z pliku .par. Mo|emy te| wpisywa je do odpowiednich pól edycyjnych. Oczywi[cie musimy uwa|a, aby byBy one poprawne. S one bowiem konieczne do poprawnego odczytania danych z pliku. W tym samym oknie mo|liwe jest równie| ograniczenie obszaru, dla którego prezentujemy wykres (clipping). Rys. 14. ModuB importu  parametry sieci Przed ostatecznym wczytaniem pliku musimy wybra znak separacji pól z danymi w tej samej linii (rekordzie). Do wyboru mamy: spacja, tabulator, [rednik, przecinek dwukropek. Mo|emy równie| zdefiniowa wBasny znak podziaBu. Na wzór moduBu importu danych Excela w oknie kreatora (Rys. 15.) wy[wietlanych jest kilkana[cie pierwszych linii pliku, które pomagaj wybra znak separacji. W tym samym oknie znajduje si te| pole wyboru pozwalajce wybra rodzaj pliku, jaki wczytujemy W przypadku plików *.plt lub plt*.dat musimy wybra jedn kolumn zawierajc warto[ci funkcji (wspóBrzdna z), za[ w przypadku plików *.dat wybieramy dwie kolumny odpowiadajce cz[ci rzeczywistej i urojonej zespolonej warto[ci funkcji. W tym przypadku na wykresie pokazywany bdzie kwadrat moduBu funkcji. W obu przypadkach wspóBrzdne x i y 39 ustalane bd na podstawie parametrów sieci (zakresy i ilo[ci wzBów)  zakBadamy przy tym |e sie jest jednorodna. Przed wczytaniem pliku, w ka|dym momencie mo|emy cofn si do dowolnego okna kreatora i zmieni ka|de z ustawieD. Je|eli jednak cofniemy si a| do pierwszego kroku i zmienimy plik danych, to we wszystkich polach zostan przywrócone standardowe warto[ci. Rys. 15. ModuB importu  znak podziaBu, kolumna z danymi Po klikniciu przycisku Wczytaj w ostatnim oknie kreatora nastpi wczytanie danych z pliku do programu. Postp wczytywania widoczny jest na pasku postpu (Rys. 16.). Je|eli w trakcie wczytywania nie wystpiB bBd, zostaniemy poinformowani, |e proces importu zakoDczyB si sukcesem. W przeciwnym przypadku pojawi si komunikat o bBdzie. 40 Rys. 16. ModuB importu  wczytywanie danych Wreszcie, po zakoDczeniu importu wy[wietli si wykres funkcji. Mo|emy nim swobodnie obraca i modyfikowa wygld wykresu (zob. opis w kolejnych podrozdziaBach). 5.4. O[wietlenie ZwiatBo ma ogromny wpByw na postrzeganie obiektów na scenie, gdy| w rzeczywistym [wiecie nie liczy si tylko kolor obiektu. Ka|dy przedmiot mo|e si wydawa l[nicy lub matowy, a jego kolor mo|e by inny w jasnym lub ciemnym o[wietleniu. OpenGL pozwala symulowa ró|ne zródBa [wiatBa i opisywa sposoby jego emisji. Biblioteka ta obsBuguje do o[miu niezale|nych zródeB [wiatBa. W programie jednak mamy mo|liwo[ zdefiniowania tylko siedmiu, gdy| jedno u|yte jest do okre[lenia globalnego [wiatBa otaczajcego. Pozwala ono o[wietli wszystkie obiekty równomiernie ze wszystkich stron. Aby w programie GrafDyn doda [wiatBo wystarczy wcisn przycisk Dodaj (Rys. 17.).Wówczas na ekranie pojawi si nowe zródBo [wiatBa w postaci kuli z odpowiednim numerem. Zaznaczone [wiatBo mo|na równie| usun ze sceny wciskajc przycisk UsuD. Warto pamita, |e po tej operacji bezpowrotnie stracimy ustawione wBa[ciwo[ci usunitego zródBa [wiatBa. Je[li z jaki[ powodów chcemy, |eby cz[ elementów nie byBa o[wietlona, mo|emy w ka|dej chwili wyBczy okre[lone o[wietlenie (przycisk WyBcz (Rys. 17.)) zachowujc jego wBa[ciwo[ci. Nieaktywne zródBo [wiatBa 41 przyjmuje wówczas kolor czerwony. Mo|emy oczywi[cie wBczy go ponownie wciskajc przycisk WBcz. Aktywne [wiatBo ma kolor biaBy i bierze udziaB w o[wietlaniu sceny. Rys. 17. O[wietlenie  kolory [wiatBa OpenGL wykorzystuje lambertowski model [wiatBa, co oznacza, |e zródBa [wiatBa okre[lane s za pomoc trzech skBadowych R (czerwony), G (zielony) i B (niebieski), definiujcych barw promieni [20]. Ponadto ka|de zródBo [wiatBo mo|emy opisa za pomoc trzech ró|nych rodzajów o[wietlenia (Rys. 17.): " ZwiatBo otaczajce (Ambient Light)  o[wietla jednakowo ka|d powierzchni wykresu (zródBo nie ma okre[lonej pozycji), " ZwiatBo rozproszone (Diffuse Light) - charakteryzuje si tym, |e jego promienie biegn z konkretnego miejsca dziki czemu jasno[ powierzchni zale|y od ustawienia wzgldem zródBa, " ZwiatBo odbBysku (Specular Light), podobnie jak rozproszone ma ustalon pozycj, a ponadto tak|e kierunek. Odbija si od o[wietlanej powierzchni 42 tylko w jednym kierunku tworzc rozbBysk gdy na drodze promieni odbitych znajduje si kamera. W programie mo|emy ustali parametry o[wietlenia w formularzu lub wBczy palet kolorów i wybra odpowiedni kolor. W podoknie O[wietlenie mamy tak|e mo|liwo[ zmiany parametrów [wiatBa otaczajcego dla caBej sceny, które jest niezale|ne od pozostaBych zródeB. Dziki temu nie musimy wBcza caBego moduBu o[wietleniowego, aby obiekty na scenie byBy widoczne. Jego nat|enie ustawiamy w zakresie od 1 do 10 za pomoc suwaka. Rys. 18. O[wietlenie  strumieD [wiatBa W zakBadce StrumieD ZwiatBa (Rys. 18.) mamy mo|liwo[ zdefiniowania innych wBasno[ci zródBa [wiatBa takich jak: " GL_SPOT_DIRECTION - okre[la kierunek strumienia [wiatBa, czyli kierunek, w którym zostanie skierowany "reflektor", " GL_SPOT_EXPONENT - okre[la intensywno[ [wiatBa. Przyjmuje warto[ci z przedziaBu [0-128], 43 " GL_SPOT_CUTOFF - okre[la kt sto|ka [wiatBa kierunkowego. Rys. 19. O[wietlenie  pozycja [wiatBa W ostatniej zakBadce (Rys. 19.) mamy mo|liwo[ zmiany pozycji zródBa [wiatBa, podajc jego wspóBrzdne x, y i z. W górnym okienku narzdzia O[wietlenie mamy wy[wietlon list wszystkich zdefiniowanych zródeB [wiatBa. Przechodzc po kolei po ka|dym zródle mo|emy obejrze jego wBasno[ci. Wybór zródBa [wiatBa mo|emy równie| dokona poprzez jego kliknicie w oknie wykresu (posta kuli z numerem [wiatBa). Implementacj tej mo|liwo[ci opisuje rozdziaB 2 dotyczcy trybu selekcji w OpenGL. Nale|y pamita, |e ka|dy zdefiniowany w OpenGL obiekt ma wBasne kolory rozumiane jako wBasno[ materiaBu. Kolor widziany na ekranie powstaje przez uwzgldnienie tego koloru oraz koloru zródBa [wiatBa. Dobranie [wiatBa tak, aby uzyska po|dany efekt wymaga od u|ytkownika odrobiny praktyki. 44 5.5. WBasno[ci wykresu Program GrafDyn daje u|ytkownikowi spore mo|liwo[ci manipulowania wykresem. Do tego celu sBu|y podokno Wykres, które jest dostpne z paska narzdzi lub menu gBównego aplikacji. Narzdzie to pozwala ustawi okre[lone wBasno[ci wy[wietlanej funkcji, jak równie| ustawi pewne wBasno[ci dotyczce okna wykresu. W pierwszej zakBadce o nazwie Kolory (Rys. 20.) mamy mo|liwo[ wyboru palety barw, która zmienia kolory u|yte do rysowania funkcji. Algorytm zaimplementowany w programie wyznacza skBadowe koloru odpowiadajce warto[ciom z wyznaczonego zakresu danych. Pierwszy okre[la jednolity kolor  jednakowy kolor dla wszystkich naszych danych (oczywi[cie przy wBczonych zródBach [wiatBa jasno[ wykresu nadal bdzie ró|na w ró|nych punktach ze wzgldu na cieniowanie). Rys. 20. WBasno[ci wykresu  kolory Barwa Szara to paleta w której mamy do czynienia z jednym przedziaBem. Warto[ci wszystkich skBadowych s sobie równe i wyznaczone z prostej proporcji (Listing 14.). 45 Listing 14. Barwa Szara rgb_triplet Color; Color.r = 0; Color.g = 0; Color.b = 0; double delta = maxVal - minVal, dp =data_Val - minVal; if (!delta) return Color; Color.r = (255*dp/delta); Color.g = (255*dp/delta); Color.b = (255*dp/delta); return Color; Kolejna paleta One jest oparta o algorytm, w którym warto[ci dzielimy na przedziaBy. Ka|dy z nich odpowiada zmianie jednej ze skBadowych koloru. Nastpnie po wczytaniu danych przypisujemy ka|dej warto[ci odpowiedni przedziaB i wyliczamy odpowiednie warto[ci skBadowych koloru. Ostatnie dwie palety Temp i Sun wykorzystuj bibliotek funkcji graficznych z pliku colormaps.cpp, której autorem jest dr Jacek Matalewski. Ka|da zmiana palety barw wymaga ponownego wyznaczenia kolorów dla ka|dej warto[ci wy[wietlanych danych. W kolejnej zakBadce o nazwie WypeBnienie (Rys. 21.) mamy mo|liwo[ ustawienia kolejnego stylu wy[wietlania naszych danych. Po wybraniu przycisku Punkty, dane na wykresie bd przedstawione w formie punktów. Podobnie po wybraniu wBasno[ci Linie, dane wy[wietla si nam w oknie w postaci linii. Najciekawsz i najbardziej naturaln a zarazem najtrudniejsz do zaimplementowania jest wBasno[ Powierzchnia. Aby wykres Badnie si prezentowaB wymagaBo to wyznaczenia normalnych do powierzchni. Wykres zBo|ony jest z poBczonych pasków czworoktów za pomoc parametru GL_QUAD_STRIP. Paski bd tworzone ze wszystkich werteksów wywoBywanych w trakcie wykonywania ptli. Powierzchnia taka ma Badny i jednolity ksztaBt. 46 Rys. 21. WBasno[ci wykresu  wypeBnienie W zakBadce Osie (Rys. 22.) mamy mo|liwo[ manipulowania osiami. Mo|emy wyBczy wszystkie osie jak równie| opisy poszczególnych z nich. Dostpny jest te| parametr pozwalajcy na ustawienie grubo[ci osi. Osie X i Y przyjmuj warto[ci z zakresu wy[wietlania, który podali[my podczas importu danych. O[ Z posiada zakres wyznaczony przez minimaln i maksymaln warto[ wczytanej z pliku funkcji. 47 Rys. 22. WBasno[ci wykresu  osie W ostatniej zakBadce (Rys. 23.) mo|emy przeskalowa nasz wykres. Gdyby[my tego nie zrobili, to po wczytaniu danych z niektórych plików, wygldaBoby one jakby miaBy t sam warto[ w ka|dym punkcie. Dzieje si tak, gdy| dane maj zbyt maB warto[ w porównaniu z rozmiarami sieci i nie widzimy |adnej interesujcej nas struktury. Aby móc zobaczy wykres, musimy przeskalowa dane z pliku do wikszej warto[ci. Dlatego te| w programie zostaBa zaimplementowana wBasno[ skala, która pozwala u|ytkownikowi samemu wybra do jakiej liczby chce skalowa wykres. 48 Rys. 23. WBasno[ci wykresu  skala 49 6. Podsumowanie Program GrafDyn zostaB napisany z my[l o wy[wietlaniu funkcji dwóch zmiennych u|ywajc do tego biblioteki OpenGL. Dziki tej bibliotece dziaBa znacznie szybciej ni| analogiczny moduB w popularnym programie gnuplot. Dane s wczytywane za pomoc specjalnego moduBu importu, który pozwala u|ytkownikowi na ustawienie wBasno[ci wczytywanych plików bez ingerencji w kod programu. Dodatkowym atutem GrafDyn jest mo|liwo[ personalizacji sposobu, w jaki funkcja jest wy[wietlania (zmiana barwy, opis osi, legenda). Mamy mo|liwo[ wBasnego definiowania zródeB [wiatBa i ustawienia dowolnego o[wietlenia na scenie. Mo|liwo[ interakcji u|ytkownika ze scen, powoduje, |e obsBuga programu jest intuicyjna.. Program zostaB napisany tak, aby mo|na go byBo rozszerza o kolejne funkcjonalno[ci bez wikszej ingerencji w dotychczasowy kod programu. Uwa|am, |e napisany przeze mnie program GrafDyn nie tylko stanie si u|ytecznym narzdziem do wy[wietlana funkcji dwóch zmiennych ale równie| bdzie niezawodnie sBu|yB swoim nowym u|ytkownikom w przejrzystym obrazowaniu wykresów. 50 7. Literatura [1] R.S. Wright, M. Sweet, Ksiga eksperta, Helion, Gliwice (1999). [2] K. Hawkins, D. Stale, OpenGL Programowanie Gier, Helion, Gliwice(2003). [3] B. Eckel, C. Allison, Thinking In C++ Tom 2, Helion, Gliwice(2004). [4] J. Grbosz, Symfonia C++, Edition 2000, Kraków (2000). [5] R.Eisberg, R.Resnick, Fizyka kwantowa, PWN, Warszawa (1983). [6] R.L.Liboff, Wstp do mechaniki kwantowej, PWN, Warszawa (1987). [7] http://nehe.gamedev.net - Strona po[wiecona grafice 3D wykorzystujca bibliotek OpenGL. [8] http://www.dimmension3.spine.pl/index.php - strona po[wicona programowaniu grafiki 3D. [9] http://www.3d.pl  strona po[wicona grafice 3D. [10] http://www.talisman.org/opengl-1.1/OpenGL.html - strona po[wiecona OpenGL. [11] http://ddt.pl/kursy/?TutorialId=10  strona zawierajca kurs OpenGL. [12] http://www.borland.pl/tech/opengl.shtml - strona opisujca funkcje OpenGL. [13] M. DeLoura, PereBki programowania gier, Helion, Gliwice(2002). [14] http://www.potu.com/man/pyopengl.sourceforge.net - strona po[wicona OpenGL. [15] http://januszg.hg.pl/opengl/index.html - strona zawiera informacje na temat programowania z zastosowaniem biblioteki OpenGL i GLUT. [16] J.Matulewski, C++ Builder 2006. 222 gotowe rozwizania, Helion, Gliwice(2006). [17] http://www.gamedev.pl/articles.php?x=view&id=269  strona po[wicona kwaternionom w grafice 3D. [18] http://rainwarrior.thenoos.net/dragon/arcball.html - strona po[wicona klasie ArcBall i u|ytych w niej kwaternionu. [19] http://www.gamedev.pl/files/articles/kwaterniony/Streszczenie.doc - strona po[wicona kwaternionom oraz ich zastosowaniu w grafice komputerowej. [20] http://www.pcworld.pl/artykuly/42219/Swiatla.na.scene.html - strona po[wicona definiowaniem o[wietlenia w OpenGL. 51 Dodatek A  Prymitywy Biblioteka OpenGL oferuje kilka rodzajów prymitywów graficznych, które sBu| do modelowania dowolnych obiektów. Definiowanie wspóBrzdnych wierzchoBków musi zawiera si pomidzy wywoBaniami funkcji: void glBegin (GLenum mode) void glEnd (void), gdzie parametr mode okre[la rodzaj prymitywu, którego wierzchoBki bd definiowane. Parametr ten przyjmuje okre[lone warto[ci i najcz[ciej u|ywane to: " GL POINTS - punkty " GL LINES - odcinki " GL LINE STRIP - Bamana " GL LINE LOOP - Bamana zamknita " GL TRIANGLES - trójkty " GL TRIANGLE STRIP - wstga trójktów " GL QUADS - czworokty, " GL QUAD STRIP - wstga czworoktów, " GL POLYGON - wielokt. 52

Wyszukiwarka

Podobne podstrony:
Open GL Podstawy
Open GL Pierwszy program
Open GL Pierwszy program
open c (3)
open
Alt klawiatura numeryczna Kurs dla opornych
Nie wspierajcie ekumenicznej organizacji Open Doors!
Szybki kurs Adobe Photoshop

więcej podobnych podstron