$$\begin{matrix}
Q_{1} = lo \\
Q_{2} = lo \\
Q_{3} = \overset{\overline{}}{I_{1}}I_{2} \\
Q_{4} = I_{1}\overset{\overline{}}{I_{2}} + \overset{\overline{}}{I_{1}}I_{2} \\
\end{matrix}$$
$$\begin{matrix}
Q_{1} = \overset{\overline{}}{I_{1}}\overset{\overline{}}{I_{2}}\overset{\overline{}}{I_{3}}I_{4} \\
\\
\end{matrix}$$
Sprawozdanie z ćwiczeń laboratoryjnych nr 1 z przedmiotu Grafika komputerowa
Imię i nazwisko studenta: | Grupa szkoleniowa: | Data przeprowadzenia ćwiczenia: |
---|---|---|
Piotr Rusinowski | I7X6S1 | 07.11.2008 |
Zestaw: | Nauczyciel prowadzący zajęcia: | Ocena: |
nr 21 | dr inż. Marek Salamon | |
Zadanie: Wykorzystując wybrane funkcje modelowania biblioteki OpenGL i Glut napisać program przedstawiający perspektywistyczny obraz bryły 3D o zadanych parametrach
- podstawy bryły zamodelować w trybie GL_TRIANGLE_FAN
- w przypadku wycinków bryły powierzchnie wewnętrzną zamodelować w dowolnym trybie
- wprowadzić możliwość zmiany liczby podziałów pionowych i poziomych bryły z zakresie o 5 do 20
- wprowadzić możliwość zmiany obserwatora
Ćwiczenie nr 21: Stożek ścięty w trybie GL_TRAINGLE_STRIP o promieniu dolnej podstawy 2 i jej środku w punkcie (0,0,0), oraz promieniu górnej podstawy 1, wysokości 1.
Sposób wykonania programu:
Do realizacji swojego ćwiczenia laboratoryjnego wykorzystałem, udostępniony w trakcie zajęć, program rysujące sześcian w trój-wymiarze.
Zaimplementowany przeze mnie algorytm wykorzystywał następujące zmienne :
h - wysokość modelowanego stożka
pr- podstawa dolna
pr2- podstawa górna
Podstawa dolna i górna:
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0,0,0);
for(i=0 ; i<=360 ; i=i+(360/a)){
z=pr*sin(pi*i/180);
x=pr*cos(pi*i/180);
glVertex3f(x, 0, z);
}
glEnd();
W pierwszej linii kodu zostaje zadeklarowana metoda, którą wykorzystałem do narysowania dolnej podstawy stożka . Deklaracja taka posiada poniższy schemat:
glBegin(nazwa_prymitywa) ; – rozpoczęcie bloku tworzenia prymitywa
Przyjętym przeze mnie prymitywem była metoda GL_TRIANGLE_FAN. Polega ona na łączeniu trzech punktów:
-pierwszego zadeklarowanego
- ostatniego zadeklarowanego
- aktualnie deklarowanego
w trójkąt. W następnej linii kodu , w punkcie o współrzędnych (0,0,0), deklaruje położenie środka dolnej podstawy stożka. W tym celu wykorzystuję funkcję ‘glVertex3f’, tworzącą wierzchołek trójwymiarowy, o współrzędnych typu Glfloat (x,y,z). Kolejno wykonywana jest pętla, w której definiowane są punkty, leżące na okręgu podstawy. Współrzędne tych punktów zmieniają się zależnie od wartości zmiennej ‘i’, określającej aktualnie rysowany wycinek pionowy. Ponad to do wyznaczenia powyższych współrzędnych wykorzystuję zależności wynikające z funkcji trygonometrycznych kątów. Przy czym należy pamiętać o zamianie wartości kątów ze stopni na radiany, a także o fakcie iż tylko dwie współrzędne ulegają zmianie. Wysokość pozostaje stała i wynosi zero. Punkty definiowane w pętli są łączone ze środkiem podstawy – punktem (0,0,0). Poleceniem glEnd( ); kończony jest blok tworzenia prymitywa.
Na tej samej podstawie tworzona jest górna podstawa:
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, h, 0);
for(i=0 ; i<=360 ; i=i+(360/a)){
z=pr2*sin(pi*i/180);
x=pr2*cos(pi*i/180);
glVertex3f(x, h, z);
}
glEnd();
Z tym wyjątkiem, że miejsce zmiennej pr zajmuje zmienna pr2, a podstawa jest rysowana w odległosci h od podstawy dolnej w osi y.
Ściany boczne:
glBegin(GL_TRIANGLE_STRIP);
for(i=0 ; i<=360 ; i=i+(360/a)){
glVertex3f(x=pr*cos(pi*i/180),0 ,(z=pr*sin(pi*i/180)));
glVertex3f(x=pr2*cos(pi*i/180), h, (z=pr2*sin(pi*i/180)));
}
glEnd();
Algorytm rozpoczyna się od określenia metody wykorzystana do narysowania powierzchni bocznej stożka – GL_TRIANGLE_STRIP. Polega ona na łączeniu ze sobą trzech ostatnio narysowanych punktów. Nowy punkt jest łączony z dwoma poprzednimi trwożąc trójkąt.
Pętla odpowiada za rysowanie wycinków pionowych. Wykorzystuje ona funkcję ‘glVertex3f’ tworzącą wierzchołek trójwymiarowy, o współrzędnych typu Glfloat (x,y,z). Pierwszy punkt w tej pętli zostaje zdefiniowany na wysokości h=0 i leży na obwodzie podstawy dolnej stożka. Drugi punkt jest rysowany na wyżej. Warunek pętli zostaje zwiększony o kąt i rozpoczyna się tworzenie kolejnego wycinka pionowego. Gdy warunek pętli zagnieżdżonej zostaje niespełniony – sumy kątów dały wartość większą lub równą 360 stopni - oznacza to że skończone zostało rysowanie wycinka poziomego wraz ze wszystkimi składającymi się na niego wycinkami pionowymi. Działanie te jest powtarzane, aż zostanie na narysowana ściana boczna do wysokości h stożka.
Klawisze obsługi:
if(klawisz == '='){
ile += 1.0;
if (ile>20)
ile=20; }
else if (klawisz == '-'){
ile -= 1.0;
if (ile<5)
ile=5; }
else if (klawisz == 'x') //obrot wokol osi X
OBSERWATOR_OBROT_X ++ ;
else if (klawisz == 'y') //obrot wokol osi Y
OBSERWATOR_OBROT_Y ++ ;
else if (klawisz == 'z') //obrot wokol osi Z
OBSERWATOR_OBROT_Z ++ ;
else if (klawisz == 'o') //oddal
OBSERWATOR_ODLEGLOSC ++ ;
else if (klawisz == 'p') //przybliz
OBSERWATOR_ODLEGLOSC -- ;
else if (klawisz == 27)
exit(0);
}
Zdefiniowane zostały klawisze obsługi: ’X’ odpowiada za obrót w osi OX, ‘Z’ w osi OZ, ’Y’ w osi OY, ‘P’ za przybliżenie, ‘O’ za oddalenie, ‘=‘ za rysowanie linii. Powyższe funkcje przypisane do tych klawiszy zostały na początku programu zdefiniowane wartościami. PO każdorazowym naciśnięciu danego klawisza jego wartość zostaje inkrementowana co powoduje w zależności od klawisza albo obrót ( w trzech płaszczyznach) albo przybliżenie albo oddalenie. W przypadku klawisza ‘=‘ jego wartość jest inkrementowana od wartości 5 linii do wartości 20 co osiągnąłem dzięki wstawieniu odpowiedniego warunku przy deklarowaniu klawisza. Klawisz ‘-‘ działa analogicznie tylko w drugą stronę.
Kod programu:
#include <GL/glut.h>
#include <math.h>
// Definicja stalych
#define ilosc_linii 5.0
// Zmienne globalne
float ile = ilosc_linii; // ile linii
int szerokoscOkna = 800;
int wysokoscOkna = 600;
int OBSERWATOR_OBROT_X = 20;
int OBSERWATOR_OBROT_Y = 20;
int OBSERWATOR_OBROT_Z = 20;
int OBSERWATOR_ODLEGLOSC = 20;
int OBSERWATOR_FOV_Y = 30;
float pi = 3.14;
float k;
// Prototypy funkcji
void RysujSzescian(float a);
void UstawParametryWidoku(int szer, int wys);
void WyswietlObraz(void);
void ObslugaKlawiatury(unsigned char klawisz, int x, int y);
void RysujSzescian(float a)k
{
float i,x,z;
float pr = 2.0;
float pr2 = 1.0;
float h = 1.0;
//podstawa dolna
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0,0,0);
for(i=0 ; i<=360 ; i=i+(360/a)){
z=pr*sin(pi*i/180);
x=pr*cos(pi*i/180);
glVertex3f(x, 0, z);
}
glEnd();
//linie siatki
for(k=0; k<=h; k=k+h/a){
glBegin(GL_LINE_STRIP);
for(i=0 ; i<=360 ; i=i+(360/a)){
z=(pr-k)*sin(pi*i/180);
x=(pr-k)*cos(pi*i/180);
glVertex3f(x, k, z);
}
glEnd();
}
//podstawa gorna
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, h, 0);
for(i=0 ; i<=360 ; i=i+(360/a)){
z=pr2*sin(pi*i/180);
x=pr2*cos(pi*i/180);
glVertex3f(x, h, z);
}
glEnd();
//boki
glBegin(GL_TRIANGLE_STRIP);
for(i=0 ; i<=360 ; i=i+(360/a)){
glVertex3f(x=pr*cos(pi*i/180),0 ,(z=pr*sin(pi*i/180)));
glVertex3f(x=pr2*cos(pi*i/180), h, (z=pr2*sin(pi*i/180)));
}
glEnd();
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja ustawiajaca parametry rzutu perspektywicznego i rozmiary viewportu. Powinna
// być wywolywana kazdorazowo po zmianie rozmiarow okna programu.
void UstawParametryWidoku(int szer, int wys)
{
// Zapamietanie wielkosci widoku
szerokoscOkna = szer;
wysokoscOkna = wys;
// Ustawienie parametrow viewportu
glViewport(0, 0, szerokoscOkna, wysokoscOkna);
// Przejscie w tryb modyfikacji macierzy rzutowania
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(OBSERWATOR_FOV_Y, (float)szerokoscOkna/(float)wysokoscOkna, 1.0, 1000.0);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja wyswietlajaca pojedyncza klatke animacji
void WyswietlObraz(void)
{
// Wyczyszczenie bufora koloru i bufora glebokosci
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Przejscie w tryb modyfikacji macierzy przeksztalcen geometrycznych
glMatrixMode(GL_MODELVIEW);
// Zastapienie aktywnej macierzy macierza jednostkowa
glLoadIdentity();
// Ustalenie polozenia obserwatora
glTranslatef(0, 0, -OBSERWATOR_ODLEGLOSC);
//glRotatef(OBSERWATOR_OBROT_X, 1, 0, 0);
//glRotatef(OBSERWATOR_OBROT_Y, 0, 1, 0);
//glTranslatef(0, 0, -OBSERWATOR_ODLEGLOSC);
glRotatef(OBSERWATOR_OBROT_X, 1, 0, 0);
glRotatef(OBSERWATOR_OBROT_Y, 0, 1, 0);
glRotatef(OBSERWATOR_OBROT_Z, 0, 0, 1);
// Narysowanie szescianu
RysujSzescian(ile);
// Przelaczenie buforow ramki
glutSwapBuffers();
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja obslugi klawiatury
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
if(klawisz == '='){
ile += 1.0;
if (ile>20)
ile=20; }
else if (klawisz == '-'){
ile -= 1.0;
if (ile<5)
ile=5; }
else if (klawisz == 'x') //obrot wokol osi X
OBSERWATOR_OBROT_X ++ ;
else if (klawisz == 'y') //obrot wokol osi Y
OBSERWATOR_OBROT_Y ++ ;
else if (klawisz == 'z') //obrot wokol osi Z
OBSERWATOR_OBROT_Z ++ ;
else if (klawisz == 'o') //oddal
OBSERWATOR_ODLEGLOSC ++ ;
else if (klawisz == 'p') //przybliz
OBSERWATOR_ODLEGLOSC -- ;
else if (klawisz == 27)
exit(0);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Glowna funkcja programu
int main(int argc, char **argv)
{
// Zainicjowanie biblioteki GLUT
glutInit(&argc, argv);
// Ustawienie trybu wyswietlania
glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
// Ustawienie polozenia dolenego lewego rogu okna
glutInitWindowPosition(100, 100);
// Ustawienie rozmiarow okna
glutInitWindowSize(szerokoscOkna, wysokoscOkna);
// Utworzenie okna
glutCreateWindow("Szescian");
// Odblokowanie bufora glebokosci
glEnable(GL_DEPTH_TEST);
// Ustawienie wartosci czyszczacej zawartosc bufora glebokosci
glClearDepth(1000.0);
// Ustawienie koloru czyszczenia bufora ramki
glClearColor (0.0f, 0.0f, 0.3f, 0.0f);
// Wlaczenie wyswietlania wielokatow w postaci obrysow (przydatne w celach diagnostycznych).
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Zarejestrowanie funkcji (callback) odpowiedzialnej za
glutDisplayFunc(WyswietlObraz);
// Zarejestrowanie funkcji (callback) wywolywanej za kazdym razem kiedy
// zmieniane sa rozmiary okna
glutReshapeFunc(UstawParametryWidoku);
// Zarejestrowanie funkcji wykonywanej gdy okno nie obsluguje
// zadnych zadan
glutIdleFunc(WyswietlObraz);
// Zarejestrowanie funkcji obslugi klawiatury
glutKeyboardFunc(ObslugaKlawiatury);
// Obsluga glownej petli programu (wywolywanie zarejestrowanych callbackow
// w odpowiedzi na odbierane zdarzenia lub obsluga stanu bezczynnosci)
glutMainLoop();
return 0;
}