Wojskowa Akademia Techniczna
Laboratorium Grafiki Komputerowej
SPRAWOZDANIE
Osoba Prowadząca: dr inż. Marek Salamon
Wykonał: Stanisław Berk
Grupa szkoleniowa: C02A
Data wykonania sprawozdania: 2005-05-08
Ocena sprawozdania: .............................................
Numer i treść zadania
19. ¾ walca w trybie GL_TRIANGLE_STRIP o promieniu podstawy 1 i jej środku w punkcie (0, 0, 0), wysokości 4.
Kod funkcji realizujący treść zadania
void RysujWalec(double h, double r, int nv, int nh)
{
double dH, dAlfa;
int i, j;
// Wyznaczenie wysokosci pojedynczego wycinka poziomego
dH = h/(double)nv;
// ľ walca
cut = 0.75;
// Wyznaczenie kata wyznaczajacego pojedynczy wycinek pionowy
dAlfa = 360.0*cut / (double)nh;
//pierwsza podstawa
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, 0.0);
for (i = 1; (i-1) * dAlfa <= 360.0L*cut; i++) glVertex3f(r*cos(DEG2RAD(i*dAlfa)), r*sin(DEG2RAD(i*dAlfa)), 0.0);
glEnd();
//druga podstawa
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, h);
for (i = 1; (i-1) * dAlfa <= 360.0L*cut; i++) glVertex3f(r*cos(DEG2RAD(i*dAlfa)), r*sin(DEG2RAD(i*dAlfa)), h);
glEnd();
for (i=0; floor((i+1)*dH*1.0E10)<=floor(h*1.0E10);i++) {
glBegin(GL_TRIANGLE_STRIP);
for (j=1; (j-1)*dAlfa <= 360.0L*cut; j++) {
glVertex3f(r*cos(DEG2RAD(j*dAlfa)), r*sin(DEG2RAD(j*dAlfa)), (i)*dH);
glVertex3f(r*cos(DEG2RAD(j*dAlfa)), r*sin(DEG2RAD(j*dAlfa)), (i+1)*dH);
}
glEnd();
//sciana wyciecia
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(r*cos(DEG2RAD(dAlfa)), r*sin(DEG2RAD(dAlfa)), i*dH);
glVertex3f(r*cos(DEG2RAD(dAlfa)), r*sin(DEG2RAD(dAlfa)), (i+1)*dH);
glVertex3f(0.0, 0.0, i*dH);
glVertex3f(0.0, 0.0, (i+1)*dH);
glVertex3f(r*cos(DEG2RAD((nh+1)*dAlfa)), r*sin(DEG2RAD((nh+1)*dAlfa)), i*dH);
glVertex3f(r*cos(DEG2RAD((nh+1)*dAlfa)), r*sin(DEG2RAD((nh+1)*dAlfa)), (i+1)*dH);
glEnd();
}
}
Opis działania funkcji
Funkcja posiada cztery parametry wejściowe:
h - określa wysokość walca
r - promień walca
nv - ilość przedziałów poziomych
nh - ilość przedziałów pionowych
na ich podstawie wyznaczane są odpowiednio stałe:
dAlfa - kąt pod jakim będziemy się przesuwać w przestrzeni
dH - wysokość pojedynczego wycinka poziomego
Po tych obliczeniach rysowane są podstawy walca, a następnie jego ściana boczna. Do tego celu zostały użyte dwie pętle. Ich jednorazowy obieg odpowiada za narysowanie jednego przedziału pionowego figury - zarówno jej ścian bocznych jak i ścian wcięć.
Wynik realizacji algorytmu (po zwiększeniu ilości przedziałów pionowych i poziomych)
Kod całego programu (modyfikacja kodu otrzymanego na zajęciach)
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <GL/glut.h>
// Definicja stalych
#define DLUGOSC_BOKU 5.0
#define OBSERWATOR_ODLEGLOSC 20.0
#define OBSERWATOR_OBROT_X 20.0
#define OBSERWATOR_OBROT_Y 20.0
#define OBSERWATOR_FOV_Y 30.0
#define M_PI 3.14159
#define DEG2RAD(x) ((float)(x)*M_PI/180.0)
// Zmienne globalne
int szerokoscOkna = 800;
int wysokoscOkna = 600;
int poziom = 3;
int pion = 3;
double promien = 1.0; // Promien walca
double wysokosc = 4.0; // Wysokosc walca
double cut;
// Prototypy funkcji
void RysujSzescian(double, int, int);
void UstawParametryWidoku(int szer, int wys);
void WyswietlObraz(void);
void ObslugaKlawiatury(unsigned char klawisz, int x, int y);
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja rysujaca szescian o boku "a" w trybie GL_QUAD_STRIP
void RysujSzescian(double h, double r, int nv, int nh)
{
double dH, dAlfa;
int i, j;
// Wyznaczenie wysokosci pojedynczego wycinka poziomego
dH = h/(double)nv;
// ? walca
cut = 0.75;
// Wyznaczenie kata wyznaczajacego pojedynczy wycinek pionowy
dAlfa = 360.0*cut / (double)nh;
//pierwsza podstawa
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, 0.0);
for (i = 1; (i-1) * dAlfa <= 360.0L*cut; i++) glVertex3f(r*cos(DEG2RAD(i*dAlfa)), r*sin(DEG2RAD(i*dAlfa)), 0.0);
glEnd();
//druga podstawa
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, h);
for (i = 1; (i-1) * dAlfa <= 360.0L*cut; i++) glVertex3f(r*cos(DEG2RAD(i*dAlfa)), r*sin(DEG2RAD(i*dAlfa)), h);
glEnd();
for (i=0; floor((i+1)*dH*1.0E10)<=floor(h*1.0E10);i++) {
glBegin(GL_TRIANGLE_STRIP);
for (j=1; (j-1)*dAlfa <= 360.0L*cut; j++) {
glVertex3f(r*cos(DEG2RAD(j*dAlfa)), r*sin(DEG2RAD(j*dAlfa)), (i)*dH);
glVertex3f(r*cos(DEG2RAD(j*dAlfa)), r*sin(DEG2RAD(j*dAlfa)), (i+1)*dH);
}
glEnd();
//sciana wyciecia
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(r*cos(DEG2RAD(dAlfa)), r*sin(DEG2RAD(dAlfa)), i*dH);
glVertex3f(r*cos(DEG2RAD(dAlfa)), r*sin(DEG2RAD(dAlfa)), (i+1)*dH);
glVertex3f(0.0, 0.0, i*dH);
glVertex3f(0.0, 0.0, (i+1)*dH);
glVertex3f(r*cos(DEG2RAD((nh+1)*dAlfa)), r*sin(DEG2RAD((nh+1)*dAlfa)), i*dH);
glVertex3f(r*cos(DEG2RAD((nh+1)*dAlfa)), r*sin(DEG2RAD((nh+1)*dAlfa)), (i+1)*dH);
glEnd();
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja ustawiajaca parametry rzutu perspektywicznego i rozmiary viewportu
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);
// Przejscie w tryb modyfikacji macierzy przeksztalcen geometrycznych
glMatrixMode(GL_MODELVIEW);
// Zmiana macierzy znajdujacej sie na wierzcholku stosu na macierz jednostkowa
glLoadIdentity();
// Wyswietlanie wielokatow w postaci obrysow.
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja generujaca pojedyncza klatke animacji
void WyswietlObraz(void)
{
// Wyczyszczenie bufora ramki i bufora glebokosci
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Okreslenie wielkosci widoku, wlaczenie rzutowania perspektywicznego
// i zainicjowanie stosu macierzy modelowania
UstawParametryWidoku(szerokoscOkna, wysokoscOkna);
// Ustalenie polozenia obserwatora
glTranslatef(0, 0, -OBSERWATOR_ODLEGLOSC);
glRotatef(OBSERWATOR_OBROT_X, 1, 0, 0);
glRotatef(OBSERWATOR_OBROT_Y, 0, 1, 0);
// Generacja obrazu szescianu
RysujSzescian(wysokosc, promien, poziom, pion);
// Przelaczenie buforow ramki
glutSwapBuffers();
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja obslugi klawiatury
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
switch(klawisz)
{
case '+':
poziom=(poziom >=16) ? 16 : poziom+1;
break;
case '-':
poziom=(poziom <=3) ? 3 : poziom-1;
break;
case 'a':
pion=(pion <=3) ? 3 : pion-1;
break;
case 's':
pion=(pion >=16) ? 16 : pion+1;
break;
}
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_RGBA|GLUT_DEPTH);
// Ustawienie polozenia dolenego lewego rogu okna
glutInitWindowPosition(100, 100);
// Ustawienie rozmiarow okna
glutInitWindowSize(szerokoscOkna, wysokoscOkna);
// Utworzenie okna
glutCreateWindow("Szescan");
// Odblokowanie bufora glebokosci
glEnable(GL_DEPTH_TEST);
// Ustawienie funkcji wykonywanej na danych w buforze glebokosci
glDepthFunc(GL_LEQUAL);
// Ustawienie wartosci czyszczacej zawartosc bufora glebokosci
glClearDepth(1000.0);
// Ustawienie koloru czyszczenia bufora ramki
glClearColor (0.8f, 0.8f, 0.8f, 0.0f);
// Zarejestrowanie funkcji (callback) wyswietlajacej
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;
}