Janusz Ganczarski. OpenGL Definiowanie sceny 3D



Podobne dokumenty
Janusz Ganczarski. OpenGL Pierwszy program

Rzutowanie DOROTA SMORAWA

2 Przygotował: mgr inż. Maciej Lasota

1 Wstęp teoretyczny. Temat: Manipulowanie przestrzenią. Grafika komputerowa 3D. Instrukcja laboratoryjna Układ współrzędnych

Wprowadzenie do programowania z wykorzystaniem biblioteki OpenGL. Dorota Smorawa

Przekształcenia geometryczne. Dorota Smorawa

Prosty program- cpp. #include <GL/glut.h>

Trójwymiarowa grafika komputerowa rzutowanie

Oprogramowanie i wykorzystanie stacji roboczych. Wykład 6

Grafika komputerowa INSTRUKCJA DO LABORATORIUM 2: operacje przestrzenne oraz obsługa klawiatury i myszki

Wykład 12. Wprowadzenie do malarstwa, str. 1 OpenGL Open Graphics Library. OpenGL składa się z

Grafika Komputerowa Wykład 4. Synteza grafiki 3D. mgr inż. Michał Chwesiuk 1/30

Wykład 12. Wprowadzenie do malarstwa, str. 1 OpenGL Open Graphics Library. OpenGL składa się z

Temat: Transformacje 3D

Światła i rodzaje świateł. Dorota Smorawa

Temat: Wprowadzenie do OpenGL i GLUT

Mieszanie kolorów. Dorota Smorawa

OPENGL PRZEKSZTAŁCENIA GEOMETRYCZNE

Materiały. Dorota Smorawa

Rysowanie punktów na powierzchni graficznej

Wprowadzenie do rysowania w 3D. Praca w środowisku 3D

Wykład 4. Rendering (1) Informacje podstawowe

Bufor koloru cd. Czyszczenie bufora koloru glclearcolor( )

Elementarne obiekty geometryczne, bufory. Dorota Smorawa

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Laboratorium 1. Część I. Podstawy biblioteki graficznej OpenGL.

gdzie (4.20) (4.21) 4.3. Rzut równoległy

GRAFIKA KOMPUTEROWA 7: Kolory i cieniowanie

PRZEWODNIK PO PRZEDMIOCIE

Animowana grafika 3D. Opracowanie: J. Kęsik.

Układy współrzędnych GUW, LUW Polecenie LUW

Grafika komputerowa Wykład 4 Geometria przestrzenna

KGGiBM GRAFIKA INŻYNIERSKA Rok III, sem. VI, sem IV SN WILiŚ Rok akademicki 2011/2012

Baltie 3. Podręcznik do nauki programowania dla klas I III gimnazjum. Tadeusz Sołtys, Bohumír Soukup

Co to jest OpenGL? Oprogramowanie i wykorzystanie stacji roboczych. Wykład 5. OpenGL - Achitektura. OpenGL - zalety. olas@icis.pcz.

BRYŁY PODSTAWOWE I OBIEKTY ELEMENTARNE

Tworzenie nowego rysunku Bezpośrednio po uruchomieniu programu zostanie otwarte okno kreatora Nowego Rysunku.

Janusz Ganczarski CIE XYZ

54. Układy współrzędnych

Grafika 3D OpenGL część II

GEOMETRIA PRZESTRZENNA (STEREOMETRIA)

TWORZENIE OBIEKTÓW GRAFICZNYCH

Plan wykładu. Wykład 3. Rzutowanie prostokątne, widoki, przekroje, kłady. Rzutowanie prostokątne - geneza. Rzutowanie prostokątne - geneza

GRAFIKA CZASU RZECZYWISTEGO Wprowadzenie do OpenGL

Zaawansowany kurs języka Python

Rysowanie precyzyjne. Polecenie:

1 Podstawy c++ w pigułce.

Co należy zauważyć Rzuty punktu leżą na jednej prostej do osi rzutów x 12, którą nazywamy prostą odnoszącą Wysokość punktu jest odległością rzutu

Część 4 życie programu

0. OpenGL ma układ współrzędnych taki, że oś y jest skierowana (względem monitora) a) w dół b) w górę c) w lewo d) w prawo e) w kierunku do

BLENDER- Laboratorium 1 opracował Michał Zakrzewski, 2014 r. Interfejs i poruszanie się po programie oraz podstawy edycji bryły

1. Opis okna podstawowego programu TPrezenter.

Grafika komputerowa Wstęp do OpenGL

Część II Wyświetlanie obrazów

DARMOWA PRZEGLĄDARKA MODELI IFC

RZUTOWANIE PROSTOKĄTNE

Delphi podstawy programowania. Środowisko Delphi

Techniki wstawiania tabel

Spis treści. Konwencje zastosowane w książce...5. Dodawanie stylów do dokumentów HTML oraz XHTML...6. Struktura reguł...9. Pierwszeństwo stylów...

Transformacje obiektów 3D

Programowanie, część III

Ćwiczenia nr 4. TEMATYKA: Rzutowanie

OpenGL - maszyna stanu. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 7. Grupy atrybutów. Zmienne stanu.

OPROGRAMOWANIE UŻYTKOWE

STEREOMETRIA CZYLI GEOMETRIA W 3 WYMIARACH

System graficzny. Potok graficzny 3D. Scena 3D Zbiór trójwymiarowych danych wejściowych wykorzystywanych do wygenerowania obrazu wyjściowego 2D.

GRK 2. dr Wojciech Palubicki

Programowanie Procesorów Graficznych

Mapowanie sześcienne otoczenia (cubic environment mapping)

1 Podstawy c++ w pigułce.

Notacja Denavita-Hartenberga

8 Przygotował: mgr inż. Maciej Lasota

Słowa kluczowe Sterowanie klawiaturą, klawiatura, klawisze funkcyjne, przesuwanie obiektów ekranowych, wydawanie poleceń za pomocą klawiatury

Wykład 10. Wprowadzene do malarstwa, str. 1 OpenGL Open Graphics Library. OpenGL składa się z

glwindowpos2d void DrawString (GLint x, GLint y, char *string) { glwindowpos2i (x,y); int len = strlen (string); for (int i = 0; i < len; i++)

Automatyczne tworzenie trójwymiarowego planu pomieszczenia z zastosowaniem metod stereowizyjnych

Oprogramowanie i wykorzystanie stacji roboczych. Wykład 5

OPISY PRZESTRZENNE I PRZEKSZTAŁCENIA

Szybkie tworzenie grafiki w GcIde

Odwrócimy macierz o wymiarach 4x4, znajdującą się po lewej stronie kreski:

Obcinanie grafiki do prostokąta

Maskowanie i selekcja

Dokument hipertekstowy

Geometria. Hiperbola

- biegunowy(kołowy) - kursor wykonuje skok w kierunku tymczasowych linii konstrukcyjnych;

Symulacja samochodu z kamerą stereowizyjną. Krzysztof Sykuła 15 czerwca 2007

Edytor tekstu MS Office Word

Zasady rzutowania prostokątnego. metodą europejską. Opracował: Robert Urbanik Zespół Szkół Mechanicznych w Opolu. Zasady rzutowania prostokątnego

Laboratorium Programowanie urządzeń mobilnych

Ćwiczenie 1 Automatyczna animacja ruchu

Wybrane aspekty teorii grafiki komputerowej - dążenie do wizualnego realizmu. Mirosław Głowacki

RYSUNEK TECHNICZNY I GEOMETRIA WYKREŚLNA INSTRUKCJA DOM Z DRABINĄ I KOMINEM W 2D

Studia Podyplomowe Grafika Komputerowa i Techniki Multimedialne, 2017, semestr II Modelowanie 3D - Podstawy druku 3D. Ćwiczenie nr 4.

Ćwiczenie nr 9 - Tworzenie brył

Politechnika Warszawska Wydział Mechatroniki Instytut Automatyki i Robotyki

FIGURY I PRZEKSZTAŁCENIA GEOMETRYCZNE

Rzutowanie. dr Radosław Matusik. radmat

Π 1 O Π 3 Π Rzutowanie prostokątne Wiadomości wstępne

Moduł Grafika komputerowa i multimedia 312[01].S2. Ćwiczenia Podstawy programu Autocad 2011 Prosta

Tekstury. Dorota Smorawa

Transkrypt:

Janusz Ganczarski OpenGL Definiowanie sceny 3D

Spis treści Spis treści..................................... 1 1. Definiowanie sceny 3D........................... 1 1.1. Obszar renderingu............................ 1 1.1.1. Plik kwadrat2.cpp........................ 2 1.2. Rzutowanie prostokątne......................... 4 1.2.1. Plik szescian1.cpp........................ 7 1.3. Rzutowanie perspektywiczne...................... 10 1.3.1. Plik szescian2.cpp........................ 12 1.3.2. Plik szescian3.cpp........................ 16 1.4. Położenie obserwatora.......................... 19 1.4.1. Plik szescian4.cpp........................ 21 Literatura..................................... 25

1. Definiowanie sceny 3D W kolejnych programach korzystających z biblioteki OpenGL zajmiemy się podstawowymi zagadnieniami, związanymi ze sceną 3D: obszarem renderingu, rzutowaniem i położeniem obserwatora. Informacje tu zawarte stanowią podstawę do wszystkich następnych programów. 1.1. Obszar renderingu W pierwszym programie obszar renderingu, który zajmował początkowo całe okno, nie był modyfikowany podczas zmiany rozmiarów tego okna. W efekcie jedyny element sceny 3D - kwadrat - zawsze znajdował się w tym samym miejscu względem lewego dolnego narożnika okna. W aplikacjach pracujących w systemach okienkowych problem zmiany rozmiaru okna jest jednak tak powszechny, że wymaga specjalnego potraktowania. Jednym z możliwych sposobów jego rozwiązania jest dynamiczna modyfikacja modyfikacja obszaru renderingu. Służy to tego funkcja: void glviewport (GLint x, GLint y, GLsizei width, GLsizei height) której parametry oznaczają: x, y - współrzędne lewego dolnego narożnika obszaru renderingu względem lewego dolnego narożnika okna, width - szerokość okna renderingu, height - wysokość okna renderingu. Domyślnie obszar renderingu zajmuje całe okno udostępnione dla aplikacji OpenGL. W naszym drugim programie w trakcie zmiany rozmiaru okna (funkcja Reshape) będziemy modyfikować obszar renderingu na dwa sposoby. Pierwszy polega na objęciu obszarem renderingu całego dostępnego okna, drugi na takim wyborze okna renderingu aby okno zachowało pierwotny aspekt obrazu, czyli stosunek szerokości do wysokości. Oczywiście przy zastosowaniu pierwszej metody kwadrat będzie zazwyczaj zdeformowany (patrz rysunki 1 i 2). Zmiany sposobu definiowania okna renderingu można dokonać w dowolnym momencie, poprzez wybranie odpowiedniej opcji w menu podręcznym. W funkcji Menu została użyta do tej pory nieopisana funkcja z biblioteki GLUT: int glutget (GLenum type) O tym jakiego rodzaju informacje zwróci funkcja glutget decyduje parametr type. W przykładowym programie są to szerokość i wysokość okna, co odpowiada parametrom opisanym stałymi GLUT WINDOW WIDTH i GLUT WINDOW HEIGHT.

1. Definiowanie sceny 3D 2 Warto jeszcze kilka słów poświęcić zagadnieniu aspektu obrazu. Typowe monitory komputerowe posiadają aspekt 4:3, który jest zgodny z większością popularnych rozdzielczości roboczych (np. 640 480, 800 600, 1.024 768, 1.600 1.200), ale inna popularna rozdzielczość 1.280 1.024 pikseli odpowiada aspektowi 5:4. Rysunek 1. Programu Kwadrat 2 - rendering na całym oknie Rysunek 2. Programu Kwadrat 2 - rendering z zachowaniem aspektu 1:1 1.1.1. Plik kwadrat2.cpp / ( c ) Janusz G a n c z a r s k i h t t p : / /www. j a n u s z g. hg. p l JanuszG@enter. n e t. p l / #include <GL/ glut. h> #include < s t d l i b. h> // s t a ł e do o b s ł u g i menu p o d r ę c z n e g o enum FULL WINDOW, // o b s z a r r e n d e r i n g u c a ł e okno ASPECT 1 1, // o b s z a r r e n d e r i n g u a s p e k t 1 : 1

1. Definiowanie sceny 3D 3 EXIT // w y j ś c i e ; // a s p e k t o b r a z u int Aspect = FULL WINDOW; // f u n k c j a g e n e r u j ą c a s c e n ę 3D void D i s p l a y ( ) // k o l o r t ł a z a w a r t o ś ć b u f o r a k o l o r u g l C l e a r C o l o r ( 1. 0, 1. 0, 1. 0, 1. 0 ) ; // c z y s z c z e n i e b u f o r a k o l o r u g l C l e a r ( GL COLOR BUFFER BIT ) ; // k o l o r k w a d r a t u g l C o l o r 3 f ( 1. 0, 0. 0, 0. 0 ) ; // p o c z ą t e k d e f i n i c j i w i e l o k ą t a g l B e g i n (GL POLYGON) ; // k o l e j n e w i e r z c h o ł k i w i e l o k ą t a g l V e r t e x 3 f ( 0. 0, 0. 0, 0. 0 ) ; g l V e r t e x 3 f ( 0. 0, 1. 0, 0. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 0. 0 ) ; g l V e r t e x 3 f ( 1. 0, 0. 0, 0. 0 ) ; // k o n i e c d e f i n i c j i prymitywu glend ( ) ; // s k i e r o w a n i e p o l e c e ń do wykonania g l F l u s h ( ) ; // zamiana b u f o r ó w k o l o r u glutswapbuffers ( ) ; // zmiana w i e l k o ś c i okna void Reshape ( int width, int h e i g h t ) // o b s z a r r e n d e r i n g u a s p e k t 1 : 1 i f ( Aspect == ASPECT 1 1 ) // s z e r o k o ś ć okna w i ę k s z a od w y s o k o ś c i okna i f ( width > h e i g h t ) g l V i e w p o r t ( ( width h e i g h t ) / 2, 0, h e i g h t, h e i g h t ) ; e l s e // w y s o k o ś ć okna w i ę k s z a od w y s o k o ś c i okna i f ( width < h e i g h t ) g l V i e w p o r t ( 0, ( h e i g h t width ) / 2, width, width ) ; e l s e // o b s z a r r e n d e r i n g u c a ł e okno ( t a k ż e, gdy a s p e k t w y n o s i 1 : 1 ) g l V i e w p o r t ( 0, 0, width, h e i g h t ) ; // g e n e r o w a n i e s c e n y 3D D i s p l a y ( ) ; // ob sług a menu podręcznego void Menu ( int v a l u e ) switch ( v a l u e ) // o b s z a r r e n d e r i n g u c a ł e okno case FULL WINDOW: Aspect = FULL WINDOW; Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; break ; // o b s z a r r e n d e r i n g u a s p e k t 1 : 1 case ASPECT 1 1 : Aspect = ASPECT 1 1 ; Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ;

1. Definiowanie sceny 3D 4 break ; // w y j ś c i e case EXIT : e x i t ( 0 ) ; int main ( int argc, char argv [ ] ) // i n i c j a l i z a c j a b i b l i o t e k i GLUT g l u t I n i t (& argc, argv ) ; // i n i c j a l i z a c j a b u f o r a ramki g l u t I n i t D i s p l a y M o d e (GLUT DOUBLE GLUT RGB ) ; // r o z m i a r y g ł ó w n e g o okna programu g l u t I n i t W i n d o w S i z e ( 4 0 0, 4 0 0 ) ; // u t w o r z e n i e g ł ó w n e g o okna programu glutcreatewindow ( Kwadrat 2 ) ; // d o ł ą c z e n i e f u n k c j i g e n e r u j ą c e j s c e n ę 3D glutdisplayfunc ( Display ) ; // d o ł ą c z e n i e f u n k c j i wywoływanej p r z y z m i a n i e r o z m i a r u okna glutreshapefunc ( Reshape ) ; // u t w o r z e n i e menu p o d r ę c z n e g o glutcreatemenu ( Menu ) ; // d o d a n i e p o z y c j i do menu p o d r ę c z n e g o glutaddmenuentry ( Obszar renderingu całe okno,full WINDOW) ; glutaddmenuentry ( Obszar renderingu aspekt 1 : 1, ASPECT 1 1 ) ; glutaddmenuentry ( Wyjście,EXIT ) ; // o k r e ś l e n i e p r z y c i s k u m y s z k i o b s ł u g u j ą c e j menu p o d r ę c z n e glutattachmenu (GLUT RIGHT BUTTON ) ; // w p r o w a d z e n i e programu do o b s ł u g i p ę t l i komunikatów glutmainloop ( ) ; return 0 ; 1.2. Rzutowanie prostokątne Rzutowaniem określamy odwzorowanie zawartości trójwymiarowej sceny graficznej na płaskim ekranie monitora. Biblioteka OpenGL oferuje standardowo dwie metody rzutowania: rzutowanie prostokątne i rzutowanie perspektywiczne. Domyślnie stosowane jest rzutowanie prostokątne. W rzutowaniu prostokątnym (lub ortogonalnym) proste rzutowania są prostopadłe do rzutni, która jest reprezentowana przez obszar renderingu. Z rzutowaniem prostokątnym ściśle związane jest pojęcie bryły odcinania - prostopadłościanu, który stanowi ograniczenie sceny 3D. Obiekty znajdujące się poza bryłą odcinania nie sa rysowane, a obiekty ją przecinające rysowane są tylko częściowo. Rozmiar bryły odcinania w rzutowaniu prostokątnym określa funkcja: void glortho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far)

1. Definiowanie sceny 3D 5 której parametry określają współrzędne punktów przecięcia płaszczyzn tworzących bryłę odcinania z osiami układu współrzędnych kartezjańskich. Płaszczyzny te opisane są następującymi równaniami: x = right x = left y = top y = bottm z = near z = far Obszar renderingu zawiera się w płaszczyźnie o równaniu z = near. Położenie poszczególnych płaszczyzn tworzących bryłę odcinania przedstawia rysunek 3. Trzeba jednak wyraźnie zwrócić uwagę, że początek układu współrzędnych nie musi znajdować się wewnątrz bryły odcinania - rozmiary i położenie bryły ograniczone są jedynie zakresem stosowanych liczb. Y top -far left right X -near Z bottom Rysunek 3. Położenie płaszczyzn bryły odcinania w rzutowaniu prostokątnym Domyślnie bryła odcinania ma postać sześcianu o bokach równych 2, którego środek pokrywa się z początkiem układu współrzędnych, co odpowiada

1. Definiowanie sceny 3D 6 wywołaniu funkcji glortho (-1,1,-1,1,-1,1). Oś OZ jest prostopadła do płaszczyzny obszaru renderingu i przechodzi przez środek tego obszaru. Dlatego rysowany w pierwszym i drugim programie kwadrat zajmował początkowo czwartą część okna. Funkcja glortho tworzy macierz rzutu prostokątnego: 2 right+left right left top+bottom top bottom far+near far near right left 0 0 2 0 top bottom 0 2 0 0 far near 0 0 0 1 która jest nastepnie mnożona przez bieżącą macierz i umieszczona na szczycie stosu z bieżącą macierzą. OpenGL zawiera kilka stosów macierzy, z których w przykładowym programie wykorzystamy stos macierzy rzutowania oraz stos macierzy modelowania. Wybór bieżącej macierzy umożliwia funkcja: void glmatrixmode (GLenum mode) gdzie parametr mode może przyjąć jedną z wartości: GL MODELVIEW - macierz modelowania, GL PROJECTION - macierz rzutowania, GL TEXTURE - macierz tekstury (omówiona później). Ponieważ początkowa wartość wybranej macierzy jest nieokreślona, przed wywołaniem glortho należy bieżącej macierzy przyporządkować macierz jednostkową. Najłatwiej można to zrobić używając funkcji: void glloadidentity (void) Analogiczne postępowanie dotyczy macierzy modelowania. Po jej wyborze przykładowym programie (plik szescian1.cpp) w funkcji Display macierzy modelowania także przyporządkowywana jest macierz jednostkowa. Jeżeli renderowana scena jest dwuwymiarowa, do ustawienia parametrów bryły odcinania w rzutowaniu prostokątnym można użyć funkcji z biblioteki GLU: void gluortho2d (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) której parametry left, right, bottom i top odpowiadają parametrom funkcji glortho, a przednia (near) i tylna (far) płaszczyzna obcinania mają wartości odpowiednio -1 i 1. W przykładowym programie początkowa bryła odcinania ma postać sześcianu o krawędziach długości 4, a rysowana figura - także sześcian - ma

1. Definiowanie sceny 3D 7 krawędzie o długości 2. Centralne umieszczenie rysowanego sześcianu w połączeniu z zastosowanym rzutowaniem prostokątnym daje w efekcie kwadrat (patrz rysunek 4). Podobnie jak w poprzednim programie możliwy jest wybór, czy scena ma być rysowana z zachowaniem początkowego aspektu obrazu czy też bez zachowania tej proporcji. Jednak w tym przypadku nie jest modyfikowany obszar renderingu ale współrzędne bryły odcinania (funkcja Reshape). Rysunek 4. Początkowe okno programu Sześcian 1 1.2.1. Plik szescian1.cpp / ( c ) Janusz G a n c z a r s k i h t t p : / /www. j a n u s z g. hg. p l JanuszG@enter. n e t. p l / #include <GL/ glut. h> #include < s t d l i b. h> // s t a ł e do o b s ł u g i menu p o d r ę c z n e g o enum FULL WINDOW, // a s p e k t o b r a z u c a ł e okno ASPECT 1 1, // a s p e k t o b r a z u 1 : 1 EXIT // w y j ś c i e ;

1. Definiowanie sceny 3D 8 // a s p e k t o b r a z u int Aspect = FULL WINDOW; // f u n k c j a g e n e r u j ą c a s c e n ę 3D void D i s p l a y ( ) // k o l o r t ł a z a w a r t o ś ć b u f o r a k o l o r u g l C l e a r C o l o r ( 1. 0, 1. 0, 1. 0, 1. 0 ) ; // c z y s z c z e n i e b u f o r a k o l o r u g l C l e a r ( GL COLOR BUFFER BIT ) ; // wybór m a c i e r z y modelowania glmatrixmode (GL MODELVIEW) ; // m a c i e r z modelowania = m a c i e r z j e d n o s t k o w a g l L o a d I d e n t i t y ( ) ; // k o l o r k r a w ę d z i s z e ś c i a n u g l C o l o r 3 f ( 0. 0, 0. 0, 0. 0 ) ; // p o c z ą t e k d e f i n i c j i k r a w ę d z i s z e ś c i a n u g l B e g i n ( GL LINES ) ; // w s p ó l r z ę d n e k o l e j n y c h k r a w ę d z i s z e ś c i a n u g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; // k o n i e c d e f i n i c j i prymitywu glend ( ) ; // s k i e r o w a n i e p o l e c e ń do wykonania g l F l u s h ( ) ; // zamiana b u f o r ó w k o l o r u glutswapbuffers ( ) ; // zmiana w i e l k o ś c i okna void Reshape ( int width, int h e i g h t ) // o b s z a r r e n d e r i n g u c a ł e okno g l V i e w p o r t ( 0, 0, width, h e i g h t ) ;

1. Definiowanie sceny 3D 9 // wybór m a c i e r z y r z u t o w a n i a glmatrixmode ( GL PROJECTION ) ; // m a c i e r z r z u t o w a n i a = m a c i e r z j e d n o s t k o w a g l L o a d I d e n t i t y ( ) ; // p a r a m e t r y b r y ł y o b c i n a n i a i f ( Aspect == ASPECT 1 1 ) // w y s o k o ś ć okna w i ę k s z a od w y s o k o ś c i okna i f ( width < h e i g h t && width > 0) glortho ( 2. 0, 2. 0, 2. 0 h e i g h t / width, 2. 0 h e i g h t / width, 2. 0, 2. 0 ) ; e l s e // s z e r o k o ś ć okna w i ę k s z a l u b równa w y s o k o ś c i okna i f ( width >= h e i g h t && h e i g h t > 0) glortho ( 2.0 width / h e i g h t, 2. 0 width / h e i g h t, 2. 0, 2. 0, 2. 0, 2. 0 ) ; e l s e glortho ( 2. 0, 2. 0, 2. 0, 2. 0, 2. 0, 2. 0 ) ; // g e n e r o w a n i e s c e n y 3D D i s p l a y ( ) ; // ob sług a menu podręcznego void Menu ( int v a l u e ) switch ( v a l u e ) // o b s z a r r e n d e r i n g u c a ł e okno case FULL WINDOW: Aspect = FULL WINDOW; Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; break ; // o b s z a r r e n d e r i n g u a s p e k t 1 : 1 case ASPECT 1 1 : Aspect = ASPECT 1 1 ; Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; break ; // w y j ś c i e case EXIT : e x i t ( 0 ) ; int main ( int argc, char argv [ ] ) // i n i c j a l i z a c j a b i b l i o t e k i GLUT g l u t I n i t (& argc, argv ) ; // i n i c j a l i z a c j a b u f o r a ramki g l u t I n i t D i s p l a y M o d e (GLUT DOUBLE GLUT RGB ) ; // r o z m i a r y g ł ó w n e g o okna programu g l u t I n i t W i n d o w S i z e ( 4 0 0, 4 0 0 ) ; // u t w o r z e n i e g ł ó w n e g o okna programu glutcreatewindow ( S z e ś c i a n 1 ) ; // d o ł ą c z e n i e f u n k c j i g e n e r u j ą c e j s c e n ę 3D glutdisplayfunc ( Display ) ; // d o ł ą c z e n i e f u n k c j i wywoływanej p r z y z m i a n i e r o z m i a r u okna glutreshapefunc ( Reshape ) ; // u t w o r z e n i e menu p o d r ę c z n e g o glutcreatemenu ( Menu ) ; // d o d a n i e p o z y c j i do menu p o d r ę c z n e g o glutaddmenuentry ( Aspekt obrazu całe okno,full WINDOW) ; glutaddmenuentry ( Aspekt obrazu 1 : 1, ASPECT 1 1 ) ; glutaddmenuentry ( Wyjście,EXIT ) ; // o k r e ś l e n i e p r z y c i s k u m y s z k i o b s ł u g u j ą c e j menu p o d r ę c z n e glutattachmenu (GLUT RIGHT BUTTON ) ;

1. Definiowanie sceny 3D 10 // w p r o w a d z e n i e programu do o b s ł u g i p ę t l i komunikatów glutmainloop ( ) ; return 0 ; 1.3. Rzutowanie perspektywiczne Rzutowanie perspektywiczne daje bardziej realistyczne efekty niż rzutowanie prostokątne, stąd jest szeroko stosowane np. w grach. Parametry bryły odcinania, która przy rzutowaniu perspektywicznym ma postać ostrosłupa ściętego o wierzchołku znajdującym się w początku układu współrzędnych (patrz rysunek 5), określa funkcja: void glfrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far) Y top -far left -near right bottom X Z Rysunek 5. Położenie płaszczyzn bryły odcinania w rzutowaniu perspektywicznym

1. Definiowanie sceny 3D 11 Parametry left, right, bottom i top wyznaczają rozmiary górnej podstawy bryły odcinania (jest to obszar bezpośrednio odwzorowywany na obszar renderingu), a near i far wyznaczają położenie odpowiednio górnej i dolnej podstawy ostrosłupa (przedniej i tylnej płaszczyzny odcinania), które zawierają się w płaszczyznach o równaniach: z = near i z = far. Parametry near i far muszą mieć wartości dodatnie. Macierz rzutowania perspektywicznego, tworzona przez funkcję glfrustum i mnożona przez aktualnie wybraną macierz, ma postać: 2near right left 0 2near 0 top bottom right+left right left 0 top+bottom top bottom 0 far+near far near 2far near far near 0 0 0 0 1 0 Warto zauważyć, że precyzja działania jeszcze przez nas nieużywanego z-bufora, zależy od wartości stosunku parametrów near i far: r = far near Im większa wartość r, tym mniej efektywne jest działanie z-bufora. Oczywiście near nigdy nie może przyjąć wartości równej 0, bowiem przednia płaszczyzna odcinania przechodziła by wówczas przez środek perspektywy. Alternatywny sposób określania rzutu perspektywicznego umożliwia funkcja z biblioteki GLU: void gluperspective (GLdouble fovy, GLdouble aspect, GLdouble znear, GLdouble zfar) gdzie parametr fovy określa w stopniach kąt widzenia obserwatora zawarty w płaszczyźnie YZ ( (top, 0, bottom)), a aspect jest stosunkiem szerokości do wysokości przedniej płaszczyzny odcinania, czyli górnej podstawy ostrosłupa ograniczającego scenę 3D. Parametry znear i zfar odpowiadają parametrom near i far funkcji glfrustum. Macierz rzutowania perspektywicznego, tworzona przez funkcję gluperspective i mnożona przez aktualnie wybraną macierz, ma postać: ctg fovy 2 aspect 0 0 0 0 ctg fovy 2 0 0 2 zf ar znear znear zf ar zf ar+znear 0 0 znear zf ar 0 0 1 0

1. Definiowanie sceny 3D 12 Wewnętrznie funkcja gluperspective wykorzystuje do ustawienia macierzy rzutowania perspektywicznego funkcję glfrustum. Oto przekształcenia parametrów gluperspective na parametry glfrustum: ( ) left = aspect znear tg π fovy ( 360) right = aspect znear tg π fovy ( ) 360 bottom = znear tg π fovy ( top = znear tg π fovy 360 ) 360 W kolejnym przykładowym programie (plik szescian2.cpp) do utworzenia macierzy rzutowania perspektywicznego wykorzystamy funkcję glfrustum. Przednia płaszczyzna odcinania będzie miała takie same rozmiary jak w poprzednim programie. Zmianie ulegną natomiast współrzędne przedniej i tylnej płaszczyzny obcinania - poprzednio jedna z tych płaszczyzn miała wartość ujemną, której nie akceptuje funkcja glfrustum. Rysowanym obiektem ponownie będzie sześcian ale próba narysowania go w tym samym miejscu jak w poprzednim programie spowoduje, że będzie widoczna tylko jedna jego ściana. Wszystko dlatego, że pozostałe ściany sześcianu znajdują się poza obszarem bryły odcinania. Możliwe są trzy sposoby rozwiązania tego problemu. Pierwszy polega na zmianie współrzędnych wierzchołków sześcianu w taki sposób, aby sześcian zmieścił się w zmienionej bryle obcinania. Rozwiązanie to ma jedną zasadniczą wadę - wierzchołki sześcianu trzeba będzie modyfikować przy każdej zmianie parametrów sceny 3D. W przypadku jednego obiektu nie stanowi to specjalnego problemu, ale czyni pomysł niewykonalnym przy każdej bardziej skomplikowanej scenie 3D. Drugie, zastosowane w programie rozwiązanie, polega na przesunięciu wierzchołków sześcianu o wektor [0, 0, 3], czyli o -3 jednostki wzdłuż osi OZ. Realizuje to funkcja gltranslatef, która wywoływana jest bezpośrednio po zainicjowaniu macierzy modelowania macierzą jednostkową (patrz funkcja Display). W efekcie otrzymamy sześcian przedstawiony na rysunku 6. Należy dodać, że taka metoda jest często stosowaną praktyką. Obiekty 3D definiowane są z różnymi współrzędnymi, a następnie odpowiednio transformowane do docelowego położenia w scenie 3D. Funkcje umożliwiające takie przekształcenia poznamy bliżej w następnym odcinku kursu. Trzecią metodą jest modyfikacja położenia obserwatora sceny 3D - zapoznamy się z tą techniką jeszcze w tym odcinku. 1.3.1. Plik szescian2.cpp / ( c ) Janusz G a n c z a r s k i h t t p : / /www. j a n u s z g. hg. p l

1. Definiowanie sceny 3D 13 Rysunek 6. Początkowe okno programu Sześcian 2 JanuszG@enter. n e t. p l / #include <GL/ glut. h> #include < s t d l i b. h> // s t a ł e do o b s ł u g i menu p o d r ę c z n e g o enum FULL WINDOW, // a s p e k t o b r a z u c a ł e okno ASPECT 1 1, // a s p e k t o b r a z u 1 : 1 EXIT // w y j ś c i e ; // a s p e k t o b r a z u int Aspect = FULL WINDOW; // f u n k c j a g e n e r u j ą c a s c e n ę 3D void D i s p l a y ( ) // k o l o r t ł a z a w a r t o ś ć b u f o r a k o l o r u g l C l e a r C o l o r ( 1. 0, 1. 0, 1. 0, 1. 0 ) ; // c z y s z c z e n i e b u f o r a k o l o r u g l C l e a r ( GL COLOR BUFFER BIT ) ; // wybór m a c i e r z y modelowania glmatrixmode (GL MODELVIEW) ; // m a c i e r z modelowania = m a c i e r z j e d n o s t k o w a g l L o a d I d e n t i t y ( ) ;

1. Definiowanie sceny 3D 14 // p r z e s u n i ę c i e o b i e k t u o w e k t o r [ 0, 0, 3 ] g l T r a n s l a t e f ( 0, 0, 3. 0 ) ; // k o l o r k r a w ę d z i s z e ś c i a n u g l C o l o r 3 f ( 0. 0, 0. 0, 0. 0 ) ; // p o c z ą t e k d e f i n i c j i k r a w ę d z i s z e ś c i a n u g l B e g i n ( GL LINES ) ; // w s p ó l r z ę d n e k o l e j n y c h k r a w ę d z i s z e ś c i a n u g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; // k o n i e c d e f i n i c j i prymitywu glend ( ) ; // s k i e r o w a n i e p o l e c e ń do wykonania g l F l u s h ( ) ; // zamiana b u f o r ó w k o l o r u glutswapbuffers ( ) ; // zmiana w i e l k o ś c i okna void Reshape ( int width, int h e i g h t ) // o b s z a r r e n d e r i n g u c a ł e okno g l V i e w p o r t ( 0, 0, width, h e i g h t ) ; // wybór m a c i e r z y r z u t o w a n i a glmatrixmode ( GL PROJECTION ) ; // m a c i e r z r z u t o w a n i a = m a c i e r z j e d n o s t k o w a g l L o a d I d e n t i t y ( ) ; // p a r a m e t r y b r y ł y o b c i n a n i a i f ( Aspect == ASPECT 1 1 ) // w y s o k o ś ć okna w i ę k s z a od w y s o k o ś c i okna i f ( width < h e i g h t && width > 0) glfrustum ( 2. 0, 2. 0, 2. 0 h e i g h t / width, 2. 0 h e i g h t / width, 1. 0, 5. 0 ) ; e l s e // s z e r o k o ś ć okna w i ę k s z a l u b równa w y s o k o ś c i okna i f ( width >= h e i g h t && h e i g h t > 0) glfrustum ( 2.0 width / h e i g h t, 2. 0 width / h e i g h t, 2. 0, 2. 0, 1. 0, 5. 0 ) ;

1. Definiowanie sceny 3D 15 e l s e glfrustum ( 2. 0, 2. 0, 2. 0, 2. 0, 1. 0, 5. 0 ) ; // g e n e r o w a n i e s c e n y 3D D i s p l a y ( ) ; // ob sług a menu podręcznego void Menu ( int v a l u e ) switch ( v a l u e ) // o b s z a r r e n d e r i n g u c a ł e okno case FULL WINDOW: Aspect = FULL WINDOW; Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; break ; // o b s z a r r e n d e r i n g u a s p e k t 1 : 1 case ASPECT 1 1 : Aspect = ASPECT 1 1 ; Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; break ; // w y j ś c i e case EXIT : e x i t ( 0 ) ; int main ( int argc, char argv [ ] ) // i n i c j a l i z a c j a b i b l i o t e k i GLUT g l u t I n i t (& argc, argv ) ; // i n i c j a l i z a c j a b u f o r a ramki g l u t I n i t D i s p l a y M o d e (GLUT DOUBLE GLUT RGB ) ; // r o z m i a r y g ł ó w n e g o okna programu g l u t I n i t W i n d o w S i z e ( 4 0 0, 4 0 0 ) ; // u t w o r z e n i e g ł ó w n e g o okna programu glutcreatewindow ( S z e ś c i a n 2 ) ; // d o ł ą c z e n i e f u n k c j i g e n e r u j ą c e j s c e n ę 3D glutdisplayfunc ( Display ) ; // d o ł ą c z e n i e f u n k c j i wywoływanej p r z y z m i a n i e r o z m i a r u okna glutreshapefunc ( Reshape ) ; // u t w o r z e n i e menu p o d r ę c z n e g o glutcreatemenu ( Menu ) ; // d o d a n i e p o z y c j i do menu p o d r ę c z n e g o glutaddmenuentry ( Aspekt obrazu całe okno,full WINDOW) ; glutaddmenuentry ( Aspekt obrazu 1 : 1, ASPECT 1 1 ) ; glutaddmenuentry ( Wyjście,EXIT ) ; // o k r e ś l e n i e p r z y c i s k u m y s z k i o b s ł u g u j ą c e j menu p o d r ę c z n e glutattachmenu (GLUT RIGHT BUTTON ) ; // w p r o w a d z e n i e programu do o b s ł u g i p ę t l i komunikatów glutmainloop ( ) ; return 0 ; Drugi program przedstawiający rzutowanie perspektywiczne (plik szescian3.cpp) stosuje funkcję gluperspective. Aby jednak nie powielać rozwiązań z poprzedniego programu dodamy mechanizm pokazujący jaki wpływ na wygląd obiektów 3D ma zmiana położenie środka perspektywy, realizowana poprzez zmianę kąta widzenia obserwatora (parametr fovy funkcji gluperspective). W tym celu potrzebna jest obsługa klawiatury. Podstawo-

1. Definiowanie sceny 3D 16 wa funkcja obsługi klawiatury (w przykładowym programie jest to funkcja Keyboard) ma trzy parametry: key - kod ASCII klawisza, x, y - współrzędne kursora myszki w chwili naciśnięcia przycisku klawiatury. Aby obsługa klawiatury działała, w części głównej programu należy włączyć funkcję obsługi klawiatury wywołując funkcję: void glutkeyboardfunc (void (*func)(unsigned char key, int x, int y)) Początkowe okno programu Sześcian 3 zawiera rysunek 7. Przyciskając klawisze + i - można modyfikować kąt patrzenia obserwatora, który początkowo wynosi 90. Rysunek 7. Początkowe okno programu Sześcian 3 1.3.2. Plik szescian3.cpp / ( c ) Janusz G a n c z a r s k i h t t p : / /www. j a n u s z g. hg. p l JanuszG@enter. n e t. p l /

1. Definiowanie sceny 3D 17 #include <GL/ glut. h> #include < s t d l i b. h> // s t a ł a do o b s ł u g i menu p o d r ę c z n e g o enum EXIT // w y j ś c i e ; // pionowy k ą t p o l a w i d z e n i a GLdouble f o v y = 9 0 ; // f u n k c j a g e n e r u j ą c a s c e n ę 3D void D i s p l a y ( ) // k o l o r t ł a z a w a r t o ś ć b u f o r a k o l o r u g l C l e a r C o l o r ( 1. 0, 1. 0, 1. 0, 1. 0 ) ; // c z y s z c z e n i e b u f o r a k o l o r u g l C l e a r ( GL COLOR BUFFER BIT ) ; // wybór m a c i e r z y modelowania glmatrixmode (GL MODELVIEW) ; // m a c i e r z modelowania = m a c i e r z j e d n o s t k o w a g l L o a d I d e n t i t y ( ) ; // p r z e s u n i ę c i e o b i e k t u o w e k t o r [ 0, 0, 3 ] g l T r a n s l a t e f ( 0, 0, 3. 0 ) ; // k o l o r k r a w ę d z i s z e ś c i a n u g l C o l o r 3 f ( 0. 0, 0. 0, 0. 0 ) ; // p o c z ą t e k d e f i n i c j i k r a w ę d z i s z e ś c i a n u g l B e g i n ( GL LINES ) ; // w s p ó l r z ę d n e k o l e j n y c h k r a w ę d z i s z e ś c i a n u g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; // k o n i e c d e f i n i c j i prymitywu glend ( ) ;

1. Definiowanie sceny 3D 18 // s k i e r o w a n i e p o l e c e ń do wykonania g l F l u s h ( ) ; // zamiana b u f o r ó w k o l o r u glutswapbuffers ( ) ; // zmiana w i e l k o ś c i okna void Reshape ( int width, int h e i g h t ) // o b s z a r r e n d e r i n g u c a ł e okno g l V i e w p o r t ( 0, 0, width, h e i g h t ) ; // wybór m a c i e r z y r z u t o w a n i a glmatrixmode ( GL PROJECTION ) ; // m a c i e r z r z u t o w a n i a = m a c i e r z j e d n o s t k o w a g l L o a d I d e n t i t y ( ) ; // o b l i c z e n i e a s p e k t u o b r a z u z u w z g l ę d n i e n i e m // przypadku, gdy wysokość obrazu wynosi 0 GLdouble a s p e c t = 1 ; i f ( h e i g h t > 0) aspect = width / ( GLdouble ) height ; // r z u t o w a n i e p e r s p e k t y w i c z n e g l u P e r s p e c t i v e ( fovy, a s p e c t, 1. 0, 5. 0 ) ; // g e n e r o w a n i e s c e n y 3D D i s p l a y ( ) ; // o b s ł u g a k l a w i a t u r y void Keyboard ( unsigned char key, int x, int y ) // k l a w i s z + i f ( key == + && f o v y < 180) f o v y++; e l s e // k l a w i s z i f ( key == && f o v y > 0) fovy ; // o d r y s o w a n i e okna Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; // ob sług a menu podręcznego void Menu ( int v a l u e ) switch ( v a l u e ) // w y j ś c i e case EXIT : e x i t ( 0 ) ; int main ( int argc, char argv [ ] ) // i n i c j a l i z a c j a b i b l i o t e k i GLUT g l u t I n i t (& argc, argv ) ; // i n i c j a l i z a c j a b u f o r a ramki g l u t I n i t D i s p l a y M o d e (GLUT DOUBLE GLUT RGB ) ; // r o z m i a r y g ł ó w n e g o okna programu g l u t I n i t W i n d o w S i z e ( 4 0 0, 4 0 0 ) ; // u t w o r z e n i e g ł ó w n e g o okna programu glutcreatewindow ( S z e ś c i a n 3 ) ; // d o ł ą c z e n i e f u n k c j i g e n e r u j ą c e j s c e n ę 3D glutdisplayfunc ( Display ) ; // d o ł ą c z e n i e f u n k c j i wywoływanej p r z y z m i a n i e r o z m i a r u okna

1. Definiowanie sceny 3D 19 glutreshapefunc ( Reshape ) ; // d o ł ą c z e n i e f u n k c j i o b s ł u g i k l a w i a t u r y glutkeyboardfunc ( Keyboard ) ; // u t w o r z e n i e menu p o d r ę c z n e g o glutcreatemenu ( Menu ) ; // d o d a n i e p o z y c j i do menu p o d r ę c z n e g o glutaddmenuentry ( Wyjście,EXIT ) ; // o k r e ś l e n i e p r z y c i s k u m y s z k i o b s ł u g u j ą c e j menu p o d r ę c z n e glutattachmenu (GLUT RIGHT BUTTON ) ; // w p r o w a d z e n i e programu do o b s ł u g i p ę t l i komunikatów glutmainloop ( ) ; return 0 ; 1.4. Położenie obserwatora Ostatnim z podstawowych elementów wymagających omówienia przy tworzeniu sceny 3D jest położenie obserwatora, nazywane także położeniem kamery lub oka. Domyślnie obserwator w OpenGL położony jest w początku układu współrzędnych i skierowany jest w stronę ujemnej półosi OZ. Obserwator jest tak zorientowany w przestrzeni, że kierunek do góry pokrywa się z kierunkiem osi OY. Zasadniczo OpenGL nie umożliwia zmiany położenia obserwatora. Wszystkie przekształcenia położenia obserwatora faktycznie realizowane są jako odpowiednie przekształcenia układu współrzędnych. Aby jednak ułatwić prace związane z definiowaniem tych przekształceń, biblioteka GLU zawiera funkcję glulookat, która pozwala na jednorazowe zdefiniowanie wszystkich parametrów opisujących obserwatora: void glulookat (GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz) Kolejne trójki parametrów funkcji glulookat oznaczają: eyex, eyey, eyez - współrzędne położenia obserwatora, centerx, centery, centerz - współrzędne punktu, w którego kierunku jest zwrócony obserwator, upx, upy, upz - współrzędne wektora określającego kierunek do góry. Domyślne położenie obserwatora odpowiada wywołaniu glulookat (0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0). W kolejnym przykładowym programie (plik szescian4.cpp) będziemy modyfikować tylko współrzędne położenia obserwatora. Przy niezmiennych współrzędnych punktu, w którego kierunku patrzy obserwator, daje to ciekawy efekt obserwacji sceny z pewnej odległości. Zmiana położenia obserwatora realizowana jest w funkcjach Keyboard (przyciski + i - ) oraz SpecialKeys (klawisze kursora). Warto zauwa-

1. Definiowanie sceny 3D 20 żyć, że zmiany współrzędnych obserwatora, które reprezentują zmienne eyex, eyey i eyez, są odwrotne niż można by się spodziewać. Przykładowo naciśnięcie strzałki w dół powoduje zwiększenie o 0,1 zmiennej eyey, która określa współrzędną Y położenia obserwatora. Jest to spowodowane tym, że macierz modelowania, modyfikowana przy wywołaniu funkcji glulookat, odgrywa podwójną rolę. Z jednej strony umożliwia przekształcenia współrzędnych obiektu (patrz poprzedni przykład), a z drugiej przekształcenia współrzędnych obserwatora. Przykładowo, to co z punktu widzenia obiektu jest przesunięciem o wektor [1, 0, 0], dla obserwatora jest przesunięciem o wektor przeciwny tj. [ 1, 0, 0]. Dobre poznanie opisanego mechanizmy wymaga eksperymentów, do których gorąco zachęcam Czytelników. Do omówienia pozostała wprowadzona w ostatnim przykładzie obsługa klawiszy kursora. Jest ona realizowana odrębnie od obsługi przycisków, które reprezentowane są bezpośrednio przez kody ASCII (funkcja Keyboard). Funkcja obsługująca klawisze kursora oraz przyciski funkcyjne (w przykładowym programie jest to funkcja SpecialKeys) ma trzy parametry: key - kod przycisku; zwracana jest jedna z poniższych wartości: GLUT KEY F1 - przycisk F1, GLUT KEY F2 - przycisk F2, GLUT KEY F3 - przycisk F3, GLUT KEY F4 - przycisk F4, GLUT KEY F5 - przycisk F5, GLUT KEY F6 - przycisk F6, GLUT KEY F7 - przycisk F7, GLUT KEY F8 - przycisk F8, GLUT KEY F9 - przycisk F9, GLUT KEY F10 - przycisk F10, GLUT KEY F11 - przycisk F11, GLUT KEY F12 - przycisk F12, GLUT KEY LEFT - kursor w lewo, GLUT KEY UP - kursor do góry, GLUT KEY RIGHT - kursor w prawo, GLUT KEY DOWN - kursor w dół, GLUT KEY PAGE UP - przycisk Page Up GLUT KEY PAGE DOWN - przycisk Page Down, GLUT KEY HOME - przycisk Home, GLUT KEY END - przycisk End, GLUT KEY INSERT - przycisk Insert. x, y - współrzędne kursora myszki w chwili naciśnięcia przycisku klawiatury. Podobnie jak w przypadku poprzedniej funkcji obsługującej klawiaturę,

1. Definiowanie sceny 3D 21 w głównym programie należy włączyć obsługę klawiszy kursora i klawiszy funkcyjnych wywołując funkcję: void glutspecialfunc (void (*func)(int key, int x, int y)) Rysunek 8 przedstawia przykładowe okno programu Sześcian 4, którego kod źródłowy znajduje się poniżej. Rysunek 8. Przykładowe okno programu Sześcian 4 1.4.1. Plik szescian4.cpp / ( c ) Janusz G a n c z a r s k i h t t p : / /www. j a n u s z g. hg. p l JanuszG@enter. n e t. p l / #include <GL/ glut. h> #include < s t d l i b. h> // s t a ł e do o b s ł u g i menu p o d r ę c z n e g o enum FULL WINDOW, // a s p e k t o b r a z u c a ł e okno ASPECT 1 1, // a s p e k t o b r a z u 1 : 1 EXIT // w y j ś c i e ; // a s p e k t o b r a z u

1. Definiowanie sceny 3D 22 int Aspect = FULL WINDOW; // w p ó ł r z ę d n e p o ł o ż e n i a o b s e r w a t o r a GLdouble eyex = 0 ; GLdouble eyey = 0 ; GLdouble e y e z = 3 ; // współrzędne punktu w k t ó r e g o kierunku j e s t zwrócony obserwator, GLdouble c e n t e r x = 0 ; GLdouble c e n t e r y = 0 ; GLdouble c e n t e r z = 100; // f u n k c j a g e n e r u j ą c a s c e n ę 3D void D i s p l a y ( ) // k o l o r t ł a z a w a r t o ś ć b u f o r a k o l o r u g l C l e a r C o l o r ( 1. 0, 1. 0, 1. 0, 1. 0 ) ; // c z y s z c z e n i e b u f o r a k o l o r u g l C l e a r ( GL COLOR BUFFER BIT ) ; // wybór m a c i e r z y modelowania glmatrixmode (GL MODELVIEW) ; // m a c i e r z modelowania = m a c i e r z j e d n o s t k o w a g l L o a d I d e n t i t y ( ) ; // u s t a w i e n i e o b s e r w a t o r a glulookat ( eyex, eyey, eyez, c e n t e r x, c e n t e r y, c e n t e r z, 0, 1, 0 ) ; // k o l o r k r a w ę d z i s z e ś c i a n u g l C o l o r 3 f ( 0. 0, 0. 0, 0. 0 ) ; // p o c z ą t e k d e f i n i c j i k r a w ę d z i s z e ś c i a n u g l B e g i n ( GL LINES ) ; // w s p ó l r z ę d n e k o l e j n y c h k r a w ę d z i s z e ś c i a n u g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; g l V e r t e x 3 f ( 1. 0, 1. 0, 1. 0 ) ; // k o n i e c d e f i n i c j i prymitywu glend ( ) ;

1. Definiowanie sceny 3D 23 // s k i e r o w a n i e p o l e c e ń do wykonania g l F l u s h ( ) ; // zamiana b u f o r ó w k o l o r u glutswapbuffers ( ) ; // zmiana w i e l k o ś c i okna void Reshape ( int width, int h e i g h t ) // o b s z a r r e n d e r i n g u c a ł e okno g l V i e w p o r t ( 0, 0, width, h e i g h t ) ; // wybór m a c i e r z y r z u t o w a n i a glmatrixmode ( GL PROJECTION ) ; // m a c i e r z r z u t o w a n i a = m a c i e r z j e d n o s t k o w a g l L o a d I d e n t i t y ( ) ; // p a r a m e t r y b r y ł y o b c i n a n i a i f ( Aspect == ASPECT 1 1 ) // w y s o k o ś ć okna w i ę k s z a od w y s o k o ś c i okna i f ( width < h e i g h t && width > 0) glfrustum ( 2. 0, 2. 0, 2. 0 h e i g h t / width, 2. 0 h e i g h t / width, 1. 0, 5. 0 ) ; e l s e // s z e r o k o ś ć okna w i ę k s z a l u b równa w y s o k o ś c i okna i f ( width >= h e i g h t && h e i g h t > 0) glfrustum ( 2.0 width / h e i g h t, 2. 0 width / h e i g h t, 2. 0, 2. 0, 1. 0, 5. 0 ) ; e l s e glfrustum ( 2. 0, 2. 0, 2. 0, 2. 0, 1. 0, 5. 0 ) ; // g e n e r o w a n i e s c e n y 3D D i s p l a y ( ) ; // o b s ł u g a k l a w i a t u r y void Keyboard ( unsigned char key, int x, int y ) // k l a w i s z + i f ( key == + ) e y e z = 0.1; e l s e // k l a w i s z i f ( key == ) e y e z + = 0. 1 ; // o d r y s o w a n i e okna Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; // o b s ł u g a k l a w i s z y f u n k c y j n y c h i k l a w i s z y k u r s o r a void SpecialKeys ( int key, int x, int y ) switch ( key ) // k u r s o r w l e w o case GLUT KEY LEFT : eyex + = 0. 1 ; break ; // k u r s o r w g ó r ę case GLUT KEY UP : eyey = 0.1; break ; // k u r s o r w prawo case GLUT KEY RIGHT : eyex = 0.1; break ; // k u r s o r w d ó ł case GLUT KEY DOWN: eyey + = 0. 1 ;

1. Definiowanie sceny 3D 24 break ; // o d r y s o w a n i e okna Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; // ob sług a menu podręcznego void Menu ( int v a l u e ) switch ( v a l u e ) // o b s z a r r e n d e r i n g u c a ł e okno case FULL WINDOW: Aspect = FULL WINDOW; Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; break ; // o b s z a r r e n d e r i n g u a s p e k t 1 : 1 case ASPECT 1 1 : Aspect = ASPECT 1 1 ; Reshape ( glutget (GLUT WINDOW WIDTH), glutget (GLUT WINDOW HEIGHT ) ) ; break ; // w y j ś c i e case EXIT : e x i t ( 0 ) ; int main ( int argc, char argv [ ] ) // i n i c j a l i z a c j a b i b l i o t e k i GLUT g l u t I n i t (& argc, argv ) ; // i n i c j a l i z a c j a b u f o r a ramki g l u t I n i t D i s p l a y M o d e (GLUT DOUBLE GLUT RGB ) ; // r o z m i a r y g ł ó w n e g o okna programu g l u t I n i t W i n d o w S i z e ( 4 0 0, 4 0 0 ) ; // u t w o r z e n i e g ł ó w n e g o okna programu glutcreatewindow ( S z e ś c i a n 4 ) ; // d o ł ą c z e n i e f u n k c j i g e n e r u j ą c e j s c e n ę 3D glutdisplayfunc ( Display ) ; // d o ł ą c z e n i e f u n k c j i wywoływanej p r z y z m i a n i e r o z m i a r u okna glutreshapefunc ( Reshape ) ; // d o ł ą c z e n i e f u n k c j i o b s ł u g i k l a w i a t u r y glutkeyboardfunc ( Keyboard ) ; // d o ł ą c z e n i e f u n k c j i o b s ł u g i k l a w i s z y f u n k c y j n y c h i k l a w i s z y k u r s o r a glutspecialfunc ( SpecialKeys ) ; // u t w o r z e n i e menu p o d r ę c z n e g o glutcreatemenu ( Menu ) ; // d o d a n i e p o z y c j i do menu p o d r ę c z n e g o glutaddmenuentry ( Aspekt obrazu całe okno,full WINDOW) ; glutaddmenuentry ( Aspekt obrazu 1 : 1, ASPECT 1 1 ) ; glutaddmenuentry ( Wyjście,EXIT ) ; // o k r e ś l e n i e p r z y c i s k u m y s z k i o b s ł u g u j ą c e j menu p o d r ę c z n e glutattachmenu (GLUT RIGHT BUTTON ) ; // w p r o w a d z e n i e programu do o b s ł u g i p ę t l i komunikatów glutmainloop ( ) ; return 0 ;

Literatura 25 Literatura [1] Mark Segal, Kurt Akeley: The OpenGL Graphics System. A Specification Version 2.0 [2] Jackie Neider, Tom Davis, Mason Woo: OpenGL Programming Guide The Red Book [3] Richard S. Wright jr, Michael Sweet: OpenGL Księga eksperta, Helion 1999 [4] The official OpenGL web page, http://www.opengl.org [5] Piotr andrzejewski, Jakub Kurzak: Wprowadzenie do OpenGL. Programowanie zastosowań graficznych, Kwantum 2000