W o j s k o w a A k a d e m i a T e c h n i c z n a
Laboratorium Grafiki Komputerowej
Ćwiczenie laboratoryjne
nr 1
Temat ćwiczenia: „Modelowanie brył”
Pracę wykonał: Bąk Marcin
Grupa: C03B
1. Treść zadania laboratoryjnego:
Zamodelować walec w trybie GL_LINE_STRIP o promieniu podstawy 3, środku podstawy dolnej w punkcie (0,0,0) i wysokości 4.
2. Sposób rozwiązania zadania:
Rozwiązując zadanie laboratoryjne stworzyłem funkcje które:
za pomocą linii (GL_LINE_STRIP) rysuje okrąg
Algorytm działający w pętli wewnętrznej wyznacza w każdej iteracji pętli wewnętrznej współrzędne kolejnego punktu na podstawie parametrycznego równania okręgu (zmienia się wartość kąta):
Współrzędne punktu x1:
X=d*cosL1
Z=d*sinL1
Współrzędne punktu x2:
X=d*cosL2
Z=d*sinL2
Przy wyznaczaniu kolejnych punktów są one łączone odcinkami. W efekcie otrzymujemy okrąg.
W każdej iteracji pętli zewnętrznej zostaje zwiększona wartość współrzędnej Y w przedziale 0..4 tak, aby rysować kolejne warstwy walca zgodnie z ilością podziałów.
Efekt wykonania algorytmu:
za pomocą trójkątów (GL_TRIANGL_FAN) rysuje pola podstaw górnej i dolnej walca
W wyznaczaniu kolejnych punktów wykorzystane zostało równanie parametryczne okręgu:
Algorytm został użyty dla podstawy dolnej i górnej.
Każdy z trójkątów ma jeden punkt wspólny (0,0,0) dla dolnej podstawy i (0,4,0) dla górnej.
Efekt:
za pomocą linii (GL_LINE_STRIP) rysuje powierzchnię boczną walca
Przy użyciu metody jak w wyznaczaniu punktów na okręgu, obliczane są kolejno odpowiednie punkty na podstawie dolnej i górnej (o tych samych współrzędnych x i z), a następnie łączone za pomocą odcinków.
Efekt:
Siatka walca po wykonaniu się całego algorytmu:
3. Podstawowe funkcje i procedury wykorzystane przy budowie modelu
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); - funkcja pozwalająca na rysowanie za pomocą lini
glBegin(GL_LINE_STRIP); - procedura rysująca siatkę za pomocą odcinków
glVertex3f(x,y,z);
glVertex3f(x1,y1,z1);
.
glEnd();
glBegin(GL_TRIANGLE_FAN); - procedura rysująca siatkę za pomocą trójkątów
glVertex3f(x1,y1,z1);
.
glEnd();
GL_LINE_STRIP - to tryb, który polega na rysowaniu odcinków, w taki sposób, że koniec jednego odcinka, jest początkiem następnego.
GL_TRIANGLE_FAN - to tryb, który polega na rysowaniu trójkątów, które mają ze sobą jeden wierzchołek wspólny. Na początku podajemy współrzędne wspólnego wierzchołka, a potem podajemy kolejne wierzchołki dla utworzenia trójkątów.
4. Uzyskane wyniki i wnioski końcowe:
Cel ćwiczenia został osiągnięty. Program realizuje zadanie poprawnie. Po włączeniu programu na ekranie pojawia się żądana bryła. Jest możliwość zmiany ilości podziałów pionowych i poziomych.
5. Kod źródłowy:
#include <GL/glut.h>
#include <math.h>
// Definicja stalych
#define DLUGOSC_BOKU 3.0 //promien walca
#define WYSOKOSC_WALCA 4.0 //wysokosc walca
#define OBSERWATOR_ODLEGLOSC 20.0
#define OBSERWATOR_OBROT_X 20.0
#define OBSERWATOR_OBROT_Y 20.0
#define OBSERWATOR_FOV_Y 30.0
#define PI 3.14155
// Zmienne globalne
double bok = DLUGOSC_BOKU; // promien walca
double wys = WYSOKOSC_WALCA;
int szerokoscOkna = 800;
int wysokoscOkna = 600;
int podzialy = 10; //poczatkowa liczba podzialow
// Prototypy funkcji
void RysujKolo(int l_podz);
void UstawParametryWidoku(int szer, int wys);
void WyswietlObraz(void);
void ObslugaKlawiatury(unsigned char klawisz, int x, int y);
void RysujKolo(int l_podz) //funkcja rysujaca walec
{
int i=0,j=0;
glBegin(GL_LINE_STRIP);
for(j=0;j<=l_podz;j++)
{
for(i=0;i<=l_podz;i++)
{
glVertex3f(3.0*cos((2.0*PI/(double)l_podz)*(double)i), 3*(double)j/l_podz,
3.0*sin((2.0*PI/(double)l_podz)*(double)i));
}
}
glEnd();
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0,3.0,0.0);
for(i=0;i<=l_podz;i++)
{
glVertex3f(3.0*cos((2.0*PI/(double)l_podz)*(double)i),3.0, 3.0*sin((2.0*PI/(double)l_podz)*(double)i));
}
glEnd();
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0,0.0,0.0);
for(i=0;i<=l_podz;i++)
{
glVertex3f(3.0*cos((2.0*PI/(double)l_podz)*(double)i),0.0,
3.0*sin((2.0*PI/(double)l_podz)*(double)i));
}
glEnd();
for(i=0;i<=l_podz;i++)
{
glBegin(GL_LINE_STRIP);
glVertex3f(3.0*cos((2.0*PI/(double)l_podz)*(double)i),0.0,
3.0*sin((2.0*PI/(double)l_podz)*(double)i));
glVertex3f(3.0*cos((2.0*PI/(double)l_podz)*(double)i),3.0, 3.0*sin((2.0*PI/(double)l_podz)*(double)i));
glEnd();
}
}
void UstawParametryWidoku(int szer, int wys)
{
szerokoscOkna = szer;
wysokoscOkna = wys;
glViewport(0, 0, szerokoscOkna, wysokoscOkna);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(OBSERWATOR_FOV_Y, (float)szerokoscOkna/(float)wysokoscOkna, 1.0, 1000.0);
}
void WyswietlObraz(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -OBSERWATOR_ODLEGLOSC);
glRotatef(OBSERWATOR_OBROT_X, 1, 0, 0);
glRotatef(OBSERWATOR_OBROT_Y, 0, 1, 0);
RysujKolo(podzialy); //wyswietlenie walca
glutSwapBuffers();
}
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
if(klawisz == '+') //zwieksza liczbe podzialow
podzialy++;
else if (klawisz == '-') //zmniejsza liczbe podzialow
podzialy--;
else if (klawisz == 27)
exit(0);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(szerokoscOkna, wysokoscOkna);
glutCreateWindow("Szescian");
glEnable(GL_DEPTH_TEST);
glClearDepth(1000.0);
glClearColor (0.0f, 0.0f, 0.3f, 0.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glutDisplayFunc(WyswietlObraz);
glutReshapeFunc(UstawParametryWidoku);
glutIdleFunc(WyswietlObraz);
glutKeyboardFunc(ObslugaKlawiatury);
glutMainLoop();
return 0;
}