Oprogramowanie i wykorzystanie stacji roboczych Wykład 7
Transkrypt
Oprogramowanie i wykorzystanie stacji roboczych Wykład 7
OpenGL - maszyna stanu OpenGL posiada zmienne przechowujace ˛ wiele wewnetrznych ˛ stanów i ustawień. Ta kolekcja jest nazywana Maszyna˛ stanu OpenGL. Oprogramowanie i wykorzystanie stacji roboczych Wiele zmiennych stanu jest dwustanowa: do właczenia ˛ stanu służy funkcja glEnable. do wyłaczenia ˛ stanu służy funkcja glDisable. Przykład: Wykład 7 // Właczenie ˛ oświetlenia glEnable(GL_LIGHTING); Dr inż. Tomasz Olas [email protected] ... Instytut Informatyki Teoretycznej i Stosowanej // Wyłaczenie ˛ oświetlenia glDisable(GL_LIGHTING); Politechnika Cz˛estochowska Wykład 7 – p. 1/32 Wykład 7 – p Grupy atrybutów Zmienne stanu W bibliotece OpenGL poszczególne stany sa˛ połaczone ˛ w grupy atrybutów: Do odczytania wartości zmiennej stanu służa˛ funkcje: glGetBooleanv(), glGetDoublev(), glGetFloatv(), glGetIntegerv(), glGetPointerv() i glIsEnabled(). Do odczytywania niektórych zmiennych stanu służa˛ specjalne funkcje, np. glGetLight*(), glGetError(), czy glGetPolygonStipple(). Przykład: GL_ACCUM_BUFFER_BIT accum-buffer GL_ALL_ATTRIB_BITS – GL_COLOR_BUFFER_BIT color-buffer GL_CURRENT_BIT current GL_DEPTH_BUFFER_BIT depth-buffer GL_ENABLE_BIT enable GL_EVAL_BIT eval GL_FOG_BIT fog GL_HINT_BIT hint GL_LIGHTING_BIT lighting GLboolean isLighting; glGetBooleanv(GL_LIGHTING, &isLighting); std::cout << (isLighting == GL_TRUE ? "true" : "false") << " ; "; GL_LINE_BIT line GL_LIST_BIT list GL_PIXEL_MODE_BIT pixel GL_POINT_BIT point GL_POLYGON_BIT polygon GL_POLYGON_STIPPLE_BIT polygon-stipple GL_SCISSOR_BIT scissor GL_STENCIL_BUFFER_BIT stencil-buffer GL_TEXTURE_BIT texture GL_TRANSFORM_BIT transform GL_VIEWPORT_BIT viewport GLfloat c[4]; glGetFloatv(GL_CURRENT_COLOR, c); std::cout << c[0] << "," << c[1] << "," << c[2] << "," << c[3]; Przykładowy wynik działania: false ; 1,1,1,1 Wykład 7 – p. 3/32 Wykład 7 – p Stos atrybutów Parametry rysowania punktów Ustalenie rozmiaru punktu Do umieszczenia na stosie grupy atrybutów służy funkcja: void glPointSize(GLfloat size); void glPushAttrib(GLbitfield mask) gdzie: Do zdjecia ˛ ze stosu umieszczonych tam atrybutów służy funkcja: size: przybliżona średnica (w pikselach) rysowanych punktów. Nie wszystkie średnice punktów sa˛ dostepne: ˛ void glPopAttrib(void) GLfloat sizes[2]; GLfloat step; Przykład: glColor3f(1.0f, 0.0f, 0.0f); drawLine(0.0f, 0.0f, 2.0f, 0.0f); glPushAttrib(GL_CURRENT_BIT); glColor3f(1.0f, 1.0f, 1.0f); drawLine(0.0f, 0.0f, 2.0f, 2.0f); glPopAttrib(); drawLine(0.0f, 0.0f, 0.0f, 2.0f); // Obsługiwany zakres wielkości punktów // Obsługiwany przyrost wielkości punktów // Pobranie zakresu obsługiwanych wielkości i przyrostu wielkości glGetFloatv(GL_POINT_SIZE_RANGE, sizes); glGetFloatv(GL_POINT_SIZE_GRANULARITY, &step); Rysowanie okragłych ˛ punktów (zamiast prostokatnych): ˛ glEnable(GL_POINT_SMOOTH); Wykład 7 – p. 5/32 Parametry rysowania linii (I) Wykład 7 – p Parametry rysowania linii (II) Ustalenie grubości linii Rysowanie linii przerywanych: void glLineWidth(GLfloat width); glEnable(GL_LINE_STIPPLE); gdzie: Określenie wzoru używanego podczas rysowania linii: width: przybliżona grubość linii (w pikselach). glLineStipple(GLint factor, GLushort pattern); Określenie dostepnych ˛ wartości: GLfloat sizes[2]; GLfloat step; gdzie: // Obsługiwany zakres wielkości punktów // Obsługiwany przyrost wielkości punktów // Pobranie zakresu obsługiwanych wielkości i przyrostu wielkości glGetFloatv(GL_LINE_WIDTH_RANGE, sizes); glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &step); Wykład 7 – p. 7/32 factor - Mnożnik określajacy ˛ ile pikseli linii odpowiada pojedynczemu bitowi wzorca przerywania [1 - 255]. pattern - 16 bitowy wzorzec przerywania (jako pierwszy implementowany jest bit najmniej znaczacy) ˛ Wykład 7 – p Ograniczenia glBegin() - glEnd() Prymitywy Najważniejszymi informacjami dotyczacymi ˛ wierzchołków sa˛ ich współrz˛edne określane poprzez funkcje˛ glVertex*(). Ponadto można określić dodatkowe informacje dotyczace ˛ wierzchołków, np. kolor, wektor normalny, współrz˛edne mapowania tekstury, itp. Funkcjami jakie moga˛ być użyte wewnatrz ˛ pary glBegin() i glEnd() sa: ˛ glVertex*(), glColor*(), glIndex*(), glNormal*(), glTexCoord*(), glEdgeFlag*(), glMaterial*(), glArrayElement(), glEvalCoord*(), glEvalPoint*(), glCallList(), glCallLists(). Wykład 7 – p. 9/32 Wykład 7 – p. GL_POLYGON - ograniczenia Kierunek Wszystkie wielokaty ˛ musza˛ być płaskie (wszystkie wierzchołki wielokata ˛ musza˛ leżeć na jednej płaszczyźnie). zgodny z ruchem wskazówek zegara clockwise winding (CW) Krawedzie ˛ wielokata ˛ nie moga˛ sie˛ przecinać, sam zaś wielokat ˛ musi być wielokatem ˛ wypukłym (nie może posiadać żadnych wcieć) ˛ 2 3 2 Wykład 7 – p. 11/32 przeciwny do ruchu wskazówek zegara counterclockwise winding (CCW) 1 3 1 Wykład 7 – p. Kierunek w OpenGL Tryby rysowania wielokatów ˛ Do określenia orientacji wielokatów ˛ w OpenGL służy funkcja: void glFrontFace(GLenum mode) gdzie: mode przyjmuje wartości: GL_CW lub GL_CCW Przykład: Wielokaty ˛ nie musza˛ być wypełnione bieżacym ˛ kolorem. Domyślnie wielokaty ˛ sa˛ rysowane jednolitym kolorem, można jednak to zmienić nakazujac, ˛ aby były rysowane jedynie jako sylwetki lub nawet jako punkty (sa˛ wtedy rysowane jedynie wierzchołki). glPolygonMode(GLenum face, GLenum); gdzie: // określenie, że wielokaty ˛ o kolejności kraw˛ edzi zgodnej // z ruchem wskazówek zegara sa˛ widoczne od frontu glFrontFace(GL_CW); // określenie, że wielokaty ˛ o kolejności kraw˛ edzi przeciwnej // do ruchu wskazówek zegara sa˛ widoczne od frontu glFrontFace(GL_CCW); face - Określa strone˛ wielokata, ˛ do której bedzie ˛ sie˛ odnosić dane wywołanie funkcji: GL_FRONT - przednia strona, GL_BACK - tylna strona, GL_FRONT_AND_BACK - obie strony. mode - Określa nowy tryb rysowania. Domyślnym trybem jest GL_FILL dajacy ˛ wypełnione wielokaty. ˛ GL_LINE powoduje rysowanie jedynie sylwetek wielokatów ˛ (zewnetrznych ˛ kraw˛edzi), zaś GL_POINT powoduje rysowanie jedynie punktów w wierzchołkach wielokata. ˛ Wykład 7 – p. 13/32 Wykład 7 – p. Kierunek wielokatów ˛ - przykład Wypełnianie wielokatów ˛ void drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3) { glBegin(GL_TRIANGLES); glVertex3i(x1, y1, 0); glVertex3i(x2, y2, 0); glVertex3i(x3, y3, 0); glEnd(); } Wypełnianie wielokatów ˛ glEnable(GL_POLYGON_STIPPLE); a nastepnie ˛ glPolygonStipple(const GLubyte *bitmap); gdzie: bitmap - wzorzec bitowy o wymiarach 32x32 bity (Jedynki we wzorcu sa˛ rysowane bieżacym ˛ kolorem wypełniania, zera nie sa˛ rysowane). void MyGLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); //glFrontFace(GL_CW); glPolygonMode(GL_FRONT, GL_FILL); glPolygonMode(GL_BACK, GL_LINE); drawTriangle(0, 0, 1, 0, 0, 1); drawTriangle(1, 0, 0, 1, 1, 1); } Wykład 7 – p. 15/32 Wykład 7 – p. Przesuniecie ˛ Skalowanie Przesuniecie ˛ jest operacja˛ przemieszczajac ˛ a˛ punkty o określona˛ wartość w danym kierunku. Skalowanie powoduje zwiekszenie ˛ lub zmniejszenie obiektu we wszystkich trzech osiach o zadane współczynniki. Do określenia przesuniecia ˛ należy określić wektor przesuniecia ˛ d. Skalowanie nie musi być jednorodne. Można go użyć do ściśniecia ˛ lub rozciagni ˛ ecia ˛ obiektu. Do skalowania służy funkcja: glTranslate[df](TYPE dx, TYPE dy, TYPE dz); gdzie: glScale[df](TYPE x, TYPE y, TYPE z); dx - współrz˛edna x wektora przesuniecia, ˛ dy - współrz˛edna y wektora przesuniecia, ˛ dz - współrz˛edna z wektora przesuniecia. ˛ Wykład 7 – p. 17/32 Wykład 7 – p. Transformacje - przykład (I) Obrót class MyGLWidget : public QGLWidget { public: MyGLWidget(QWidget* parent = NULL, const char* name = NULL); protected: void initializeGL(); void paintGL(); void resizeGL(int w, int h); Obrót jest dokonywany poprzez określenie kata ˛ o jaki maja˛ zostać obrócone punkty oraz wektora wyznaczajacego ˛ oś obrotu. void keyPressEvent(QKeyEvent* event); glRotate[df](TYPE angle, TYPE x, TYPE y, TYPE z); GLfloat zRoll; }; gdzie: angle - kat ˛ obrotu w stopniach, x, y, z - współczynniki wektora obrotu. Obrót jest wykonywany w kierunku przeciwnym do ruchu wskazówek zegara. Wykład 7 – p. 19/32 Wykład 7 – p. Transformacje - przykład (II) Rzutowanie równoległe void MyGLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glRotatef(zRoll, 0.0f, 0.0f, 1.0f); drawTriangle(-1, -1, 1, -1, 0, 1); } Rzutowanie równoległe jest cz˛esto używane w projektowaniu architektonicznym i programach CAD. W OpenGL do określenia rzutu równoległego służy funkcja glOrtho. glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far); void MyGLWidget::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Left) { zRoll -= 3.0f; updateGL(); } if (event->key() == Qt::Key_Right) { zRoll += 3.0f; updateGL(); } } Wykład 7 – p. 21/32 Rzutowanie perspektywiczne (I) Wykład 7 – p. Rzutowanie perspektywiczne (II) Ustalanie rzutu perspektywicznego przy użyciu funkcji glFrustum: Ustalanie rzutu perspektywicznego przy użyciu funkcji gluPerspective: glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far); gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); fovy - szerokość kata ˛ widzenia w pionie (w stopniach), aspect - używany do wyznaczenia konta widzenia w poziomie. Wykład 7 – p. 23/32 Wykład 7 – p. „Pozycja kamery” Zmiana „pozycji kamery” Do zmiany położenia „kamery” może zostać wykorzystana transformacja: glTranslatef(0.0, 0.0, -10.0); rysuj_kwiatek(); Wykład 7 – p. 25/32 Funkcja gluLookAt Wykład 7 – p. Definiowanie widoku (I) Funkcja gluLookAt umożliwia umieszczenie obserwatora (kamery) w pewnym punkcie w przestrzeni i określenie kierunku w którym obserwator patrzy (zwrócona jest kamera). Do ustalenia obszaru okna (widok), przeznaczonego do wykorzystania przez OpenGL służy funkcja glViewport glViewport(GLint x, GLint y, GLsizei width, GLsizei height); void gluLookAt(GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ, GLdouble centerX, GLdouble centerY, GLdouble centerZ, GLdouble upX, GLdouble upY, GLdouble upZ); eyeX, eyeY, eyeZ - punkt obserwacji (współrz˛edne kamery), centerX, centerY, centerZ - określa kierunek patrzenia (kierunek w którym zwrócona jest kamera), upX, upY, upZ - określa kierunek „do góry” z miejsca patrzenia. Wykład 7 – p. 27/32 Wykład 7 – p. Definiowanie widoku (II) Bufor głeboko ˛ ści (I) void MyGLWidget::resizeGL( int w, int h ) { if (h == 0) h = 1; Gdy jest rysowany piksel przypisywana jest mu wartość (zwana wartościa˛ z ) określajac ˛ a˛ odległość punktu tego piksel od obserwatora. Później gdy w tym samym miejscu ekranu ma zostać narysowany piksel, wartość z nowego piksel jest porównywana z wartościa˛ z piksel już narysowanego. Jeżeli jest wieksza, ˛ oznacza to, że jego punkt jest bliżej obserwatora, wiec ˛ stary piksel jest zasłaniany przez nowy. if (w > h) glViewport((w - h)/2, 0, h, h); else glViewport(0, (h - w)/2, w, w); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); if (ortho) glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f); else gluPerspective(60.0f, 1.0f, 0.1, 2.0); glMatrixMode(GL_MODELVIEW); } Wykład 7 – p. 29/32 Bufor głeboko ˛ ści (II) Wykład 7 – p. Bufor głeboko ˛ ści - przykład Właczenie ˛ bufora głebokości: ˛ glEnable(GL_DEPTH_TEST); Bufor głebokości ˛ musi być wyzerowany za każdym razem gdy przystepujemy ˛ do narysowania sceny. // Wyczyszczenie okna i bufora gł˛ ebokości glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(0.0f, 0.0f, 1.0f); glBegin(GL_QUADS); glVertex3f(0.1f, 0.1f, 0.1f); glVertex3f(0.5f, 0.5f, 0.1f); glEnd(); glColor3f(1.0f, 0.0f, 0.0f); glBegin(GL_TRIANGLES); glVertex3f(0.5f, 0.0f, 0.0f); glVertex3f(0.0f, 0.5f, 0.0f); glEnd(); Bufor głebokości ˛ wyłaczony ˛ Wykład 7 – p. 31/32 glVertex3f(0.1f, 0.5f, 0.1f); glVertex3f(0.5f, 0.1f, 0.1f); glVertex3f(0.0f, 0.0f, 0.0f); Bufor głebokości ˛ właczony ˛ Wykład 7 – p.