Sprawozdanie Lab 2


Sprawozdanie z ćwiczeń laboratoryjnych z przedmiotu Grafika komputerowa

Imię i nazwisko:

Grupa szkoleniowa:

Data:

Prowadzący zajęcia:

Andrzej Sobolewski

I7X6S1

19.11.2008

dr inż. Marek Salamon

Zestaw:

Ocena:

20

1. Treść zadania:

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.

20. 1/4 sfery w trybie GL_TRIANGLE_STRIP o promieniu 1 i środku w punkcie (0, 0, 0).

2. Algorytm rozwiązania zadania na podstawie kodu programu (funkcji) odpowiedzialnego za narysowanie na ekranie zadanego obiektu:

void RysujSzescian(double r)

{

for(y=-1.57;y<1.57;y+=delta)

{

for(x=1.57-delta;x<=3.14;x+=delta)

{

glBegin(GL_TRIANGLE_STRIP);

glVertex3f(r*cos(y)*cos(x) , r*sin(y) , r*cos(y)*sin(x));

glVertex3f(r*cos(y)*cos(x+delta) , r*sin(y) , r*cos(y)*sin(x+delta));

glVertex3f(r*cos(y+delta)*cos(x+delta) , r*sin(y+delta) , r*cos(y+delta)*sin(x+delta));

glVertex3f(r*cos(y+delta)*cos(x) , r*sin(y+delta) , r*cos(y+delta)*sin(x));

glEnd();

}

}

for(y=-1.57;y<1.57;y+=delta)

{

for(x=3,14;x<4.71;x+=delta)

{

glBegin(GL_TRIANGLE_STRIP);

glVertex3f(0 , r*sin(y) , -r*cos(y)*sin(x));

glVertex3f(0 , r*sin(y) , -r*cos(y)*sin(x+delta));

glVertex3f(0 , r*sin(y+delta) , -r*cos(y+delta)*sin(x+delta));

glVertex3f(0 , r*sin(y+delta) , -r*cos(y+delta)*sin(x));

glEnd();

}

}

for(y=-1.57;y<1.57;y+=delta)

{

for(x=3,14;x<4.71;x+=delta)

{

glBegin(GL_TRIANGLE_STRIP);

glVertex3f(r*cos(y)*cos(x) , r*sin(y) , 0);

glVertex3f(r*cos(y)*cos(x+delta) , r*sin(y) , 0);

glVertex3f(r*cos(y+delta)*cos(x+delta) , r*sin(y+delta) , 0);

glVertex3f(r*cos(y+delta)*cos(x) , r*sin(y+delta) , 0);

glEnd();

}

}

}

3. Opis działania funkcji:

Funkcja RysujSzescian posiada jeden argument wejściowy. Jest to zmienna r typu double, której wartość możemy zmieniać w kodzie programu „szescian.c”, regulując w ten sposób promień zadanej sfery. Algorytm rozpoczyna się od dwóch zagnieżdżonych pętli for, które są odpowiedzialne za rysowanie powłoki sfery. Zmienne x, y oraz r używane w tych pętlach są potrzebne do określania położenia punktu w przestrzeni. Pętle for zawierają parametry zmiany kąta rysowania. Zmienna delta służy do zmieniania liczby podziałów pionowych i poziomych bryły. Wyrażenie glBegin(GL_TRIANGLE_STRIP); rozpoczyna blok, w którym tworzona jest powierzchnia w zadanym trybie. Tryb GL_TRIANGLE_STRIP polega na definiowaniu połączonych ze sobą trójkątów w taki sposób, że pierwszy tworzą wierzchołki p1, p2, p3, drugi p3, p2, p4, …, ostatni pn-1, pn-2m pn. Tutaj w każdej iteracji łączymy ze sobą cztery kolejne punkty (wierzchołki trójwymiarowe o współrzędnych typu GLfloat(x, y, z)), które są zdefiniowane za pomocą wyrażenia glVertex3f();. Funkcja ta pochodzi z biblioteki OpenGL, a wartościami przekazywanymi do niej są współrzędne x, y, z w układzie kartezjańskim, którym nadaję odpowiednie wartości za pomocą funkcji sinus oraz cosinus odpowiednio pomnożonych przez siebie oraz promień.

Blok tworzący powłokę sfery zamyka funkcja glEnd();. Następnie w podwójnie zagnieżdzonych pętlach for tworzone są po kolei powierzchnie wewnętrzne bryły, wycinające ¼ sfery. Działają one w podobny sposób. Różnią się tylko parametrami oraz ich zmianami określającymi współrzędne wierzchołków trójwymiarowych w funkcji glVertex3f();, opisanej powyżej. Realizują rysowanie półokręgów. Ponadto do wyznaczenia powyższych współrzędnych wykorzystuje się zależności wynikające z funkcji trygonometrycznych kątów. Należy tu 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. Podobnie jak w przypadku sfery, glBegin(GL_TRIANGLE_STRIP); rozpoczyna blok, w którym tworzona jest powierzchnia w zadanym trybie, a glEnd(); kończy ten blok. Algorytm działania pętli jest następujący - jednorazowy obieg jest odpowiedzialny za narysowanie wycinka powierzchni związanego z jednym przedziałem pionowym. W tym celu określana jest długość promienia potrzebna do narysowania okręgów stanowiących ograniczenia przedziału. Następnie zagnieżdżona pętla odpowiada za narysowanie punktów przestrzennych na okręgach o wyżej obliczonych promieniach.

Wprowadzenie możliwości zmiany obserwatora:

Kod realizujący powyższą czynność wygląda następująco:

int odl=OBSERWATOR_ODLEGLOSC;

int obr_x=OBSERWATOR_OBROT_X;

int obr_y=OBSERWATOR_OBROT_Y;

void ObslugaKlawiatury(unsigned char klawisz, int x, int y)

{

if(klawisz == '+')

r *= 2.0;

else if (klawisz == '-')

r /= 2.0;

else if (klawisz == 'p')

{

if (delta<0.5) delta=delta+0.01;

else if (delta =0.5) delta=0.2;

}

else if (klawisz == 'o')

{

if (delta>0.155) delta=delta-0.01;

else if (delta =0.155) delta=0.5;

}

else if (klawisz == 's') odl=odl+2;

else if (klawisz == 'w') odl=odl-2;

else if (klawisz == 'a') obr_x=obr_x+2;

else if (klawisz == 'd') obr_x=obr_x-2;

else if (klawisz == 'q') obr_y=obr_y+2;

else if (klawisz == 'e') obr_y=obr_y-2;

else if (klawisz == 27)

exit(0);

}

Klawisze obsługi są następujące:

-'a' oraz `d' odpowiadają za obrót w osi OX,

-`q' oraz `e' odpowiadają za obrót w osi OY,

-`w' za przybliżenie, `s' za oddalenie,

-`o` za zwiększanie liczby podziałów pionowych i poziomych bryły,

-`p' za zmniejszanie liczby podziałów pionowych i poziomych bryły.

Zmienne:

int odl=OBSERWATOR_ODLEGLOSC;

int obr_x=OBSERWATOR_OBROT_X;

int obr_y=OBSERWATOR_OBROT_Y;

zostały zdefiniowane globalnie wartościami na początku programu. Po naciśnięciu danego klawisza, wartości odpowiadające położeniu obserwatora zostają zmienione zgodnie z przypisaniami zawartymi w instrukcjach, co powoduje obrót bryły, jej przybliżenie bądź oddalenie oraz zmianę liczby podziałów pionowych lub poziomych.

4. Wynik działania algorytmu:

Rysunek przedstawia 1/4 sfery wykreślonej w trybie GL_TRIANGLE_STRIP przy pomocy zamieszczonego powyżej algorytmu. Została tu zwiększona liczba przedziałów pionowych i poziomych, co pozwoliło na przybliżenie żądanego kształtu.

0x01 graphic

5. Wnioski:

Przy pomocy bibliotek OpenGL oraz GLUT jesteśmy w stanie wygenerować na ekranie obraz bryły zadanej algorytmem. Przy rysowanie należy jednak zwracać uwagę na dokładne dopasowanie kątów wyrażonych w radianach, ponieważ przy niewielkiej niedokładności, przy iteracjach pętli for, błędy w obliczeniach współrzędnych wierzchołków narastają, co może spowodować niedopasowanie ścian bryły. Wyświetlony w ten sposób obraz ma ściany, które nie zachodzą na siebie, bądź wychodzą poza obszar bryły, tworząc postrzępione powierzchnie. Dzięki zmiennym globalnym możliwe jest łatwe ustawianie parametrów bryły oraz położenia obserwatora. Kąty w pętlach można wyrażać w radianach bądź w stopniach, jednak łatwiejsze w użyciu są radiany, ponieważ nie wymagają dalszej konwersji w funkcjach sin oraz cos. Algorytm generujący bryłę zadaną w wykonywanym przeze mnie programie jest dostosowany do zmiany trybu rysowania z GL_TRIANGLE_STRIP na inny, np. GL_TRIANGLE_FAN bez zmiany właściwości zarysu bryły. Algorytmem tym można również się posłużyć rysując dowolny wycinek sfery bądź całą sferę. Należy wtedy tylko pamiętać o właściwej zmianie zmiennych potrzebnych do wyznaczenia współrzędnych wierzchołków punktów oraz odpowiedniej zmianie wartości zmiennych pętli for zarówno wewnętrznej, jak i zewnętrznej.

6. Kod całego programu „sześcian.c”

//////////////////////////////////////////////////////////////////////////////////////////

//

// Program wyswietlajacy szescian w rzucie perspektywicznym. Dlugosc boku szescianu

// moze byc interaktywnie zmieniana za pomoca klwiszy '+' i '-'.

//

//////////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

// Definicja stalych

#define DLUGOSC_BOKU 1.0

#define OBSERWATOR_ODLEGLOSC 20.0

#define OBSERWATOR_OBROT_X 20.0

#define OBSERWATOR_OBROT_Y 20.0

#define OBSERWATOR_FOV_Y 30.0

// Zmienne globalne

double r = DLUGOSC_BOKU; // Dlugosc boku szescianu

int szerokoscOkna = 800;

int wysokoscOkna = 600;

double x,y, delta=0.155;

int odl=OBSERWATOR_ODLEGLOSC;

int obr_x=OBSERWATOR_OBROT_X;

int obr_y=OBSERWATOR_OBROT_Y;

// Prototypy funkcji

void RysujSzescian(double a);

void UstawParametryWidoku(int szer, int wys);

void WyswietlObraz(void);

void ObslugaKlawiatury(unsigned char klawisz, int x, int y);

//////////////////////////////////////////////////////////////////////////////////////////

// Funkcja rysujaca 1/4 sfery w trybie GL_TRIANGLE_STRIP o promieniu 1 i srodku w punkcie (0, 0, 0)

void RysujSzescian(double r)

{

for(y=-1.57;y<1.57;y+=delta)

{

for(x=1.57-delta;x<=3.14;x+=delta)

{

glBegin(GL_TRIANGLE_STRIP);

glVertex3f(r*cos(y)*cos(x) , r*sin(y) , r*cos(y)*sin(x));

glVertex3f(r*cos(y)*cos(x+delta) , r*sin(y) , r*cos(y)*sin(x+delta));

glVertex3f(r*cos(y+delta)*cos(x+delta) , r*sin(y+delta) , r*cos(y+delta)*sin(x+delta));

glVertex3f(r*cos(y+delta)*cos(x) , r*sin(y+delta) , r*cos(y+delta)*sin(x));

glEnd();

}

}

for(y=-1.57;y<1.57;y+=delta)

{

for(x=3,14;x<4.71;x+=delta)

{

glBegin(GL_TRIANGLE_STRIP);

glVertex3f(0 , r*sin(y) , -r*cos(y)*sin(x));

glVertex3f(0 , r*sin(y) , -r*cos(y)*sin(x+delta));

glVertex3f(0 , r*sin(y+delta) , -r*cos(y+delta)*sin(x+delta));

glVertex3f(0 , r*sin(y+delta) , -r*cos(y+delta)*sin(x));

glEnd();

}

}

for(y=-1.57;y<1.57;y+=delta)

{

for(x=3,14;x<4.71;x+=delta)

{

glBegin(GL_TRIANGLE_STRIP);

glVertex3f(r*cos(y)*cos(x) , r*sin(y) , 0);

glVertex3f(r*cos(y)*cos(x+delta) , r*sin(y) , 0);

glVertex3f(r*cos(y+delta)*cos(x+delta) , r*sin(y+delta) , 0);

glVertex3f(r*cos(y+delta)*cos(x) , r*sin(y+delta) , 0);

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, -odl);

glRotatef(obr_x, 1, 0, 0);

glRotatef(obr_y, 0, 1, 0);

// Narysowanie szescianu

RysujSzescian(r);

// Przelaczenie buforow ramki

glutSwapBuffers();

}

//////////////////////////////////////////////////////////////////////////////////////////

// Funkcja obslugi klawiatury

void ObslugaKlawiatury(unsigned char klawisz, int x, int y)

{

if(klawisz == '+')

r *= 2.0;

else if (klawisz == '-')

r /= 2.0;

else if (klawisz == 'p')

{

if (delta<0.5) delta=delta+0.01;

else if (delta =0.5) delta=0.2;

}

else if (klawisz == 'o')

{

if (delta>0.155) delta=delta-0.01;

else if (delta =0.155) delta=0.5;

}

else if (klawisz == 's') odl=odl+2;

else if (klawisz == 'w') odl=odl-2;

else if (klawisz == 'a') obr_x=obr_x+2;

else if (klawisz == 'd') obr_x=obr_x-2;

else if (klawisz == 'q') obr_y=obr_y+2;

else if (klawisz == 'e') obr_y=obr_y-2;

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;

}



Wyszukiwarka

Podobne podstrony:
WYDZIA~1, Labolatoria fizyka-sprawozdania, !!!LABORKI - sprawozdania, Lab, !!!LABORKI - sprawozdania
sprawozdanie lab 6
spr-122, Labolatoria fizyka-sprawozdania, !!!LABORKI - sprawozdania, Lab, !!!LABORKI - sprawozdania,
SPRAWOZDANIE Z LAB 2 Badanie wypływu cieczy ze zbiornika
SPRAWOZDANIE LAB 4 mieszacz
Fizyka cw 123 wyniki, Labolatoria fizyka-sprawozdania, !!!LABORKI - sprawozdania, Lab, !!!LABORKI -
półprzewodnikowe złącze p-n, Labolatoria fizyka-sprawozdania, !!!LABORKI - sprawozdania, Lab, !!!LAB
Sprawozdanie Lab 1 (2)
Natężenie światla, LAB21, Sprawozdanie z lab. fizyki
Sprawozdanie 7 lab my
I8G1S1 Suchocki Mateusy Systemy Dialogowe sprawozdanie lab 3 i 4 sprawozdanie
Forma sprawozdania z LAB (dz i z)
LAB113, Labolatoria fizyka-sprawozdania, !!!LABORKI - sprawozdania, Lab, !!!LABORKI - sprawozdania,
Wnioski sprawozdania - Lab 2, Politechnika Wrocławska - Inżynieria Lotnicza, Semestr VII, Podstawy e
laborka37, Labolatoria fizyka-sprawozdania, !!!LABORKI - sprawozdania, Lab, !!!LABORKI - sprawozdani
41konspekt, Labolatoria fizyka-sprawozdania, !!!LABORKI - sprawozdania, Lab, !!!LABORKI - sprawozdan
Wyniki do ćwiczenia 82 dla dave, Labolatoria fizyka-sprawozdania, !!!LABORKI - sprawozdania, Lab, !!

więcej podobnych podstron