WOJSKOWA AKADEMIA TECHNICZNA
GRAFIKA KOMPUTEROWA
SPRAWOZDANIE
Z
ZADANIA LABORATORYJNEGO
MODELOWANIE OŚWIETLENIA
Grupa szkoleniowa: I7X6S1
Sprawozdanie wykonał : Michał Małek
Prowadzący ćwiczenie: dr inż. Marek Salamon
Treść zadania.
Wykorzystując biblioteki OpenGL i GLUT napisać program przedstawiający perspektywiczny obraz obiektu o następujących parametrach:
1. Typ obiektu: sfera o zmiennej parzystej liczbie podziałów pionowych i poziomych,
2. Właściwości materiału nr 1: zielony matowy (widziany w białym świetle),
3. Właściwości materiału nr 2: fioletowy błyszczący (widziany w białym świetle),
Sposób przyporządkowania materiałów do obiektu zgodnie ze wzorem : szachownica z uwzględnieniem podziałów poziomych i pionowych.
Obiekt należy oświetlić dwoma źródłami światła o następujących parametrach:
Źródło nr 1:
typ: reflektor (ang. spot),
kolor: żółty,
natężenie: 1,
kąt odcięcia: 45o,
położenie: zmienne po orbicie kołowej o środku w punkcie S(0,0,0) z możliwością interaktywnej zmiany następujących parametrów:
- promienia orbity,
- kąta nachylenia orbity do osi OX,
- kąta nachylenia orbity do osi OZ,
kierunek świecenia: na obiekt.
Źródło nr 2:
typ: kierunkowe,
kolor: czerwony,
natężenie: 0.8,
położenie: stałe w punkcie P(10,10, 10) układu współrzędnych sceny.
kierunek świecenia: na obiekt.
Program powinien umożliwiać:
interaktywne, niezależne włączanie i wyłączanie źródeł światła,
Interaktywną zmianę liczby podziałów pionowych i poziomych bryły,
interaktywną zmianę położenia obserwatora poprzez podanie następujących parametrów :
- odległości obserwatora od środka układu współrzędnych sceny,
- kąta obrotu wokół osi OY w zakresie [0 o,360 o] z krokiem 1 o.
Oświetlony obiekt powinien zawsze znajdować się w centralnej części okna.
Wykonanie zadania
Pierwszym etapem wykonania zadania było zamodelowanie kuli. Ze względu na sposób przyporządkowania materiałów nie mogłem wykorzystać gotowych prymitywów. Zastosowałem tryb GL_QUADS i obliczyłem poszczególne współrzędne punktów należących do sfery. Zmienne odpowiadające za kąty są iterowane przy użyciu pętli, a promień i liczba podziałów zmieniane z klawiatury. Kod rysujący sferę :
//Sfera
for(i=0; i < poziom; i++) {
if (i%2 == 0) licznik=1;
else licznik=0;
for (j=0; j < pion; j++){
if (licznik%2 == 0)
{Material1();licznik=1;}
else {Material2();licznik=0;}
glBegin(GL_QUADS);
x = R*cos(-pi/2+(pi*j/pion))*cos(2*pi*i/poziom);
y = R*sin(-pi/2+(pi*j/pion));
z = R*cos(-pi/2+(pi*j/pion))*sin(2*pi*i/poziom);
glVertex3f(x,y,z);
temp_y = y;
temp_x = x;
temp_z = z;
x = R*cos(-pi/2+(pi*(j+1)/pion))*cos(2*pi*i/poziom);
y = R*sin(-pi/2+(pi*(j+1)/pion));
z = R*cos(-pi/2+(pi*(j+1)/pion))*sin(2*pi*i/poziom);
glVertex3f(x,y,z);
wektor1[0]= x - temp_x;
wektor1[1]= y - temp_y;
wektor1[2]= z - temp_z;
x = R*cos(-pi/2+(pi*(j+1)/pion))*cos(2*pi*(i+1)/poziom);
y = R*sin(-pi/2+(pi*(j+1)/pion));
z = R*cos(-pi/2+(pi*(j+1)/pion))*sin(2*pi*(i+1)/poziom);
glVertex3f(x,y,z);
x = R*cos(-pi/2+(pi*j/pion))*cos(2*pi*(i+1)/poziom);
y = R*sin(-pi/2+(pi*j/pion));
z = R*cos(-pi/2+(pi*j/pion))*sin(2*pi*(i+1)/poziom);
glVertex3f(x,y,z);
wektor2[0]= x - temp_x;
wektor2[1]= y - temp_y;
wektor2[2]= z - temp_z;
IloczynWektorowy();
glNormal3f(wektor3[0],wektor3[1],wektor3[2]);
glEnd();
}
}
glPopMatrix();
Mając zamodelowaną kulę i obliczone jej wektory normalne przystąpiłem do pracy nad materiałami z jakich powinien być zbudowany rysowany obiekt. Parametry obu materiałów :
//zielony matowy
const GLfloat ambient_m1[4] = {0,1,0,1};
const GLfloat diffuse_m1[4] = {0,1,0,1};
GLfloat specular_m1[4] = {0,0.1,0,0.1};
// filetowy polysk
const GLfloat ambient_m2[4] = {0.8,0,0.8,1};
const GLfloat diffuse_m2[4] = {0.5,0,0.5,1};
GLfloat specular_m2[4] = {1,0,1,1};
Następnym etapem było przygotowanie tablic opisujących źródła światła:
//reflektor
GLfloat ambient_s1[4] = {1,1,0,1};
GLfloat diffuse_s1[4] = {1,1,0,1};
GLfloat specular_s1[4] = {1,1,0,1};
GLfloat position_s1[] = {0,0,0,1};
GLfloat direction_s1[] = {0,-1,0};
// kierunkowe
GLfloat ambient_s2[4] = {0.8,0,0,1};
GLfloat diffuse_s2[4] = {0.8,0,0,1};
GLfloat specular_s2[4] = {0.8,0,0,1};
GLfloat position_s2[] = {-10,10,10,0};
GLfloat direction_s2[] = {0,-1,0};
Efekt działania programu
Wnioski z przeprowadzonego ćwiczenia
Celem zadań laboratoryjnych było zamodelowanie obiektu składającego się z dwóch różniących się materiałów, oświetlenie sceny dwoma odmiennymi źródłami światła, a następnie zaobserwowaniu relacji łączących te elementy i ich wpływ na otrzymywane efekty wizualne. Napisany program, doskonale ukazuje zasady powstawania barwy, oraz jej związek z właściwościami materiału tworzącego przedmiot, oraz światła na niego padającego. Zatem możemy stwierdzić, że cele zajęć zostały osiągnięte.
Wydruk kodu programu
#include <GL/glut.h>
#include <math.h>
// Definicja stalych
#define DLUGOSC_BOKU 5.0
float OBSERWATOR_ODLEGLOSC = 50.0;
float OBSERWATOR_OBROT_X = 20.0;
float OBSERWATOR_OBROT_Y = 20.0;
float OBSERWATOR_FOV_Y = 30.0;
float OBSERWATOR_WYSOKOSC = 10;
//PI
float pi = 3.1415;
//Podzial pion i poziom
int poziom = 40;
int pion = 40;
//Macierze definiujace materialy
//zielony matowy
const GLfloat ambient_m1[4] = {0,1,0,1};
const GLfloat diffuse_m1[4] = {0,1,0,1};
GLfloat specular_m1[4] = {0,0.1,0,0.1};
// filetowy polysk
const GLfloat ambient_m2[4] = {0.8,0,0.8,1};
const GLfloat diffuse_m2[4] = {0.5,0,0.5,1};
GLfloat specular_m2[4] = {1,0,1,1};
//Macierze definiujace swiatla
//reflektor
GLfloat ambient_s1[4] = {1,1,0,1};
GLfloat diffuse_s1[4] = {1,1,0,1};
GLfloat specular_s1[4] = {1,1,0,1};
GLfloat position_s1[] = {0,0,0,1};
GLfloat direction_s1[] = {0,-1,0};
// kierunkowe
GLfloat ambient_s2[4] = {0.8,0,0,1};
GLfloat diffuse_s2[4] = {0.8,0,0,1};
GLfloat specular_s2[4] = {0.8,0,0,1};
GLfloat position_s2[] = {-10,10,10,0};
GLfloat direction_s2[] = {0,-1,0};
float kat_x = 0, kat_z = 0, R_L1 = 45;
//Tablice wektorow
float wektor1[3], wektor2[3], wektor3[3];
// Zmienne globalne
double bok = DLUGOSC_BOKU; // srednica
int szerokoscOkna = 800;
int wysokoscOkna = 600;
void RysujSfere(double a);
void UstawParametryWidoku(int szer, int wys);
void WyswietlObraz(void);
void ObslugaKlawiatury(unsigned char klawisz, int x, int y);
void Material1() {
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_m1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_m1);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_m1);
glMaterialf (GL_FRONT, GL_SHININESS, 128);
}
void Material2() {
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_m2);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_m2);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_m2);
}
void Swiatlo1() {
glPushMatrix();
glRotatef(kat_x,1,0,0);
glRotatef(kat_z,0,0,1);
glTranslatef(0,R_L1,0);
glPushMatrix();
//glutWireSphere(1,10,10);
glPopMatrix();
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse_s1);
glLightfv(GL_LIGHT1, GL_SPECULAR, specular_s1);
glLightfv(GL_LIGHT1, GL_POSITION, position_s1);
glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 30.0);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION,direction_s1);
glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 1);
glPopMatrix();
}
void Swiatlo2() {
glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse_s2);
glLightfv(GL_LIGHT2, GL_SPECULAR, specular_s2);
glLightfv(GL_LIGHT2, GL_POSITION, position_s2);
}
void IloczynWektorowy() {
wektor3[0] = wektor1[1]*wektor2[2] - wektor2[1]*wektor1[2];
wektor3[1] = wektor1[2]*wektor2[0] - wektor2[2]*wektor1[0];
wektor3[2] = wektor1[0]*wektor2[1] - wektor2[0]*wektor1[1];
}
void RysujSfere(double a)
{
float alfa = 0, teta = 0, x, y, z;
float R = 6, temp_y=0, temp_x=0, temp_z=0;
int licznik = 0, i=0, j=0;
//Sfera
for(i=0; i < poziom; i++)
{
if (i%2 == 0)
{licznik=1;}
else licznik=0;
for (j=0; j < pion; j++)
{
if (licznik%2 == 0)
{Material1();licznik=1;}
else {Material2();licznik=0;}
glBegin(GL_QUADS);
x = R*cos(-pi/2+(pi*j/pion))*cos(2*pi*i/poziom);
y = R*sin(-pi/2+(pi*j/pion));
z = R*cos(-pi/2+(pi*j/pion))*sin(2*pi*i/poziom);
glVertex3f(x,y,z);
temp_y = y;
temp_x = x;
temp_z = z;
x = R*cos(-pi/2+(pi*(j+1)/pion))*cos(2*pi*i/poziom);
y = R*sin(-pi/2+(pi*(j+1)/pion));
z = R*cos(-pi/2+(pi*(j+1)/pion))*sin(2*pi*i/poziom);
glVertex3f(x,y,z);
wektor1[0]= x - temp_x;
wektor1[1]= y - temp_y;
wektor1[2]= z - temp_z;
x = R*cos(-pi/2+(pi*(j+1)/pion))*cos(2*pi*(i+1)/poziom);
y = R*sin(-pi/2+(pi*(j+1)/pion));
z = R*cos(-pi/2+(pi*(j+1)/pion))*sin(2*pi*(i+1)/poziom);
glVertex3f(x,y,z);
x = R*cos(-pi/2+(pi*j/pion))*cos(2*pi*(i+1)/poziom);
y = R*sin(-pi/2+(pi*j/pion));
z = R*cos(-pi/2+(pi*j/pion))*sin(2*pi*(i+1)/poziom);
glVertex3f(x,y,z);
wektor2[0]= x - temp_x;
wektor2[1]= y - temp_y;
wektor2[2]= z - temp_z;
IloczynWektorowy();
glNormal3f(wektor3[0],wektor3[1],wektor3[2]);
glEnd();
}
}
glPopMatrix();
Swiatlo1();
Swiatlo2();
}
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);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
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(atan(OBSERWATOR_WYSOKOSC/OBSERWATOR_ODLEGLOSC) * 180/pi,1,0,0);
glRotatef(OBSERWATOR_OBROT_Y, 0, 1, 0);
// Narysowanie szescianu
RysujSfere(bok);
// Przelaczenie buforow ramki
glutSwapBuffers();
}
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
switch(klawisz){
case ';' : OBSERWATOR_ODLEGLOSC++;break;
case '.' : OBSERWATOR_ODLEGLOSC--;break;
case 'l' : OBSERWATOR_WYSOKOSC++;break;
case ',' : OBSERWATOR_WYSOKOSC--;break;
case 'k' : OBSERWATOR_OBROT_Y++;break;
case 'm' : OBSERWATOR_OBROT_Y--;break;
//PODZIAL - rownolezniki i poludniki
case '1' : poziom+=2;break;
case '2' : poziom-=2;break;
case '3' : pion+=2;break;
case '4' : pion-=2;break;
//Swiatlo
case 'q' : glEnable(GL_LIGHT0);break;
case 'w' : glDisable(GL_LIGHT0);break;
case 'e' : glEnable(GL_LIGHT1);break;
case 'r' : glDisable(GL_LIGHT1);break;
case 't' : glEnable(GL_LIGHT2);break;
case 'y' : glDisable(GL_LIGHT2);break;
//Regulowanie orbity L1
case 'a' : R_L1+=1;break;
case 'z' : R_L1-=1;break;
case 's' : kat_x++;break;
case 'x' : kat_x--;break;
case 'd' : kat_z++;break;
case 'c' : kat_z--;break;
case 27 : exit(0);break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(szerokoscOkna, wysokoscOkna);
glutCreateWindow("Modelowanie oświetlenia");
glEnable(GL_DEPTH_TEST);
glClearDepth(1000.0);
glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glutDisplayFunc(WyswietlObraz);
glutReshapeFunc(UstawParametryWidoku);
glutIdleFunc(WyswietlObraz);
glutKeyboardFunc(ObslugaKlawiatury);
glutMainLoop();
return 0;
}