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-06-10
Ocena sprawozdania: .............................................
Numer i treść zadania
Realizacja zadania laboratoryjnego
Funkcja wypełniająca tablice tekstury pasów
void UtworzWzorzecTekstury(GLubyte c1R, GLubyte c1G, GLubyte c1B, GLubyte c1A,
GLubyte c2R, GLubyte c2G, GLubyte c2B, GLubyte c2A)
{
int wysokoscPola = TEX_WYSOKOSC/texLWierszy;
int szerokoscPola= TEX_SZEROKOSC/texLKolumn;
int t, s;
for (t = 0; t < TEX_WYSOKOSC; t++)
for (s = 0; s < TEX_SZEROKOSC; s++)
// Pole ma kolor c1 jesli znajduje sie w parzystej kolumnie i parzystym
// wierszu lub w nieparzystej kolumnie i nieparzystym wierszu
if ((t/wysokoscPola)%2)
{
tekstura[t][s][0] = c1R;
tekstura[t][s][1] = c1G;
tekstura[t][s][2] = c1B;
tekstura[t][s][3] = c1A;
}
else
{
tekstura[t][s][0] = c2R;
tekstura[t][s][1] = c2G;
tekstura[t][s][2] = c2B;
tekstura[t][s][3] = c2A;
}
}
Parametrami wejściowymi funkcji są kolory określone za pomocą składowych RGBA. Następnie obliczana jest wysokość pojedynczego pasa. W pętli wypełniana jest tablica tekstur pasów GLubyte tekstura[TEX_WYSOKOSC][TEX_SZEROKOSC][4]. Pas ma kolor c1 jeżeli znajduje się w parzystym wierszu i kolor c2 gdy znajduje się w wierszu nieparzystym. Wartość liczby pasów będącą potęgą liczby 2 uzyskałem, odpowiednio mnożąc i dzieląc zmienną texLWierszy (wartość zmieniana za pomocą klawiatury).
Funkcja tworząca teksturę
void UtworzTeksture(GLint modMiesz, GLfloat trybTeksturowania, GLfloat trybfiltrowania)
{
// Zdefiniowanie dwuwymiarowej tekstury
glTexImage2D(GL_TEXTURE_2D, 0, modMiesz, TEX_SZEROKOSC, TEX_WYSOKOSC,
0, GL_RGBA, GL_UNSIGNED_BYTE, (GLubyte *) &tekstura[0][0][0]);
// Okreslenie podstawowych parametrow tekstury - tekstura nie bedzie powtarzana w obu kierunkach
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// - przy powiekszaniu i pomniejszaniu tekstury zastosowane zostanie filtrowanie liniowe
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, trybfiltrowania);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, trybfiltrowania);
// Okreslenie trybu teksturowania zgodnie z wartoscia argumentu <trybTeksturowania>
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, trybTeksturowania);
// Odblokowanieteksturowania
glEnable(GL_TEXTURE_2D);
}
Funkcja przyjmuje trzy parametry wejściowe:
modMiesz - oznacza które składowe koloru,
trybTeksturowania - określa w jaki sposób wyznaczony jest kolor wynikowy obiektu (GL_DECAL - finalnym kolorem piksela na ekranie będzie kolor teksela przyporządkowany danemu fragmentowi, GL_MODULATE - kolor piksela będzie wyliczony z uwzględnieniem oświetlenia, GL_BLEND - barwa piksela może zostać zmieniona przez zmieszanie z jakimś stałym kolorem),
trybfiltrowania - możemy ustalić sposób filtrowania mapy przy powiększaniu i zmniejszaniu wielokąta (GL_LINEAR - zwraca średnią ważoną czterech tekseli, będących najbliżej środka teksturowanego piksela - tzw. filtrowanie dwuliniowe (Bilinear Filtering), GL_NEAREST - zwraca wartość tekstury będącej najbliżej środka mapowanego piksela)
glTexImage2D jest podstawową funkcją służącą do specyfikacji tekstury. Pierwszy parametr to zazwyczaj stała GL_TEXTURE_2D, następny to zero, jeśli nie włączamy mipmappingu lub liczba map pośrednich dalej określamy liczbę komponentów opisujących jeden teksel. Następne parametry to odpowiednio długość i szerokość tekstury oraz grubość otaczającej ramki (zwykle 0). Kolejny argument to odpowiednia stała wyznaczająca format tekstury. Najpopularniejsze z nich to GL_RGBA i GL_RGB. Przedostatni parametr określa typ danych komponentów opisujących teksel. Ostatni argument jest wskaźnikiem do tablicy w pamięci zawierającej obraz tekstury. Dzięki funkcji glTexParameterf możemy ustalić sposób filtrowania mapy przy powiększaniu i zmniejszaniu wielokąta oraz ustalić granice tekstury.
glTexEnvf ta funkcja pozwala wybrać tryb teksturowania (jeden z wyżej wymienionych).
Zmiana położenia źródła światła
Źródło światła ma być ruchome, dlatego w oparciu o wiedzę zdobytą na poprzednich ćwiczeniach laboratoryjnych jego położenie oraz kierunek świecenia zdefiniowane są przy pomocy funkcji trygonometrycznych wewnątrz funkcji void WlaczOswietlenie(void):
katYRef=(katYRef+1)%360;
swiatlo[3][0]=rRef*sin(DEG2RAD(katYRef));
swiatlo[3][1]=3;
swiatlo[3][2]=rRef*cos(DEG2RAD(katYRef));
swiatlo[4][0]=-rRef*sin(DEG2RAD(katYRef));
swiatlo[4][1]=-3;
swiatlo[4][2]=-rRef*cos(DEG2RAD(katYRef));
Ponieważ źródło ma być reflektorowe to w tablicy parametrów światła w wierszu pobieranym jako pozycja źródła na czwartej pozycji pojawia się wartość 1.0. Również kolor światła oraz określenie składowej światła odbłysków zdefiniowane jest w tablicy parametrów światła (odpowiednio drugi i trzeci wiersz). Następnie wszystkie parametry z tablicy są inicjalizowane za pomocą funkcji glLightf() wywoływanej z odpowiednimi argumentami.
Funkcja rysująca stożek
void RysujSfere(double r, double h, int nv, int nh)
{
double dH, dAlfa, dR;
float i, j;
int zmienna=1;
// Wyznaczenie kata wyznaczajacego pojedynczy wycinek pionowy
dAlfa = 360.0L/(double)nh;
// Wyznaczenie wysokosci poje$ynczego wycinka poziomego
dH = h/(double)nv;
dR = r/nv;
// Wyznaczenie wierzcholkow i wektorow normalnych dolnej podstawy
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0, -1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
for (i = 0; i * dAlfa <= 360.0L + dAlfa; i++)
glVertex3f(r*sin(DEG2RAD(i*dAlfa)), 0.0, r*cos(DEG2RAD(i*dAlfa)));
glEnd();
// Wyznaczanie wierzcholkow i wektorow normalnych powierzchni bocznych
glBegin(GL_QUADS);
//dR=0;
for (i = 0; i<= h; i+=dH)
{
for (j = 0; j < 360.0L; j+=dAlfa)
{
glTexCoord2f((j+dAlfa)/360.0, (i+dH)/h);
glNormal3f( sin(DEG2RAD((j+dAlfa))), 0.0, cos(DEG2RAD((j+dAlfa))));
glVertex3f((r-dR)*sin(DEG2RAD((j+dAlfa))), i+dH, (r-dR)*cos(DEG2RAD((j+dAlfa))));
glTexCoord2f((j+dAlfa)/360.0, i/h);
glNormal3f( sin(DEG2RAD((j+dAlfa))), 0.0, cos(DEG2RAD((j+dAlfa))));
glVertex3f(r*sin(DEG2RAD((j+dAlfa))), i, r*cos(DEG2RAD((j+dAlfa))));
glTexCoord2f(j/360.0, i/h);
glNormal3f( sin(DEG2RAD(j)), 0.0, cos(DEG2RAD(j)));
glVertex3f(r*sin(DEG2RAD(j)), i, r*cos(DEG2RAD(j)));
glTexCoord2f(j/360.0, (i+dH)/h);
glNormal3f( sin(DEG2RAD(j)), 0.0, cos(DEG2RAD(j)));
glVertex3f((r-dR)*sin(DEG2RAD(j)), i+dH, (r-dR)*cos(DEG2RAD(j)));
}
r-=dR;
}
glEnd();
}
Funkcja przyjmuje cztery parametry: r - promień stożka, h - wysokość stożka, nv - liczba podziałów pionowych, nh - liczba podziałów poziomych. Następnie, przy pomocy technik poznanych na pierwszych ćwiczeniach laboratoryjnych, rysuje stożek w trybie graficznym GL_QUADS.
W wewnętrznej pętli została użyta dodatkowo funkcja glTexCoord2f() przed każdym z wierzchołków. Funkcja ta działa tak jak glVertex2f(), tyle że zamiast przekazywać współrzędne wierzchołka przekazuje współrzędne tekstury dla wierzchołka, który zostanie przesłany za chwilę poprzez glVertex3f().
Interaktywna zmiana położenia obserwatora
Aby umożliwić interaktywną zmianę położenia obserwatora dokonałem modyfikacji wewnątrz procedury void WyswietlObraz(void). W funkcji glTranslatef(0, 0, -rObs), która określa położenie obserwatora, współrzędna „z” została określona za pomocą zmiennej rObs. Zaś funkcja glRotatef(katYObs, 0, 1, 0), gdzie kąt obrotu został zadeklarowany jako zmienna, umożliwia obrót obserwatora wokół obiektu.
Wyniki
Po dodaniu w funkcji void ObslugaKlawiatury(unsigned char klawisz, int x, int y) obsługi dodatkowych klawiszy, które zmieniają wartości różnych wyżej wymienionych zmiennych otrzymałem następujące efekty:
Tryb GL_NEAREST i GL_MODULATE
Tryb GL_LINEAR i GL MODULATE
Tryb GL_LINEAR i GL_DECAL
Tryb GL_LINEAR i GL_BLEND
Kod całego programu
//////////////////////////////////////////////////////////////////////////////////////////
// Program demonstrujacy odwzorowanie dwuwymiarowej tekstury kraty na sfere.
// Autor: Wojciech Satala
//
//////////////////////////////////////////////////////////////////////////////////////////
#include <math.h>
#include <GL/glut.h>
#include <stdio.h>
#include <string.h>
// Definicja stalych
// Parametry kuli
#define KULA_R 4
#define KULA_LPODZ_H 30
#define KULA_LPODZ_V 30
// Parametry tekstury kratownicy
#define TEX_SZEROKOSC 128 // szerokosc tekstury (musi byc potega 2)
#define TEX_WYSOKOSC 128 // dlugosc tekstury (musi byc potega 2)
#define TEX_LKOLUMN 4 // liczba kolumn kratownicy
#define TEX_LWIERSZY 4 // liczba wierszy kratownicy
#define M_PI 3.14159
// Makro przeliczajace stopnie na radiany
#define DEG2RAD(x) ((float)(x)*M_PI/180.0)
// Zmienne globalne
// Tablica zawierajaca teksture kraty zapisana w trybie RGBA
GLubyte tekstura[TEX_WYSOKOSC][TEX_SZEROKOSC][4];
// Tablica parametrow swiatla
GLfloat swiatlo[10][4] = {
{0.0, 0.0, 0.0, 1.0}, // [0] otoczenie
{1.0, 1.0, 1.0, 1.0}, // [1] rozproszenie
{1.0, 1.0, 1.0, 1.0}, // [2] lustrzane
{0.0, 0.0, 0.0, 1.0}, // [3] polozenie
{0.0, 0.0, -1.0, 1.0}, // [4] kierunek swiecenia
{2.0, 0.0, 0.0, 0.0}, // [5] tlumienie katowe swiatla
{1000.0, 0.0, 0.0, 0.0},// [6] kat odciecia swiatla
{1.0, 0.0, 0.0, 0.0}, // [7] stale tlumienie
{0.0, 0.0, 0.0, 0.0}, // [8] tlumienie liniowe
{0.0, 0.0, 0.0, 0.0}}; // [9] tlumienie kwadratowe
// Tablica parametrow materialu
GLfloat material[6][4] = {
{0.2, 0.2, 0.2, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{0.8, 0.8, 0.8, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{1.0, 1.0, 1.0, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{20.0, 0.0, 0.0, 0.0}, // [3] polysk
{0.0, 0.0, 0.0, 1.0}}; // [4] kolor swiatla emitowanego
// Pozostale zmienne
int szerokoscOkna = 800;
int wysokoscOkna = 600;
float kat = 0.0;
int licznik = 0;
int texTryb = 0;
int trybfiltr = 0;
int texLKolumn = 1;//TEX_LKOLUMN;
int texLWierszy = 1;//TEX_LWIERSZY;
int krokObrotu =2;
int rObs =20;
int katXObs =20;
int katYObs =0;
double rRef =100;
int katYRef =0;
int s=0;
// Naglowki funkcji
void WlaczOswietlenie(void);
void DefiniujMaterial(void);
void UtworzWzorzecTekstury(GLubyte c1R, GLubyte c1G, GLubyte c1B, GLubyte c1A,
GLubyte c2R, GLubyte c2G, GLubyte c2B, GLubyte c2A);
void UtworzTeksture(GLint modMiesz, GLfloat trybTeksturowania, GLfloat trybfiltrowania);
void RysujSfere(double, double, int, int);
void UstawParametryWidoku(int szer, int wys);
void WyswietlObraz(void);
void ObslugaKlawiatury(unsigned char klawisz, int x, int y);
void RysujNakladke(void);
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja wypelniajaca tablice tekstury kraty, ktorej kolory podane zostaly jako
// argumenty wejsciowe.
void UtworzWzorzecTekstury(GLubyte c1R, GLubyte c1G, GLubyte c1B, GLubyte c1A,
GLubyte c2R, GLubyte c2G, GLubyte c2B, GLubyte c2A)
{
int wysokoscPola = TEX_WYSOKOSC/texLWierszy;
int szerokoscPola= TEX_SZEROKOSC/texLKolumn;
int t, s;
for (t = 0; t < TEX_WYSOKOSC; t++)
for (s = 0; s < TEX_SZEROKOSC; s++)
// Pole ma kolor c1 jesli znajduje sie w parzystej kolumnie i parzystym
// wierszu lub w nieparzystej kolumnie i nieparzystym wierszu
if ((t/wysokoscPola)%2)
{
tekstura[t][s][0] = c1R;
tekstura[t][s][1] = c1G;
tekstura[t][s][2] = c1B;
tekstura[t][s][3] = c1A;
}
else
{
tekstura[t][s][0] = c2R;
tekstura[t][s][1] = c2G;
tekstura[t][s][2] = c2B;
tekstura[t][s][3] = c2A;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja tworzaca teksture na podstawie wzorca umieszczonego w tablicy 'tekstura'.
// Argument <modMiesz> oznacza, ktore skladowe koloru wykorzystywane sa w procesie
// modulacji/mieszania kolorow. Argument <trybTeksturowania> okresla w jaki sposob
// wyznaczany jest kolor wynikowy obiektu. Dozwolone wartosci: GL_DECAL, GL_MODULATE,
// GL_BLEND.
void UtworzTeksture(GLint modMiesz, GLfloat trybTeksturowania, GLfloat trybfiltrowania)
{
// Okreslenie wyrownania bytow w czasie odczytywania tekstury z pamieci
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Zdefiniowanie dwuwymiarowej tekstury
glTexImage2D(GL_TEXTURE_2D, 0, modMiesz, TEX_SZEROKOSC, TEX_WYSOKOSC,
0, GL_RGBA, GL_UNSIGNED_BYTE, (GLubyte *) &tekstura[0][0][0]);
// Okreslenie podstawowych parametrow tekstury
// - tekstura nie bedzie powtarzana w obu kierunkach
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// - przy powiekszaniu i pomniejszaniu tekstury zastosowane zostanie filtrowanie liniowe
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, trybfiltrowania);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, trybfiltrowania);
// Okreslenie trybu teksturowania zgodnie z wartoscia argumentu <trybTeksturowania>
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, trybTeksturowania);
// Odblokowanieteksturowania
glEnable(GL_TEXTURE_2D);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja rysujaca tekst rastrowy <tekst> za pomca fontow bitmapowych <font>.Rysowanie
// tekstu wykonywane jest poczawszy od biezacej pozycji ekranu.
void RysujTekstRastrowy(void *font, char *tekst)
{
int i;
for (i = 0; i < (int)strlen(tekst); i++)
glutBitmapCharacter(font, tekst[i]);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Wlaczenie oswietlenia sceny
void WlaczOswietlenie(void)
{
katYRef=(katYRef+1)%360;
swiatlo[3][0]=rRef*sin(DEG2RAD(katYRef));
swiatlo[3][1]=3;
swiatlo[3][2]=rRef*cos(DEG2RAD(katYRef));
swiatlo[4][0]=-rRef*sin(DEG2RAD(katYRef));
swiatlo[4][1]=-3;
swiatlo[4][2]=-rRef*cos(DEG2RAD(katYRef));
// Odblokowanie oswietlenia
glEnable(GL_LIGHTING);
// Odblokowanie zerowego zrodla swiatla
glEnable(GL_LIGHT0);
// Inicjowanie zrodla swiatla
glLightfv(GL_LIGHT0, GL_AMBIENT, swiatlo[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo[1]);
glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo[2]);
glLightfv(GL_LIGHT0, GL_POSITION, swiatlo[3]);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, swiatlo[4]);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, swiatlo[5][0]);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, swiatlo[6][0]);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, swiatlo[7][0]);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, swiatlo[8][0]);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, swiatlo[9][0]);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Zdefiniowanie walasciwosci materialu walca na podstawie zapisanych w tablcy 'material'
// parametrow (material obowiazuje tylko do scian skierowanych przodem do obserwatora)
void DefiniujMaterial(void)
{
glMaterialfv(GL_FRONT, GL_AMBIENT, material[0]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, material[1]);
glMaterialfv(GL_FRONT, GL_SPECULAR, material[2]);
glMaterialfv(GL_FRONT, GL_SHININESS, material[3]);
glMaterialfv(GL_FRONT, GL_EMISSION, material[4]);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja rysujaca sfere o srodku w punkcie (0, 0, 0) i promieniu <R>. Powierzchnia
// sfery modelowana jest w trybie GL_TRIANGLE_STRIP z rownoczesnym wyznaczaniem
// wektorow normalnych i generowaniem wspolrzednych tekstury (odwzorowanie na sfere).
void RysujSfere(double r, double h, int nv, int nh)
{
double dH, dAlfa, dR;
float i, j;
int zmienna=1;
// Wyznaczenie kata wyznaczajacego pojedynczy wycinek pionowy
dAlfa = 360.0L/(double)nh;
// Wyznaczenie wysokosci poje$ynczego wycinka poziomego
dH = h/(double)nv;
dR = r/nv;
// Wyznaczenie wierzcholkow i wektorow normalnych dolnej podstawy
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0, -1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
for (i = 0; i * dAlfa <= 360.0L + dAlfa; i++)
glVertex3f(r*sin(DEG2RAD(i*dAlfa)), 0.0, r*cos(DEG2RAD(i*dAlfa)));
glEnd();
// Wyznaczanie wierzcholkow i wektorow normalnych powierzchni bocznych
glBegin(GL_QUADS);
//dR=0;
for (i = 0; i<= h; i+=dH)
{
for (j = 0; j < 360.0L; j+=dAlfa)
{
glTexCoord2f((j+dAlfa)/360.0, (i+dH)/h);
glNormal3f( sin(DEG2RAD((j+dAlfa))), 0.0, cos(DEG2RAD((j+dAlfa))));
glVertex3f((r-dR)*sin(DEG2RAD((j+dAlfa))), i+dH, (r-dR)*cos(DEG2RAD((j+dAlfa))));
glTexCoord2f((j+dAlfa)/360.0, i/h);
glNormal3f( sin(DEG2RAD((j+dAlfa))), 0.0, cos(DEG2RAD((j+dAlfa))));
glVertex3f(r*sin(DEG2RAD((j+dAlfa))), i, r*cos(DEG2RAD((j+dAlfa))));
glTexCoord2f(j/360.0, i/h);
glNormal3f( sin(DEG2RAD(j)), 0.0, cos(DEG2RAD(j)));
glVertex3f(r*sin(DEG2RAD(j)), i, r*cos(DEG2RAD(j)));
glTexCoord2f(j/360.0, (i+dH)/h);
glNormal3f( sin(DEG2RAD(j)), 0.0, cos(DEG2RAD(j)));
glVertex3f((r-dR)*sin(DEG2RAD(j)), i+dH, (r-dR)*cos(DEG2RAD(j)));
}
r-=dR;
}
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(40.0, (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();
}
//////////////////////////////////////////////////////////////////////////////////////////
// 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);
// Wyznaczenie polozenia obserwatora (przeksztalcenie uladu wspolrzednych
// sceny do ukladu wspolrzednych obserwatora). Obserwator obraca sie wokol punktu 0.0
// na osi OY. Promien obrotu = 20, pochylenie = 20 stopni,
// predkosc obrotu = 0.25 stopnia/ramke.
WlaczOswietlenie();
glTranslatef(0, 0, -rObs);
glRotatef(katXObs, 1, 0, 0);
glRotatef(katYObs, 0, 1, 0);
// Zdefiniowanie materialu walca
DefiniujMaterial();
// Utworzenie wzorca tekstury (czarno-biala krata)
UtworzWzorzecTekstury(255, 255, 255, 255, 0, 0, 255, 255);
// Utworzenie tekstury na podstawie zdefiniowanego wzorca (wlaczona modulacja
// pierwotnego koloru sfery wszystkimi skladowymi koloru tekstury)
UtworzTeksture(4, texTryb, trybfiltr);
// Generacja obrazu sfery
RysujSfere(KULA_R, 4, KULA_LPODZ_V, KULA_LPODZ_H);
// Narysowanie nakladki
RysujNakladke();
// Przelaczenie buforow ramki
glutSwapBuffers();
// Modyfikacja kata obrotu
kat += krokObrotu;
// Zwiekszenie licznika narysowanych klatek
licznik++;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja rysujaca na wygenerowanym obrazie sfery nkladke z tekstem
void RysujNakladke(void)
{
GLboolean stanOswietlenia = GL_FALSE;
// Zapamietanie stanu oswietlenia
if (glIsEnabled(GL_LIGHTING))
{
stanOswietlenia = GL_TRUE;
glDisable(GL_LIGHTING);
}
// Zmiana typu rzutu z perspektywicznego na ortogonalny
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, szerokoscOkna, 0.0, wysokoscOkna,-100.0, 100.0);
// Modelowanie sceny 2D (zawartosci nakladki)
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
// Zablokowanie oswietlenia (mialoby ono wplyw na kolor tekstu)
glDisable(GL_LIGHTING);
// Okreslenie koloru tekstu
glColor3f(1.0, 1.0, 1.0);
glRasterPos2i(10, 10);
RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, "Aktywne klawisz: wWkKldbm");
// Przywrocenie macierzy sprzed wywolania funkcji
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
// Odblokowanie oswietlenia
if(stanOswietlenia)
glEnable(GL_LIGHTING);
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja obslugi klawiatury
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
switch(klawisz)
{
case 'p':
rObs=(rObs<30) ? rObs+1: rObs;
break;
case 'P':
rObs=(rObs>5) ? rObs-1 : rObs;
break;
case 'o':
katXObs=(katXObs<90) ? katXObs+1: katXObs;
break;
case 'O':
katXObs=(katXObs>0) ? katXObs-1: katXObs;
break;
case 'i':
katYObs=(katYObs<360) ? katYObs+1: 0;
break;
case 'I':
katYObs=(katYObs>0) ? katYObs-1: 360;
break;
case 'f':
trybfiltr = GL_NEAREST;
break;
case 'F':
trybfiltr = GL_LINEAR;
break;
case 'd':
texTryb = GL_DECAL;
break;
case 'm':
texTryb = GL_MODULATE;
break;
case 'b':
texTryb = GL_BLEND;
break;
case 's':
s = !s;
break;
case 'l':
if (glIsEnabled(GL_LIGHTING)) glDisable(GL_LIGHTING);
else glEnable(GL_LIGHTING);
break;
case 'w':
//texLWierszy+=1;
texLWierszy=texLWierszy*2;
break;
case 'W':
texLWierszy = (texLWierszy == 1) ? 1 : texLWierszy/2;
break;
case 'k':
texLKolumn+=1;
break;
case 'K':
texLKolumn = (texLKolumn == 1) ? 1 : texLKolumn - 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("Teksturowana kula");
// 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);
// Odblokowanie wykonywania operacji na skladowych "alfa"
glEnable(GL_BLEND);
// Wybor funkcji mieszajacej kolory
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Ustawienie koloru czyszczenia bufora ramki
glClearColor (0.0, 0.3, 0.0, 0.0);
// 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);
// Ustawienie oswietlenia sceny (polozenie zrodla swiatla wyznaczane jest w ukladzie
// wspolrzednych obserwatora)
WlaczOswietlenie();
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Obsluga glownej petli programu (wywolywanie zarejestrowanych callbackow
// w odpowiedzi na odbierane zdarzenia lub obsluga stanu bezczynnosci)
glutMainLoop();
return 0;
}