sprawko 3 grafika

WOJSKOWA AKADEMIA TECHNICZNA

Laboratorium z przedmiotu

Grafika komputerowa

SPRAWOZDANIE

Laboratorium nr 3

Wykonanie: Justyna Kozon

Grupa: I9X5S1

Data wykonania ćwiczenia:02.12.2010

  1. Treść wykonywanych zadań.

Zadanie 2.

Napisać program przedstawiający obiekt zbudowany z prymitywów przestrzennych udostępnianych przez biblioteki GLU i GLUT. Użytkownik za pomocą klawiatury mieć możliwość wprowadzania zmian następujących parametrów:

W programie uwzględnić możliwość interakcyjnej zmiany położenia obserwatora poprzez podanie następujących parametrów:

Schemat obiektu do zbudowania:

  1. Wstęp teoretyczny.

Do wykonania zadania laboratoryjnego należało użyć odpowiednich funkcji związanych z modelowaniem przestrzeni zawartych w bibliotekach OpenGL oraz GLUT.

Przydatne były cztery rodzaje funkcji:

glPushMatrix(); - funkcja odkładająca aktualną macierz przekształceń na wierzchołek stosu,

glPopMatrix(); - funkcja zdejmująca macierz ze stosu,

glTranslatef(x,y,z); -funkcja przesuwająca układ współrzędnych o dany wektor

glRotatef(kat,x,y,z); - funkcja obracająca układ współrzędnych o dany kąt w kierunku przeciwnym do ruchu wskazówek zegara, ujemny kąt oznacza rotację zgodnie z ruchem wskazówek zegara, obrót wykonywany jest wokół osi równoległej do wektora (x,y,z)

glScalef(sx,sys,z); - funkcja skaluje osie zgodnie z nadanymi współczynnikami skalowania

glutWireCube(a); -funkcja rysująca sześcian, gdzie a jest długością boku

gluCylinder(*obj, R1, R2, H, a,b); - funkcja rysująca walec bez podstaw, gdzie *obj to wskaźnik do wcześniej utworzonej kwadryki, R1-promień dolnej podstawy, R2-promień górnej podstawy, H- wysokość, a-ilość podziałów promienistych, b – ilość podziałów koncentrycznych.

gluDisc(*obj, Rw, Rz, a, b); - funkcja rysująca dysk, gdzie *obj – wskaźnik do kwadryki, Rw – promień wewnętrzny, Rz – promień zewnętrzny, a – ilość podziałów koncentrycznych, b – ilość podziałów promienistych.

  1. Sposoby rozwiązania zadania i kod źródłowy.

Pracę należało rozpocząć od stworzenia zadanego obiektu za pomocą funkcji modelujących oraz rysujących bryły oraz kwadryki. Aby osiągnąc wymagany efekt należy wykonywać odpowiednio operacje na stosie macierzowym, aby mieć potem możliwość wprowadzenia ruchomych części obiektu. Aby móc wykorzystywać kwadryki inicjujemy je w specjalnej funkcji inicjującej znajdującej się przed rozpoczęciem rysowania właściwego obiektu:

// Zainicjowanie scian bocznych walca

podstawaSciany = gluNewQuadric();

gluQuadricDrawStyle(podstawaSciany, GLU_LINE);

// Zainicjowanie podstawy walca

podstawaDyskG = gluNewQuadric();

gluQuadricDrawStyle(podstawaDyskG, GLU_LINE);

Aby lepiej widzieć jak jest położony w przestrzeni nasz obiekt rysujemy za pomocą trybu GL_LINES osie współrzędnych:

glBegin(GL_LINES);

// Os X

glColor3f(1.0, 0.0, 0.0);

glVertex3f(-20.0, 0.0, 0.0);

glVertex3f(20.0, 0.0, 0.0);

// Os Y

glColor3f(0.0,1.0,0.0);

glVertex3f(0.0, -20.0, 0.0);

glVertex3f(0.0, 20.0, 0.0);

// Os Z

glColor3f(0.0,0.0,1.0);

glVertex3f(0.0, 0.0, -20.0);

glVertex3f(0.0, 0.0, 20.0);

// Koniec tworzenia ukladu wspolrzednych

glEnd();

Teraz możemy przejść do właściwego tworzenia obiektu. Zaczynamy od odłożenia na stos aktualnej macierzy modelowania. Dzięki temu będziemy mogli potem po różnych operacjach obrotu, translacji lub skalowania powrócić do poprzedniego stanu sprzed tych zmian sposobu tworzenia obiektu. Piszemy więc:

// Przygotowanie stosu macierzy modelowania

glPushMatrix();

Podstawę lampki tworzymy za pomocą walca, a zatem kwadryki. Walec jest tworzony wzdłuż osi Z od z=0, tak że jego podstawa znajduje się w płaszczyźnie OXY. Jednak zgodnie z układem do jakiego jesteśmy przyzwyczajeni chcemy, aby lampka była tworzona w górę wyświetlanego podglądu, a nie w bok. W związku z tym musimy obrócić osie układu współrzędnych. Aby obrót był wykonany poprawnie powinniśmy dokonać go wokół osi OX o -90°, tak żeby oś z była zwrócona odpowiednio.

// - walec podstawy

glRotatef(-90.0, 1, 0, 0);

gluCylinder(podstawaSciany, 2.5, 2.5, 0.5, 20, 4);

// - podstawa dolna walca

gluDisk(podstawaDyskG, 0.0, 2.5, 20, 4);

// - podstawa górna walca

glTranslatef(0.0, 0.0, 0.5);

gluDisk(podstawaDyskG, 0.0, 2.5, 20, 4);

Widać zatem, że po obrocie przystępujemy do rysowania walca. Zgodnie z Wysokiem powinien mieć on średnicę 5, więc promienie podstaw będą równe 2,5. Wysokość jest równa 5, natomiast podziały pionowe i poziome wynoszą 20 i 4 (mogły być dowolnie dobrane, jednak takie parametry odzwierciedlają walec wystarczająco dokładnie, a zarazem nie jest ich zbyt wiele i rysowanie nie obciąża wiele pamięci). Następnie rysujemy dolną podstawę walca za pomocą dysku o promieniu wewnętrznym równym 0 i zewnętrznym równym promieniowi walca, czyli 2,5. Podziały pozostają takie jak przy walcu. Aby narysować podstawę górną musimy przenieść układ współrzędnych o 0,5 do góry. W związku z tym używany funkcji glTranslatef(0.0, 0.0, 0.5), z parametrem 0,5 podwyższającym oś Z do góry ze względu na to, że aktualnie taką mamy orientację osi po wcześniejszym obrocie. Teraz możemy już bez przeszkód utworzyć górn,ą podstawę walca. Gotowa podstawa:

Widok pod kątem: Widok z góry:

Teraz będziemy rysować pionową nóżkę lampy. W związku z tym najwygodniej powrócić do tradycyjnego układu współrzędnych, gdzie oś Y skierowana jest do góry. Zdejmujemy zatem ze stosu macierz modelowania, w której był zapisany pierwotny stan. Aby ułatwić sobie obliczenia oraz aby mieć później możliwość dodania obrotu lampki bez podstawy podwyższamy oś Y o 0,5 do góry za pomocą funkcji glTranslatef.

glPopMatrix();

glTranslatef(0.0, 0.5, 0.0);

glRotatef(kat, 0, 1, 0);

glPushMatrix();

glScalef(0.5, 5.0, 0.5);

glTranslatef(0.0, 2.5/5, 0.0);

glutWireCube(1);

Następnie określamy kąt o jaki nastąpi obrót. Górna część lampki będzie się obracała w płaszczyźnie OXZ, zatem obrotu dokonujemy wokół osi OY. Aby mieć możliwość późniejszego obracania lampką za pomocą klawiatury nie wpisujemy stałego kąta, a jedynie zmienną, która będzie mogła być zmieniana. Zmienne służące jako parametry w obrotach są zdefiniowane globalnie na początku programu:

GLfloat katObr = 0.0;

GLfloat kat = 0.0;

Na początku przyjmują wartości 0, abyśmy mogli zobaczyć lampkę w stanie podstawowym. Gdy już określimy obrót musimy odłożyć przygotowaną koncepcję rysowania obiektu na stos. Dzięki temu będzie się obracała cała górna część lampki a nie jedynie następny tworzony element. Aby narysować rozciągnięty sześcian, tak aby odpowiadał temu z rysunku przedstawiającego lampkę musimy zeskalować osie, a następnie przesunąć odpowiednio oś Y, gdyż narysowany prostopadłościan będzie miał środek w punkcie określonej przez aktualną macierz modelowania jako (0,0,0). Środek znajduje się na wysokości 2,5, ale ze względu na to, że osie zostały wcześniej zeskalowane musimy tą wartość podzielić na 5, gdyż w aktualnej koncepcji 5 dawnych jednostek odpowiada 1 teraźniejszej. Możemy teraz narysować sześcian o boku 1, który po zeskalowaniu przez program będzie miał proporcje tego z rysunku podglądowego.

Podstawa z dorysowaną nóżką pionową:

Teraz rysować będziemy ramię poziome. Ponieważ będzie ono ruchome, znów musimy odpowiednio przygotować macierz modelowania.

glPopMatrix();

glTranslatef(0.0, 4.5, 0.0);

glRotatef(katObr, 0, 0, 1);

glPushMatrix();

glTranslatef(-1, 0.0, -0.375);

glScalef(5.0, 0.5, 0.25);

glutWireCube(1);

Zdejmujemy ze stosu ostatnio odłożoną macierz modelowania, aby pozbyć się skalowania osi i pozostałych niepotrzebnych już przekształceń. Podwyższamy oś Y o 4,5, gdyż na tej wysokości będzie znajdował się środek poziomego ramienia. Następnie określamy kąt obrotu poziomego ramienia (będzie on się obracał wzdłuż osi znajdującej się na wysokości 4,5). Ponieważ chcemy aby ramię poruszało się do góry i do dołu, to za oś obrotu przyjmujemy oś Z. Tak przygotowaną macierz modelowania odkładamy na stos, aby wszystkie elementy rysowane później poruszały się razem i zgodnie z określonym kątem. Następnie przesuwamy środek układów współrzędnych o -1, gdyż chcemy aby figura ‘wystawała’ bardziej w kierunku strony, z której będzie później rysowany klosz oraz o -0.375 (połowa ‘grubości’ ramienia pionowego i poziomego w widoku z góry) na osi Z, bo ramię poziome ma być przystające do pionowego i nie przecinać go. Dzięki temu przesunięciu i późniejszym zeskalowaniu odpowiednio osi (5-krotnie zwiększamy oś X, pozostałe osie zmniejszamy) otrzymujemy prostopadłościan podzielony w stosunku 3,5:1,5.

Gotowa kolejna część lampki:

Przechodzimy teraz do rysowania klosza lampki.

//klosz

glPopMatrix();

glTranslatef(-3.75, -0.25, -0.375);

glRotatef(-90.0, 1, 0, 0);

gluCylinder(przegubDyskD, 0.25, 0.25, 1.0, 20, 4);

gluDisk(podstawaDyskG, 0.0, 0.25, 20, 4);

glTranslatef(0.0, 0.0, 1.0);

gluDisk(podstawaDyskG, 0.0, 0.25, 20, 4);

glTranslatef(0.0, 0.0, -2.0);

gluCylinder(przegubDyskD, 1.0, 0.5, 1.0, 20, 4);

glTranslatef(0.0, 0.0, 1.0);

gluDisk(podstawaDyskG, 0.0, 0.5, 20, 4);

Zdejmujemy ze stosu poprzednią macierz modelowania. Rozpoczynamy zatem znowu z punktu znajdującego się na wysokości 4,5 i umożliwiającego obroty lampki. Aby narysować odpowiednio górną część klosza musimy dokonać translacji o -3,75 na osi X (na -3,5 kończy się poziome ramię lampki i musimy odjąć od tego jeszcze długość promienia walca, który będziemy tworzyć), -0,25 na osi Y (obniżamy środek walca tak, aby znajdował się na równym poziomie z poziomym ramieniem) oraz -0,375 na osi Z (gdyż ramię poziome jest przesunięte o tyle wzdłuż osi Z i dokonujemy przesunięcia, aby wyrównać te dwa obiekty i żeby nie były względem siebie przesunięte). Następnie dokonujemy obrotu takiego jak przy rysowaniu podstawy lampki gdyż będziemy rysować walec w takiej samej płaszczyźnie. Teraz możemy już narysować odpowiedni walec o wymiarach takich jak na rysunku oraz jego podstawę dolną (promień pokrywa się z promieniem walca). Żeby narysować górną podstawę walca dokonujemy translacji o 1 do góry, czy wzdłuż osi Z, gdyż taką wysokość ma walec. Do narysowania dolnej części klosza wykorzystujemy także walec, jednak o różnych podstawach dolnej i górnej. Teraz musimy przemieścić się na poziom dolnej podstawy dolnego klosza i stąd rozpocząć rysowanie. Dokonujemy translacji o -2 na osi Z i rysujemy walec o dolnej podstawie długości 1 i górnej – 0,5. Pozostała teraz jedynie górna podstawa dolnego walca. Walec ma wysokość 1, więc przesuwamy oś Z o 1 w górę i rysujemy ostatni element lampki.

Gotowa lampka (różne kąty wychylenia):

Aby możliwa była zmiana odległości obserwatora od obiektu dodana została zmienna

GLfloat odleglosc = 30.0;

Jest ona używana w funkcji wyświetlania obrazu w następujący sposób:

glTranslatef(0, 0, -odleglosc);

W miejscu, gdzie ustalane jest położenie obserwatora. Dzięki nadaniu tu zmiennej zamiast stałej wartości będziemy mogli odległość tę zmieniać w funkcji obsługi klawiatury, która opisana będzie niżej.

Wysokość nad obiektem i obrót wokół obiektu zmieniane są w następującej funkcji:

void ObslugaKlawiszySpecjalnych(int klawisz, int x, int y)

{

switch(klawisz)

{

case GLUT_KEY_UP:

rotObsX = (rotObsX < 360.0) ? rotObsX + 1.0 : rotObsX;

break;

case GLUT_KEY_DOWN:

rotObsX = (rotObsX > 0.0) ? rotObsX - 1.0 : rotObsX;

break;

case GLUT_KEY_LEFT:

rotObsY = (rotObsY < 360.0) ? rotObsY + 1.0 : rotObsY;

break;

case GLUT_KEY_RIGHT:

rotObsY = (rotObsY > 0.0) ? rotObsY - 1.0 : rotObsY;

break;

}

}

Gdzie rotObsX jest to zmiana wysokości nad obiektem i umożliwia nam spojrzenie na obiekt z góry i z dołu, nie zmienia poza tym odległości obserwatora od obiektu. Zmiana ta następuje w zakresie [0;360]. Podobnie Jest ze zmienną rotObsY, która umożliwia obrót poziomy wokół obiektu.

Ruchy lampki i odległość obserwatora od obiektu zmieniane są w następującej funkcji:

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

{

switch(klawisz)

{

case 'q':

katObr=(katObr<360)? katObr+1.0 :0; // zmiana kąta nachylenia ramienia

break; //poziomego

case 'a':

katObr=(katObr>0)? katObr-1.0:360;

break;

case 'w':

kat=(kat<360)? kat+1.0 :0; //zmiana kąta obrotu lampki

break;

case 's':

kat=(kat>0)? kat-1.0:360;

break;

case 'e': //zmiana odległości od obiektu

odleglosc+=1.0;

break;

case 'd':

odleglosc-=1.0;

break;

}

if(klawisz == 27)

exit(0);

}

Wnioski:

Wszystkie zadania postawione przede mną zostały wykonane poprawnie. Na zajęciach laboratoryjnych nie miałam wykonanego obrotu lampki dookoła, wynikało to ze złego zrozumienia treści zadania i wykonania obrotu całej lampki razem z podstawą. Ponadto źle zinterpretowałam zmianę wysokości w stosunku do obiektu wykonując tę część tak, że wraz z wysokością zmieniała się również odległość od obiektu. Błędy te zostały przeze mnie poprawione i program działa w pełni poprawnie. Ćwiczenie to nauczyło nas korzystania ze stosu macierzy modelujących i pokazało korzyści z tego wynikające. Operacje odkładania macierzy na stos i zdejmowania z niego pozwalają nam na tworzenie praktycznie każdego obiektu jaki możemy sobie wymyśleć i można przedstawić w postaci podstawowych figur, których tworzenie umożliwia nam OpenGL i dodatkowe biblioteki. Dzięki zajęciom mogliśmy doświadczyć jak ważne w budowaniu tych obiektów są odpowiednie współrzędne umożliwiające idealne dopasowanie do siebie tworzonych obiektów. Ciekawym doświadczeniem było stworzenie obiektów umożliwiających poruszanie nimi z poziomu klawiatury.


Wyszukiwarka

Podobne podstrony:
sprawko 1 grafika Ask
sprawko 4 grafika Ask
sprawko 3 grafika Ask
sprawko 2 grafika Ask
sprawko 1 grafika
sprawko 4 grafika
sprawko 2 grafika
sprawko 1 grafika Ask
gk sprawko lab4 w szachownice wook, Studia, WAT Informatyka, s3 - GK - grafika komputerowa, LAB4
sprawko-pieci, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab2
gk sprawko, WAT, semestr III, Grafika komputerowa
sprawko na grafike
sprawko na ostatnią grafike
Grafika 2
Grafika komputerowa 2
Grafika 11

więcej podobnych podstron