Kaiser lampka, WAT, semestr III, Grafika komputerowa


WOJSKOWA AKADEMIA TECHNICZNA

INSTYTUT TELEINFORMATYKI I AUTOMATYKI

Laboratorium - Grafika Komputerowa

0x01 graphic

Sprawozdanie

Ćwiczenie laboratoryjne nr 3

Przekształcenia geometryczne

Student: Marcin Kaiser

Grupa: I5B1N0

Data wykonania: 24.01.2009 (z grupą I7X1N1)


Treść zadania

0x01 graphic

Sposób wykonania zadania, przyjęta metoda, algorytm

Do wykonania zadania użyłem prymitywów przestrzennych udostępnianych przez biblioteki GLU i GLUT.

Modelowanie lampki zrealizowałem w 4 etapach:

1) modelowanie podstawy

2) modelowanie wspornika

3) modelowanie ramienia

4) modelowanie lampy.

Na początku zdefiniowałem wskaźniki do kwadryk

GLUquadricObj *podstawa;

GLUquadricObj *podstawaDyskG;

GLUquadricObj *podstawaDyskD;

GLUquadricObj *czescKlosza;

GLUquadricObj *czescDyskG;

GLUquadricObj *czescDyskD;

GLUquadricObj *klosz;

GLUquadricObj *kloszDyskG;

oraz zainicjowałem je w funkcji Inicjujlampke

void Inicjujlampke(void)

{

// Zainicjowanie scian bocznych walca bedacego podstawa lampki

podstawa = gluNewQuadric();

gluQuadricDrawStyle(podstawa, GLU_LINE);

// Zainicjowanie gornej podstawy walca

podstawaDyskG = gluNewQuadric();

gluQuadricDrawStyle(podstawaDyskG, GLU_LINE);

// Zainicjowanie dolnej podstawy walca

podstawaDyskD = gluNewQuadric();

gluQuadricDrawStyle(podstawaDyskD, GLU_LINE);

// Zainicjowanie scian bocznych walca gornej czesci klosza

czescKlosza = gluNewQuadric();

gluQuadricDrawStyle(czescKlosza, GLU_LINE);

// Zainicjowanie gornej podstawy walca

czescDyskG = gluNewQuadric();

gluQuadricDrawStyle(czescDyskG, GLU_LINE);

// Zainicjowanie dolnej podstawy walca

czescDyskD = gluNewQuadric();

gluQuadricDrawStyle(czescDyskD, GLU_LINE);

// Zainicjowanie scian bocznych stozka bedacego kloszem

klosz = gluNewQuadric();

gluQuadricDrawStyle(klosz, GLU_LINE);

// Zainicjowanie gornej podstawy walca

kloszDyskG = gluNewQuadric();

gluQuadricDrawStyle(kloszDyskG, GLU_LINE);

}

Modelowanie podstawy

//podstawa lampki

glPushMatrix();

glColor3f(1.0,1.0,1.0);

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

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

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

glTranslatef(0.0,0.0,0.5);

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

glPopMatrix();

Przy pomocy funkcji glColor3f() ustawiłem kolor na biały. Kolor ten pozostaje obowiązujący również w później modelowanych elementach. Funkcja glRotatef() zmienia płaszczyznę modelowanej podstawy z płaszczyzny XY na płaszczyznę XZ poprzez obrót o -90o wokół osi X. Funkcja gluCylinder() wyświetla walec o promieniu dolnej i górnej podstawy równym 2,5 i o wysokości 0,5. Walec ten jest bokiem podstawy. Aby podstawa była kompletna rysuję dolne zamknięcie, a następnie - po przesunięciu o 0,5 - górne zamknięcie za pomocą funkcji gluDisk(). Wszystkie powyższe operacje wykonuję na osobnej macierzy.

0x01 graphic

Zanim przechodzę do modelowania dalszych elementów, wykorzystuję funkcję glRotatef do umożliwienia obrotu tych dalszych elementów wokół osi Y

//rotacja lampki

glRotatef(obrotGlowicy, 0, 1, 0);

Parametr obrotGlowicy odpowiada za kąt obrotu, zmieniany później w zakresie
0 - 360o przy pomocy klawiszy 3 i #

Modelowanie wspornika

//wspornik

glPushMatrix();

glTranslatef(0.0,0.5+2.5,0.0);

glScalef(0.5,5.0,0.5);

glutWireCube(1);

glPopMatrix();

Do jego narysowania używam funkcji glutWireCube(). Po wywołaniu tej funkcji otrzymuję szkielet sześcianu, który skaluję przy pomocy funkcji glScalef() tak aby otrzymać szkielet prostopadłościanu o wymiarach 0,5 na 0,5 na 5. Ponadto, ponieważ środek sześcianu leży w środku układu współrzędnych, przesuwam go
w górę o wartość równą połowie wysokości ramienia plus grubość podstawy przy pomocy funkcji glTranslate(). Wszystkie powyższe operacje wykonuję na osobnej macierzy.

0x01 graphic

W celu modelowania dalszych elementów przesuwam środek układu współrzędnych z punktu (0,0,0) do punktu (-0.4 , 5 , 0) przy pomocy funkcji glTranslate() oraz umożliwiam obrót tych elementów wokół osi X przy pomocy funkcji glRotate().

glTranslatef(-0.4,0.5+4.5,0.0);

glRotatef(obrotRamienia1, 1, 0, 0);

Parametr obrotRamienia1 odpowiada za kąt obrotu i zmieniany jest później
w zakresie -30o do 60o przy pomocy klawiszy 2 i @.

Modelowanie ramienia

//ramie

glPushMatrix();

glTranslatef(0.0,0.0,-2.0);

glScalef(0.25,0.25,5.0);

glutWireCube(1);

glPopMatrix();

Do jego narysowania używam funkcji glutWireCube(). Po wywołaniu tej funkcji otrzymuję szkielet sześcianu (już w nowym środku układu współrzędnych), który skaluję przy pomocy funkcji glScalef(), tak aby otrzymać szkielet prostopadłościanu
o wymiarach 0,25 na 0,25 na 5. Ponadto przesuwam go wzdłuż osi Z o wartość -2 przy pomocy funkcji glTranslate(). Wszystkie powyższe operacje wykonuję na osobnej macierzy.

0x01 graphic

Modelowanie lampy (części klosza)

//czesc klosza

glPushMatrix();

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

glTranslatef(0.0,4.5,-0.5);

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

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

glTranslatef(0.0,0.0,1.0);

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

glPopMatrix();

Funkcja gluCylinder() wyświetla walec o promieniu dolnej i górnej podstawy równym 0,25 i wysokości 1, będący bokiem części klosza. Aby część klosza była kompletna rysuję dolne zamknięcie, a następnie - po przesunięciu o 1 - górne zamknięcie za pomocą gluDisk(). Walec przesuwam wzdłuż osi Y o wartość 4,5 i wzdłuż osi Z
o wartość -0,5 przy pomocy funkcji glTranslate() oraz przemieszczam z obrotem
o 90o wokół osi X zgodnie z ruchem wskazówek zegara przy pomocy funkcji glRotatef(), tak że trafia on na koniec ramienia. Wszystkie powyższe operacje wykonuję na osobnej macierzy.

0x01 graphic

Modelowanie lampy (klosza)

//klosz

glPushMatrix();

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

glTranslatef(0.0,4.5,-0.5-1.0);

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

glTranslatef(0.0,0.0,1.0);

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

glPopMatrix();

Funkcja gluCylinder() wyświetla rozszerzający się cylinder o promieniu dolnej podstawy równym 1 i górnej podstawy równym 0,5 i wysokości 1. Cylinder jest bokiem klosza. Aby klosz był kompletny rysuję górne zamknięcie za pomocą gluDisk(). Klosz przesuwam wzdłuż osi Y o wartość 4,5 i wzdłuż osi Z o wartość -1,5 przy pomocy funkcji glTranslate() oraz przemieszczam z obrotem o 90o wokół osi X zgodnie z ruchem wskazówek zegara przy pomocy funkcji glRotatef(), tak że trafia on pod część klosza. Wszystkie powyższe operacje wykonuję na osobnej macierzy.

Stworzenie obserwatora zgodnie z założeniami

// Funkcja generujaca pojedyncza klatke animacji

void WyswietlObraz(void)

{

// Wyczyszczenie bufora ramki i bufora glebokosci

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

// Powielenie macierzy na wierzcholku stosu

glPushMatrix();

// Wyznaczenie polozenia obserwatora (przeksztalcenie uladu wspolrzednych

// sceny do ukladu wspolrzednych obserwatora).

zmienna=RAD2DEG(atan(obs_wys/obs_odl));

glTranslatef(0,0, -obs_odl);

glRotatef(zmienna,1,0,0);

glRotatef(rotObsY,0,1,0);

// Generacja obrazu sceny w niewidocznym buforze ramki

RysujLampke(rotRamienia1,rotGlowicy);

// Usuniecie macierzy lezacej na wierzcholku stosu (powrot do stanu

// sprzed wywolania funkcji)

glPopMatrix();

// Przelaczenie buforow ramki

glutSwapBuffers();

}

Parametr obs_wys odpowiada za wysokość obserwatora, a obs_odl za odległość obserwatora od obiektu. Przy zmianie jednego z tych parametrów liczony jest arctg(obs_wys/obs_odl), dzięki czemu wyznaczam kąt pomiędzy płaszczyzną na której postawiona jest lampka oraz linią łączącą środek układu współrzędnych
z obserwatorem.

0x01 graphic

Uzyskany wynik

Bezpośrednio po uruchomieniu programu, przed użyciem klawiszy nawigacyjnych:

0x01 graphic

Przykładowy wynik po powiększeniu, opuszczeniu ramienia i zmianie pozycji obserwatora:

0x01 graphic

Wszystkie elementy rysowane są w oddzielnych macierzach. Aby lampce nadać odpowiednie zachowania, tzn obrót po zadanych osiach, wszystkie operacje obracania wykonywane są na jednej, wspólnej macierzy. Np.: rotacja wokół osi X obraca ramieniem oraz lampą (kloszem i częścią klosza). Gdybym dołączył funkcję obrotu np. do funkcji rysującej ramię (operującej na swojej macierzy), wtedy zmiana parametru obrotRamienia1 spowodowałaby obrót tylko tego ramienia, ale już nie klosza i części klosza.

Obsługa klawiszy

2 - podniesienie ramienia lampki

@ - opuszczenie ramienia lampki

3 - obrót głowicy w kierunku przeciwnym do kierunku wskazówek zegara

# - obrót głowicy w kierunku zgodnym z kierunkiem wskazówek zegara

= - zbliżenie obserwatora

+ - oddalenie obserwatora

strzałki - zmiana orientacji obserwatora względem osi X,Y,Z

Wnioski

W celu zrealizowania zadania potrzebna była wiedza w zakresie przekształceń geometrycznych w przestrzeni 3D. Mogłem stwierdzić, że kolejność składania przekształceń ma znaczenie. Zapoznałem się z podstawowymi funkcjami bibliotek GLU i GLUT służącymi do modyfikacji kształtu i położenia obiektów oraz
z prymitywami przestrzennymi udostępnionymi przez te biblioteki.



Wyszukiwarka