WOJSKOWA AKADEMIA TECHNICZNA
Laboratorium z przedmiotu
Grafika komputerowa
SPRAWOZDANIE
Laboratorium nr 4
Wykonanie: Justyna Kozon
Grupa: I9X5S1
Data wykonania ćwiczenia:09.12.2010
Treść wykonywanych zadań.
Wstęp teoretyczny.
Aby przystąpić do wykonania zadania powinniśmy znać dobrze funkcje pochodzące z bibliotek OpenGL i GLUT, które umożliwiają nam rysowanie obiektów za pomocą prymitywów oraz przekształcenia przestrzeni (obroty, przesunięcia, operacje na macierzach). Wszystkie te rzeczy wykonywaliśmy na 2 i 3 laboratoriach dlatego też nie będę opisywać dokładnie tych funkcji, a jedynie zajmę się tymi, które są nowe, a zarazem niezbędne do wykonania ćwiczenia.
Do pokrycia zbudowanej przez nas bryły materiałem musimy określić parametry materiału:
1.GL_AMBIENT - współczynnik odbicia światła otoczenia
2.GL_DIFFUSE -współczynnik odbicia światła rozproszonego
3.GL_SPECULAR - współczynnik odbicia światła lustrzanego
4.GL_SHININESS – połysk
5.GL_EMISSION – kolor światła emitowanego
Każdy z tych parametrów przedstawiamy w postaci wektora wartości, który przedstawia wartości RGBA, gdzie R – red, G – green, B – blue, A – współczynnik określający natężenie barwy (im mniejszy współczynnik, tym bardziej przezroczysty materiał, gdy jest równy 0, to materiał przyjmuje barwę otoczenia). Każdy ze współczynników oprócz połysku przyjmuje wartości od [0.0-1.0]. Połysk przyjmuje wartości [0.0-128.0].
Inicjowanie materiału dokonuje się, np. za pomocą funkcji:
glMaterialfv(GL_FRONT, GL_AMBIENT, material2[0]);
Gdzie 1 parametr określa, że materiałem ma być pokryta widoczna część bryły, 2 parametr mówi o tym, który rodzaj współczynnika będziemy określać i ostatni parametr jest wektorem określającym współczynniki RGBA.
Materiał błyszczący: aby go uzyskać musimy podać większe wartości GL_SPECULAR, a mniejsze GL_DIFFUSE. Dzięki temu uzyskamy efekt dużego odbicia światła i małego pochłaniania, czyli materiał będzie wydawał się błyszczący.
Materiał matowy: do uzyskania tego efektu podajemy większe wartości GL_DIFFUSE, a mniejsze GL_SPECULAR. Dzięki temu materiał będzie dużą cześć światła pochłaniał, odbijając małą jego część i materiał będzie się wydawał matowy.
Materiał emitujący: aby uzyskać taki efekt musimy ustawić w odpowiedni sposób parametr GL_EMISSION, tak aby kolor światła emitowanego był odpowiedni. (W poprzednich przypadkach parametr ten mógł nie być używany).
Po określeniu materiałów należało określić w odpowiedni sposób światła, które będą oświetlały nasz obiekt. Robimy to w podobny sposób jak w przypadku materiałów:
1.GL_AMBIENT - światło otoczenia (brak określonego kierunku),
2.GL_DIFFUSE – światło rozproszone (główny składnik światła),
3.GL_SPECULAR – światło zwierciadlane,
4.GL_POSITION – określa pozycje światła (4 składowa 1.0 dla reflektora, 0.0 dla światła kierunkowego),
5.GL_SPOT_DIRECTION – kierunek świecenia reflektora,
6.GL_SPOT_CUTOFF – połowa kąta rozwarcia światła reflektora.
Światło jest inicjowane za pomocą funkcji:
glLightfv(GL_LIGHT2, GL_DIFFUSE, swiatlo2[1]);
Gdzie 1 parametr mówi o tym, które światło będziemy określać, 2 – który rodzaj współczynnika będziemy określać i ostatni wskazuje na wektor wartości RGBA.
Do poprawnego oświetlania obiektu niezbędne jest określenie wektorów normalnych powierzchni. W naszym przypadku określamy wektory normalne w każdym punkcie siatki bryły. Ze względu na to, że mamy do czynienia z walcem możemy posłużyć się następującą zależnością określającą wektor normalny po powierzchni bocznej:
Z rysunku widać, że wektor normalny do punktu (x,y,z) określamy jako [x,0,z]. Wektory normalne do powierzchni podstaw walca są zawsze równoległe do którejś z osi układu współrzędnych, a kierunek tego wektora określamy wstawiając bądź nie znak ‘-‘ przed współrzędną na osi.
Realizacja zadania.
Na początku należało określić zmienne, jakie będą używane później do zmiany parametrów.
double kat = 0.0; //kąt obserwatora względem osi Y
double kat2=0.0; //kąt obserwatora względem osi X
int a=0,b=0; // zmienne wykorzystywane do włączania i wyłączania świateł
int lPionowych; // Liczba podziałów pionowych
int lPoziomych; // Liczba podziałów poziomych
double promien; // Promień walca
double wysokosc; // Wysokość walca
int szerokoscOkna = 800;
int wysokoscOkna = 600;
float R_L1 = 3; //promień orbity, po której porusza się światło
double katRX=0.0; // kąt nachylenia orbity światła do osi X
double katRZ=0.0; // kąt nachylenia orbity światła do osi Z
int obrot; // kąt obrotu światła względem obiektu
float odleglosc=20; //odległość obserwatora od obiektu
Następnie określamy prototypy funkcji używanych do określania parametrów świateł oraz materiałów (dla każdego materiału oraz światła oddzielna funkcja).
void Material1(void);
void Material2(void);
void Material3(void);
void Swiatlo1(void);
void Swiatlo2(void);
Następnie definiujemy tablice dwuwymiarowe określające materiały:
Materiał niebieski błyszczący:
GLfloat material1[6][4] = {
{0.2, 0.2, 0.4, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{0.0, 0.0, 0.3, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{0.0, 0.0, 1.0, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{10.0, 0.0, 0.0, 0.0}, // [3] polysk
{0.0, 0.0, 0.0, 1.0}}; // [4] kolor swiatla emitowanego
Posiada duży współczynnik odbicia światła lustrzanego oraz mały współczynnik odbicia światła rozproszonego, ponadto dla poprawienia efektu ma ustawiony parametr określający połysk.
Materiał szary matowy:
GLfloat material2[6][4] = {
{0.2, 0.2, 0.2, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{0.7, 0.7, 0.7, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{0.0, 0.0, 0.0, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{0.0, 0.0, 0.0, 0.0}, // [3] polysk
{0.0, 0.0, 0.0, 1.0}}; // [4] kolor swiatla emitowanego
Posiada duży współczynnik odbicia światła rozproszonego i nie odbija światła lustrzanego.
Materiał czerwony emitujący:
GLfloat material3[6][4] = {
{0.2, 0.2, 0.2, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{1.0, 0.0, 0.0, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{0.0, 0.0, 0.0, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{0.0, 0.0, 0.0, 0.0}, // [3] polysk
{1.0, 0.0, 0.0, 1.0}}; // [4] kolor swiatla emitowanego
Ma określony kolor światła emitowanego.
Następnie określamy światła dodatkowe, które będą służyły do oświetlania obiektu.
Światło reflektora:
GLfloat swiatlo1[6][4] = {
{0.4, 0.1, 0.1, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{0.8, 0.4, 0.4, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{0.8, 0.4, 0.4, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{0.0, 0.0, 1.0, 1.0}, // [3] pozycja
{0.0, 0.0, -1.0} //[4] kierunek
};
Ma tak dobrane współczynniki, aby światło było różowe. Jest określona pozycja początkowa, która będzie później zmieniana i uzależniana od współrzędnych biegunowych, tak by światło mogło poruszać się po orbicie kołowej. Kierunek jest odwrotny do położenia, dzięki czemu światło jest skierowane cały czas na obiekt.
Światło kierunkowe:
GLfloat swiatlo2[6][4] = {
{1.0, 1.0, 0.0, 0.7}, // [0] wspolczynnik odbicia swiatla otoczenia
{1.0, 1.0, 0.0, 0.7}, // [1] wspolczynnik odbicia swiatla rozproszonego
{1.0, 1.0, 0.0, 0.7}, // [2] wspolczynnik odbicia swiatla lustrzanego
{10.0, -5.0, 10.0, 0.0}, // [3] pozycja
{-10.0,5.0,-10.0} //[4] kierunek
};
O tym , że jest to taki rodzaj światła decyduje ostatnia wartość z wektora pozycji, gdzie zawarty jest także punkt, z którego świeci to światło. Kierunek jest określany w ten sam sposób co w przypadku światła reflektora.
Funkcje ustawiające odpowiednie parametry materiałów i świateł:
void Material1(void)
{
glMaterialfv(GL_FRONT, GL_AMBIENT, material1[0]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, material1[1]);
glMaterialfv(GL_FRONT, GL_SPECULAR, material1[2]);
glMaterialfv(GL_FRONT, GL_SHININESS, material1[3]);
glMaterialfv(GL_FRONT, GL_EMISSION, material1[4]);
}
void Material2(void)
{
glMaterialfv(GL_FRONT, GL_AMBIENT, material2[0]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, material2[1]);
glMaterialfv(GL_FRONT, GL_SPECULAR, material2[2]);
glMaterialfv(GL_FRONT, GL_SHININESS, material2[3]);
glMaterialfv(GL_FRONT, GL_EMISSION, material2[4]);
}
void Material3(void)
{
glMaterialfv(GL_FRONT, GL_AMBIENT, material3[0]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, material3[1]);
glMaterialfv(GL_FRONT, GL_SPECULAR, material3[2]);
glMaterialfv(GL_FRONT, GL_SHININESS, material3[3]);
glMaterialfv(GL_FRONT, GL_EMISSION, material3[4]);
}
void Swiatlo1() {
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo1[1]);
glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo1[2]);
glLightfv(GL_LIGHT1, GL_POSITION, swiatlo1[3]);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF,25.0);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, swiatlo1[4]);
}
void Swiatlo2() {
glLightfv(GL_LIGHT2, GL_DIFFUSE, swiatlo2[1]);
glLightfv(GL_LIGHT2, GL_SPECULAR, swiatlo2[2]);
glLightfv(GL_LIGHT2, GL_POSITION, swiatlo2[3]);
glLightfv(GL_LIGHT2, GL_POSITION, swiatlo2[4]);
}
Podstawowym zadaniem było zbudowanie bryły i oświetlenie jej światłem białym oraz pokrycie odpowiednimi materiałami. Funkcja rysująca odpowiedni walec:
void RysujWalec(double h, double r, int nv, int nh)
{
double dH, dAlfa;
int i, j,d;
double cnt;
double dp=2*r/nh;
double krok;
// Wyznaczenie kata wyznaczajacego pojedynczy wycinek pionowy
dAlfa = 360.0L/(double)nh;
// Wyznaczenie wysokosci pojedynczego wycinka poziomego
dH = h/(double)nv;
// Wyznaczanie wierzcholkow i wektorow normalnych powierzchni bocznych
for (i = 0; floor((i+1)*dH*1.0E10) <= floor(0.5*h*1.0E10); i++) //boczna dolna
{
if((i%3)==0){
Material1();
}
else if((i%3)==1){
Material2();
}
else if((i%3)==2){
Material3();
}
glBegin(GL_TRIANGLE_STRIP);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(0.0, (i + 1)*dH, r);
glVertex3f(0.0, i*dH, r);
for (j = 1; j*dAlfa <= 360.0L + dAlfa; j++)
{
glNormal3f(sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j*dAlfa)), (i + 1)*dH, r*cos(DEG2RAD(j*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j*dAlfa)), i*dH, r*cos(DEG2RAD(j*dAlfa)));
}
glEnd();
}
for (i = nv/2; floor((i+1)*dH*1.0E10) <= floor(h*1.0E10); i++) //boczna gorna
{
if((i%3)==0){
Material1();
}
else if((i%3)==1){
Material2();
}
else if((i%3)==2){
Material3();
}
glBegin(GL_TRIANGLE_STRIP);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(0.0, (i + 1)*dH, r);
glVertex3f(0.0, i*dH, r);
for (j = 0; j*dAlfa < 180.0L + dAlfa; j++)
{
glNormal3f(sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j*dAlfa)), (i + 1)*dH, r*cos(DEG2RAD(j*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j*dAlfa)), i*dH, r*cos(DEG2RAD(j*dAlfa)));
}
glEnd();
}
d=j;
// Wyznaczenie wierzcholkow i wektorow normalnych dolnej podstawy
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0, -1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
for (i = 0; i * dAlfa <= 360.0L + dAlfa; i++)
glVertex3f(r*sin(DEG2RAD(i*dAlfa)), 0.0, r*cos(DEG2RAD(i*dAlfa)));
glEnd();
// Wyznaczenie wierzcholkow i wektorow normalnych gornej podstawy
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(0.0, h, 0.0);
for (i = 0; i * dAlfa < 180.0L + dAlfa; i++)
glVertex3f(r*sin(DEG2RAD(i*dAlfa)), h, r*cos(DEG2RAD(i*dAlfa)));
glEnd();
// Wyznaczenie wierzcholkow i wektorow normalnych srodkowej podstawy
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.5*h, 0.0);
for (cnt=180; cnt< 360.0L + dAlfa; cnt+=dAlfa)
glVertex3f(r*sin(DEG2RAD(cnt)),0.5*h, r*cos(DEG2RAD(cnt)));
glEnd();
// boczna pionowa
glBegin(GL_TRIANGLE_STRIP);
glNormal3f(-1.0, 0.0, 0.0);
for (i = nv/2; floor((i+1)*dH*1.0E10) <= floor(h*1.0E10); i++)
{
if((i%3)==0){
Material1();
}
else if((i%3)==1){
Material2();
}
else if((i%3)==2){
Material3();
}
for(krok=0; krok<=2*r; krok+=dp){
glVertex3f(0.0, i*dH, -r+krok);
glVertex3f(0.0, (i+1)*dH, -r+krok);
}
}
glEnd();
Swiatlo1(); //ustawienie parametrów świateł
Swiatlo2();
}
Do określenia rodzaju materiału, którym będzie pokryty poziomy krążek wykorzystujemy:
if((i%3)==0){
Material1();
}
else if((i%3)==1){
Material2();
}
else if((i%3)==2){
Material3();
}
Czyli zgodnie z tym kodem jeśli reszta z dzielenia numeru wiersza przez 3 jest równa 0 wybieramy 1 materiał, jeśli jest równa 1, wybieramy drugi, a jeśli 2 – wybieramy trzeci. Dzięki temu uzyskujemy pożądany przez nas efekt.
Walec pokryty materiałami, widok w świetle białym:
Następnie definiujemy funkcję, która będzie włączała odpowiednie światła, zgodnie z życzeniem użytkownika programu:
void WlaczOswietlenie(int a,int b)
{
// Odblokowanie oswietlenia
glEnable(GL_LIGHTING);
if(a==1){
glEnable(GL_LIGHT1);
swiatlo1[3][0]=R_L1*cos(DEG2RAD(obrot));
swiatlo1[3][1]=0.0;
swiatlo1[3][2]=R_L1*sin(DEG2RAD(obrot));
swiatlo1[3][3]=1.0;
swiatlo1[4][0]=-R_L1*cos(DEG2RAD(obrot));
swiatlo1[4][1]=0.0;
swiatlo1[4][2]=-R_L1*sin(DEG2RAD(obrot));
swiatlo1[4][3]=-1.0;
}
else (glDisable(GL_LIGHT1));
if(b==1){
glEnable(GL_LIGHT2);
}
else ( glDisable(GL_LIGHT2));
}
Za pomocą współrzędnych biegunowych określamy na nowo położenie światła. Teraz będzie ono zależne od zmiennej obrót oraz od promienia orbity, po której będzie się poruszało. Podobnie modyfikujemy kierunek świecenia światła, przypisując odpowiednie wartości w zdefiniowanej wcześniej tablicy dwuwymiarowej (będą odwrotne do tych, które zamieściliśmy w wektorze określającym pozycję, aby światło świeciło zawsze na obiekt). Zmienne a i b będzie można zmieniać za pomocą klawiatury, dzięki czemu będzie można włączać i wyłączać światła zgodnie z własnym życzeniem.
W funkcji wyświetlającej obraz zamieszczamy wyrysowanie kuli symbolizującej źródło światła oraz wyliczanie współrzędnych związanych z pochyleniem osi obrotu do osi X oraz do osi Z.
void WyswietlObraz(void)
{
int j=0;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
UstawParametryWidoku(szerokoscOkna, wysokoscOkna);
WlaczOswietlenie(a,b);
glTranslatef(0, 0, -odleglosc);
glRotatef(kat2, 1, 0, 0);
glRotatef(kat, 0, 1, 0);
glPushMatrix();
glRotatef(katRX, 1,0,0);
glRotatef(katRZ, 0,0,1);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(0.0,0.0,0.0);
for(j=0; j<=360.0L; j++)
{
glVertex3f(R_L1*sin(DEG2RAD(j)), 0.0, R_L1*cos(DEG2RAD(j)));
glVertex3f(R_L1*sin(DEG2RAD(j+1)), 0.0, R_L1*cos(DEG2RAD(j+1)));
}
glEnd();
glTranslatef(R_L1*cos(DEG2RAD(obrot)), 0.0, R_L1*sin(DEG2RAD(obrot)));
glutWireSphere(0.25, 20, 20);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT1, GL_POSITION, swiatlo1[3]);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, swiatlo1[4]);
glPopMatrix();
// Generacja obrazu walca
RysujWalec(wysokosc, promien, lPoziomych, lPionowych);
// Przelaczenie buforow ramki
glutSwapBuffers();
}
Dokonujemy zatem translacji, aby zmieniać odległość obserwatora od obiektu, następnie określamy kąty nachylenia względem osi X (wraz ze zmianą tego kąta będziemy mogli zmieniać wysokość obserwatora nad obiektem) oraz kat obrotu wokół osi Y. Następnie odkładamy tą macierz modelowania na stos, aby móc później obracać osią obrotu orbity światła niezależnie od walca (położenie walca się nie zmienia, zmienia się jedynie położenie orbity kuli symbolizującej źródło światła). Gdy odłożymy macierz na stos możemy określić kąt nachylenia do osi X oraz kąt nachylenia do osi Z, gdyż te kąty będą zmieniane za pomocą klawiatury. Następnie wyłączamy oświetlenie, aby nie działało na kolejny tworzony przez nas obiekt. W kolejnej części jest rysowana za pomocą GL_LINES pomocnicza linia rysują orbitę, po której będzie poruszało się światło. Teraz zmieniamy współrzędne położenia zgodnie ze wzorami na współrzędne biegunowe wyznaczając położenie źródła światła i kuli i możemy już wyrysować odpowiednią nieoświetloną kulę. Następnie włączamy światło i ustawiamy jego współrzędne na taki, aby zgadzały się z położeniem wyrysowanej wcześniej kuli (były one określone w funkcji WlaczOswietlenie).
Pozostaje już tylko skonstruowanie funkcji obsługi klawiatury, która będzie nam umożliwiała interaktywną zmianę poszczególnych parametrów.
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
switch(klawisz)
{
case 'v':
lPionowych = (lPionowych == LPION_MAX)? LPION_MAX : lPionowych + 2; //zwiększenie liczby podziałów pionowych
break;
case 'V':
lPionowych = (lPionowych == LPION_MIN)? LPION_MIN : lPionowych - 2; //zmniejszenie liczby podziałów pionowych
break;
case 'h':
lPoziomych = (lPoziomych == LPOZ_MAX)? LPOZ_MAX : lPoziomych + 2; //zwiększenie liczby podziałów poziomych
break;
case 'H':
lPoziomych = (lPoziomych == LPOZ_MIN)? LPOZ_MIN : lPoziomych - 2; //zmniejszenie liczby podziałów poziomych
break;
case 'w':
wysokosc = (wysokosc == WYS_MAX) ? WYS_MAX : wysokosc + 1; //zwiększenie wysokości bryły
break;
case 'W':
wysokosc = (wysokosc == 1) ? wysokosc : wysokosc - 1; // zmniejszenie wysokości bryły
break;
case 'p':
promien = (promien == R_MAX) ? R_MAX : promien + 1; //zwiększenie promienia bryły
break;
case 'P':
promien = (promien == 1) ? promien : promien - 1; //zmniejszenie promienia bryły
break;
case 'r':
UstawDomyslneWartosciParametrow();
break;
case 'f':
katRX=(katRX>-90) ? katRX-1 : -90;
//zmniejszenie kąta nachylenia osi X orbity światła
break;
case 'g':
katRX=(katRX<90) ? katRX+1 : 90;
//zwiększenie kąta nachylenia osi X orbity światła
break;
case 'o':
katRZ=(katRZ>-90) ? katRZ-1 : -90;
//zmniejszenie kąta nachylenia osi Y orbity światła
break;
case 'i':
katRZ=(katRZ<90) ? katRZ+1 : 90;
//zwiększenie kąta nachylenia osi Y orbity światła
break;
case 'a' : (a=1);
//włączenie reflektora
break;
case 'A' : (a=0);
//wyłączenie reflektora
break;
case 'b' : (b=1);
//włączenie światła kierunkowego
break;
case 'B' : (b=0);
//wyłączenie światła kierunkowego
break;
case 'z' : R_L1 += 0.1;
//zwiększenie promienia orbity po której porusza się światło
break;
case 'Z' : R_L1 -= 0.1;
//zmniejszenie promienia orbity po której porusza się światło
break;
case '+' : odleglosc++;
//zwiększenie odległości obserwatora od obiektu
break;
case '-' : odleglosc--;
//zmniejszenie odległości obserwatora od obiektu
break;
case 'y' : obrot = (obrot == 360) ? 0 : obrot + 1;
//zwiększenie kąta obrotu światła wokół bryły
break;
case 'u' : obrot = (obrot == 0) ? 360 : obrot - 1;
//zmniejszenie zwiększenie kąta obrotu światła wokół bryły
break;
// Wcisniecie klawisza ESC powoduje wyjscie z programu
case 27:
exit(0);
}
}
void ObslugaKlawiszySpecjalnych(int klawisz, int x, int y)
{
switch(klawisz)
{
case GLUT_KEY_UP:
kat2 = (kat2 == 360) ? 0 : kat2 + 1;
break;
//zwiększenie wysokości obserwatora nad obiektem
case GLUT_KEY_DOWN:
kat2 = (kat2 == 0) ? 360 : kat2 - 1;
break;
//zmniejszenie wysokości obserwatora nad obiektem
case GLUT_KEY_RIGHT:
kat = (kat == 360) ? 0 : kat + 1;
break;
//zwiększenie kąta obrotu wokół osi Y
case GLUT_KEY_LEFT:
kat = (kat == 0) ? 360 : kat - 1;
break;
//zmniejszenie kąta obrotu wokół osi Y
}
}
Włączone tylko żółte światło kierunkowe:
Włączone oba światła:
Włączone tylko różowe światło reflektora:
Zwiększona odległość obserwatora:
Wnioski
Za zadanie mieliśmy zamodelować odpowiednią bryłę i pokryć ją materiałem oraz w odpowiedni sposób oświetlić dwoma rodzajami światła. Okazało się to bardzie trudne i wymagało dużo czasu jeśli się nie miało odpowiedniej wprawy w tego typu ćwiczeniach. Na laboratorium udało mi się jedynie zbudować odpowiednia bryłę oraz pokryć ją materiałami w odpowiednich barwach w zadany sposób. W domu zmodyfikowałam program dodając do niego odpowiednie światła i wprowadzając znacznie więcej możliwości modyfikacji sceny z poziomu klawiatury. Ćwiczenie to miało na celu pokazanie nam jak ważną rolę w tworzeniu grafiki trójwymiarowej mają materiały oraz światła. Wykorzystanie ich znacznie ożywia tworzone przez nas obiekty i sprawia, że stają się one bardziej rzeczywiste.