Wprowadzenie do grafiki komputerowej OpenGL Transformacje i rzutowanie (podejście klasyczne 2.1) Podstawy OpenGL
Transformacje geometryczne Całość przekształceń geometrycznych składa się z czterech etapów Transformacje widoku określają położenie kamery Transformacje modelowania przemieszczają obiekty na scenie Transformacje rzutowania definiują bryłę widoku i płaszczyzny obcięcia Mapowanie na okno Podstawy OpenGL
Analogia z aparatem fotograficznym Podstawy OpenGL
Analogia, c.d. Podstawy OpenGL
Od czego zacząć transformacje? Transformacje polegają na zmianie obiektów na scenie – ich położenia, proporcji, w pewnym zakresie kształtu poprzez zmianę położenia współrzędnych wierzchołków Podstawowe transformacje w 2D na początek: scale, shear, rotation skalowanie, ścinanie, obrót W dalszej kolejności Składanie transformacji Transformacje w 3D
Skalowanie Możemy to zapisać macierzowo:
Transformacje jako operacje macierzowe Chcemy przedstawić transformację wierzchołków w postaci: Podstawy OpenGL
Transformowanie modelu, macierze transformacji... geometrycznych we współrzędnych jednorodnych w 3D – potraktowane ogólnie, niekoniecznie w kontekście OpenGL: Macierz translacji Macierz skalowania Podstawy OpenGL
Macierze rzutowania Macierz translacji Podstawy OpenGL
Transformowanie modelu, macierze transformacji... geometrycznych we współrzędnych jednorodnych w 3D – potraktowane ogólnie, niekoniecznie w kontekście OpenGL: Macierze obrotów Podstawy OpenGL
Transformacje można składać... np. obrót o 90o wokół osi x i translacja o 10 jednostek w głąb wzdłuż osi z: Podstawy OpenGL
Cztery podstawowe funkcje transformacji w OpenGL void glMatrixMode(Glenum mode) mode = GL_MODELVIEW | GL_PROJECTION void glLoadIdentity(void) void glLoadMatrix{fd}(const TYPE *m) void glMultMatrix{fd}(const TYPE *m) glMultMatrix() mnoży bieżącą macierz transformacji przez macierz wskazaną argumentem Podstawy OpenGL
Jak myśleć o transformacjach? Kolejność transformacji ma znaczenie! Podstawy OpenGL
Kolejność transformacji Przykład: glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(N); /*transformation N */ glMultMatrixf(M); /*transformation M */ glMultMatrixf(L); /*transformation L */ glBegin(GL_POINTS); glVertex3f(v); /*rysuj vertex v */ glEnd(); Podstawy OpenGL
Nieruchomy układ współrzędnych Przykład: glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(T); /* translation */ glMultMatrixf(R); /* rotation */ draw_the_object(); A co z układem lokalnym? Podstawy OpenGL
Nieruchomy, a lokalny układ Układ lokalny – związany z obiektami. Stosujemy go przy wielu związanych z sobą (często poruszających się obiektach). Np. robot, układ słoneczny. Zapis instrukcji pozostaje taki sam, ale interpretacja jest inna. glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(T); /* translation */ glMultMatrixf(R); /* rotation */ draw_the_object(); Podstawy OpenGL
Spójrzmy jeszcze na translację wynik translacji: w jest zazwyczaj ustawiane na 1, można jednak nadać mu inną wartość; wtedy w pełni funkcje skalującą, np.: Podstawy OpenGL
Jeszcze o składaniu przekształceń... p jest punktem, który należy obrócić wokół prostej A przechodzącej przez początek układu współrzędnych o kąt Ry : obróć wokół osi Y o kąt Rx : obróć wokół osi X o kąt Rz : obróć wokół osi Z o kąt Rx -1: cofnij obrót wokół osi X o kąt Ry-1 : cofnij obrót wokół osi Y by W jakiej kolejności mnożymy? Podstawy OpenGL
Składanie transformacji c.d. p’ = Ry-1 Rx -1 Rz Rx Ry p Zauważmy, że macierze obrotów są ortonormalne: (Dla przypomnienia: wektory są liniowo niezależne i mają jednostkową długość) Takie macierze łatwo odwracać: Podstawy OpenGL
Transformacje w OpenGL void glTranslate{fd}(TYPE x, TYPE y, TYPE z) void glRotate{fd}(TYPE angle TYPE x, TYPE y, TYPE z) void glScale{fd}(TYPE x, TYPE y, TYPE z) Na później zostawiamy sobie: void glPushMatrix(void) void glPopMatrix(void) Podstawy OpenGL
Rzutowanie W OpenGL pracujemy w jednym z dwóch trybów: wyświetlania i transformowania obiektów na scenie rzutowania sceny na płaszczyznę Tryb rzutowania uaktywnia się po wywołaniu: glMatrixMode(GL_PROJECTION) (widać z wywołania, że ma związek macierzami – omówimy to później) Jeśli nie dokonaliśmy żadnych przesunięć, to położenie obserwatora jest w początku układu współrzędnych; obserwator patrzy w kierunku ujemnej osi z. Podstawy OpenGL
Rzutowanie ortogonalne (ang. orthographic) void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far) void glOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) Podstawy OpenGL
Rzutowanie ortogonalne c.d Działanie glOrtho należy rozumieć następująco: Funkcja przygotowuje macierz równoległego rzutu ortogonalnego i mnoży ją przez bieżącą macierz rzutowania. Obszar rzutowania wzdłuż osi Z zawarty jest między wartościami –near i –far. Jeśli pominiemy wywołanie glOrtho to domyślna postać jest następująca: glOrtho(-1., 1.,-1. ,1.,-1.,1.); Podstawy OpenGL
Rzutowanie na fragment okna - glViewPort Standardowo rzutowanie odbywa się na całe okno. Można powiedzieć, że domyślnie jest wywoływana funkcja glViewPort(0,0,w,h); Można za jej pomocą ograniczyć obszar rzutowania.
Rzut perspektywiczny void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far) left, right, bottom, top określają granicę współrzędnych okna, near, far określają odległość bliższej i dalszej płaszczyzny od znajdującego się w początku układu współrzędnych obserwatora; wartości near i far muszą być dodatnie; jeśli obserwator jest zwrócony w kierunku ujemnej osi z (default), to obie płaszczyzny przecinają oś z w punktach (0,0,-near) i (0,0,-far). Podstawy OpenGL
glFrustum glFrustum (-28.0/2, 28.0/2, -20.0/2, 20.0/2 80.0, 500.0 Podstawy OpenGL
Rzut perspektywiczny c.d. Nieco wygodniejsze jest użycie, ale nie tożsame: void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far) fovy – kąt widzenia w płaszczyźnie yz aspect – stosunek szerokości do wysokości pola widzenia Podstawy OpenGL
glFrustum, a gluPerspective W glFrustum bliższa płaszczyzna odcięcia jest jednocześnie płaszczyzną rzutowania (ekranu). W gluPerspective – nie. Jeżeli argumentowi near nadamy odpowiednio małą wartość (>0), to możemy teoretycznie oglądać obiekty między ekranem, a obserwatorem. Przykładowe ustawienie gluPerspective dla 15” monitora: gluPerspective(14.25, 1.4, 80.0, 500.0) Podstawy OpenGL
glFrustum, a GluPerspective Można stwierdzić, że glFrustum częściej jest używane przy nieruchomym obserwatorze, natomiast gluPerspective – przy poruszającym się. Nie jest to całkiem ścisłe. Jednak z gluPerspective na ogół łączy się funkcję transformacji widoku gluLookAt, która służy do przemieszczania kamery.
Transformowanie widoku void gluLookAt(…) Funkcja szczególnie przydatna, gdy chcemy zmieniać wygodnie położenie kamery i punkt, na który patrzy. Na przykład gdy chcemy wykonać przelot nad sceną. Podstawy OpenGL
Położenie obserwatora void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz,) Podstawy OpenGL
Położenie obserwatora Domyślne położenie kamery: gluLookat (0.0, 0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0); gluLookat należy do biblioteki GLU - bo zawiera złożenie kilku podstawowych operacji OpenGL Podstawy OpenGL
Przykład Przykład rzutowania (www.xmission.com/~nate) Podstawy OpenGL
Uwaga o transformacji widoku i transformacji modelu Transformowanie widoku (czyli położenia obserwatora w układzie współrzędnych) i transformowanie modelu dopełniają się. Możemy uzyskać identyczny widok sceny np. przesuwając obserwatora w prawo lub obiekt na scenie w lewo. Podstawy OpenGL
Przykład transformacji Podstawy OpenGL
Dwa uzupełnienia Przykład animacji z czerwonej książki. Elementarny przykład użycia stosu w transformacjach. Podstawy OpenGL
Pierwsza animacja (1/4) #include <stdio.h> #include <windows.h> #include <gl\gl.h> #include <gl\glu.h> #include <gl\glut.h> static GLfloat spin = 0.0; void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel (GL_FLAT); } Podstawy OpenGL
Pierwsza animacja (2/4) void display(void) { glClear (GL_COLOR_BUFFER_BIT); glPushMatrix(); glRotatef(spin, 0.0, 0.0, 1.0); glColor3f(1.0, 1.0, 1.0); glRectf(-25.0, -25.0, 25.0, 25.0); glPopMatrix(); glutSwapBuffers(); } void spinDisplay(void) spin = spin + 2.0; if (spin > 360.0) spin = spin - 360.0; glutPostRedisplay(); Podstawy OpenGL
Pierwsza animacja (3/4) void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); } void mouse(int button, int state, int x, int y) switch (button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) glutIdleFunc(spinDisplay); break; case GLUT_MIDDLE_BUTTON: if (state == GLUT_DOWN) glutIdleFunc(NULL); default: Podstawy OpenGL
Pierwsza animacja (4/4) /* * Request double buffer display mode, * Register mouse input callback functions */ int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize (250, 250); glutInitWindowPosition (100, 100); glutCreateWindow(argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutMainLoop(); return 0; } Podstawy OpenGL
Potok transformacji Podstawy OpenGL
Potok transformacji Modelview Matrix Projection Perspective Division Viewport Transform object eye clip normalized device window Podstawy OpenGL