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.