Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor artykułu: mgr Jerzy Wałaszek, wersja1.0 |
©2011 mgr
Jerzy Wałaszek
|
Do grafiki 3D opłaca się stosować profesjonalne biblioteki graficzne. Taką właśnie biblioteką jest OpenGL, którą w prosty sposób możemy zastosować w SDL. W lekcji korzystamy z materiałów kursu NeHe, który jest dostępny w sieci. Kurs ten co prawda dotyczy środowiska Windows, jednakże w prosty sposób da się przetworzyć na środowisko SDL. Oczywiście w materiale stosujemy własne podejście do poruszanych problemów.
W ten sposób udostępnimy naszemu programowi dwie biblioteki: opengl oraz glu. W pierwszej są zdefiniowane procedury graficzne 3D, natomiast druga udostępnia kilka funkcji pomocniczych, które ułatwiają operowanie obiektami 3D. Ten krok jest bardzo ważny - bez tego wpisu żaden z dalszych programów się nie uruchomi.
Nasz program będzie działał wg następującego schematu:
Rysowanie sceny w pętli
Wyświetlenie narysowanej sceny
Obsługa zdarzeń (reakcja na klawisz ESC = zakończenie programu)
Kontynuacja pętli
Poniższy program jest szablonem dla aplikacji SDL / OpenGL. Wprowadź go do edytora i zapisz projekt jako szablon: File/Save project as template. Później będzie można go szybko wybierać z kreatora projektów w Code::Blocks.
Na tym etapie po uruchomieniu programu ekran staje się czarny, pojawia się na nim kursor myszki, a naciśnięcie klawisza ESC kończy jego działanie.
Code::Blocks |
// Szablon SDL / OpenGL // (C)2012 Koło Informatyczne // I LO w Tarnowie //------------------------------- #include <SDL/SDL.h> #include <GL/gl.h> #include <GL/glu.h> const int W = 1280; const int H = 1024; int main(int argc, char *argv[]) { SDL_Event event; SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,32); SDL_SetVideoMode(W, H, 0, SDL_OPENGL | SDL_FULLSCREEN); glViewport(0, 0, W, H); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)W/(GLfloat)H,0.1f,300.0f); glMatrixMode(GL_MODELVIEW); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); for(int done = 0; !done;) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Tutaj umieszczamy rysowanie scenySDL_GL_SwapBuffers(); // wyświetlamy scenę w oknie podglądu SDL_PollEvent(&event); // sprawdzamy kolejkę zdarzeń if(event.key.keysym.sym == SDLK_ESCAPE) done = 1; } } |
Kod | Objaśnienia |
---|---|
#include <SDL/SDL.h> #include <GL/gl.h> #include <GL/glu.h> |
Na początku programu wstawiamy dyrektywy dołączenia plików nagłówkowych, w których znajdują się definicje funkcji oraz typów danych używanych przez SDL oraz OpenGL. Nazwy wszystkich funkcji biblioteki OpenGL rozpoczynają się od liter gl, a nazwy funkcji biblioteki użytkowej glu rozpoczynają się od liter glu. |
const int W = 1280; const int H = 1024; |
Stała W definiuje szerokość ekranu w pikselach. Stała H definiuje wysokość ekranu w pikselach. |
int main(int argc, char *argv[]) { |
Główna funkcja programu |
SDL_Event event; |
Struktura event służy do obsługi zdarzeń w trakcie działania programu. |
SDL_Init(SDL_INIT_VIDEO); |
Inicjujemy podsystem wideo biblioteki SDL. |
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,32); |
Ustawiamy stan początkowy biblioteki OpenGL poprzez określenie kilku atrybutów. Pierwsze trzy funkcje definiują rozmiar pól barw składowych na 8 bitów. Ostatnia funkcja określa rozmiar piksela w bitach. Takie ustawienia dają nam pełną głębię kolorów - 16mln barw. |
SDL_SetVideoMode(W, H, 0, SDL_OPENGL | SDL_FULLSCREEN); |
Ustawiamy pożądany tryb wyświetlania. Pierwsze dwa parametry określają szerokość i wysokość ekranu. Trzeci parametr jest ignorowany, ponieważ rozmiar piksela dla OpenGL ustawiamy w atrybutach powyżej. Czwarty parametr określa, że SDL będzie tworzyło obraz poprzez bibliotekę OpenGL na pełnym ekranie. |
glViewport(0, 0, W, H); |
To wywołanie określa okno podglądu sceny. Pierwsze dwa parametry to współrzędne x i y lewego dolnego narożnika (standardowo 0, 0). Następnie mamy szerokość i wysokość okna podglądu. W naszym przypadku okno podglądu obejmie cały obszar ekranu. Układ współrzędnych sceny jest umieszczany na środku okna podglądu. |
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)W/(GLfloat)H,0.1f,300.0f); |
Wybieramy do przetwarzania macierz projekcji, która
odpowiada za sposób prezentacji naszej sceny w obrębie okna
podglądu. Dokładniejsze wyjaśnienie zastosowania tej macierzy
zostanie podane później. Kolejna funkcja ustawia w macierzy projekcji macierz jednostkową. Jeśli wyobrazimy sobie kolejne przekształcenia jako mnożenia, to macierz jednostkowa odpowiada mnożeniu przez 1, zatem nie wprowadza żadnych przekształceń. Zawsze macierz jednostkową ustawiamy na początku przekształceń, aby zdefiniować neutralny stan początkowy. Ostatnia funkcja definiuje perspektywę patrzenia na scenę - dzięki perspektywie obiekty sceny będą wyglądały jak w świecie rzeczywistym - bliższe będą większe, a dalsze mniejsze. Pierwszy parametr określa kąt patrzenia poprzez okno podglądu - to jak judasz przy drzwiach - większy kąt daje szersze pole widzenia, mniejszy zmniejsza je. Kąty w OpenGL podajemy w stopniach. Drugi parametr określa tzw. aspekt okna podglądu, czyli iloraz jego szerokości przez wysokość. Wg tego aspektu będą rysowane obiekty sceny. Zapewni on ich odpowiednie proporcje. Ostatnie dwa parametry określają głębię rysowania. W naszym przypadku element sceny będzie rysowany, jeśli znajdzie się w odległości pomiędzy 0.1 a 300 jednostek. |
glMatrixMode(GL_MODELVIEW); |
Przełączamy się na macierz widoku modelu. Macierz ta kontroluje układ współrzędnych, wg którego są wykonywane przekształcenia oraz operacje graficzne. |
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
Funkcja określa kolor tła. Pierwsze trzy parametry definiują składowe R, G i B. Wartość 0 oznacza brak danej składowej. Wartość 1 oznacza maksymalne natężenia wybranej składowej. Ten schemat obowiązuje dla pozostałych funkcji definiujących kolor w OpenGL. |
glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); |
Pierwsza funkcja włącza rysowanie ścian ze sprawdzaniem głębokości. Druga funkcja określa sposób testowania głębokości pikseli ścian. Przy rysowaniu ścian OpenGL odnotowuje w buforze głębokości odległość ich pikseli na osi z. Jeśli nowy piksel posiada równą lub mniejszą odległość, to zostanie narysowany. W przeciwnym razie znajduje się za już narysowanym wcześniej pikselem i nie będzie rysowany. Bufor głębokości pozwala realistycznie oddawać kształty rysowanych obiektów. |
for(int done = 0; !done;) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Tutaj umieszczamy rysowanie sceny SDL_GL_SwapBuffers(); SDL_PollEvent(&event); if(event.key.keysym.sym == SDLK_ESCAPE) done = 1; } return 0; } |
Pętla rysowania sceny. Na początku czyścimy bufor obrazu
oraz bufor głębokości. Następnie zerujemy bieżące
przekształcenie ustawiając w macierzy widoku modelu macierz
jednostkową. W miejscu komentarza będziemy umieszczali kod rysujący ściany naszych obiektów. Po narysowaniu sceny wywołujemy funkcję, która prześle ją na ekran monitora. Ostatnim elementem jest sprawdzenie kolejki zdarzeń. Jeśli użytkownik nacisnął klawisz ESC, to program kończy pętlę i w konsekwencji kończy również swoje działanie. |
Układ współrzędnych OpenGL wygląda następująco:
Oś OZ jest skierowana w kierunku obserwatora. Za pomocą macierzy widoku modelu dokonujemy przekształceń tego układu współrzędnych (przesunięcia, obroty, skalowanie). Jako pierwsze ćwiczenie przesuniemy układ współrzędnych o 6 jednostek (przez jednostkę w OpenGL rozumiemy pewną umowną wielkość, która nie zależy od aktualnej rozdzielczości ekranu) w głąb przestrzeni i narysujemy trójkąt. Trójkąt będzie zbudowany z 3 punktów, które w przesuniętym układzie posiadają współrzędne:
Pod komentarzem umieść następujący kod:
glTranslatef(0.0f,0.0f,-6.0f); glBegin(GL_TRIANGLES); // rysujemy trójkąt glVertex2f( 0.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glEnd();
Przyjrzyjmy się dokładnie temu kodowi:
Kod | Objaśnienia |
---|---|
glTranslatef(0.0f,0.0f,-6.0f); |
Wywołanie tej funkcji przesuwa bieżący układ współrzędnych o 6 jednostek w głąb przestrzeni. Parametrami są przesunięcia względem obecnego układu współrzędnych kolejno wzdłuż osi x, y i z. Ponieważ dwa pierwsze parametry mają wartość 0, to układ współrzędnych przemieści się tylko wzdłuż osi z o 6 jednostek. |
glBegin(GL_TRIANGLES); |
Ta funkcja włącza tryb rysowania w bieżącym układzie współrzędnych, który teraz jest przesunięty o 6 jednostek w głąb z powodu poprzedniej funkcji. Parametr glBegin() określa rodzaj rysowanych obiektów - tutaj będą to trójkąty. |
glVertex2f( 0.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); |
Za pomocą kolejnych wywołań funkcji glVertex() określamy współrzędne wierzchołków trójkąta. Funkcji glVertex() jest wiele odmian, które przyjmują różne rodzaje parametrów. Funkcja glVertex2f() przyjmuje dwa parametry - współrzędne x i y wierzchołka, natomiast współrzędną z automatycznie ustawia na zero - pamiętajmy jednakże, że współrzędne te odnoszą się do bieżącego układu współrzędnych, który został na początku przesunięty o 6 jednostek w głąb przestrzeni 3D. Wczytane wierzchołki są zapamiętywane w wewnętrznej kolejce OpenGL. |
glEnd(); |
Po wywołaniu tej funkcji OpenGL przetwarza wczytane wierzchołki zgodnie z przekształceniem w macierzy widoku modelu - zostanie dla nich zastosowane przesunięcie o 6 jednostek w głąb przestrzeni. Po tej operacji OpenGL wyświetla zdefiniowany obiekt zgodnie z przekształceniem w macierzy projekcji. Innymi słowy, nasz trójkąt pojawi się na ekranie. |
Poeksperymentuj z różnymi parametrami funkcji glTranslatef(). Ostatni parametr reguluje odległość obiektu od płaszczyzny obrazu. Im będzie on mniejszy (bardziej ujemny), tym dalej znajdzie się nasz trójkąt i z uwagi na perspektywę ustawioną przez funkcję gluPerspective() stanie się on coraz mniejszy. Dodajmy teraz kwadrat obok trójkąta. Aby nie zmieniać definicji wierzchołków trójkąta, dokonamy wstępnego przesunięcia o 6 jednostek w głąb oraz o 1,5 jednostki w lewo. Narysujemy nasz trójkąt, po czym przesuniemy układ współrzędnych o 3 jednostki w prawo i narysujemy kwadrat. Zastąp poprzedni kod następującym:
glTranslatef(-1.5f,0.0f,-6.0f); // przesuwamy układ współrzędnych glBegin(GL_TRIANGLES); // rysujemy trójkąt glVertex2f( 0.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glEnd(); glTranslatef(3.0f,0.0f,0.0f); // zmieniamy pozycję układu współrzędnych glBegin(GL_QUADS); // rysujemy kwadrat glVertex2f( 1.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glVertex2f(-1.0f, 1.0f); glEnd();
Kod | Objaśnienia |
---|---|
glTranslatef(-1.5f,0.0f,-6.0f); |
Pierwsze przesunięcie ustawia nowy układ współrzędnych o 6 jednostek w głąb oraz o 1,5 jednostki w lewo. |
glBegin(GL_TRIANGLES); glVertex2f( 0.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glEnd(); |
Teraz nasz trójkąt zostanie narysowany nieco na lewo od poprzedniej wersji programu. Zwróć uwagę, że wierzchołki posiadają takie same współrzędne, ale cały układ współrzędnych jest teraz w innym miejscu. |
glTranslatef(3.0f,0.0f,0.0f); |
Po narysowaniu trójkąta przesuwamy układ współrzędnych o 3 jednostki w prawo. Głębokość zostaje taka sama: 6 jednostek. |
glBegin(GL_QUADS); glVertex2f( 1.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); |
Rysujemy kwadrat. Zwróć uwagę, iż w wywołaniu funkcji
glBegin() umieściliśmy inną stałą, która informuje OpenGL, iż
nowa figura posiada 4 wierzchołki. Kolejne 4 wywołania definiują kolejne wierzchołki kwadratu. Zauważ, że są one podane w kolejności zgodnej z ruchem wskazówek zegara. Ta własność stanie się istotna później, gdy będziemy rysować bardziej skomplikowaną grafikę. Po wywołaniu glEnd() OpenGL rysuje nasz kwadrat po prawej stronie trójkąta. |
GLfloat z = -3.0f; // przesunięcie na osi z GLfloat dz = -0.1; // przyrost przesunięcia na osi z for(int done = 0; !done;) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Tutaj umieszczamy rysowanie sceny glTranslatef(-1.5f,0.0f,z); // przemieszczamy o z jednostek w głąb glBegin(GL_TRIANGLES); glVertex2f( 0.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glEnd(); glTranslatef(3.0f,0.0f,0.0f); glBegin(GL_QUADS); glVertex2f( 1.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); z += dz; // modyfikujemy przesunięcie dla następnego obiegu pętli if((z < -10) || (z > -3)) dz = -dz;
SDL_GL_SwapBuffers(); // wyświetlamy scenę w oknie podglądu SDL_PollEvent(&event); // sprawdzamy kolejkę zdarzeń if(event.key.keysym.sym == SDLK_ESCAPE) done = 1; }
Początek wektora zawsze znajduje się w początku bieżącego układu współrzędnych. Po wykonaniu obrotu osie nowego układu zostają odpowiednio zorientowane w przestrzeni. Jeśli teraz będziemy rysować w takim obróconym układzie współrzędnych, to nasz obiekt na ekranie będzie wyglądał na obrócony. Poniższy program dodaje obrót wokół osi z o kat k. Szybkość obrotu regulujemy wielkością parametru dk.
GLfloat z = -3.0f, dz = -0.05; GLfloat k = 0, dk = 1; for(int done = 0; !done;) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Tutaj umieszczamy rysowanie sceny glTranslatef(0.0f,0.0f,z); // przemieszczamy o z jednostek w głąb glRotatef(k, 0.0f, 0.0f, 1.0f); // obrót wokół osi z glTranslatef(-1.5f,0.0f,0.0f); // przemieszczamy o 1.5 jednostki w lewo // w obróconym układzie współrzędnych glBegin(GL_TRIANGLES); glVertex2f( 0.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glEnd(); glTranslatef(3.0f,0.0f,0.0f); // przesuwamy się o 3 jednostki w prawo // we wciąż obróconym układzie współrzędnych glBegin(GL_QUADS); glVertex2f( 1.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); z += dz; // modyfikujemy przesunięcie dla następnego obiegu pętli if((z < -10) || (z > -3)) dz = -dz; k += dk; // modyfikujemy kąt obrotu if(k > 360) k = 1;
SDL_GL_SwapBuffers(); // wyświetlamy scenę w oknie podglądu SDL_PollEvent(&event); // sprawdzamy kolejkę zdarzeń if(event.key.keysym.sym == SDLK_ESCAPE) done = 1; }
W powyższym programie wymień wywołanie funkcji glRotatef() kolejno na:
glRotatef(k, 1.0f, 0.0f, 0.0f); // obrót wokół osi x
glRotatef(k, 0.0f, 1.0f, 0.0f); // obrót wokół osi y
glRotatef(k, 1.0f, 1.0f, 1.0f); // odkryj sam, wokół jakiej osi wykonywany jest obrót
Załóżmy teraz, że chcemy osobno obracać trójkąt wokół osi y przechodzącej przez jego środek, a kwadrat wokół osi x, która też przechodzi przez jego środek. Zasada będzie następująca:
Obracamy ten układ o kat k wokół wektora (0,1,0) - oś y.
Rysujemy trójkąt - będzie on obrócony.
Obracamy układ o kąt -k wokół tego samego wektora. Otrzymamy układ współrzędnych nie obrócony.
Przesuwamy go do miejsca rysowania kwadratu i obracamy o kąt k wokół wektora (1,0,0) - oś x.
Rysujemy kwadrat.
Oto odpowiedni kod:
GLfloat z = -3.0f, dz = -0.05; GLfloat k = 0, dk = 1; for(int done = 0; !done;) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Tutaj umieszczamy rysowanie sceny glTranslatef(-1.5f,0.0f,z); // do miejsca rysowania trójkata glRotatef(k,0.0f,1.0f,0.0f); // obrót wokół osi y glBegin(GL_TRIANGLES); // rysujemy obrócony trójkąt glVertex2f( 0.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glEnd(); glRotatef(-k,0.0f,1.0f,0.0f); // usuwamy z przekształcenia poprzedni obrót glTranslatef(3.0f,0.0f,0.0f); // do miejsca rysowania kwadratu glRotatef( k,1.0f,0.0f,0.0f); // obrót wokół osi x glBegin(GL_QUADS); // rysujemy kwadrat glVertex2f( 1.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); z += dz; // modyfikujemy przesunięcie dla następnego obiegu pętli if((z < -10) || (z > -3)) dz = -dz; k += dk; // modyfikujemy kąt obrotu if(k > 360) k = 1; SDL_GL_SwapBuffers(); // wyświetlamy scenę w oknie podglądu SDL_PollEvent(&event); // sprawdzamy kolejkę zdarzeń if(event.key.keysym.sym == SDLK_ESCAPE) done = 1; }
Różna ilość natężenia kolorów podstawowych daje różne barwy. Stopień natężenia barwy podstawowej jest określany przez wartość od 0 (brak barwy) do 1 (pełna intensywność).
Kolor wprowadzamy wywołując funkcję glColor3f() przed zdefiniowaniem wierzchołka. Parametrami tej funkcji są trzy liczby określające stopień natężenia barw podstawowych R, G i B. Zmień w programie sposób rysowania trójkąta na:
glBegin(GL_TRIANGLES); // rysujemy obrócony trójkąt glColor3f( 1.0f, 0.0f, 0.0f); // kolor czerwony glVertex2f( 0.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glEnd();
Fragment rysujący kwadrat zmień na:
glBegin(GL_QUADS); // rysujemy kwadrat glColor3f( 0.0f, 1.0f, 0.0f); // kolor zielony glVertex2f( 1.0f, 1.0f); glVertex2f( 1.0f,-1.0f); glVertex2f(-1.0f,-1.0f); glVertex2f(-1.0f, 1.0f); glEnd();
Zamiast standardowych białych figur otrzymasz teraz czerwony trójkąt i zielony kwadrat.
Jeśli kolory będą się zmieniać przy każdym wierzchołku ściany, to OpenGL zastosuje płynne przejście barw. Dokonaj w programie następującej zmiany:
glBegin(GL_TRIANGLES); // rysujemy obrócony trójkąt glColor3f( 1.0f, 0.0f, 0.0f); // kolor czerwony glVertex2f( 0.0f, 1.0f); glColor3f( 0.0f, 1.0f, 0.0f); // kolor zielony glVertex2f( 1.0f,-1.0f); glColor3f( 0.0f, 0.0f, 1.0f); // kolor niebieski glVertex2f(-1.0f,-1.0f); glEnd();
oraz
glBegin(GL_QUADS); // rysujemy kwadrat glColor3f( 1.0f, 1.0f, 0.0f); // kolor żółty glVertex2f( 1.0f, 1.0f); glColor3f( 1.0f, 0.0f, 1.0f); // kolor buraczkowy glVertex2f( 1.0f,-1.0f); glColor3f( 0.0f, 1.0f, 1.0f); // kolor jasnoniebieski glVertex2f(-1.0f,-1.0f); glColor3f( 1.0f, 1.0f, 1.0f); // kolor biały glVertex2f(-1.0f, 1.0f); glEnd();
Po uruchomieniu otrzymasz tęczowe barwy na trójkącie i kwadracie:
Ostrosłup będzie składał się z czterech trójkątnych ścian A (przednia), B (z prawej strony), C (z tyłu) i D (z lewej strony):
Zmień kod rysowania trójkąta na (najlepiej wprowadzaj kolejne ściany osobno i uruchamiaj program obserwując wynik - jest to bardzo pouczające):
glBegin(GL_TRIANGLES); // rysujemy obrócony ostrosłup // ściana A - z przodu glColor3f( 1.0f, 0.0f, 0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); // ściana B - po prawej glColor3f( 0.0f, 1.0f, 0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); // ściana C - z tyłu glColor3f( 0.0f, 0.0f, 1.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); // ściana D - z lewej glColor3f( 1.0f, 1.0f, 0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glEnd();
Sześcian będzie zbudowany z 6 ścian kwadratowych od A do F:
Zmień kod rysowania kwadratu na:
glBegin(GL_QUADS); // rysujemy sześcian // ściana A - z przodu glColor3f( 0.0f, 0.5f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); // ściana B - z prawej glColor3f( 0.5f, 0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); // ściana C - z tyłu glColor3f( 0.5f, 0.5f, 1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); // ściana D - z lewej glColor3f( 0.0f, 1.0f, 0.5f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); // ściana E - z góry glColor3f( 1.0f, 0.5f, 0.5f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // ściana F - z dołu glColor3f( 1.0f, 1.0f, 0.5f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glEnd();
W ramach ćwiczeń postaraj się pokolorować ściany różnymi gradientami.
Zbliż do siebie sześcian i ostrosłup (jak to zrobić?) i zwróć uwagę na przenikanie się ścian.
Dodaj dodatkowy obrót względem osi pionowej znajdującej się pomiędzy ostrosłupem a sześcianem.
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe