Strona główna
Kursy
Artykuły
Forum
Pliki
Promuj Nas!
[Kurs OpenGL, C++] IV. Przekształcenia geometryczne
http://kursy.ddt.pl/?LessonId=186
1 z 8
2010-04-30 14:22
Powrót
Historia odwiedzonych stron
Poprzednia lekcja
Kurs OpenGL, C++
Następna lekcja
Autor: Janusz Ganczarski
http://januszg.hg.pl/opengl/
IV. Przekształcenia geometryczne
W tym odcinku kursu poznamy mechanizmy biblioteki OpenGL umożliwiające dowolne przekształcenia
geometryczne obiektów. Wykorzystamy takze stos macierzy w celu modelowania sceny 3D zawierajacej wiele
elementów.
4.1. Obrót
Obrót w OpenGL wykonuja funkcje glRotated i glRotatef:
void
glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
void
glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
których parametry oznaczaja:
angle - kat obrotu w stopniach,
x, y, z - współrzedne wektora okreslajacego os obrotu.
Obrót realizowany jest w kierunku przeciwnym do ruchu wskazówek zegara w kierunku prostej
wyznaczonej przez wektor [x, y, z] zaczepionym w początku układu współrzednych. Jezeli wektor ma długosc
rózna od 1 wektor jest normalizowany.
Funkcje glRotated i glRotatef mnoza biezaca macierz przez przez macierz obrotu, która ma nastepujaca
postac (parametr angle zamieniono na a):
4.2. Skalowanie
Skalowanie wykonuja nastepujace funkcje:
void
glScalef (GLfloat x, GLfloat y, GLfloat z)
void
glScalex (GLfixed x, GLfixed y, GLfixed z)
gdzie x, y, z sa współczynnikami skalowania wzgledem kolejnych osi układu współrzednych. Funkcje te
mnoza biezaca macierz przez macierz skalowania, która ma postac:
1.3. Przesunięcie
Trzecia z podstawowych operacji geometrycznych jest przesuniecie o wektor (transalcja), która realizuja
funkcje:
void
glTranslatef (GLfloat x, GLfloat y, GLfloat z)
void
glTranslatex (GLfixed x, GLfixed y, GLfixed z)
gdzie x, y, z sa współrzednymi wektora przesuniecia. Podobnie jak poprzednio opisane funkcje, glTranslatef
i glTranslatex mnoza biezaca macierz przez macierz translacji, która ma postac:
4.4. Mnożenie macierzy
W przypadku, gdy zestaw standardowych przekształcen macierzowych okazuje sie niewystarczajacy,
biblioteka OpenGL udostepnia mozliwosc przemnożenia biezacej macierzy przez macierz okreslona funkcja z
grupy glMultMatrix:
void
glMultMatrixd (
const
GLdouble *m)
void
glMultMatrixf (
const
GLfloat *m)
Parametr m obu funkcji zawiera wskaznik na dane macierzy o rozmiarach 4 × 4, które musza byc ułozone
kolejno kolumnami, tj. w kolejności transponowanej w stosunku do przyjetej w jezykach C i C++:
P anel Logowania
dast19
Administracja
Twój profil
Wyloguj
Uż yt kowników
Obecnie aktywnych:
14
Zalogowanych:
2
Zarejestrowanych:
3855
Ostatnie 24h:
646
Non-cookie 24h:
2051
Wszystkich:
178944
O c z e kuj ąc e t e mat y
Lista jest pusta.
Pokaż wszystkie (0)
Os tatnia Aktualizacja
2010-04-29 22:01:07
(wczoraj)
O st atnio akt ywni
dast19
1 min
Piotr Szawdyński
5 min
Iname
(√ιק)
17 min
szywro5
29 min
Saiph
34 min
markon
57 min
imandre
75 min
WunM
93 min
kuba1817
2 godz
killersft
2 godz
fish13
2 godz
kizia
2 godz
[Kurs OpenGL, C++] IV. Przekształcenia geometryczne
http://kursy.ddt.pl/?LessonId=186
2 z 8
2010-04-30 14:22
4.5. Ładowanie macierzy
Ostatnia z opisywanych operacji na macierzach jest zastepowanie bieżącej macierzy przez dowolnie
okreslona macierz o rozmiarach 4 × 4. Operacje te wykonuja funkcje z grupy glLoadMatrix:
void
glLoadMatrixd (
const
GLdouble *m)
void
glLoadMatrixf (
const
GLfloat *m)
Format danych ładowanej macierzy jest taki sam jak w przedstawionych wyzej funkcjach glMultMatrixd i
glMultMatrixf.
1.6. Składanie przekształceń
Macierzowy opis przekształcen geometrycznych znacznie ułatwia składanie kilku róznych przekształcen
obiektów. Wywołujac funkcje generujące macierze odpowiednich przekształcen dokonujemy jednoczesnie ich
składania. W tej sytuacji jedyna rzecza, o której nalezy pamietac, to kolejność przekształcen, bowiem od tego
zalezy koncowy efekt. Przykładowy program (plik przeksztalcenia.cpp) przedstawia przekształcenia
geometryczne dostepne w bibliotece OpenGL. Scena 3D zawiera pojedynczy obiekt geometryczny zawarty w
bibliotece GLUT. Klawisze kursora pozwalaja na obracanie wyswietlanego obiektu, przyciski „+” i „-” na jego
skalowanie, a lewy przycisk myszki przesuwa obiekt. W ramach eksperymentu Czytelnik moze w programie
zamienic kolejnosc składania wykonywanych tam przekształcen (funkcja Display) np. przesuniecia i obrotu.
Poznajmy jeszcze nowe elementy biblioteki GLUT wykorzystanie w przykładowym programie tj. sposób obsługi
myszki i zdefiniowane obiekty geometryczne. Biblioteka GLUT udostepnia obiekty 3D w wersji szkieletowej
(tzw. „druciaki”) oraz w wersji pełnej. W najblizszych przykładowych programach wykorzystamy wersje
szkieletowe obiektów.
4.6.1. Kula
Powierzchnia kuli rysowana jest jako szkielet składajacy sie z południków i równolezników (rysunek 1).
Powierzchnie kuli, której srodek znajduje się w poczatku układu współrzednych rysuje funkcja:
void
glutWireSphere (GLdouble radius, GLint slices, GLint stacks)
której parametry oznaczaja:
radius - promien kuli,
slices - ilosc południków,
stacks - ilosc równolezników.
Rysunek 1. P rogram P rzekształcenia - kula
4.6.2. Szescian
Szescian o boku długosci size i srodku połozonym w poczatku układu współrzednych rysuje funkcja:
void
glutWireCube (GLdouble size)
4.6.3. Stozek
Stozek rysowany jest podobnie jak kula - jako szkielet oparty na równoległe do podstawy „południki” i
tworzace biegnace od wierzchołka stozka do krawedzi jego podstawy (rysunek 2). Stozek ze srodkiem podstawy
umieszczonym w poczatku układu współrzednych i wierzchołkiem umieszczonym na dodatniej półosi OZ rysuje
funkcja:
void
glutWireCone (GLdouble base, GLdouble height, GLint slices, GLint
stacks)
której parametry oznaczaja:
base - promien podstawy stozka,
height - wysokosc stozka,
slices - ilosc tworzacych,
stacks - ilosc „południków”.
[Kurs OpenGL, C++] IV. Przekształcenia geometryczne
http://kursy.ddt.pl/?LessonId=186
3 z 8
2010-04-30 14:22
Rysunek 2. P rogram P rzekształcenia - s tożek
4.6.4. Torus
Kolejna bryła obrotowa dostepna w bibliotece GLUT jest torus rysowany jako seria walców o
nierównoległych podstawach (rysunek 3) i osi obrotu pokrywajacej sie z osia OZ. Torus rysuje funkcja:
void
glutWireTorus (GLdouble innerRadius, GLdouble outerRadius, GLint
sides, GLint rings)
której parametry oznaczaja odpowiednio:
innerRadius - promien koła tworzacego torus,
outerRadius - promien torusa,
sides - ilosc scian bocznych, z których składa sie pojedynczy walec,
rings - ilosc walców, z których składa sie torus.
Rysunek 3. P rogram P rzekształcenia - torus
4.6.5. Dwunastoscian
Dwunastoscian o srodku połozonym w poczatku układu współrzędnych rysuje funkcja:
void
glutWireDodecahedron (
void
)
4.6.6. Czajnik
Klasycznym obiektem 3D dostepnym w bibliotece GLUT jest opracowany w 1975 roku przez Martina
Newella czajnik - przedstawiony na rysunku 4. Czajnik o wielkosci regulowanej parametrem size rysuje funkcja:
void
glutWireTeapot (GLdouble size)
[Kurs OpenGL, C++] IV. Przekształcenia geometryczne
http://kursy.ddt.pl/?LessonId=186
4 z 8
2010-04-30 14:22
Rysunek 4. P rogram P rzekształcenia - czajnik
4.6.7. Osmioscian
Osmioscian o srodku połozonym w poczatku układu współrzednych rysuje funkcja:
void
glutWireOctahedron (
void
)
4.6.8. Czworoscian
Czworoscian o srodku połozonym w poczatku układu współrzednych rysuje funkcja:
void
glutWireTetrahedron (
void
)
4.6.9. Dwudziestoscian
Dwudziestoscian o srodku połozonym w poczatku układu współrzędnych rysuje funkcja:
void
glutWireIcosahedron (
void
)
4.6.10. Obsługa myszki
Obsługa myszki składa sie z dwóch etapów i jest wykonywana przez dwie funkcje. Pierwsza z nich to:
void
MouseButton (
int
button,
int
state,
int
x,
int
y)
która wykrywa nacisniecie i zwolnienie lewego przycisku myszki. W zależności od stanu lewego przycisku
myszki ustawiana jest wartosc zmiennej globalnej button state na przekazana przez parametr state. Druga
funkcja:
void
MouseMotion (
int
x,
int
y)
wywoływana jest podczas ruchu kursora myszki a jej zadaniem jest odpowiednie (dobrane czesciowo
doswiadczalnie) przeliczenie ruchu myszki na przesuniecie obiektu znajdujacego sie na scenie. Efekt przeliczen
ruchu kursora myszki umieszczony jest w zmiennych globalnych translatex i translatey, które sa bezposredni
przekazywane jako parametry funkcji glTranslatef. Parametry x i y obu funkcji oznaczaja współrzedne kursora
myszki w odniesieniu do układu współrzednych okna, które oczywiscie nie maja nic
wspólnego ze współrzednymi okreslonymi w scenie 3D. Parametr buton funkcji MouseButton okresla który
przycisk myszki został nacisniety lub zwolniony. Parametr ten przyjmuje jedna z wartosci:
GLUT LEFT BUTTON - lewy przycisk myszki,
GLUT MIDDLE BUTTON - srodkowy przycisk myszki,
GLUT RIGHT BUTTON - prawy przycisk myszki.
Jezeli w danym systemie myszka ma tylko dwa przyciski, wartosc GLUT MIDDLE BUTTON nie bedzie
generowana. Natomiast w przypadku myszki z jednym przyciskiem funkcja generuje jedynie wartosc GLUT
LEFT BUTTON. Ostatni nieopisany parametr funkcji MouseButton to state, który okresla czy przycisk myszki
został nacisniety (stała GLUT UP) czy zwolniony (stała GLUT - DOWN).
Aby opisane funkcje obsługi myszki działały nalezy je dołaczyc do listy funkcji zwrotnych wywołujac
odpowiednio:
void
glutMouseFunc (
void
(*func)(
int
button,
int
state,
int
x,
int
y))
void
glutMotionFunc (
void
(*func)(
int
x,
int
y))
1.6.11. Menu wielopoziomowe
W programie został uzyty nowy element biblioteki GLUT — wielopoziomowe menu podreczne. Czesc
menu podrecznego, które bedzie znajdowało sie na drugim (lub wyzszym) poziomie tworzymy w taki sam sposób
jak dotychczas tworzylismy główne menu, czyli przy uzyciu funkcji glutCreateMenu i glutAddMenuEntry. Tak
utworzony fragment menu umieszczamy w menu głównym (nadrzednym) uzywajac funkcji:
void
glutAddSubMenu (
const
char
*label,
int
submenu)
Parametr label okresla nazwe menu podrecznego, a submenu jego identyfikator zwrócony przez funkcje
glutCreateMenu.
[Kurs OpenGL, C++] IV. Przekształcenia geometryczne
http://kursy.ddt.pl/?LessonId=186
5 z 8
2010-04-30 14:22
4.6.12. Odrysowanie okna
Aby zmiany sceny 3D zostały wyswietlone na ekranie potrzebne jest odrysowanie biezacego okna. Mozna
to zrealizowac wywołujac funkcje:
void
glutPostRedisplay (
void
)
4.6.13. Plik przeksztalcenia.cpp
/*
(c) Janusz Ganczarski
http://www.januszg.hg.pl
JanuszG(małpeczka)enter.net.pl
*/
#include <GL/glut.h>
#include <stdlib.h>
// stałe do obsługi menu podręcznego
enum
{
FULL_WINDOW,
// aspekt obrazu - całe okno
ASPECT_1_1,
// aspekt obrazu 1:1
WIRE_SPHERE,
// kula
WIRE_CONE,
// stożek
WIRE_CUBE,
// sześcian
WIRE_TORUS,
// torus
WIRE_DODECAHEDRON,
// dwunastościan
WIRE_TEAPOT,
// czajnik
WIRE_OCTAHEDRON,
// ośmiościan
WIRE_TETRAHEDRON,
// czworościan
WIRE_ICOSAHEDRON,
// dwudziestościan
EXIT
// wyjście
4.7. Stos macierzy modelowania
Do składania przekształcen biblioteka OpenGL wykorzystuje wspomniany juz wczesniej stos macierzy
modelowania. W dotychczasowych programach, oraz pierwszym z przykładowych programów z tego odcinka
kursu, mechanizm stosu nie był faktycznie wykorzystywany. Wszystkie operacje zwiazane ze stosem macierzy
modelowania wykonywane były na macierzy połozonej na szczycie stosu. Pozwala to jednak na efektywna
manipulacje jedynie jednym obiektem na scenie. Oczywiscie obsługa wielu obiektów także jest mozliwa, ale
wymaga to stosowania mniej wygodnych i efektywnych mechanizmów. W szczególnosci mogło by sie okazac
konieczne przechowywanie macierzy modelowania - czyli dublowanie mozliwosci oferowanej przez mechanizm
stosu.
Po lekturze powyzszego wstepu Czytelnik zastanawia sie zapewne jak w praktyce efektywnie mozna
wykorzystac mechanizm stosu macierzy modelowania. Klasycznym przykładem jest budowa obiektów złozonych
z wielu obiektów podstawowych (np. takich jak wyzej opisane obiekty 3D dostępne w bibliotece GLUT).
Drugim, równie czesto wykorzystywanym przykładem, jest animacja sceny składajacej sie z wielu obiektów 3D.
4.7.1. Operacje na stosie
Specyfikacja biblioteki OpenGL przewiduje, ze stos macierzy modelowania przechowuje co najmniej 32
macierze. Oczywiscie konkretne implementacje OpenGL moga dowolnie zwiekszac maksymalna pojemnosc tego
stosu. Opisane ponizej funkcje słuza do operacji na kazdym rodzaju stosu dostepnym w OpenGL. Operacja
zawsze zostanie wykonana na aktualnie wybranym rodzaju stosu. Operacje odłozenia biezacej macierzy na stos
realizuje funkcja:
void
glPushMatrix (
void
)
Natomiast operacje zdjecia macierzy ze stosu wykonuje funkcja:
void
glPopMatrix (
void
)
Próba wykonania niedozwolonej operacji na stosie spowoduje wygenerowanie kodu błedu zwracanego przez
funkcje glGetError:
GL STACK UNDERFLOW - próba pobrania elementu z pustego stosu (niedobór stosu),
GL STACK OVERFLOW - przepełnienie stosu.
Przykładowy program (plik stos modelowania.cpp) opiera sie na poprzednim przykładzie. Podstawowa
róznica jest rysowanie jednego obiektu - piramidy, ale złozonego z duzej ilosci elementów podstawowych -
szescianów. Dla ułatwienia pracy program zawiera dwie funkcje rysujace czesci piramidy w postaci bloków 3 ×
3 (funkcja Cube3x3) i bloków 2 × 2 (funkcja Cube2x2). Pierwszy poziom piramidy ma rozmiary 6 × 6 i jest
rysowany z czterech bloków 3 × 3 (funkcja Pyramid). Przed narysowaniem kazdego z elementów pierwszego
poziomu macierz modelowania odkładana jest na stos – po zakonczeniu rysowania nastepuje zdjecie macierzy ze
stosu. Przy rysowaniu drugiego i trzeciego poziomu piramidy nastepuje dwukrotne odłozenie macierzy
modelowania na stos. Po pierwszym przesuwamy układ współrzednych od odpowiednia ilosc jednostek do góry.
Drugie w kolejności odkładanie macierzy na stos wiaze sie juz bezposrednio z rysowaniem kolejnych elementów
danego poziomu piramidy. Rysowanie kolejnych poziomów nie wymaga juz dodatkowego opisu – wystarcza
jednokrotne odłozenie macierzy modelowania na stos. Przykładowy efekt tych wszystkich przekształcen zawiera
rysunek 5. Oczywiscie uzyskanie takiej figury nie wymaga stosowania mechanizmu stosu macierzy
modelowania. Jednak juz w tak prostym przykładzie widoczne sa korzysci wynikajace z takiego rozwiazania. Po
pierwsze wszystkie elementy obiektu 3D, w tym wypadku poziomy piramidy, sa od siebie niezalezne. Czytelnik
moze to łatwo sprawdzic odpowiednio modyfikujac tekst zródłowy programu. Trudno nie docenic takiej cechy
przy tworzeniu bardziej skomplikowanych obiektów. Druga zaleta jest duza przejrzystosc rozwiazania, co ułatwia
pózniejsza modyfikacje programu i usuwanie ewentualnych błedów.Warto takze dodac, ze mechanizm stosu jest
bardzo szybki i dotyczy to wszystkich implementacji biblioteki OpenGL, nie tylko sprzetowych.
[Kurs OpenGL, C++] IV. Przekształcenia geometryczne
http://kursy.ddt.pl/?LessonId=186
6 z 8
2010-04-30 14:22
W programie wykorzystano takze kilka innych nieopisanych wczesniej funkcji biblioteki OpenGL i GLU. W
poprzednim przykładzie przy przesuwaniu obiektu za pomoca myszki obliczanie wektora przesuniecia oparto o
dobrane doswiadczalnie współczynniki. W przypadku, gdy zmienimy parametry bryły odcinania te współczynniki
trzeba bedzie dobierac ponownie. Biblioteka GLU zawiera funkcje przeliczajace współrzedne w przestrzeni okna
na współrzedne w przestrzeni widoku i odwrotnie.
Przeliczenie współrzednych w przestrzeni widoku (objx, objy, objz) na współrzedne w przestrzeni okna
(winx,winy,winz) wykonuje funkcja gluProject:
GLint gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
const
GLdouble modelMatrix [16],
const
GLdouble projMatrix [16],
const
GLint viewport [4],
GLdouble *winx, GLdouble *winy, GLdouble *winz)
Do przeliczania współrzednych funkcja gluProject wykorzystuje macierz modelowania, macierz rzutowania
oraz współrzedne okna renderingu, które zawarte sa kolejno w parametrach: modelMatrix, projMatrix i viewport
Przeliczenie współrzednych w przestrzeni okna (winx,winy,winz) na współrzedne w przestrzeni widoku
(objx, objy, objz) wykonuje funkcja gluUnProject:
GLint gluUnProject (GLdouble winx, GLdouble winy, GLdouble winz,
const
GLdouble modelMatrix [16],
const
GLdouble projMatrix [16],
const
GLint viewport [4],
GLdouble *objx, GLdouble *objy, GLdouble *objz)
której parametry maja analogiczne znaczenie jak parametry poprzedniej funkcji gluProject.
W wersji 1.3 biblioteki GLU dodano funkcje gluUnProject4:
GLint gluUnProject4 (GLdouble winx, GLdouble winy, GLdouble winz,
GLdouble clipw,
const
GLdouble modelMatrix[16],
const
GLdouble projMatrix[16],
const
GLint viewport[4],
GLdouble near, GLdouble far, GLdouble *objx,
GLdouble *objy, GLdouble *objz, GLdouble *objw)
stanowiaca rozszerzenie gluUnProject umozliwiajaca obliczenia przy niestandardowych ustawieniach bufora
głebokosci (parametry near i far odpowiadające parametrom funkcji glDepthRange) lub w przypadku, gdy
czwarta współrzedna (parametr clipw) przestrzeni okna przyjmuje inna wartość niz 1. Funkcja zwraca dodatkowo
wartosc czwartej współrzednej w przestrzeni widoku (parametr objw). Znaczenie tych dodatkowych
współrzędnych poznamy w kolejnych odcinkach kursu. Wartosci macierzy modelowania, macierzy rzutowania
oraz obszaru renderingu stanowia zmienne stanu maszyny stanu OpenGL. Do odczytu zmiennych stanu słuzy
bardzo liczna grupa funkcji glGet, z których najbardziej uniwersalne sa nastepujace funkcje:
void
glGetBooleanv (GLenum pname, GLboolean *params)
void
glGetDoublev (GLenum pname, GLdouble *params)
void
glGetFloatv (GLenum pname, GLfloat *params)
void
glGetIntegerv (GLenum pname, GLint *params)
Parametr pname okresla która wartosc maszyny stanów OpenGL chcemy pobrac (tabela wszystkich
mozliwych wartosci zajmuje 35 stron specyfikacji OpenGL 2.1), a params wskaznik na zwracana wartosc. W
zależności od rodzaju pobieranej wartosci params wskazuje na pojedyncza zmienna lub tablice. Rodzaj
zwracanej (zwracanych) wartosci jednoznacznie okresla koncowa czesc nazwy funkcji.
Rysunek 5. P rogram Stos modelowania
4.7.2. Plik stos modelowania.cpp
[Kurs OpenGL, C++] IV. Przekształcenia geometryczne
http://kursy.ddt.pl/?LessonId=186
7 z 8
2010-04-30 14:22
/*
(c) Janusz Ganczarski
http://www.januszg.hg.pl
JanuszG(małpeczka)enter.net.pl
*/
#include <GL/glut.h>
#include <stdlib.h>
// stałe do obsługi menu podręcznego
enum
{
FULL_WINDOW,
// aspekt obrazu - całe okno
ASPECT_1_1,
// aspekt obrazu 1:1
EXIT
// wyjście
};
// aspekt obrazu
int
aspect = FULL_WINDOW;
// rozmiary bryły obcinania
const
GLdouble left = -10.0;
4.8. Źródło materiału
Materiał został pobrany ze strony
http://januszg.hg.pl/opengl/
, za uprzednim otrzymaniem zgody od jego
autora. Podziekowania dla
Janusza Ganczarskiego
za udostępnienie materiałów
Poprzednia lekcja
Kurs OpenGL, C++
Następna lekcja
Wsz e lkie prawa z ast rz e ż one . Aut or: ź ródło z e wnę t rz ne
Wszystkie teksty są chronione prawami autorskimi. Kopiowanie lub
rozpowszechnianie treści bez wyraźnej zgody jego autora jest zabronione.
Powrót
Historia odwiedzonych stron
O portalu
Archiwum
Historia
Indeks
Regulamin
Wyszukiwarka
Linki
© Wszelkie prawa zastrzeżone 2005-2010
Czas wygenerowania strony: 0.183s
Autor: Piotr Szawdyński
[Kurs OpenGL, C++] IV. Przekształcenia geometryczne
http://kursy.ddt.pl/?LessonId=186
8 z 8
2010-04-30 14:22