Laszuk kubek, WAT, semestr III, Grafika komputerowa


Wojskowa Akademia Techniczna im. Jarosława Dąbrowskiego

Laboratorium Grafiki Komputerowej

Sprawozdanie do ćwiczenia laboratoryjnego nr 2

Wykonujący ćwiczenie: Maciej Laszuk grupa I7X1S1

Data wykonania :02.02.2009

1.Zadnie 1

Wykorzystując biblioteki OpenGL i GLUT napisać program wyświetlający perspektywiczny obraz obiektu przedstawionego na rysunku:

0x01 graphic
0x01 graphic
0x01 graphic

Obiekt należy zamodelować w trybach:

-GL_QUADS

-GL_TRIANGLES_FAN

Z uwzględnieniem możliwaości interakcyjnego wprowadzenia następujących parametrów:

- wysokości obiektu,

-średnicy obiektu,

-grubości ścian,

-liczby podziałów pionowych

Program powinien umożliwiać zmianę położenia obserwatora (odległość od obiektu i obroty wokół osi Y, X i Z)

2. Sposób rozwiązania zadania:

W celu rozwiązanie zadania należało użyć programu Microsoft Visual Studio oraz zmodyfikować program sześcian.c udostępniony przez prowadzącego ćwiczenia. Program można podzielić na dwie części. Część odpowiedzialną za narysowanie bryły na ekranie monitora oraz część zajmującą się przekształceniami bryły.

a.)Rysowanie bryły

void RysujSzescian(double a)

{

double x;

//podstawa dolna

glColor3f(0.1,0.9,0.1);

glBegin(GL_TRIANGLE_FAN);

glVertex3f(0.0,0.0,0.0);

for(x=0.0;x<=360.0;x+=360.0/podzialka2)

{

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

}

glEnd();

//podstawa gorna

glBegin(GL_TRIANGLE_FAN);

glVertex3f(0.0,h*0.15,0.0);

for(x=0.0;x<=360.0;x+=360.0/podzialka2)

{

glVertex3f(r*cos(radian(x)) , h*0.15 , r*sin(radian(x)));

}

glEnd();

//zalamianie podstawy

glBegin(GL_QUADS);

glVertex3f( r , 0.0, 0.0);

for(x=0.0;x<=360.0;x+=360.0/podzialka1)

{

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

glVertex3f(r*cos(radian(x+360.0/podzialka1)) , 0 ,r*sin(radian(x+360.0/podzialka1)));

glVertex3f((r+g)*cos(radian(x+360.0/podzialka1)) , h*0.15 ,(r+g)*sin(radian(x+360.0/podzialka1)));

glVertex3f((r+g)*cos(radian(x)) , h*0.15, (r+g)*sin(radian(x)));

}

glEnd();

//sciana boczna zewnetrzna

glBegin(GL_QUADS);

for(x=0.0;x<360.0;x=x+360.0/podzialka1)

{

glVertex3f((r+g)*cos(radian(x)) , h*0.15 , (r+g)*sin(radian(x)));

glVertex3f((r+g)*cos(radian(x+360.0/podzialka1)) , h*0.15 ,(r+g)*sin(radian(x+360.0/podzialka1)));

glVertex3f((r+g)*cos(radian(x+360.0/podzialka1)) , h ,(r+g)*sin(radian(x+360.0/podzialka1)));

glVertex3f((r+g)*cos(radian(x)) , h , (r+g)*sin(radian(x)));

}

glEnd();

//pierscien na gorze

glBegin(GL_QUADS);

for(x=0.0;x<360.0;x=x+360.0/podzialka1)

{

glVertex3f(r*cos(radian(x)) , h , r*sin(radian(x)));

glVertex3f(r*cos(radian(x+360.0/podzialka1)) , h ,r*sin(radian(x+360.0/podzialka1)));

glVertex3f((r+g)*cos(radian(x+360.0/podzialka1)) , h ,(r+g)*sin(radian(x+360.0/podzialka1)));

glVertex3f((r+g)*cos(radian(x)) , h , (r+g)*sin(radian(x)));

}

glEnd();

//sciana boczna wewnetrzna

glBegin(GL_QUADS);

for(x=0.0;x<360.0;x=x+360.0/podzialka1)

{

glVertex3f(r*cos(radian(x)) , h*0.15 , r*sin(radian(x)));

glVertex3f(r*cos(radian(x+360.0/podzialka1)) , h*0.15 ,r*sin(radian(x+360.0/podzialka1)));

glVertex3f(r*cos(radian(x+360.0/podzialka1)) , h ,r*sin(radian(x+360.0/podzialka1)));

glVertex3f(r*cos(radian(x)) , h , r*sin(radian(x)));

}

glEnd();

//ucho

glBegin(GL_QUADS);

glVertex3f(0,0.3*h,r+g);

glVertex3f(0.5,0.3*h,r+g);

glVertex3f(0.5,0.3*h,r+0.4*r+g);

glVertex3f(0,0.3*h,r+0.4*r+g);

glVertex3f(0.5,0.3*h,r+0.4*r+g);

glVertex3f(0,0.3*h,r+0.4*r+g);

glVertex3f(0,0.35*h,r+0.5*r+g);

glVertex3f(0.5,0.35*h,r+0.5*r+g);

glVertex3f(0,0.35*h,r+0.5*r+g);

glVertex3f(0.5,0.35*h,r+0.5*r+g);

glVertex3f(0.5,0.75*h,r+0.5*r+g);

glVertex3f(0,0.75*h,r+0.5*r+g);

glVertex3f(0,0.75*h,r+0.5*r+g);

glVertex3f(0.5,0.75*h,r+0.5*r+g);

glVertex3f(0.5,0.8*h,r+0.4*r+g);

glVertex3f(0,0.8*h,r+0.4*r+g);

glVertex3f(0.5,0.8*h,r+0.4*r+g);

glVertex3f(0,0.8*h,r+0.4*r+g);

glVertex3f(0,0.8*h,r+g);

glVertex3f(0.5,0.8*h,r+g);

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

glVertex3f(0,0.3*h-0.3,r+g);

glVertex3f(0.5,0.3*h-0.3,r+g);

glVertex3f(0.5,0.3*h-0.3,r+0.4*r+g+0.3);

glVertex3f(0,0.3*h-0.3,r+0.4*r+g+0.3);

glVertex3f(0.5,0.3*h-0.3,r+0.4*r+g+0.3);

glVertex3f(0,0.3*h-0.3,r+0.4*r+g+0.3);

glVertex3f(0,0.35*h-0.3,r+0.5*r+g+0.3);

glVertex3f(0.5,0.35*h-0.3,r+0.5*r+g+0.3);

glVertex3f(0,0.35*h-0.3,r+0.5*r+g+0.3);

glVertex3f(0.5,0.35*h-0.3,r+0.5*r+g+0.3);

glVertex3f(0.5,0.75*h+0.3,r+0.5*r+g+0.3);

glVertex3f(0,0.75*h+0.3,r+0.5*r+g+0.3);

glVertex3f(0,0.75*h+0.3,r+0.5*r+g+0.3);

glVertex3f(0.5,0.75*h+0.3,r+0.5*r+g+0.3);

glVertex3f(0.5,0.8*h+0.3,r+0.4*r+g+0.3);

glVertex3f(0,0.8*h+0.3,r+0.4*r+g+0.3);

glVertex3f(0.5,0.8*h+0.3,r+0.4*r+g+0.3);

glVertex3f(0,0.8*h+0.3,r+0.4*r+g+0.3);

glVertex3f(0,0.8*h+0.3,r+g);

glVertex3f(0.5,0.8*h+0.3,r+g);

glEnd();

}

Analizując powyższy kod łatwo zauważyć, że bryła narysowana jest przy pomocy dwóch trybów: GL_TRIANGLE_FAN oraz GL_QUADS. Zastosowanie tych trybów narzuciły wymogi zadania. Różnica w ich zastosowaniu jest ogromna. Pierwsza i chyba najważniejszą jest typ rysowanego wielokąt. GL_TRIANGLE_FAN generuje trójkąt natomiast GL_QUADS kwadrat. Co za tym idzie również sposób deklarowanych wierzchołków musi być inny(choćby z uwagi na ich ilość). W pierwszym trybie każdy trójką ma jeden wierzchołek wspólny - p1. Natomiast trójką deklaruje się w następujący sposób (p1,p2,p3) (p1,p4,p5) (p1,p6,p7) itd. W drugim trybie generowane są nie połączone ze sobą kwadraty tak więc deklaracja wierzchołków odbywa się w następujący sposób: (p1,p2,p3,p4) (p5,p6,p7,p8) itd.

Ponieważ zadanie charakteryzowało się sporą dowolnością wyboru odnośnie konkretnego zastosowania trybu stwierdziłem, że najwygodniej będzie mi posłużenie się trybem GL_TRIANGLE_FAN do zamodelowania podstawy zewnętrznej i wewnętrznej natomiast trybu GL_QUADS użyłem przy modelowaniu reszty obiektu. Przy większości z części kubka musiałem posłużyć się pętlą , otrzymać pożądaną trygonometryczność obiektu jak również liczbę podziałów pionowych. Jest to w moim przekonaniu dość prosty i efektywny sposób modelowania bryły. Wyjątek stanowi ucho. Najłatwiej było uzyskać pożądany efekt deklarując punkt po punkcie kolejne kwadraty.

Uzyskany efekt (20 podziałów pionowych):

0x01 graphic

b.)Przekształcenia bryły

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(xRot, 1, 0, 0);

glRotatef(yRot, 0, 1, 0);

glRotatef(zRot, 0, 0, 1);

// Narysowanie szescianu

RysujSzescian(bok);

// Przelaczenie buforow ramki

glutSwapBuffers();

}

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

// Funkcja obslugi klawiatury

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

{

switch(klawisz){

case '1' : podzialka1++;break;

case '!' : podzialka1--;break;

case '2' : h+=0.5;break;

case '@' : if(h>1) h-=0.5;break;

case '3' : g+=0.1;break;

case '#' : if(g>0.2)g-=0.1;break;

case '4' : r+=0.1;break;

case '$' : if(r>0.2)r-=0.1;break;

case '5' : OBSERWATOR_ODLEGLOSC ++;break;

case '%' : OBSERWATOR_ODLEGLOSC --;break;

case '6' : xRot ++;break;

case '^' : xRot--;break;

case '7' : yRot++;break;

case '&' : yRot--;break;

case '8' : zRot++;break;

case '*' : zRot--;break;

}

}

Po prawidłowym zamodelowaniu bryły należało umożliwić interaktywność obiektu.

Zadnie okazało się dość proste. Wystarczyło deklarowane punkty uzależnić od zmiennych odpowiedzialnych za wysokość obiektu, promień, grubość ścian oraz liczbę podziałów pionowych. Do obrotu wokół osi X, Y, Z użyłem funkcji glRotatef. Natomiast zmianę odległości od obiektu uzyskałem stosując funkcję glTranslatef. Obie funkcje znajdujące się w bibliotece GL/glut.h umożliwiają w niezwykle łatwy sposób uzyskanie pożądanego efektu. Aby użytkownik mógł dowolnie manipulować podanymi wcześniej przekształceniami dodałem w funkcji ObslugaKlawiatury klawisze za nie odpowiedzialne.

-zmiana ilości podziałów pionowych

Za zmianę odpowiedzialne są klawisze „1”,”!”

10 podziałów pionowych

0x01 graphic

40 podziały pionowy

0x01 graphic

Łatwo dostrzec różnice w szczegółowości , dokładności odwzorowania obiektu. Przy mniejszej liczbie podziałów kubek staje się dużo bardziej kanciasty przez co można powiedzieć, że przybiera kształt bryły foremnej a nie owalnej jak powinien. Zwiększając liczbę podziałów ściany zyskują owalność. Przy bardzo dużej liczbie podziałów chropowatość bryły jest praktycznie niewidoczna.

-Zmiana wielkości bryły

wysokość = 4

0x01 graphic

Wysokość =2

0x01 graphic

średnica = 3

0x01 graphic

Średnica = 0.5

0x01 graphic

grubość = 2

0x01 graphic

Grubość = 0.5

0x01 graphic

-Zmiana orientacji obserwatora

Obrót względem OX:

0x01 graphic

Względem OY:

0x01 graphic

Względem OZ:

0x01 graphic

3.) Deklaracja zmiennych.

Zamieszczam sposób zadeklarowanych przeze mnie zmiennych.

#include <GL/glut.h>

#include <math.h>

// Definicja stalych

#define DLUGOSC_BOKU 5.0

#define OBSERWATOR_FOV_Y 30.0

#define PI 3.1415926535897932384626433832795

// Zmienne globalne

double bok = DLUGOSC_BOKU; // Dlugosc boku szescianu

int szerokoscOkna = 800;

int wysokoscOkna = 600;

float OBSERWATOR_ODLEGLOSC = 20.0;

static GLfloat xRot = 0.0f;

static GLfloat yRot = 0.0f;

static GLfloat zRot = 0.0f;

float h = 4.0;

float r=1.0,podzialka1=20.0,podzialka2=12.0,g=0.5;

double radian(double a)

{

return (a*PI)/180;

}

double radian(double a)

{

return (a*PI)/180;

}

4.) Wnioski.

Celem laboratorium było sprawdzenie wiedzy z zakresu modelowania brył za pomocą trybów dostępnych w bibliotece GLU/GLUT przy modelowaniu brył oszukujących nasze oko. Kubek przez mnie stworzony składał się wyłącznie z kwadratów oraz trójkątów. Figur na pozór nie mających nic wspólnego z walcem pierścieniem czy stożkiem ściętym. Jednak dzięki zastosowaniu bardzo wielu podziałów pionowych bryła nabierała kształtów w dużej mierze przypominających kubek stosowany w życiu codziennym. Wynika z tego, że posługując się ledwie kilkoma figurami geometrycznymi jesteśmy w stanie zamodelować niemal każdą bryłę. Największym problemem podczas tego laboratorium było odpowiednie zadeklarowanie punktów stosując wzory trygonometryczne.



Wyszukiwarka