Wojskowa Akademia Techniczna
Grafika Komputerowa
Sprawozdanie z pracy laboratoryjnej nr 3
Prowadzący: mgr inż. Mariusz Pazur
Data wykonania ćwiczenia: 14.01.2008r.
Wykonał: Karol Zalewski - I6Y3S1
1.Treść zadania
Zadanie 2
Wykorzystując biblioteki OpenGL i GLUT napisać program przedstawiający perspektywiczny obraz obiektu przedstawionego na rysunku. Powierzchnie obiektu pokryte są dwoma materiałami o następujących właściwościach:
Materiał nr 1: niebieski matowy (widziany w białym świetle),
Materiał nr 2: szary błyszczący (widziany w białym świetle),
Obiekt należy oświetlić dwoma źródłami światła o następujących parametrach:
Źródło nr 1:
typ: reflektor (ang. spot),
kolor: biały,
natężenie: 1,
kąt odcięcia: 30o,
położenie: zmienne po orbicie kołowej o środku w punkcie S(0,0,0) z możliwością interaktywnej zmiany następujących parametrów:
promienia orbity,
kąta nachylenia orbity do osi OX,
kąta nachylenia orbity do osi OZ,
kierunek świecenia: na obiekt.
Źródło nr 2:
typ: kierunkowe,
kolor: żółty,
natężenie: 0.7,
kierunek świecenia zadany wektorem V(10,10, 10) w układu współrzędnych obserwatora.
Program powinien umożliwiać interaktywne, niezależne włączanie i wyłączanie źródeł światła. Należy również zapewnić użytkownikowi możliwość zmiany położenia obserwatora poprzez podanie następujących parametrów:
odległości obserwatora od środka układu współrzędnych sceny,
wysokości względem płaszczyzny XZ,
kąta obrotu wokół osi OY w zakresie [0o, 360o] z krokiem 1o.
Oświetlony obiekt powinien zawsze znajdować się w centralnej części okna.
2.Metoda rozwiązania zadania
2.1 Rysowanie walca
Rozwiązywanie zadania zacząłem od utworzenia funkcji rysującej walec. Funkcja ta jednocześnie wyznaczała wektory normalne powierzchni walca, oraz „dzieliła” w szachownice umożliwiając jednocześnie przypisanie każdemu prostokątowi różnego materiału.
2.2 Pierwsze źródło światła (typu reflektor)
Światło typu reflektor charakteryzuje się kątem odcięcia mniejszym niż 180 stopni, oraz kierunkiem świecenia „źródło->obiekt”. Źródle temu przypisałem następujące wartości:
{1.0, 1.0, 1.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
{5.0, 0.0, 0.0, 1.0}, // [3] położenie
{-1.0, 0.0, 0.0, 0.0}, // [4] kierunek świecenia
{0.0, 0.0, 0.0, 0.0}, // [5] tłumienie kątowe światła
{ 30.0, 0.0, 0.0, 0.0}, // [6] kąt odcięcia światła
{2.0, 2.0, 2.0, 0.0}, // [7] stale tłumienie
{0.0, 0.0, 0.0, 0.0}, // [8] tłumienie liniowe
{0.0, 0.0, 0.0, 0.0}}; // [9] tłumienie kwadratowe
Drugie źródło światła (typu kierunkowe):
Światło kierunkowe charakteryzuje się równoległym rozchodzeniem promieni.
Źródle temu przypisałem następujące wartości:
{1.0, 1.0, 0.0, 1.0}, // [0] otoczenie
{1.0, 1.0, 0.0, 1.0}, // [1] rozproszenie
{1.0, 1.0, 0.0, 1.0}, // [2] lustrzane
{10.0, 10.0, 10.0, 0.0},// [3] położenie
{-1.0, -1.0, -1.0, 0.0},// [4] kierunek świecenia
{0.0, 0.0, 0.0, 0.0}, // [5] tłumienie kątowe światła
{180.0, 0.0, 0.0, 0.0}, // [6] kąt odcięcia światła
{0.0, 0.0, 0.0, 0.0}, // [7] stale tłumienie
{0.0, 0.0, 0.0, 0.0}, // [8] tłumienie liniowe
{0.0, 0.0, 0.0, 0.0}}; // [9] tłumienie kwadratowe
Materiał nr 1 (niebieski matowy):
Materiałowi pierwszemu przypisałem następujące wartości:
{ 0.0, 0.0, 1.0, 1.0}, // [0] współczynnik odbicia światła otoczenia
{0.0, 0.0, 1.0, 1.0}, // [1] współczynnik odbicia światła rozproszonego
{0.0, 0.0, 0.0, 1.0}, // [2] współczynnik odbicia światła lustrzanego
{0.0, 0.0, 0.0, 0.0}, // [3] połysk
{0.0, 0.0, 0.0, 1.0}}; // [4] kolor światła emitowanego
2.5 Materiał nr 2 (szary błyszczący):
Materiałowi drugiemu przypisałem następujące wartości:
{0.8, 0.8, 0.8, 1.0}, // [0] współczynnik odbicia światła otoczenia
{0.0, 0.0, 0.0, 1.0}, // [1] współczynnik odbicia światła rozproszonego
{0.8, 0.8, 0.8, 1.0}, // [2] współczynnik odbicia światła lustrzanego
{10.0, 0.0, 0.0, 0.0}, // [3] połysk
{0.0, 0.0, 0.0, 1.0}}; // [4] kolor światła emitowanego
2.6 Włącznie i wyłączenie źródeł światła:
W celu włączania i wyłączania źródeł światła zaprojektowałem funkcje
void WlaczOswietlenie(void) . Oto jej definicja:
// Wlaczenie oswietlenia sceny
void WlaczOswietlenie(void)
{
// Odblokowanie oswietlenia
glEnable(GL_LIGHTING);
// Odblokowanie zrodla swiatla nr 1
if (zrodlo1 == 1){
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, swiatlo1[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo1[1]);
glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo1[2]);
glLightfv(GL_LIGHT0, GL_POSITION, swiatlo1[3]);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, swiatlo1[4]);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, swiatlo1[5][0]);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, swiatlo1[6][0]);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, swiatlo1[7][0]);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, swiatlo1[8][0]);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, swiatlo1[9][0]);
//ustawienie czarnej kulki symbolizujacej pozycje reflektora
//kulka nie jest oswietlana
glPushAttrib(GL_LIGHTING_BIT);
glPushMatrix();
glDisable(GL_LIGHTING);
glTranslatef(swiatlo1[3][0],swiatlo1[3][1],swiatlo1[3][2]);
glColor3f(0.0,0.0,0.0);
glutSolidSphere(0.4,20,20);
glPopMatrix();
glPopAttrib();
}
else
//wylaczenie zrodla swiatla nr 1
glDisable(GL_LIGHT0);
// Odblokowanie zrodla swiatla nr 2
if (zrodlo2 == 1 ) {
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_AMBIENT, swiatlo2[0]);
glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo2[1]);
glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo2[2]);
glLightfv(GL_LIGHT1, GL_POSITION, swiatlo2[3]);
// glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, swiatlo2[4]);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, swiatlo2[5][0]);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, swiatlo2[6][0]);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, swiatlo2[7][0]);
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, swiatlo2[8][0]);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, swiatlo2[9][0]);
}
else
//wylaczenie zrodla swiatla nr 2
glDisable(GL_LIGHT1);
}
3.Wyniki
Oba źródła światła wyłączone:
Włączone pierwsze źródło światła:
Włączone drugie źródło światła:
Oba źródła światła włączone:
4.Kod źródłowy:
#include "stdafx.h"
#include <math.h>
#include <GL/glut.h>
#include <string.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 LPOZ_MENU_SWIATLA 10
#define LPOZ_MENU_MATERIALU 5
#define M_PI 3.14159265
// Makro przeliczajace stopnie na radiany
#define DEG2RAD(x) ((float)(x)*M_PI/180.0)
#define POT(x) (x*x)
// Zmienne globalne
double rotObsX,rotObsY; // 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
double odleglosc = 20; //odleglosc obserwatora
int szerokoscOkna = 800;
int wysokoscOkna = 600;
int zrodlo1 = 1; //zrodlo nr 1 wlaczone
int zrodlo2 = 1; //zrodlo nr 2 wlaczone
float rswiatla = 5.0; //odleglosc reflektora od obiektu
float katXZ = 0.0; //katy polozenia
float katXY = 0.0; //reflektora
// Tablice parametrow swiatla
GLfloat swiatlo1[10][4];
GLfloat swiatlo2[10][4];
// Tablice parametrow materialu z jakiego wykonany jest stozek
GLfloat material1[5][4];
GLfloat material2[5][4];
// Prototypy funkcji
void UstawDomyslneWartosciParametrow(void);
void WlaczOswietlenie(void);
void DefiniujMaterial1(void);
void DefiniujMaterial2(void);
void RysujStozek(double h, double r, int nv, int nh);
void UstawParametryWidoku(int szer, int wys);
void WyswietlObraz(void);
void ObslugaKlawiatury(unsigned char klawisz, int x, int y);
void ObslugaKlawiszySpecjalnych(int klawisz, int x, int y);
///////////////////////////////////////////////////////////////////////////////
// Funkcja ustawiajaca domyslne parametry walca, materialu i zrodla swiatla
void UstawDomyslneWartosciParametrow(void)
{
// Tablica parametrow materialu nr 1
GLfloat param_materialu1[5][4] = {
{ 0.0, 0.0, 1.0, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{0.0, 0.0, 1.0, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{0.0, 0.0, 0.0, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{0.0, 0.0, 0.0, 0.0}, // [3] polysk
{0.0, 0.0, 0.0, 1.0}}; // [4] kolor swiatla emitowanego
// Tablica parametrow materialu nr 2
GLfloat param_materialu2[5][4] = {
{0.8, 0.8, 0.8, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{0.0, 0.0, 0.0, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{0.8, 0.8, 0.8, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{10.0, 0.0, 0.0, 0.0}, // [3] polysk
{0.0, 0.0, 0.0, 1.0}}; // [4] kolor swiatla emitowanego
// Tablica parametrow zrodla swiatla nr 1
GLfloat param_swiatla1[10][4] = {
{1.0, 1.0, 1.0, 1.0}, // [0] otoczeniea
{1.0, 1.0, 1.0, 1.0}, // [1] rozproszenie
{1.0, 1.0, 1.0, 1.0}, // [2] lustrzane
{5.0, 0.0, 0.0, 1.0}, // [3] polozenie
{-1.0, 0.0, 0.0, 0.0}, // [4] kierunek swiecenia
{0.0, 0.0, 0.0, 0.0}, // [5] tlumienie katowe swiatla
{ 30.0, 0.0, 0.0, 0.0}, // [6] kat odciecia swiatla
{2.0, 2.0, 2.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 zrodla swiatla nr 2
GLfloat param_swiatla2[10][4] = {
{1.0, 1.0, 0.0, 1.0}, // [0] otoczenie
{1.0, 1.0, 0.0, 1.0}, // [1] rozproszenie
{1.0, 1.0, 0.0, 1.0}, // [2] lustrzane
{10.0, 10.0, 10.0, 0.0},// [3] polozenie
{-1.0, -1.0, -1.0, 0.0},// [4] kierunek swiecenia
{0.0, 0.0, 0.0, 0.0}, // [5] tlumienie katowe swiatla
{180.0, 0.0, 0.0, 0.0}, // [6] kat odciecia swiatla
{0.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
// Skopiowanie zawartosci tablic param_* do tablic globalnych
memcpy(material1, param_materialu1, LPOZ_MENU_MATERIALU*4*sizeof(GLfloat));
memcpy(swiatlo1, param_swiatla1, LPOZ_MENU_SWIATLA*4*sizeof(GLfloat));
memcpy(material2, param_materialu2, LPOZ_MENU_MATERIALU*4*sizeof(GLfloat));
memcpy(swiatlo2, param_swiatla2, LPOZ_MENU_SWIATLA*4*sizeof(GLfloat));
// Parametry stozka
lPionowych = 8; // Liczba podzialow pionowych
lPoziomych = 8; // Liczba podzialow poziomych
promien = 2.0; // Promien stozka
wysokosc = 4.0; // Wysokosc stozka
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// Wlaczenie oswietlenia sceny
void WlaczOswietlenie(void)
{
// Odblokowanie oswietlenia
glEnable(GL_LIGHTING);
// Odblokowanie zrodla swiatla nr 1
if (zrodlo1 == 1){
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, swiatlo1[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo1[1]);
glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo1[2]);
glLightfv(GL_LIGHT0, GL_POSITION, swiatlo1[3]);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, swiatlo1[4]);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, swiatlo1[5][0]);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, swiatlo1[6][0]);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, swiatlo1[7][0]);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, swiatlo1[8][0]);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, swiatlo1[9][0]);
//ustawienie czarnej kulki symbolizujacej pozycje reflektora
//kulka nie jest oswietlana
glPushAttrib(GL_LIGHTING_BIT);
glPushMatrix();
glDisable(GL_LIGHTING);
glTranslatef(swiatlo1[3][0],swiatlo1[3][1],swiatlo1[3][2]);
glColor3f(0.0,0.0,0.0);
glutSolidSphere(0.4,20,20);
glPopMatrix();
glPopAttrib();
}
else
//wylaczenie zrodla swiatla nr 1
glDisable(GL_LIGHT0);
// Odblokowanie zrodla swiatla nr 2
if (zrodlo2 == 1 ) {
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_AMBIENT, swiatlo2[0]);
glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo2[1]);
glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo2[2]);
glLightfv(GL_LIGHT1, GL_POSITION, swiatlo2[3]);
// glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, swiatlo2[4]);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, swiatlo2[5][0]);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, swiatlo2[6][0]);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, swiatlo2[7][0]);
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, swiatlo2[8][0]);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, swiatlo2[9][0]);
}
else
//wylaczenie zrodla swiatla nr 2
glDisable(GL_LIGHT1);
}
///////////////////////////////////////////////////////////////////////////////
//Zdefiniowanie wlasciwosci materialu stozka na podstawie
//parametrow zapisanych w tablicy 'material'
void DefiniujMaterial1(void)
{
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material1[0]);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material1[1]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material1[2]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material1[3]);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material1[4]);
}
void DefiniujMaterial2(void)
{
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material2[0]);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material2[1]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material2[2]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material2[3]);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material2[4]);
}
////////////////////////////////////////////////////////////////////////////////
//Funkcja rysujaca stozek o zadanej wysokosci, promieniu oraz liczbie podzialow
//pionowych i poziomych. Tryb modelowania powierzchni bocznej - GL_QUADS,
//podstawy - GL_TRIANGLE_FAN.
void RysujStozek(double h, double r, int ilPoz, int ilPion)
{
double dH, dAlfa;
int i, j;
// int szach = 0;
GLfloat wektorA[3];
GLfloat wektorB[3];
GLfloat wektorN[3];
GLfloat dlugoscN;
// Wyznaczenie kata wyznaczajacego pojedynczy wycinek pionowy
dAlfa = 360.0L/ilPoz;
// Wyznaczenie wysokosci pojedynczego wycinka poziomego
dH = h/ilPion;
//Wzynaczenie wierzcholkow i wektorow normalnych dla powierzchni bocznej
glBegin(GL_QUADS);
for (i = 0; i < ilPion; i++) {
for (j = 0; j <= ilPoz; j++) {
if ((i % 2) == 0) {
DefiniujMaterial1();
// szach = 1;
}
else {
DefiniujMaterial2();
// szach = 0;
}
//Obliczanie normalnych do powierzchni bocznej
//WektorA lezacy na plaszczyznie
wektorA[0] = r*cos(DEG2RAD(j*dAlfa)) -
r*cos(DEG2RAD(j*dAlfa));
wektorA[1] = (i+1)*dH - i*dH;
wektorA[2] = r*sin(DEG2RAD(j*dAlfa)) -
r*sin(DEG2RAD(j*dAlfa));
//WektorB lezacy na plaszczyznie
wektorB[0] = r*cos(DEG2RAD((j+1)*dAlfa)) -
r*cos(DEG2RAD(j*dAlfa));
wektorB[1] = (i+1)*dH - i*dH;
wektorB[2] = r*sin(DEG2RAD((j+1)*dAlfa)) -
r*sin(DEG2RAD(j*dAlfa));
//WektorN = WektorA x WektorB (iloczyn wektorowy)
wektorN[0] = wektorA[1]*wektorB[2] - wektorB[1]*wektorA[2];
wektorN[1] = wektorB[0]*wektorA[2] - wektorA[0]*wektorB[2];
wektorN[2] = wektorA[0]*wektorB[1] - wektorB[0]*wektorA[1];
//Normalizacja wektora normalnego do powierzchni
dlugoscN = sqrt(POT(wektorN[0])+POT(wektorN[1])+POT(wektorN[2]));
wektorN[0] = wektorN[0]/dlugoscN;
wektorN[1] = wektorN[1]/dlugoscN;
wektorN[2] = wektorN[2]/dlugoscN;
glNormal3fv(wektorN);
/*glNormal3f(((double)(ilPion - i)/(double)ilPion)*cos(DEG2RAD(j*dAlfa)),
i*dH,
((double)(ilPion - i)/(double)ilPion)*sin(DEG2RAD(j*dAlfa)));*/
glVertex3f(r*cos(DEG2RAD(j*dAlfa)),
i*dH,
r*sin(DEG2RAD(j*dAlfa)));
//glNormal3f(((double)(ilPion - (i+1))/(double)ilPion)*cos(DEG2RAD(j*dAlfa)),
// (i+1)*dH,
// ((double)(ilPion - (i+1))/(double)ilPion)*sin(DEG2RAD(j*dAlfa)));
glVertex3f(r*cos(DEG2RAD(j*dAlfa)),
(i+1)*dH,
r*sin(DEG2RAD(j*dAlfa)));
//glNormal3f(((double)(ilPion - (i+1))/(double)ilPion)*cos(DEG2RAD((j+1)*dAlfa)),
// (i+1)*dH,
// ((double)(ilPion - (i+1))/(double)ilPion)*sin(DEG2RAD((j+1)*dAlfa)));
glVertex3f(r*cos(DEG2RAD((j+1)*dAlfa)),
(i+1)*dH,
r*sin(DEG2RAD((j+1)*dAlfa)));
//glNormal3f(((double)(ilPion - i)/(double)ilPion)*cos(DEG2RAD((j+1)*dAlfa)),
// i*dH,
// ((double)(ilPion - i)/(double)ilPion)*sin(DEG2RAD((j+1)*dAlfa)));
glVertex3f(r*cos(DEG2RAD((j+1)*dAlfa)),
i*dH,
r*sin(DEG2RAD((j+1)*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 <= ilPoz ; i++)
glVertex3f(r*cos(DEG2RAD(i*dAlfa)), 0.0, r*sin(DEG2RAD(i*dAlfa)));
glEnd();
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(0.0, wysokosc, 0.0);
for (i = 0; i <= ilPoz ; i++)
glVertex3f(r*cos(DEG2RAD(i*dAlfa)), wysokosc, r*sin(DEG2RAD(i*dAlfa)));
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).
glTranslatef(0, 0, -odleglosc);
glRotatef(rotObsX, 1, 0, 0);
glRotatef(rotObsY, 0, 1, 0);
WlaczOswietlenie();
// Generacja obrazu stozka
RysujStozek(wysokosc, promien, lPoziomych, lPionowych);
// Przelaczenie buforow ramki
glutSwapBuffers();
}
//////////////////////////////////////////////////////////////////////////////////////////
// Funkcja obslugi klawiatury
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
switch(klawisz)
{
case '1':
zrodlo1 = (zrodlo1 == 1) ? 0 : 1;
break;
case '2':
zrodlo2 = (zrodlo2 == 1) ? 0 : 1;
break;
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 't':
wysokosc = (wysokosc == WYS_MAX) ? WYS_MAX : wysokosc + 1;
break;
case 'g':
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 'o':
odleglosc = (odleglosc < 60) ? odleglosc + 1 : 60;
break;
case 'O':
odleglosc = (odleglosc > 5) ? odleglosc - 1 : 5;
break;
case 'w':
katXZ = (katXZ == 355) ? 0 : katXZ + 5;
swiatlo1[3][0] = rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[3][1] = rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[3][2] = rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
swiatlo1[4][0] = -rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[4][1] = -rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[4][2] = -rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
break;
case 's':
katXZ = (katXZ == 0) ? 355 : katXZ - 5;
swiatlo1[3][0] = rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[3][1] = rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[3][2] = rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
swiatlo1[4][0] = -rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[4][1] = -rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[4][2] = -rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
break;
case 'd':
katXY = (katXY == 0) ? 355 : katXY - 5;
swiatlo1[3][0] = rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[3][1] = rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[3][2] = rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
swiatlo1[4][0] = -rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[4][1] = -rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[4][2] = -rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
break;
case 'a':
katXY = (katXY == 355) ? 0 : katXY + 5;
swiatlo1[3][0] = rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[3][1] = rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[3][2] = rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
swiatlo1[4][0] = -rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[4][1] = -rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[4][2] = -rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
break;
case 'q':
rswiatla = (rswiatla == 2) ? 2 : rswiatla - 1;
swiatlo1[3][0] = rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[3][1] = rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[3][2] = rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
swiatlo1[4][0] = -rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[4][1] = -rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[4][2] = -rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
break;
case 'e':
rswiatla = (rswiatla == 20) ? 20 : rswiatla + 1;
swiatlo1[3][0] = rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[3][1] = rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[3][2] = rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
swiatlo1[4][0] = -rswiatla*cos(DEG2RAD(katXZ))*cos(DEG2RAD(katXY));
swiatlo1[4][1] = -rswiatla*sin(DEG2RAD(katXZ));
swiatlo1[4][2] = -rswiatla*cos(DEG2RAD(katXZ))*sin(DEG2RAD(katXY));
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:
rotObsX = (rotObsX < 90.0) ? rotObsX + 1.0 : rotObsX;
break;
case GLUT_KEY_DOWN:
rotObsX = (rotObsX > -90.0) ? rotObsX - 1.0 : rotObsX;
break;
case GLUT_KEY_RIGHT:
rotObsY = (rotObsY == 0) ? 359 : rotObsY - 1;
break;
case GLUT_KEY_LEFT:
rotObsY = (rotObsY == 359) ? 0 : rotObsY + 1;
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("Oswietlony stozek");
// 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 (1.0f, 1.0f, 1.0f, 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);
// 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;}