lab4 Paweł Madejski I7X1, Studia, WAT Informatyka, s3 - GK - grafika komputerowa, LAB4


WOJSKOWA AKADEMIA TECHNICZNA

Sprawozdanie laboratoryjne z przedmiotu

GRAFIKA KOMPUTEROWA

Wykonujący ćwiczenie: Paweł Madejski

Prowadzący: dr inż. Marek Salamon

Data wykonania: 15.12.2008r

Grupa szkoleniowa: I7X1S1

MODELOWANIE OŚWIETLENIA

Zadanie 4.

Wykorzystując biblioteki OpenGL i GLUT napisać program przedstawiający perspektywiczny obraz obiektu o następujacych parametrach:

  1. Typ obiektu: walec o zmiennej parzystej liczbie podziałów pionowych i poziomych,

  2. Właściwości materiału nr 1: zielony matowy (widziany w białym świetle),

  3. Właściwości materiału nr 2: fioletowy błyszczący (widziany w białym świetle),

  4. Sposób przyporządkowania materiałów do obiektu zgodnie ze wzorem: pasy poziome z uwzględnieniem podziałów poziomych.

Obiekt należy oświetlić dwoma źródłami światła o następujących parametrach:

Źródło nr1:

Źródło nr 2:

Program powinien umożliwiać:

a) interaktywne, niezależne włączanie i wyłączanie źródeł światła;

b) interaktywną zmianę liczby podziałów pionowych i poziomych bryły;

c) interaktywną zmianę wielkości bryły;

d)interaktywną zmianę położenia obserwatora poprzez podanie następujących parametrów:

Oświetlony obiekt powinien zawsze znajdować się w centralnej części okna

Realizacja zadania laboratoryjnego

Funkcje ustawiające właściwości materiałów.

GLfloat material_fioletowy[4][4]=

{

{1,0,1,1},

{1,0,1,1},

{1,1,1,1},

{0,0,0,0}

};

GLfloat material_zielony[4][4]=

{

{0,1,0,1},

{0,0.5,0,1},

{0,1,0,1},

{128,0,0,0}

};

void Material_fioletowy()

{

glMaterialfv(GL_FRONT, GL_AMBIENT, material_fioletowy[0]);

glMaterialfv(GL_FRONT, GL_DIFFUSE, material_fioletowy[1]);

glMaterialfv(GL_FRONT, GL_SPECULAR, material_fioletowy[2]);

glMaterialf(GL_FRONT, GL_SHININESS, material_fioletowy[3][0]);

}

void Material_zielony()

{

glMaterialfv(GL_FRONT, GL_AMBIENT, material_zielony[0]);

glMaterialfv(GL_FRONT, GL_DIFFUSE, material_zielony[1]);

glMaterialfv(GL_FRONT, GL_SPECULAR, material_zielony[2]);

glMaterialf(GL_FRONT, GL_SHININESS, material_zielony[3][0]);

}

Obie te funkcje wykorzystuja zadeklarowane wczesniej tablice dwuwymiarowe jako argumenty wykorzystywane we wnetrzu. Kolejne wartosci ustawiane przez funkcje glMaterialfv() mają nastepujace znaczenia:

Tablice opisu materialu określaja jego parametru za pomocą wektora RGBA (reed green blue alfa) z czego każda składowa mieści sie w przedziale <0;1>. Wyjatkiem w tym przypadku jest atrybut GL_SHININESS, który ma jeden parametr z przedziału <0; 27>.

Funkcje ustawiające właściwości światła.

GLfloat swiatlo_reflektor[5][4]=

{

{1,1,1,1},

{1,1,1,1},

{1,1,1,1},

{0,0,0,1},

{-1,0,0}

};

GLfloat swiatlo_glowne[5][4]=

{

{1,1,0,0.7},

{1,1,0,0.7},

{1,1,0,0.7},

{-10,10,10},

{0,0,0}

};

void Swiatlo_reflektor(){

glPushMatrix();

glEnable(GL_LIGHTING);

glRotatef(kat,0,1,0);

glRotatef(kat_z,0,0,1);

glTranslatef(R_L1,0,0);

glPushMatrix();

float vektor[1][4] = {{0.5,0,0.1,0}};

glTranslatef(0,3,0);

glMaterialfv(GL_FRONT, GL_AMBIENT, vektor[0]);

glutSolidSphere(0.5,10,10);

glPopMatrix();

glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo_reflektor[1]);

glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo_reflektor[2]);

glLightfv(GL_LIGHT0, GL_POSITION, swiatlo_reflektor[3]);

glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, 30.0);

glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION,swiatlo_reflektor[4]);

glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 1);

glPopMatrix();

}

void Swiatlo_glowne(){

glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo_glowne[1]);

glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo_glowne[2]);

glLightfv(GL_LIGHT1, GL_POSITION, swiatlo_glowne[3]);

glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION,swiatlo_glowne[4]);

}

Przedstawione funkcje określają i uruchamiają dwa rodzaje światła: kierunkowe włączane przez Swiatlo_glowne(); reflektora włączane przez funkcje Swiatlo_reflektor(). Bazują one podobnie jak funkcje opisujące materiał na macierzach o składowych wektorów RGBA. Obydwie funkcje są wywołane po narysowaniu obiektu (w funkcji RysujWalec();). Bardziej złożona w tym przypadku jest funkcja Swiatlo_reflektor() i to jest jeden z powodów dlaczego omówię przykład modelowania światła właśnie na jej podstawie. Drugim aspektem jest to iż funkcja Swiatlo_glowne() nie wnosi praktycznie żadnych nowych teoretycznych wiadomości do jej poprzedniczki.

Procedura zaczyna i kończy się od odłożenia na stosie macierzy i kończy się jej zdjęciem. Takie postępowanie jest uzasadnione tym iż w jej wnętrzu jest rysowana sfera która służy jako graficzne zobrazowanie miejsca źródła światła. Źródło to jest obracane wokół osi OY na podstawie zmiennej kąt (jest ona albo automatycznie inkrementowana/dekrementowana w funkcji WyswietlObraz(); bądź zmieniana o ustalony skok z klawiatury), nachylane do osi OZ pod kątem określonym przez zmienną kat_z (ustalaną przez operatora z klawiatury) oraz jest oddalane lub przybliżane do obiektu na podstawie zmiennej R_L1 ustalanej z klawiatury. Następnie jest rysowana zapowiedziana przeze mnie wcześniej sfera wraz z paroma „kosmetycznymi” detalami. Właściwa część zaczyna się dopiero w tym miejscu. Funkcja glLightfv(); ustawia parametry światła posługując się parametrami:

Światło jest włączane za pomocą funkcji glEnable(); natomiast wyłączane za pomocą glDisable();. Parametrami tych funkcji są numery źródeł świateł natomiast aby światło działało po wywołaniu takiej konstrukcji należy uprzednio odblokować oświetlenie za pomocą glEnable(GL_LIGHTING); Włączać jak i wyłączać oświetlenie możemy obsługiwać zadeklarowanymi wcześniej klawiszami.

Funkcja rysująca obiekt (walec w paski poziome o naprzemiennie zmiennych materiałach).

void RysujWalec(double h, double r, int nv, int nh)

{

double dH, dAlfa;

int i, j;

// Wyznaczenie kata wyznaczajacego pojedynczy wycinek pionowy

dAlfa = 360.0L/(double)nh;

// Wyznaczenie wysokosci pojedynczego wycinka poziomego

dH = h/(double)nv;

glPushMatrix();

glRotatef(180,0,1,0);

// Wyznaczanie wierzcholkow i wektorow normalnych powierzchni bocznych

for (i = 0; floor((i+1)*dH*1.0E10) <= floor(h*1.0E10); i++)

{

glBegin(GL_TRIANGLE_STRIP);

glNormal3f(0.0, 0.0, 1.0);

glVertex3f(0.0, (i + 1)*dH, r);

glVertex3f(0.0, i*dH, r);

if (i%2 == 0) Material_fioletowy();

else Material_zielony();

for (j = 1; j*dAlfa <= 360.0L + dAlfa; j++){

glNormal3f(sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));

glVertex3f(r*sin(DEG2RAD(j*dAlfa)), (i + 1)*dH, r*cos(DEG2RAD(j*dAlfa)));

glVertex3f(r*sin(DEG2RAD(j*dAlfa)), i*dH, r*cos(DEG2RAD(j*dAlfa)));

}

glEnd();

}

// 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();

// Wyznaczenie wierzcholkow i wektorow normalnych gornej podstawy

glBegin(GL_TRIANGLE_FAN);

glNormal3f(0.0, 1.0, 0.0);

glVertex3f(0.0, h, 0.0);

for (i = 0; i * dAlfa <= 360.0L + dAlfa; i++)

glVertex3f(r*sin(DEG2RAD(i*dAlfa)), h, r*cos(DEG2RAD(i*dAlfa)));

glEnd();

glPopMatrix();

Swiatlo_reflektor();

Swiatlo_glowne();

}

Ponieważ rysowanie za pomocą prymitywów było już omawiane przy okazji drugiego zadania laboratoryjnego nie będę omawiał sposobu utworzenia walca z możliwością interaktywnej zmiany podziałów pionowych i poziomych oraz promienia i wysokośći. Jedyną ciekawostką jest wykorzystanie w pierwszej pętli (odpowiadającej za konstrukcję pionowych podziałów) wyrażenia warunkowego od którego zależy wywołanie materiału według jakiego dany pasek będzie narysowany. if (i%2 == 0) Material_fioletowy();

else Material_zielony();

W tej funkcji kluczową rolę odgrywa konstrukcja glNormal3f(); wyznaczająca wektor normalny do powierzchni w naszym przypadku trójkąta opisującego połówkę szachownicy. Dla uściślenia wektor normalny jest to wektor prostopadły do powierzchni dla jakiej jest wyznaczany. Pomaga on określać położenie, orientację w przestrzeni dzięki czemu można określić kąty odbicia i padania światła.

Po wyznaczeniu wektorów dla każdej składowej walca należy wywołać funkcje oświetlenia.

Kolejne funkcje (poza RysujNakladke();) nie wnoszą nic nowego do tematu od poprzednich zajęć bądź są tylko dodatkiem do zadania o charakterze informującym (znów mamy do czynienia z RysujNakladke();). Nie będę ich więc omawiał. Ich prototypy oraz konstrukcje można zobaczyć w załączonym dalej kodzie źródłowym całego programu.

Wynik pracy.

0x08 graphic
Rys1. Ogólny widok zawartości okna programu zaraz po uruchomieniu bądź zresetowaniu ustawień (wartości domyślne).

0x08 graphic
0x08 graphic

Rys2. Walec z oświetleniem kierunkowym. Rys3. Walec z oświetleniem z reflektora.

0x08 graphic
Rys4. Walec ze zwiększoną liczbą podziałów poziomych i pionowych oświetlony obydwoma rodzajami światła.

Opis obsługi klawiatury:

Wnioski:

Podczas ćwiczenia zadaniem było zamodelowanie figury o zadanym w treści stylu, materiale i oświetleniu. Celem było zaprzyjaźnienie się z bardzo ważną według mnie rolą światła oraz oświetlenia w programowaniu obiektów graficznych. Umiejętne posługiwanie się oświetleniem pozwala ożywić i stworzyć scenę bliższą rzeczywistemu odpowiednikowi danego obiektu. Wykorzystanie wielu świateł pozwala wzmocnić to złudzenie gdyż. Weźmy na przykład człowieka idącego po ulicy w słoneczne popołudnie, jego otoczenie i jego cień. Widać że potrzebne są co najmniej dwa rodzaje świateł do zamodelowania podobnego przykładu. Jedno ze źródeł jest to światło kierunkowe oświetlające całą scenę (słońce) natomiast drugie to człowiek który oświetla jakiś teren podłoża po którym się przemieszcza światłem typu reflektor (odpowiednik lampki zaimplementowanej w naszym przykładzie). Jeśli elementy sceny będą miały dobrze dobrane materiały oraz zostanie dobrze zaimplementowane światło wtedy wszystko razem będzie ładnie wyglądało.

Zadanie jakie mieliśmy wykonać podczas laboratorium było według mnie nastawione na przyswojenie podstawowej wiedzy o oświetleniu i materiałach. Miało ono też służyć jako przykład mieszania się różnych materiałów z różnym światłem.

Sądzę, iż zadanie wykonane zostało poprawnie i zgodnie z założeniami postawionymi w treści.

Kod źródłowy programu:

#include <math.h>

#include <string.h>

#include <stdio.h>

#include <GL/glut.h>

// Definicja stalych

#define LPOZ_MAX 100

#define LPOZ_MIN 4

#define LPION_MAX 100

#define LPION_MIN 4

#define R_MAX 10.0

#define WYS_MAX 5.0

#define KROK_FLOAT 0.1

#define X_OFFSET_SWIATLO 10

#define Y_OFFSET_SWIATLO 120

#define X_OFFSET_MAT 10

#define Y_OFFSET_MAT 220

#define X_OFFSET_OBIEKT 10

#define Y_OFFSET_OBIEKT 300

#define ID_MENU_SWIATLA 0

#define ID_MENU_MATERIALU 1

#define LPOZ_MENU_SWIATLA 10

#define LPOZ_MENU_MATERIALU 5

#define M_PI 3.14159

// Makro przeliczajace stopnie na radiany

#define DEG2RAD(x) ((float)(x)*M_PI/180.0)

// Zmienne globalne

double kat = 0.0; // Kat obrotu obserwatora wokol osi OY [stopnie]

int lPionowych; // Liczba podzialow pionowych

int lPoziomych; // Liczba podzialow poziomych

double promien; // Promien walca

double wysokosc; // Wysokosc walca

int sIndeks; // Wybrana pozycja w tablicy parametrow swiatla

int mIndeks; // Wybrana pozycja w tablicy parametrow materialu

int menu; // Identyfikator wybranego menu (menu swiatla lub menu materialu)

int szerokoscOkna = 800;

int wysokoscOkna = 600;

int poziom = 30;

int pion = 30;

float kat_x = 0, kat_z = 0, R_L1 = 10;

GLfloat OBSERWATOR_ODLEGLOSC=4;

GLfloat OBSERWATOR_OBROT_Y=0;

int lampka=0;

int gswiatlo=0;

// Tablica parametrow swiatla

GLfloat swiatlo_reflektor[5][4]=

{

{1,1,1,1},

{1,1,1,1},

{1,1,1,1},

{0,0,0,1},

{-1,0,0}

};

GLfloat swiatlo_glowne[5][4]=

{

{1,1,0,0.7},

{1,1,0,0.7},

{1,1,0,0.7},

{-10,10,10},

{0,0,0}

};

// Tablica parametrow materialu z jakiego wykonany jest walec

GLfloat material_fioletowy[4][4]=

{

{1,0,1,1},

{1,0,1,1},

{1,1,1,1},

{0,0,0,0}

};

GLfloat material_zielony[4][4]=

{

{0,1,0,1},

{0,0.5,0,1},

{0,1,0,1},

{128,0,0,0}

};

// Prototypy funkcji

void UstawDomyslneWartosciParametrow(void);

void RysujTekstRastrowy(void *font, char *tekst);

void RysujWalec(double h, double r, int nv, int nh);

void UstawParametryWidoku(int szer, int wys);

void RysujNakladke(void);

void WyswietlObraz(void);

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

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

void Material_fioletowy();

void Material_zielony();

void Swiatlo_reflektor();

void Swiatlo_glowne();

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

// Funkcja ustawiajaca domyslne parametry walca, materialu i zrodla swiatla

void UstawDomyslneWartosciParametrow(void)

{

lPionowych = 8; // Liczba podzialow pionowych

lPoziomych = 4; // Liczba podzialow poziomych

promien = 4.0; // Promien walca

wysokosc = 6.0; // Wysokosc walca

glDisable(GL_LIGHT0); // wylaczenie swiatla z lampki

glDisable(GL_LIGHT1); // wylaczenie swiatla otoczenia

kat_x = 0; // predkosc katowa lamki wzgledem osi OY

kat_z = 0; // kat nachylenia lampki do osi OX

kat = 0; // polozenie lampki wzgledem osi OY

R_L1 = 10; // promien orbity

OBSERWATOR_ODLEGLOSC=4; // odleglosc obserwatora od walca

OBSERWATOR_OBROT_Y=0; // kat obrotu wokol oso OY

lampka=0; // ustawienie wypisywaniastanu lampki na ekran

gswiatlo=0; // ustawienie wypisywania stanu swiatla glownego na ekran

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

}

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

// 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]);

}

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

// Zdefiniowanie walasciwosci materialu walca na podstawie zapisanych w tablcy 'material'

// parametrow (material obowiazuje tylko do scian skierowanych przodem do obserwatora)

void Material_fioletowy()

{

glMaterialfv(GL_FRONT, GL_AMBIENT, material_fioletowy[0]);

glMaterialfv(GL_FRONT, GL_DIFFUSE, material_fioletowy[1]);

glMaterialfv(GL_FRONT, GL_SPECULAR, material_fioletowy[2]);

glMaterialf(GL_FRONT, GL_SHININESS, material_fioletowy[3][0]);

}

void Material_zielony()

{

glMaterialfv(GL_FRONT, GL_AMBIENT, material_zielony[0]);

glMaterialfv(GL_FRONT, GL_DIFFUSE, material_zielony[1]);

glMaterialfv(GL_FRONT, GL_SPECULAR, material_zielony[2]);

glMaterialf(GL_FRONT, GL_SHININESS, material_zielony[3][0]);

}

void Swiatlo_reflektor(){

glPushMatrix();

glEnable(GL_LIGHTING);

glRotatef(kat,0,1,0);

glRotatef(kat_z,0,0,1);

glTranslatef(R_L1,0,0);

glPushMatrix();

float vektor[1][4] = {{0.5,0,0.1,0}};

glTranslatef(0,3,0);

glMaterialfv(GL_FRONT, GL_AMBIENT, vektor[0]);

glutSolidSphere(0.5,10,10);

glPopMatrix();

glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo_reflektor[1]);

glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo_reflektor[2]);

glLightfv(GL_LIGHT0, GL_POSITION, swiatlo_reflektor[3]);

glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, 30.0);

glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION,swiatlo_reflektor[4]);

glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 1);

glPopMatrix();

}

void Swiatlo_glowne(){

glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo_glowne[1]);

glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo_glowne[2]);

glLightfv(GL_LIGHT1, GL_POSITION, swiatlo_glowne[3]);

glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION,swiatlo_glowne[4]);

}

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

// Funkcja rysujaca walec o zadanej wysokosci, promieniu oraz liczbie podzialow

// pionowych i poziomych. Tryb modelowania powierzchni bocznej - GL_TRIANGLE_STRIP,

// podstaw - GL_TRIANGLE_FAN.

void RysujWalec(double h, double r, int nv, int nh)

{

double dH, dAlfa;

int i, j;

// Wyznaczenie kata wyznaczajacego pojedynczy wycinek pionowy

dAlfa = 360.0L/(double)nh;

// Wyznaczenie wysokosci pojedynczego wycinka poziomego

dH = h/(double)nv;

glPushMatrix();

glRotatef(180,0,1,0);

// Wyznaczanie wierzcholkow i wektorow normalnych powierzchni bocznych

for (i = 0; floor((i+1)*dH*1.0E10) <= floor(h*1.0E10); i++)

{

glBegin(GL_TRIANGLE_STRIP);

glNormal3f(0.0, 0.0, 1.0);

glVertex3f(0.0, (i + 1)*dH, r);

glVertex3f(0.0, i*dH, r);

if (i%2 == 0) Material_fioletowy();

else Material_zielony();

for (j = 1; j*dAlfa <= 360.0L + dAlfa; j++){

glNormal3f(sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));

glVertex3f(r*sin(DEG2RAD(j*dAlfa)), (i + 1)*dH, r*cos(DEG2RAD(j*dAlfa)));

glVertex3f(r*sin(DEG2RAD(j*dAlfa)), i*dH, r*cos(DEG2RAD(j*dAlfa)));

}

glEnd();

}

// 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();

// Wyznaczenie wierzcholkow i wektorow normalnych gornej podstawy

glBegin(GL_TRIANGLE_FAN);

glNormal3f(0.0, 1.0, 0.0);

glVertex3f(0.0, h, 0.0);

for (i = 0; i * dAlfa <= 360.0L + dAlfa; i++)

glVertex3f(r*sin(DEG2RAD(i*dAlfa)), h, r*cos(DEG2RAD(i*dAlfa)));

glEnd();

glPopMatrix();

Swiatlo_reflektor();

Swiatlo_glowne();

}

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

// 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 rysujaca na wygenerowanym obrazie walca nkladke z tekstem opisujacym

// aktualne parametry zrodla swiatla i materialu.

void RysujNakladke(void)

{

char buf[255];

// 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);

// RYSOWANIE MENU PARAMETROW ZRODLA SWIATLA reflektora

sprintf(buf, "Lampka");

glRasterPos2i(X_OFFSET_SWIATLO, Y_OFFSET_SWIATLO);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - katowa predkosc (%.1f) x,X", kat_x);

glRasterPos2i(X_OFFSET_SWIATLO, Y_OFFSET_SWIATLO - 10);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - promien orbity (%.1f) z,Z", R_L1);

glRasterPos2i(X_OFFSET_SWIATLO, Y_OFFSET_SWIATLO - 20);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - kat nachylenia do osOX (%.1f) up,down", kat_z);

glRasterPos2i(X_OFFSET_SWIATLO, Y_OFFSET_SWIATLO - 30);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - wlaczona lampka (%s)", (lampka == 1)? "tak":"nie");

glRasterPos2i(X_OFFSET_SWIATLO, Y_OFFSET_SWIATLO - 40);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

// RYSOWANIE MENU PARAMETROW polozenia

glColor3f(1.0, 1.0, 1.0);

sprintf(buf, "polozenie");

glRasterPos2i(X_OFFSET_MAT, Y_OFFSET_MAT);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - swiatlo (%s)", (gswiatlo == 1)? "tak": "nie");

glRasterPos2i(X_OFFSET_MAT, Y_OFFSET_MAT - 10);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - odleglosc od obserwatora (%.1f)", OBSERWATOR_ODLEGLOSC);

glRasterPos2i(X_OFFSET_MAT, Y_OFFSET_MAT - 20);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - obrot wokol OY (%.1f)", OBSERWATOR_OBROT_Y);

glRasterPos2i(X_OFFSET_MAT, Y_OFFSET_MAT - 30);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

// RYSOWANIE MENU PARAMETROW WALCA

glColor3f(1.0, 1.0, 1.0);

sprintf(buf, "Walec:");

glRasterPos2i(X_OFFSET_OBIEKT, Y_OFFSET_OBIEKT);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - promien (%.1f)", promien);

glRasterPos2i(X_OFFSET_OBIEKT, Y_OFFSET_OBIEKT - 10);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - wysokosc (%.1f)", wysokosc);

glRasterPos2i(X_OFFSET_OBIEKT, Y_OFFSET_OBIEKT - 20);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - podzialow pionowych (%d)", lPionowych);

glRasterPos2i(X_OFFSET_OBIEKT, Y_OFFSET_OBIEKT - 30);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

sprintf(buf, " - podzialow poziomych (%d)", lPoziomych);

glRasterPos2i(X_OFFSET_OBIEKT, Y_OFFSET_OBIEKT - 40);

RysujTekstRastrowy(GLUT_BITMAP_8_BY_13, buf);

// Przywrocenie macierzy sprzed wywolania funkcji

glMatrixMode(GL_PROJECTION);

glPopMatrix();

glMatrixMode(GL_MODELVIEW);

glPopMatrix();

// Odblokowanie oswietlenia

glEnable(GL_LIGHTING);

}

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

// 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);

// Ustawienie oswietlenia sceny (polozenie zrodla swiatla wyznaczane jest w ukladzie

// wspolrzednych obserwatora)

//WlaczOswietlenie();

// 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.

glTranslatef(0, -5-wysokosc/6+2, -20);

glTranslatef(0, 0 , -OBSERWATOR_ODLEGLOSC);

glRotatef(OBSERWATOR_OBROT_Y, 0, 1, 0);

// Generacja obrazu walca

RysujWalec(wysokosc, promien, lPoziomych, lPionowych);

// Narysowanie tekstow z opisem parametrow oswietlenia i materialu

RysujNakladke();

// Przelaczenie buforow ramki

glutSwapBuffers();

// Modyfikacja kata obrotu

kat += kat_x;

}

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

// Funkcja obslugi klawiatury

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

{

switch(klawisz)

{

case 'v':

lPionowych = (lPionowych == LPION_MAX)? LPION_MAX : lPionowych + 2;

break;

case 'V':

lPionowych = (lPionowych == LPION_MIN)? LPION_MIN : lPionowych - 2;

break;

case 'h':

lPoziomych = (lPoziomych == LPOZ_MAX)? LPOZ_MAX : lPoziomych + 2;

break;

case 'H':

lPoziomych = (lPoziomych == LPOZ_MIN)? LPOZ_MIN : lPoziomych - 2;

break;

case 'w':

wysokosc = (wysokosc == WYS_MAX) ? WYS_MAX : wysokosc + 1;

break;

case 'W':

wysokosc = (wysokosc == 1) ? wysokosc : wysokosc - 1;

break;

case 'p':

promien = (promien == R_MAX) ? R_MAX : promien + 1;

break;

case 'P':

promien = (promien == 1) ? promien : promien - 1;

break;

case 'r':

UstawDomyslneWartosciParametrow();

break;

case 'q' : glEnable(GL_LIGHT0);

lampka = 1;

break;

case 'Q' : glDisable(GL_LIGHT0);

lampka = 0;

break;

case 'a' : glEnable(GL_LIGHT1);

gswiatlo = 1;

break;

case 'A' : glDisable(GL_LIGHT1);

gswiatlo = 0;

break;

case 'z' : R_L1 += 0.1;break;

case 'Z' : R_L1 -= 0.1;break;

case 'x' : kat_x = (kat_x == 3) ? 3 : kat_x+1;

break;

case 'X' : kat_x = (kat_x == -3) ? 3 : kat_x-1;

break;

case 'c' : kat_z++;break;

case 'C' : kat_z--;break;

case '+' : OBSERWATOR_ODLEGLOSC++;break;

case '-' : OBSERWATOR_ODLEGLOSC--;break;

case '.' : OBSERWATOR_OBROT_Y = (OBSERWATOR_OBROT_Y == 360) ? 0 : OBSERWATOR_OBROT_Y + 1;break;

case ',' : OBSERWATOR_OBROT_Y = (OBSERWATOR_OBROT_Y == 0) ? 360 : OBSERWATOR_OBROT_Y - 1;break;

// Wcisniecie klawisza ESC powoduje wyjscie z programu

case 27:

exit(0);

}

}

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

// Funkcja klawiszy specjalnych

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

{

switch(klawisz)

{

case GLUT_KEY_UP:

kat_z++;break;

case GLUT_KEY_DOWN:

kat_z--;break;

case GLUT_KEY_LEFT:

kat++;break;

case GLUT_KEY_RIGHT:

kat--;break;

}

}

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

// 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("i7x1s1 Madejski ***Lab 4");

// 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.3, 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);

// Zarejestrowanie funkcji obslugi klawiszy specjalnych

glutSpecialFunc(ObslugaKlawiszySpecjalnych);

// Ustawienie domyslnych wartosci parametrow

UstawDomyslneWartosciParametrow();

// Obsluga glownej petli programu (wywolywanie zarejestrowanych callbackow

// w odpowiedzi na odbierane zdarzenia lub obsluga stanu bezczynnosci)

glutMainLoop();

return 0;

}



Wyszukiwarka