POLITECHNIKA WROCŁAWSKA
Instytut Informatyki, Automatyki i Robotyki
Zakład Systemów Komputerowych
Wprowadzenie do grafiki komputerowej
Kurs: INEK00012L
Sprawozdanie z ćwiczenia nr 5
TEMAT ĆWICZENIA
Oświetlenie góry wygenerowanej za pomocą funkcji weierstrassa.
Wykonał: |
Gwidon Jóźwiak |
Termin: |
Np. CZ/P 8.00-11.00 |
Data wykonania ćwiczenia: |
27.01.2011r. |
Data oddania sprawozdania: |
|
Ocena: |
|
Uwagi prowadzącego:
|
//*********************************************************************
//
//
// OPIS: Program generujący górę przy pomocy funkcjij weierstrassa
// i oświetlający ją.
//
// AUTOR: Gwidon Jóźwiak, 171864
//
// DATA 27 Stycznia 2011 (Versja 1.00).
// MODYFIKACJI:
//
// PLATFORMA: System operacyjny: Microsoft Windows XP/7.
// Kompilator: Microsoft Visual C++ 2008.
//
// MATERIAŁY Nie wykorzystano.
// ŹRÓDŁOWE:
//
// UŻYTE BIBLIOTEKI OpenGL
// NIESTANDARDOWE
//
//*********************************************************************
/*************************************************************************************/
#include <windows.h>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <gl/gl.h>
#include <gl/glut.h>
#include <iostream>
using namespace std;
typedef float point3[3];
typedef float point2[2];
const int szczeg = 15; //stała określająca liczbę losowanych funkcji
static int doc = 25; //zmienna przechowująca dokładność szczegółów
point2 tab2D[100]; //tablica z funkcją w 2D
point3 tab[szczeg][100];//tablica przechowująca współrzędne wszystkich punktów w przestrzeni 3D
point3 tabn[szczeg][100];//tablica przechowująca wektory normalne dla punktów
float taba[szczeg]; //przechowje współczynniki a dla poszczególnych funkcji
int poziom = 90; //maksymalna granica losowania parametru a
int model = 0; //1-zwiększanie górnej granicy losowania parametru a, 2-zmniejszenie
int gen = 1; //jeżeli 1 to należy generować nowe współrzędne
point3 kolor[szczeg][100]; //tablica przechowująca kolory
//zmienne interakcji
static GLfloat pix2angleh;
static GLfloat pix2anglev;
static GLfloat viewer[] = {0.0, 0.0, 0.0};
static int x_stare = 0;
static int y_stare = 0;
static int z_stare = 0;
static GLfloat azymut = 0.0;
static GLfloat elewacja = 0.0;
static GLfloat d_azymut = 0.0;
static GLfloat d_elewacja = 0.0;
static GLfloat zoom = 0.0;
static GLfloat R = 30.0;
static int status = 0;
/*************************************************************************************/
//losowanie koloru
void losowanie_kolorow()
{
for( int i = 0 ; i<szczeg ; i++ )
{
for( int j = 0 ; j<100 ; j++ )
{
kolor[i][j][2] = kolor[i][j][1] = kolor[i][j][0] = rand()%2;
}
}
}
//funkcja zwracająca wartość (y) funkcji weierstrassa w punkcie x
float weierstrass(float a, float x)
{
float wynik = 0;
for( int k = 1 ; k<=20 ; k++ )
{
wynik += sin(3.14*pow(k,a)*x)/(3.14*pow(k,a));
}
if( wynik < 0 )
wynik *= (-1);
return wynik;
}
// funkcja generująca współrzędne 2D (wykres funkcji weierstrassa)
void generuj_tab2D( float a )
{
float x = 0;
float s = 1.0/doc;
float mn = 10;
for( int i = 0 ; i<doc-1 ; i++ )
{
tab2D[i][0] = x*mn;
tab2D[i][1] = mn*weierstrass(a,x);
x += s;
}
tab2D[doc-1][0] = x*mn;
tab2D[doc-1][1] = 0;
}
// funkcja obracająca wykres wokół OX (rzutowanie na 3D)
void generuj_3D()
{
float alfa = 0.0; // zmienna przechowująca aktualny kąt obrotu funkcji (w stopniach)
for( int j = 0 ; j<szczeg ; j++ ) // dla wszystkich funkcji
{
generuj_tab2D(taba[j]); //generujemy wykres funkcji dla podanego parametru a
for( int i = 0 ; i<doc ; i++ ) //każdą współrzędną 2D przeliczamy na współrzędną 3D
{
tab[j][i][0] = tab2D[i][0]-5;
tab[j][i][1] = tab2D[i][1] * sin(3.14*(alfa/180.0));
tab[j][i][2] = tab2D[i][1] * cos(3.14*(alfa/180.0));
}
alfa += 180.0/(szczeg-1); //zwiększamy kąt obrotu
}
}
void gen_vec()
{
point3 pom1, pom2, a,b,c,d;
float suma = 0;
for( int j = 1 ; j<szczeg-1 ; j++ )
{
for( int i = 1 ; i<doc-1 ; i++ )
{
//obliczamy wektor normalny plaszczyzny a
//współrzędne wektorów
pom1[0] = tab[j][i-1][0] - tab[j][i][0];
pom1[1] = tab[j][i-1][1] - tab[j][i][1];
pom1[2] = tab[j][i-1][2] - tab[j][i][2];
pom2[0] = tab[j+1][i][0] - tab[j][i][0];
pom2[1] = tab[j+1][i][1] - tab[j][i][1];
pom2[2] = tab[j+1][i][2] - tab[j][i][2];
//iloczyn wektorowy
a[0] = pom1[1] * pom2[2] - pom2[1] * pom1[2];
a[1] = pom2[0] * pom1[2] - pom1[0] * pom2[2];
a[2] = pom1[0] * pom2[1] - pom2[0] * pom1[1];
//normalizacja
for( int k = 0 ; k<3 ; k++ )
suma += pow(a[k],2);
suma = sqrt(suma);
for( int k = 0 ; k<3 ; k++ )
a[k] /= suma*(-1);
//obliczamy wektor normalny plaszczyzny b
//współrzędne wektorów
pom1[0] = tab[j+1][i][0] - tab[j][i][0];
pom1[1] = tab[j+1][i][1] - tab[j][i][1];
pom1[2] = tab[j+1][i][2] - tab[j][i][2];
pom2[0] = tab[j][i+1][0] - tab[j][i][0];
pom2[1] = tab[j][i+1][1] - tab[j][i][1];
pom2[2] = tab[j][i+1][2] - tab[j][i][2];
//iloczyn wektorowy
b[0] = pom1[1] * pom2[2] - pom2[1] * pom1[2];
b[1] = pom2[0] * pom1[2] - pom1[0] * pom2[2];
b[2] = pom1[0] * pom2[1] - pom2[0] * pom1[1];
//normalizacja
suma = 0;
for( int k = 0 ; k<3 ; k++ )
suma += pow(b[k],2);
suma = sqrt(suma);
for( int k = 0 ; k<3 ; k++ )
b[k] /= suma*(-1);
//obliczamy wektor normalny plaszczyzny c
//współrzędne wektorów
pom1[0] = tab[j-1][i][0] - tab[j][i][0];
pom1[1] = tab[j-1][i][1] - tab[j][i][1];
pom1[2] = tab[j-1][i][2] - tab[j][i][2];
pom2[0] = tab[j][i+1][0] - tab[j][i][0];
pom2[1] = tab[j][i+1][1] - tab[j][i][1];
pom2[2] = tab[j][i+1][2] - tab[j][i][2];
//iloczyn wektorowy
c[0] = pom1[1] * pom2[2] - pom2[1] * pom1[2];
c[1] = pom2[0] * pom1[2] - pom1[0] * pom2[2];
c[2] = pom1[0] * pom2[1] - pom2[0] * pom1[1];
//normalizacja
suma = 0;
for( int k = 0 ; k<3 ; k++ )
suma += pow(c[k],2);
suma = sqrt(suma);
for( int k = 0 ; k<3 ; k++ )
c[k] /= suma;
//obliczamy wektor normalny plaszczyzny d
//współrzędne wektorów
pom1[0] = tab[j][i-1][0] - tab[j][i][0];
pom1[1] = tab[j][i-1][1] - tab[j][i][1];
pom1[2] = tab[j][i-1][2] - tab[j][i][2];
pom2[0] = tab[j-1][i][0] - tab[j][i][0];
pom2[1] = tab[j-1][i][1] - tab[j][i][1];
pom2[2] = tab[j-1][i][2] - tab[j][i][2];
//iloczyn wektorowy
d[0] = pom1[1] * pom2[2] - pom2[1] * pom1[2];
d[1] = pom2[0] * pom1[2] - pom1[0] * pom2[2];
d[2] = pom1[0] * pom2[1] - pom2[0] * pom1[1];
//normalizacja
suma = 0;
for( int k = 0 ; k<3 ; k++ )
suma += pow(d[k],2);
suma = sqrt(suma);
for( int k = 0 ; k<3 ; k++ )
d[k] /= suma;
// uśrednianie wektorów płaszczyzny
for( int k = 0 ; k<3 ; k++ )
tabn[j][i][k] = (a[k]+b[k]+c[k]+d[k])/4.0;
}
}
}
void drawk()
{
if( gen )
{
for( int i = 0 ; i<szczeg ; i++ )
{
taba[i] = rand()%poziom;
taba[i] /= 10;
taba[i] += 1;
}
losowanie_kolorow();
gen = 0;
}
generuj_3D();
gen_vec();
for( int j = 0 ; j<szczeg-1 ; j++ )
{
for( int i = 0 ; i<doc-1 ; i++ )
{
// rysowanie wykresu o konkretnym koncie (kąt zależny od j)
glBegin(GL_POLYGON);
//glColor3fv(kolor[j][i]);
glNormal3fv(tabn[j][i]);
glVertex3fv(tab[j][i]);
//glColor3fv(kolor[j][i+1]);
glNormal3fv(tabn[j][i+1]);
glVertex3fv(tab[j][i+1]);
//glColor3fv(kolor[j+1][i+1]);
glNormal3fv(tabn[j+1][i+1]);
glVertex3fv(tab[j+1][i+1]);
//glColor3fv(kolor[j+1][i]);
glNormal3fv(tabn[j+1][i]);
glVertex3fv(tab[j+1][i]);
glEnd();
//jeżeli nie jest to ostatni wykres to łączymy kolejne punkty (x) sąsiedniego (o większym koncie) wykresu
}
}
}
GLfloat xs()
{
GLfloat pom = R*cos(azymut)*cos(elewacja);
return pom;
}
GLfloat ys()
{
GLfloat pom = R*sin(elewacja);
return pom;
}
GLfloat zs()
{
GLfloat pom = R*sin(azymut)*cos(elewacja);
return pom;
}
/*************************************************************************************/
// Funkcaja określająca, co ma być rysowane
// (zawsze wywoływana, gdy trzeba przerysować scenę)
void RenderScene(void)
{
srand(time(0));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Czyszczenie okna aktualnym kolorem czyszczącym
glLoadIdentity();
// Czyszczenie macierzy bieżącej
glColor3f(1.0f, 1.0f, 1.0f); // Ustawienie koloru rysowania na biały
if( status == 2 )
{
R += zoom;
if( R<7 )
R=7;
if( R>30 )
R=30;
if( zoom>0 )
doc -= 3;
else
doc += 3;
if( doc > 100 )
doc = 100;
if( doc < 25 )
doc = 25;
}
if( status == 1 )
{
azymut += d_azymut;
elewacja += d_elewacja;
if( azymut > 360 ) //zabezpieczenie by kąty nie wykraczały poza przedział (0;360)
azymut -= 360;
else if( azymut < 0 )
azymut += 360;
if( elewacja > 360 )
elewacja -= 360;
else if( elewacja < 0 )
elewacja += 360;
}
if( ys()>=0 ) //zabezpiecza przed oglądaniem góry od dołu
{
viewer[0] = xs();
viewer[1] = ys();
viewer[2] = zs();
}
gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 4.0, 0.0, 0.0, 1.0, 0.0);
if( model == 1 )
{
gen = 1;
if( poziom < 90 )
poziom += 10;
model = 0;
}
else if( model == 2 )
{
gen = 1;
if( poziom > 10 )
poziom -= 10;
model = 0;
}
drawk();
glFlush();
// Przekazanie poleceń rysujących do wykonania
glutSwapBuffers();
//
}
void keys(unsigned char key, int x, int y)
{
if(key == '+') model = 1;
if(key == '-') model = 2;
RenderScene(); // przerysowanie obrazu sceny
}
/*************************************************************************************/
// Funkcja "bada" stan myszy i ustawia wartości odpowiednich zmiennych globalnych
void Mouse(int btn, int state, int x, int y)
{
if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
x_stare = x;
y_stare = y;
status = 1; // wciśnięty został lewy klawisz myszy
}
else if( btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
{
z_stare = y;
status = 2; // wciśnięty został prawy klawisz myszy
}
else
status = 0; // nie został wciśnięty żaden klawisz
}
/*************************************************************************************/
// Funkcja "monitoruje" położenie kursora myszy i ustawia wartości odpowiednich
// zmiennych globalnych
void Motion( GLsizei x, GLsizei y )
{
d_azymut = (x-x_stare)*pix2anglev/5.0;
d_elewacja = (y-y_stare)*pix2angleh/5.0;
zoom = y-z_stare;
x_stare=x; // podstawienie bieżacego położenia jako poprzednie
y_stare=y;
z_stare=y;
glutPostRedisplay(); // przerysowanie obrazu sceny
}
/*************************************************************************************/
// Funkcja ustalająca stan renderowania
void MyInit(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Kolor czyszcący (wypełnienia okna) ustawiono na czarny
/*************************************************************************************/
// Definicja materiału z jakiego zrobiony jest czajnik
// i definicja źródła światła
/*************************************************************************************/
/*************************************************************************************/
// Definicja materiału z jakiego zrobiony jest czajnik
GLfloat mat_ambient[] = {1.0, 1.0, 1.0, 1.0};
// współczynniki ka =[kar,kag,kab] dla światła otoczenia
GLfloat mat_diffuse[] = {1.0, 1.0, 1.0, 1.0};
// współczynniki kd =[kdr,kdg,kdb] światła rozproszonego
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
// współczynniki ks =[ksr,ksg,ksb] dla światła odbitego
GLfloat mat_shininess = {20.0};
// współczynnik n opisujący połysk powierzchni
/*************************************************************************************/
// Definicja źródła światła
GLfloat light_position[] = {0.0, 0.0, 10.0, 1.0};
// położenie źródła
GLfloat light_ambient[] = {0.1, 0.1, 0.1, 1.0};
// składowe intensywności świecenia źródła światła otoczenia
// Ia = [Iar,Iag,Iab]
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
// składowe intensywności świecenia źródła światła powodującego
// odbicie dyfuzyjne Id = [Idr,Idg,Idb]
GLfloat light_specular[]= {1.0, 1.0, 1.0, 1.0};
// składowe intensywności świecenia źródła światła powodującego
// odbicie kierunkowe Is = [Isr,Isg,Isb]
GLfloat att_constant = {1.0};
// składowa stała ds dla modelu zmian oświetlenia w funkcji
// odległości od źródła
GLfloat att_linear = {0.05};
// składowa liniowa dl dla modelu zmian oświetlenia w funkcji
// odległości od źródła
GLfloat att_quadratic = {0.001};
// składowa kwadratowa dq dla modelu zmian oświetlenia w funkcji
// odległości od źródła
/*************************************************************************************/
// Ustawienie parametrów materiału i źródła światła
/*************************************************************************************/
// Ustawienie patrametrów materiału
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);
/*************************************************************************************/
// Ustawienie parametrów źródła
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, att_constant);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, att_linear);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, att_quadratic);
/*************************************************************************************/
// Ustawienie opcji systemu oświetlania sceny
glShadeModel(GL_SMOOTH); // właczenie łagodnego cieniowania
glEnable(GL_LIGHTING); // właczenie systemu oświetlenia sceny
glEnable(GL_LIGHT0); // włączenie źródła o numerze 0
glEnable(GL_DEPTH_TEST); // włączenie mechanizmu z-bufora
/*************************************************************************************/
}
/*************************************************************************************/
// Funkcja ma za zadanie utrzymanie stałych proporcji rysowanych
// w przypadku zmiany rozmiarów okna.
// Parametry vertical i horizontal (wysokość i szerokość okna) są
// przekazywane do funkcji za każdym razem gdy zmieni się rozmiar okna.
void ChangeSize(GLsizei horizontal, GLsizei vertical )
{
pix2angleh = 360.0/(float)horizontal; // przeliczenie pikseli na stopnie
pix2anglev = 360.0/(float)vertical;
glMatrixMode(GL_PROJECTION);
// Przełączenie macierzy bieżącej na macierz projekcji
glLoadIdentity();
// Czyszcznie macierzy bieżącej
gluPerspective(70, 1.0, 1.0, 30.0);
// Ustawienie parametrów dla rzutu perspektywicznego
if(horizontal <= vertical)
glViewport(0, (vertical-horizontal)/2, horizontal, horizontal);
else
glViewport((horizontal-vertical)/2, 0, vertical, vertical);
// Ustawienie wielkości okna okna widoku (viewport) w zależności
// relacji pomiędzy wysokością i szerokością okna
glMatrixMode(GL_MODELVIEW);
// Przełączenie macierzy bieżącej na macierz widoku modelu
glLoadIdentity();
// Czyszczenie macierzy bieżącej
}
/*************************************************************************************/
// Główny punkt wejścia programu. Program działa w trybie konsoli
void main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB |GLUT_DEPTH);
glutInitWindowSize(300, 300);
glutCreateWindow("Funkcja Weierstrassa");
glutMouseFunc(Mouse);
// Ustala funkcję zwrotną odpowiedzialną za badanie stanu myszy
glutMotionFunc(Motion);
// Ustala funkcję zwrotną odpowiedzialną za badanie ruchu myszy
glutDisplayFunc(RenderScene);
// Określenie, że funkcja RenderScene będzie funkcją zwrotną
// (callback function). Bedzie ona wywoływana za każdym razem
// gdy zajdzie potrzba przeryswania okna
glutReshapeFunc(ChangeSize);
// Dla aktualnego okna ustala funkcję zwrotną odpowiedzialną
// zazmiany rozmiaru okna
glutKeyboardFunc(keys);
MyInit();
// Funkcja MyInit() (zdefiniowana powyżej) wykonuje wszelkie
// inicjalizacje konieczne przed przystąpieniem do renderowania
glEnable(GL_DEPTH_TEST);
// Włączenie mechanizmu usuwania powierzchni niewidocznych
glutMainLoop();
// Funkcja uruchamia szkielet biblioteki GLUT
}
/*************************************************************************************/