Temat indywidualnego zadania laboratoryjnego
Wstęp
W trakcie trwania ćwiczenia laboratoryjnego nie udało mi się wykonać wszystkich punków zadania. Brakowało implementacji zmiennego nachylenia orbity względem osi X i Z oraz zmiany promienia orbity kołowej reflektora.
Dodałem kod, który umożliwia taką interakcję. Ponadto dla pełniejszego zobrazowania umieściłem w programie sekwencje instrukcji, która odpowiada za narysowanie aktualnej orbity reflektora. Dodałem także sferę która wskazuje położenie źródła światła nr 1 oraz osie układu współrzędnych.
Modyfikacje zaznaczyłem w algorytmie rozwiązania zadania pionową linią.
Algorytm rozwiązania zadania - rysowanie zadanego obiektu
- kod programu
// Zmienne globalne
double katY = -20.0; // kat okreslajacy polozenie obserwatora względem osi Y
double katRX = 0.0; // kat odchylenia orbity reflektora (swiatlo nr 1) wzgledem osi X
double katRY = 0.0; // kat określający położenie reflektora (swiatlo nr 1) wzgledem osi Y
double katRZ = 0.0; // kat odchylenia orbity reflektora (swiatlo nr 1) wzgledem osi Z
double katX = 20.0; // kat okreslajacy polozenie obserwatora względem osi X
int lPionowych; // liczba pionowych podziałow bryly
int lPoziomych; // liczba piozminych podzialow bryly
double promien; // promien podstawy rysowanej bryly
double wysokosc; // wysokosc rysowanej bryly
int szerokoscOkna = 800;
Int wysokoscOkna = 600;
int lightSwitch[2]={0,0}; // tablica okreslajaca stan źrodla swiatla 0 - wylaczone, 1- wlaczone
float rRef=4; // promien orbity po ktorej porusza sie reflektor
// Tablica parametrow swiatla
GLfloat swiatlo[7][4];
GLfloat swiatlo2[7][4];
// Tablica parametrow materialu z jakiego wykonany jest walec
GLfloat material[4][4];
GLfloat material2[4][4];
void RysujStozek(double h, double r, int nv, int nh)
{
double dH, dAlfa, dR;
int i, j;
int zmienna=1;
dAlfa = 360.0L/(double)nh;
dH = h/(double)nv;
dR = r/nv;
// Pocztaek tworzenia ukladu wspolrzednych
glBegin(GL_LINES);
// Os X
glColor3f(1.0, 0.0, 0.0);
glVertex3f(-20.0, 0.0, 0.0);
glVertex3f(20.0, 0.0, 0.0);
// Os Y
glColor3f(0.0,1.0,0.0);
glVertex3f(0.0, -20.0, 0.0);
glVertex3f(0.0, 20.0, 0.0);
// Os Z
glColor3f(0.0,0.0,1.0);
glVertex3f(0.0, 0.0, -20.0);
glVertex3f(0.0, 0.0, 20.0);
// Koniec tworzenia ukladu wspolrzednych
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();
// Wyznaczanie wierzcholkow i wektorow normalnych powierzchni bocznych
for (i = 0; floor((i+1)*dH*1.0E10) <= floor(h*1.0E10); i++)
{
for (j = 1; j*dAlfa <= 360.0L + dAlfa; j++)
{
DefiniujMaterial(zmienna);
glBegin(GL_QUADS);
glNormal3f( sin(DEG2RAD((j+1)*dAlfa)), 0.0, cos(DEG2RAD((j+1)*dAlfa)));
glVertex3f( (r-dR)*sin(DEG2RAD((j+1)*dAlfa)),(i+1)*dH, (r-dR)*cos(DEG2RAD((j+1)*dAlfa)));
glNormal3f( sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));
glVertex3f((r-dR)*sin(DEG2RAD(j*dAlfa)), (i+1)*dH, (r-dR)*cos(DEG2RAD(j*dAlfa)));
glNormal3f( sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j*dAlfa)), i*dH, r*cos(DEG2RAD(j*dAlfa)));
glNormal3f( sin(DEG2RAD((j+1)*dAlfa)), 0.0, cos(DEG2RAD((j+1)*dAlfa)));
glVertex3f(r*sin(DEG2RAD((j+1)*dAlfa)), i*dH, r*cos(DEG2RAD((j+1)*dAlfa)));
glEnd();
zmienna=!zmienna;
}
r-=dR;
}
}
void UstawDomyslneWartosciParametrow(void)
{
// Tablica parametrow materialu
GLfloat param_materialu[6][4] = {
{1.0, 1.0, 0.2, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{1.0, 1.0, 0.0, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{1.0, 1.0, 0.0, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{1.0, 1.0, 0.0, 1.0}}; // [3] polysk
GLfloat param_materialu2[6][4] = {
{0.0, 0.0, 0.0, 0.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, 0.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{0.0, 0.0, 0.0, 0.0}}; // [3] polysk
// Tablica parametrow swiatla
GLfloat param_swiatla[10][4] = {
{0.0, 0.0, 0.0, 0.0}, // [0] otoczenie
{1.0, 1.0, 1.0, 0.0}, // [1] rozproszenie
{1.0, 1.0, 1.0, 0.0}, // [2] lustrzane
{0.0, 0.0, 1.0, 0.0}, // [3] polozenie
{0.0, 0.0, -1.0, 0.0}, // [4] kierunek swiecenia
{120.0, 0.0, 0.0, 0.0}, // [5] tlumienie katowe swiatla
{10.0, 0.0, 0.0, 0.0}};// [6] kat odciecia swiatla
GLfloat param_swiatla2[10][4] = {
{1.0, 1.0, 0.0, 0.8}, // [0] otoczenie
{1.0, 1.0, 0.0, 0.8}, // [1] rozproszenie
{1.0, 1.0, 0.0, 0.8}, // [2] lustrzane
{10.0, 10.0, 10.0, 0.0}, // [3] polozenie
{0.0, 0.0, -1.0, 0.0}, // [4] kierunek swiecenia
{0.0, 0.0, 0.0, 0.0}, // [5] tlumienie katowe swiatla
{0.0, 0.0, 0.0, 0.0}};// [6] kat odciecia swiatla
// Skopiowanie zawartosci tablic param_* do tablic globalnych
memcpy(material, param_materialu, 4*4*sizeof(GLfloat));
memcpy(swiatlo, param_swiatla, 7*4*sizeof(GLfloat));
memcpy(material2, param_materialu2, 4*4*sizeof(GLfloat));
memcpy(swiatlo2, param_swiatla2, 7*4*sizeof(GLfloat));
lPionowych = 8; // Liczba podzialow pionowych
lPoziomych = 4; // Liczba podzialow poziomych
promien = 1.0; // Promien walca
wysokosc = 2.0; // Wysokosc walca
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
}
void WlaczOswietlenie(int s1, int s2)
{
// Odblokowanie oswietlenia
glEnable(GL_LIGHTING);
// Odblokowanie zerowego zrodla swiatla
if (s1==1)
{
glEnable(GL_LIGHT0);
katRY=( katRY +5)%360;
swiatlo[3][0]=rRef*cos(DEG2RAD(katRY));
swiatlo[3][1]=wysokosc/2;
swiatlo[3][2]=rRef*sin(DEG2RAD(katRY));
swiatlo[3][3]=1.0;
swiatlo[4][0]=-rRef*cos(DEG2RAD(katRY));
swiatlo[4][1]=-wysokosc/3;
swiatlo[4][2]=-rRef*sin(DEG2RAD(katRY));
swiatlo[4][3]=-1.0;
// Inicjowanie zrodla swiatla
glLightfv(GL_LIGHT0, GL_AMBIENT, swiatlo[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo[1]);
glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo[2]);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, swiatlo[5][0]);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, swiatlo[6][0]);
}
else glDisable(GL_LIGHT0);
if (s2==1)
{
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo2[1]);
glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo2[2]);
glLightfv(GL_LIGHT1, GL_POSITION, swiatlo2[3]);
}
else glDisable(GL_LIGHT1);
}
void DefiniujMaterial(int typ)
{
if(typ==0)
{
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]);
}
else
{
glMaterialfv(GL_FRONT, GL_AMBIENT, material2[0]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, material2[1]);
glMaterialfv(GL_FRONT, GL_SPECULAR, material2[2]);
glMaterialfv(GL_FRONT, GL_SHININESS, material2[3]);
}
}
void WyswietlObraz(void)
{
int j;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
UstawParametryWidoku(szerokoscOkna, wysokoscOkna);
WlaczOswietlenie(lightSwitch[0], lightSwitch[1]);
glTranslatef(0, 0, -obsR); glRotatef(katX, 1, 0, 0); glRotatef(katY, 0, 1, 0); glPushMatrix(); glTranslatef(0.0, swiatlo[3][1], 0.0); glRotatef(katRX, 1,0,0); glRotatef(katRZ, 0,0,1); glDisable(GL_LIGHTING); glBegin(GL_LINES); glColor3f(0.0,0.0,0.0); for(j=0; j<=360.0L; j++) { glVertex3f(rRef*sin(DEG2RAD(j)), 0.0, rRef*cos(DEG2RAD(j))); glVertex3f(rRef*sin(DEG2RAD(j+1)), 0.0, rRef*cos(DEG2RAD(j+1))); } glEnd(); glTranslatef(swiatlo[3][0], 0.0, swiatlo[3][2]); glutWireSphere(0.25, 20, 20); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_POSITION, swiatlo[3]); glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, swiatlo[4]); glPopMatrix(); |
Wprowadzona modyfikacja |
RysujWalec(wysokosc, promien, lPoziomych, lPionowych);
glutSwapBuffers();
}
opis funkcjonowania algorytmu
Realizacja zadania opiera się o kod i funkcje zamieszczone powyżej.
Pierwsza procedura odpowiedzialna jest na narysowanie w scenie oświetlanego obiektu - stożek oraz osi układu współrzędnych, w odniesieniu do których łatwo ocenić aktualne położenie elementów sceny.
Funkcja przyjmuje jako parametry kolejno
void RysujStozek(double h, double r, int nv, int nh)
i interpretuje w następujący sposób
1. wysokość bryły
2. promień podstawy
3. liczba podziałów pionowych
4. liczba podziałów poziomych
Wstępnie procedura rysuje układ współrzędnych
glBegin(GL_LINES);
// Os X
glColor3f(0.0, 0.0, 0.0);
glVertex3f(-20.0, 0.0, 0.0);
glVertex3f(20.0, 0.0, 0.0);
// Os Y
glColor3f(0.0,0.0,0.0);
glVertex3f(0.0, -20.0, 0.0);
glVertex3f(0.0, 20.0, 0.0);
// Os Z
glColor3f(0.0,0.0,0.0);
glVertex3f(0.0, 0.0, -20.0);
glVertex3f(0.0, 0.0, 20.0);
// Koniec tworzenia ukladu wspolrzednych
glEnd();
z wykorzystaniem trybu graficznego opartego na liniach. Łączy dwa punkty umieszczone na odpowiedniej osi. Następnie, w oparciu o techniki poznane na pierwszych ćwiczeniach laboratoryjnych, w trybie graficznym GL_QUADS wykreślam stożek
// 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
for (i = 0; floor((i+1)*dH*1.0E10) <= floor(h*1.0E10); i++)
{
for (j = 1; j*dAlfa <= 360.0L + dAlfa; j++)
{
DefiniujMaterial(zmienna);
glBegin(GL_QUADS);
glNormal3f( sin(DEG2RAD((j+1)*dAlfa)), 0.0, cos(DEG2RAD((j+1)*dAlfa)));
glVertex3f( (r-dR)*sin(DEG2RAD((j+1)*dAlfa)),(i+1)*dH, (r-dR)*cos(DEG2RAD((j+1)*dAlfa)));
glNormal3f( sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));
glVertex3f((r-dR)*sin(DEG2RAD(j*dAlfa)), (i+1)*dH, (r-dR)*cos(DEG2RAD(j*dAlfa)));
glNormal3f( sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j*dAlfa)), i*dH, r*cos(DEG2RAD(j*dAlfa)));
glNormal3f( sin(DEG2RAD((j+1)*dAlfa)), 0.0, cos(DEG2RAD((j+1)*dAlfa)));
glVertex3f(r*sin(DEG2RAD((j+1)*dAlfa)), i*dH, r*cos(DEG2RAD((j+1)*dAlfa)));
glEnd();
zmienna=!zmienna;
}
r-=dR;
}
Poprzez wprowadzenie co ciała procedury zmiennej
Int zmienna=0;
której wartość ulega zmianie przy każdym obiegu wewnętrznej pętli oraz wywoływaniu w wewnętrznej pętli procedury:
DefiniujMaterial(zmienna);
Uzyskałem możliwość zmiany charaktery wykorzystywanego materiału pomiędzy dwoma. Wynikiem takiego działania jest stożek o układzie powierzchni bocznej - szachownica.
Wykorzystana procedura została opisana w dalszej części sprawozdania.
Druga procedura odpowiada za nadanie wartości początkowych parametrom określającym charakter źródeł światła i materiałów.
Parametry dla światła składają się na tablice dwu wymiarową:
GLfloat swiatlo[10][4];
gdzie pierwszy wymiar [10] określa kolejne parametry a drugi [4] i wartości w systemie RGBA. I kolejno są to:
1. GL_AMBIENT - światło otaczające (brak określonego kierunku)
2. GL_DIFFUSE - światło rozproszone (główny składnik światłą)
3. GL_SPECULAR - światło odbłysków (podobne do GL_AMBIENT)
4. GL_POSITION - określa pozycje światła (4 składowa 1.0 dla refl.)
5. GL_SPOT_DIRECTION - kierunek świecenia reflektora
6. GL_SPOT_EXPONENT - tłumienie kątowe światła (1. element, pozostałe składowe eliminowane)
7. GL_SPOT_CUTOFF - połowa kąta rozwarcia snopa światła refl. (1. element, pozostałe składowe eliminowane).
Dalej wypełniane są dwie tablice zawierające informacje o charakterze materiału, z jakiego zamodelowany będzie obiekt. Tablica materiału jest również dwuwymiarowa:
GLfloat material[4][4];
Gdzie pierwszy wymiar [4] określa parametr, natomiast drugi [4] składowe parametru. I są to:
1. GL_AMBIENT - współczynnik odbicia światła otoczenia
2. GL_DIFFUSE -współczynnik odbicia światła rozproszonego
3. GL_SPECULAR - współczynnik odbicia światła lustrzanego
4. GL_SHININESS - połysk
Kolejna funkcja odpowiada za nadawaniu parametrów światłom oraz udostępnia możliwość niezależne ich włączanie/wyłączanie. Przyjmuje dwa parametry, na podstawie których określa stan źródła światła - włączone/wyłączone. Interpretacja pierwszej zmiennej ma wpływ na światło nr 1, drugiej na nr 2. Dla wartości jeden światło jest włączone, a dla różnej od 1 wyłączone. Dla reflektora podczas włączenia światła następuje obliczanie położenia na obicie dla każdej klatki obrazu.
katRY=( katRY +5)%360;
Pozwala to na uzyskanie obrotu, ruchu po orbicie, poprzez wyznaczenie położenia z równania okręgu.
swiatlo[3][0]=rRef*cos(DEG2RAD(katRY));
swiatlo[3][1]=wysokosc/2;
swiatlo[3][2]=rRef*sin(DEG2RAD(katRY));
swiatlo[3][3]=1.0;
natomiast kierunek świecenia wyznaczany jest jako wartość przeciwna do położenia
swiatlo[4][0]=-rRef*cos(DEG2RAD(katRY));
swiatlo[4][1]=-wysokosc/3;
swiatlo[4][2]=-rRef*sin(DEG2RAD(katRY));
swiatlo[4][3]=-1.0;
Po określeniu położenia i kierunku następuje przypisanie parametrów do światła (tablica GLfloat swiatlo[10][4];)
glLightfv(GL_LIGHT0, GL_AMBIENT, swiatlo[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo[1]);
glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo[2]);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, swiatlo[5][0]);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, swiatlo[6][0]);
W przypadku źródła nr 2, przy włączaniu następuje jedynie określenie parametrów źródła (tablica GLfloat swiatlo2[10][4];)
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo2[1]);
glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo2[2]);
glLightfv(GL_LIGHT1, GL_POSITION, swiatlo2[3]);
Drugie światło, kierunkowe, określane jest za pomocą tylko czterech pierwszych parametrów. Pozostałe spowodowałyby zmianę charakteru źródła z kierunkowego na reflektor.
Kolejna procedura odpowiada za nadanie parametrów wykorzystywanemu materiałowi. Ponieważ wykorzystuje dwa rodzaje materiału funkcja pobiera parametr, po którego interpretacji nadaje parametry materiałowi. Dla wartości zero materiał ma właściwości określone przez tablice
GLfloat material[4][4
czyli żółty błyszczący. Natomiast dla parametry różnego od zera charakter materiału określa tablica
GLfloat material2[4][4];
czyli niebieski matowy.
Ostatnia funkcja umieszcza w scenie aktualną orbitę po której porusza się reflektor oraz rysuje na niej kulę, której położenie odpowiada aktualnej pozycji reflektora
glPushMatrix();
glTranslatef(0.0, swiatlo[3][1], 0.0);
glRotatef(katRX, 1,0,0);
glRotatef(katRZ, 0,0,1);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(0.0,0.0,0.0);
for(j=0; j<=360.0L; j++)
{
glVertex3f(rRef*sin(DEG2RAD(j)), 0.0, rRef*cos(DEG2RAD(j)));
glVertex3f(rRef*sin(DEG2RAD(j+1)), 0.0, rRef*cos(DEG2RAD(j+1)));
}
glEnd();
glTranslatef(swiatlo[3][0], 0.0, swiatlo[3][2]);
glutWireSphere(0.25, 20, 20);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_POSITION, swiatlo[3]);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, swiatlo[4]);
glPopMatrix();
Wstępnie dokonywana jest rotacja układu współrzędnych względem środka orbity - pozwala to na uzyskanie efektu zmiany kąta orbity reflektora względem odpowiednio osi X i Z. Wyłączam światło, żeby nie miało wpływy na kolor rysowanej orbity. Dalej rysuje orbitę - linie łączące ramiona kąta o wartości 1° w odległości równej promieniowi orbity od jej środka.
Translacja pozwala mi się przesunąć na orbitę, do miejsca, gdzie aktualnie znajduje się reflektor. W tym punkcie rysuje sferę wykorzystując wbudowaną funkcję OpenGL.
Włączam wyłączone światło i ustawiam pozycje oraz kierunek świecenia reflektora poprzez jego odpowiednie parametry.
Dalej wywołują procedurę rysującą stożek. Otrzymuje pełną scenę (brak oświetlenia):
Poprzez interaktywnie rozwiązane niezależne włączanie świateł
case '1':
if (lightSwitch[0]==0) lightSwitch[0]=1;
else lightSwitch[0]=0;
break;
case '2':
if (lightSwitch[1]==0) lightSwitch[1]=1;
else lightSwitch[1]=0;
break;
umieszczone w procedurze obsługującą klawiaturę otrzymuje następujące efekty
włączone światło nr 1 reflektor |
włączone oświetlenie nr 2 kierunkowe (10,10,10) |
włączone oświetlenie nr 1 oraz nr 2 |
Poniższe rysunki obrazują zmianę promienia orbity reflektora. Obywa się to poprzez zmianę wartości zmiennej w procedurze obsługującej klawiaturę:
case 'R':
case 'r':
rRef=(rRef<30) ? rRef+0.1 : 30;
break;
case 'F':
case 'f':
rRef=(rRef>wysokosc/2) ? rRef-0.1 : wysokosc/2;
break;
Oraz obliczanie położenia reflektora dla każdej klatki animacji w procedurze odpowiedzialnej za sterowaniem światłem.
|
|
Interaktywna zmiana kąta nachylenia orbity do osi Z
|
|
Interaktywna zmiana kąta nachylenia orbity do osi X
|
|
Kod źródłowy programu
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <GL/glut.h>
#define M_PI 3.14159
// Makro przeliczajace stopnie na radiany
#define DEG2RAD(x) ((float)(x)*M_PI/180.0)
// Zmienne globalne
double katY = -20.0;
double katRX = 0.0;
double katRY = 0.0;
double katRZ = 0.0;
double katX = 20.0;
int lPionowych;
int lPoziomych;
double promien;
double wysokosc;
int szerokoscOkna = 800;
int wysokoscOkna = 600;
int lightSwitch[2]={0,0};
int obrot;
float rRef=4;
int obsR=10;
GLfloat swiatlo[7][4];
GLfloat swiatlo2[7][4];
GLfloat material[6][4];
GLfloat material2[6][4];
void UstawDomyslneWartosciParametrow(void);
void WlaczOswietlenie(int, int);
void DefiniujMaterial(int);
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 UstawDomyslneWartosciParametrow(void)
{
GLfloat param_materialu[6][4] = {
{1.0, 1.0, 0.0, 1.0}, // [0] wspolczynnik odbicia swiatla otoczenia
{1.0, 1.0, 0.0, 1.0}, // [1] wspolczynnik odbicia swiatla rozproszonego
{1.0, 1.0, 0.0, 1.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{1.0, 1.0, 1.0, 1.0}, // [3] polysk
{0.0, 0.0, 0.0, 1.0}}; // [4] kolor swiatla emitowanego
GLfloat param_materialu2[6][4] =
{
{0.0, 0.0, 0.0, 0.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, 0.0}, // [2] wspolczynnik odbicia swiatla lustrzanego
{0.0, 0.0, 0.0, 0.0}, // [3] polysk
{0.0, 0.0, 0.0, 0.0}}; // [4] kolor swiatla emitowanego
GLfloat param_swiatla[7][4] = {
{0.0, 0.0, 0.0, 0.0}, // [0] otoczenie
{1.0, 1.0, 1.0, 0.0}, // [1] rozproszenie
{1.0, 1.0, 1.0, 0.0}, // [2] lustrzane
{0.0, 0.0, 1.0, 0.0}, // [3] polozenie
{0.0, 0.0, -1.0, 0.0}, // [4] kierunek swiecenia
{10.0, 0.0, 0.0, 1.0}, // [5] tlumienie katowe swiatla
{10.0, 0.0, 0.0, 0.0}};// [6] kat odciecia swiatla
GLfloat param_swiatla2[7][4] = {
{1.0, 1.0, 0.0, 0.8}, // [0] otoczenie
{1.0, 1.0, 0.0, 0.8}, // [1] rozproszenie
{1.0, 1.0, 0.0, 0.8}, // [2] lustrzane
{10.0, 10.0, 10.0, 0.0}, // [3] polozenie
{0.0, 0.0, -1.0, 0.0}, // [4] kierunek swiecenia
{0.0, 0.0, 0.0, 0.0}, // [5] tlumienie katowe swiatla
{0.0, 0.0, 0.0, 0.0}};// [6] kat odciecia swiatla
memcpy(material, param_materialu, 5*4*sizeof(GLfloat));
memcpy(swiatlo, param_swiatla, 7*4*sizeof(GLfloat));
memcpy(material2, param_materialu2, 5*4*sizeof(GLfloat));
memcpy(swiatlo2, param_swiatla2, 7*4*sizeof(GLfloat));
lPionowych = 8; // Liczba podzialow pionowych
lPoziomych = 4; // Liczba podzialow poziomych
promien = 1.0; // Promien walca
wysokosc = 2.0; // Wysokosc walca
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
}
void WlaczOswietlenie(int s1, int s2)
{
glEnable(GL_LIGHTING);
if (s1==1)
{
glEnable(GL_LIGHT0);
obrot=(obrot+5)%360;
obrot=45;
swiatlo[3][0]=rRef*cos(DEG2RAD(obrot));
swiatlo[3][1]=wysokosc/2;
swiatlo[3][2]=rRef*sin(DEG2RAD(obrot));
swiatlo[3][3]=1.0;
swiatlo[4][0]=-rRef*cos(DEG2RAD(obrot));
swiatlo[4][1]=-wysokosc/3;
swiatlo[4][2]=-rRef*sin(DEG2RAD(obrot));
swiatlo[4][3]=-1.0;
glLightfv(GL_LIGHT0, GL_AMBIENT, swiatlo[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE, swiatlo[1]);
glLightfv(GL_LIGHT0, GL_SPECULAR, swiatlo[2]);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, swiatlo[5][0]);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, swiatlo[6][0]);
}
else glDisable(GL_LIGHT0);
if (s2==1)
{
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, swiatlo2[1]);
glLightfv(GL_LIGHT1, GL_SPECULAR, swiatlo2[2]);
glLightfv(GL_LIGHT1, GL_POSITION, swiatlo2[3]);
}
else glDisable(GL_LIGHT1);
}
void DefiniujMaterial(int typ)
{
if(typ==0)
{
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]);
}
else
{
glMaterialfv(GL_FRONT, GL_AMBIENT, material2[0]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, material2[1]);
glMaterialfv(GL_FRONT, GL_SPECULAR, material2[2]);
glMaterialfv(GL_FRONT, GL_SHININESS, material2[3]);
glMaterialfv(GL_FRONT, GL_EMISSION, material2[4]);
}
}
void RysujWalec(double h, double r, int nv, int nh)
{
double dH, dAlfa, dR;
int i, j;
int zmienna=1;
dAlfa = 360.0L/(double)nh;
dH = h/(double)nv;
dR = r/nv;
glBegin(GL_LINES);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(-20.0, 0.0, 0.0);
glVertex3f(20.0, 0.0, 0.0);
glColor3f(0.0,1.0,0.0);
glVertex3f(0.0, -20.0, 0.0);
glVertex3f(0.0, 20.0, 0.0);
glColor3f(0.0,0.0,1.0);
glVertex3f(0.0, 0.0, -20.0);
glVertex3f(0.0, 0.0, 20.0);
glEnd();
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
for (i = 0; floor((i+1)*dH*1.0E10) <= floor(h*1.0E10); i++)
{
for (j = 1; j*dAlfa <= 360.0L + dAlfa; j++)
{
DefiniujMaterial(zmienna);
glBegin(GL_QUADS);
glNormal3f( sin(DEG2RAD((j+1)*dAlfa)), 0.0, cos(DEG2RAD((j+1)*dAlfa)));
glVertex3f((r-dR)*sin(DEG2RAD((j+1)*dAlfa)), (i+1)*dH, (r-dR)*cos(DEG2RAD((j+1)*dAlfa)));
glNormal3f( sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));
glVertex3f((r-dR)*sin(DEG2RAD(j*dAlfa)), (i+1)*dH, (r-dR)*cos(DEG2RAD(j*dAlfa)));
glNormal3f( sin(DEG2RAD(j*dAlfa)), 0.0, cos(DEG2RAD(j*dAlfa)));
glVertex3f(r*sin(DEG2RAD(j*dAlfa)), i*dH, r*cos(DEG2RAD(j*dAlfa)));
glNormal3f( sin(DEG2RAD((j+1)*dAlfa)), 0.0, cos(DEG2RAD((j+1)*dAlfa)));
glVertex3f(r*sin(DEG2RAD((j+1)*dAlfa)), i*dH, r*cos(DEG2RAD((j+1)*dAlfa)));
glEnd();
zmienna=!zmienna;
}
r-=dR;
}
}
void UstawParametryWidoku(int szer, int wys)
{
szerokoscOkna = szer;
wysokoscOkna = wys;
glViewport(0, 0, szerokoscOkna, wysokoscOkna);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, (float)szerokoscOkna/(float)wysokoscOkna, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void WyswietlObraz(void)
{
int j;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
UstawParametryWidoku(szerokoscOkna, wysokoscOkna);
WlaczOswietlenie(lightSwitch[0], lightSwitch[1]);
glTranslatef(0, 0, -obsR);
glRotatef(katX, 1, 0, 0);
glRotatef(katY, 0, 1, 0);
glPushMatrix();
glTranslatef(0.0, swiatlo[3][1], 0.0);
glRotatef(katRX, 1,0,0);
glRotatef(katRZ, 0,0,1);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(0.0,0.0,0.0);
for(j=0; j<=360.0L; j++)
{
glVertex3f(rRef*sin(DEG2RAD(j)), 0.0, rRef*cos(DEG2RAD(j)));
glVertex3f(rRef*sin(DEG2RAD(j+1)), 0.0, rRef*cos(DEG2RAD(j+1)));
}
glEnd();
glTranslatef(swiatlo[3][0], 0.0, swiatlo[3][2]);
glutWireSphere(0.25, 20, 20);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_POSITION, swiatlo[3]);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, swiatlo[4]);
glPopMatrix();
RysujWalec(wysokosc, promien, lPoziomych, lPionowych);
glutSwapBuffers();
}
void ObslugaKlawiatury(unsigned char klawisz, int x, int y)
{
switch(klawisz)
{
case '+':
obsR=(obsR<30) ? obsR+1 : 30;
break;
case '-':
obsR=(obsR>5) ? obsR-1 : 5;
break;
case 'R':
case 'r':
rRef=(rRef<30) ? rRef+0.1 : 30;
break;
case 'F':
case 'f':
rRef=(rRef>wysokosc/2) ? rRef-0.1 : wysokosc/2;
break;
case 'l':
wysokosc=(wysokosc<10) ? wysokosc+1 : 10;
break;
case 'L':
wysokosc=(wysokosc>1) ? wysokosc-1 : 1;
break;
case '1':
if (lightSwitch[0]==0) lightSwitch[0]=1;
else lightSwitch[0]=0;
break;
case '2':
if (lightSwitch[1]==0) lightSwitch[1]=1;
else lightSwitch[1]=0;
break;
case 'v':
lPionowych = (lPionowych == 40)? 40 : lPionowych + 2;
break;
case 'V':
lPionowych = (lPionowych == 4)? 4 : lPionowych - 2;
break;
case 'h':
lPoziomych = (lPoziomych == 40)? 40 : lPoziomych + 2;
break;
case 'H':
lPoziomych = (lPoziomych == 4)? 4 : lPoziomych - 2;
break;
case 'W':
case 'w':
katRX=(katRX>-90) ? katRX-1 : -90;
break;
case 'S':
case 's':
katRX=(katRX<90) ? katRX+1 : 90;
break;
case 'A':
case 'a':
katRZ=(katRZ>-90) ? katRZ-1 : -90;
break;
case 'D':
case 'd':
katRZ=(katRZ<90) ? katRZ+1 : 90;
break;
case 27:
exit(0);
}
}
void ObslugaKlawiszySpecjalnych(int klawisz, int x, int y)
{
switch(klawisz)
{
case GLUT_KEY_UP:
katX=(katX<90) ? katX+1 : 90;
break;
case GLUT_KEY_DOWN:
katX=(katX>0) ? katX-1 : 0;
break;
case GLUT_KEY_RIGHT:
katY=(katY<360) ? katY+1 : 0;
break;
case GLUT_KEY_LEFT:
katY=(katY>0) ? katY-1 : 360;
break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(szerokoscOkna, wysokoscOkna);
glutCreateWindow("Oswietlony walec");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClearDepth(1000.0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor (1.0, 1.0, 1.0, 0.0);
glutDisplayFunc(WyswietlObraz);
glutReshapeFunc(UstawParametryWidoku);
glutIdleFunc(WyswietlObraz);
glutKeyboardFunc(ObslugaKlawiatury);
glutSpecialFunc(ObslugaKlawiszySpecjalnych);
UstawDomyslneWartosciParametrow();
glutMainLoop();
return 0;
}
13
Copyright ©2005 Piotr Barankiewicz