Lekce 11

Lekce 11 - Efekt vlnφcφ se vlajky

NauΦφme se jak pomocφ sinusovΘ funkce animovat obrßzky. Pokud znßte standartnφ Üet°iΦ Windows "LΘtajφcφ 3D objekty" (i on by m∞l b²t programovan² v OpenGL), tak budeme d∞lat n∞co podobnΘho.

Budeme vychßzet z ÜestΘ lekce. Neopisuji cel² zdrojov² k≤d, tak₧e mo₧nß bude lepÜφ, kdy₧ budete mφt n∞kde po ruce i zdrojov² k≤d ze zmi≥ovanΘ lekce. Prvnφ v∞c, kterou musφte ud∞lat je vlo₧it hlaviΦkov² soubor matematickΘ knihovny. Nebudeme pracovat s moc slo₧itou matematikou, nebojte se, pou₧ijete pouze siny a kosiny.

#include <windows.h>// HlaviΦkov² soubor pro Windows

#include <stdio.h>// HlaviΦkov² soubor pro standardnφ vstup/v²stup

#include <math.h>// HlaviΦkov² soubor pro matematickou knihovnu

#include <gl\gl.h>// HlaviΦkov² soubor pro OpenGL32 knihovnu

#include <gl\glu.h>// HlaviΦkov² soubor pro Glu32 knihovnu

#include <gl\glaux.h>// HlaviΦkov² soubor pro Glaux knihovnu

HDC hDC = NULL;// Privßtnφ GDI Device Context

HGLRC hRC = NULL;// Trval² Rendering Context

HWND hWnd = NULL;// Obsahuje Handle naÜeho okna

HINSTANCE hInstance;// Obsahuje instanci aplikace

bool keys[256];// Pole pro uklßdßnφ vstupu z klßvesnice

bool active = TRUE;// Ponese informaci o tom, zda je okno aktivnφ

bool fullscreen = TRUE;// Ponese informaci o tom, zda je program ve fullscreenu

Deklarujte trojrozm∞rnΘ pole bod∙ k ulo₧enφ sou°adnic v jednotliv²ch osßch. Wiggle_count se pou₧ije k nastavenφ a nßslednΘmu zjiÜ¥ovßnφ, jak rychle se bude textura vlnit. Prom∞nnß hold zajistφ plynulΘ vln∞nφ textury.

float points[45][45][3];// Pole pro body v m°φ₧ce vlny

int wiggle_count = 0;// Rychlost vln∞nφ

GLfloat xrot;// Rotace na ose x

GLfloat yrot;// Rotace na ose y

GLfloat zrot;// Rotace na ose z

GLfloat hold;// Pomocnß, k zajiÜt∞nφ plynulosti pohybu

GLuint texture[1];// Uklßdß texturu

P°esu≥te se dol∙ k funkci LoadGLTexture(). Budete pou₧φvat novou texturu s nßzvem Tim.bmp, tak₧e najd∞te funkci LoadBMP("Data/NeHe.bmp") a p°epiÜte ji tak, aby nahrßvala nov² obrßzek.

if(TextureImage[0]=LoadBMP("Data/Tim.bmp"))// Loading bitmapy

Te∩ p°idejte nßsledujφcφ k≤d na konec funkce InitGL(). V²sledek uvidφte na prvnφ pohled. P°ednφ strana textury bude normßln∞ vybarvenß, ale jak se po chvφli obrßzek natoΦφ, zjistφte, ₧e ze zadnφ strany zbyl drßt∞n² model. GL_FILL urΦuje klasickΘ kreslenφ polygony, GL_LINES vykresluje pouze okrajovΘ linky, p°i GL_POINTS by Ülo vid∞t pouze vrcholovΘ body. Kterß strana polygonu je p°ednφ a kterß zadnφ nelze urΦit jednoznaΦn∞, staΦφ rotace a u₧ je to naopak. Proto vznikla konvence, ₧e mnoho·helnφky, u kter²ch byly p°i vykreslovßnφ zadßny vrcholy proti sm∞ru hodinov²ch ruΦiΦek jsou p°ivrßcenΘ.

// Konec funkce InitGL()

glPolygonMode(GL_BACK, GL_FILL);// P°ednφ strana vypln∞nß polygony

glPolygonMode(GL_FRONT, GL_LINE);// Zadnφ strana vypln∞nß m°φ₧kou

Nßsledujφcφ dva cykly inicializujφ naÜi sφ¥. Abychom dostali sprßvn² index musφme d∞lit °φdφcφ prom∞nou smyΦky p∞ti (tzn. 45/9=5). OdΦφtßm 4,4 od ka₧dΘ sou°adnice, aby se vlna vycentrovala na poΦßtku sou°adnic. StejnΘho efektu m∙₧e b²t dosa₧eno s pomocφ posunutφ, ale jß mßm radÜi tuto metodu. Hodnota points[x][y][2] je tvo°enß hodnotou sinu. Funkce sin() pot°ebuje radißny, tudφ₧ vezmeme hodnotu ve stupnφch, co₧ je naÜe x/5 nßsobenΘ Φty°iceti a pomocφ vzorce (radißny=2*P═*stupn∞/360) ji p°epoΦφtßme.

for (int x=0; x<45; x++)// Inicializace vlny

{

for (int y=0; y<45; y++)

{

points[x][y][0]=float((x/5.0f)-4.5f);

points[x][y][1]=float((y/5.0f)-4.5f);

points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));

}

}

return TRUE;

}

Na zaΦßtku vykreslovacφ funkce deklarujeme prom∞nnΘ. Jsou pou₧ity jako °φdφcφ v cykl∙. Uvidφte je v k≤du nφ₧, ale v∞tÜina z nich neslou₧φ k n∞Φemu jinΘmu ne₧, ₧e kontrolujφ cykly a uklßdajφ doΦasnΘ hodnoty

int DrawGLScene(GLvoid)// Vykreslovßnφ

{

int x, y;

float float_x, float_y, float_xb, float_yb;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Sma₧e obrazovku a hloubkov² buffer

glLoadIdentity();// Reset matice

glTranslatef(0.0f,0.0f,-12.0f);// Posunutφ do obrazovky

glRotatef(xrot,1.0f,0.0f,0.0f);// Rotace na ose x

glRotatef(yrot,0.0f,1.0f,0.0f);// Rotace na ose y

glRotatef(zrot,0.0f,0.0f,1.0f);// Rotace na ose z

glBindTexture(GL_TEXTURE_2D, texture[0]);// V²b∞r textury

VÜimn∞te si, ₧e Φtverce jsou kresleny po sm∞ru hodinov²ch ruΦiΦek. Z toho plyne, ₧e Φelnφ plocha, kterou vidφte bude vypln∞nß a ze zadu bude drßt∞n² model. Pokud bychom Φtverce vykreslovali proti sm∞ru hodinov²ch ruΦiΦek drßt∞n² model by byl na p°ednφ stran∞.

glBegin(GL_QUADS);// ZaΦßtek kreslenφ Φtverc∙

for( x = 0; x < 44; x++ )// Cykly prochßzejφ pole

{

for( y = 0; y < 44; y++ )

{

Ka₧d² z polygon∙ (Φtverce v sφti) mß 1/44x1/44 textury. Cyklus urΦuje lev² dolnφ bod (prvnφ 2 °ßdky). PotΘ spoΦφtßme prav² hornφ (dalÜφ 2 °ßdky). Tak₧e mßme dva body na ·hlop°φΦce Φtverce a kombinacφ hodnot jejich sou°adnic zφskßme zbylΘ dva body na textu°e.

// VypoΦφtßnφ texturov²ch koordinßt∙

float_x = float(x)/44.0f;

float_y = float(y)/44.0f;

float_xb = float(x+1)/44.0f;

float_yb = float(y+1)/44.0f;

// Zadßnφ jednotliv²ch bod∙

glTexCoord2f(float_x, float_y);

glVertex3f(points[x][y][0], points[x][y][1], points[x][y][2]);

glTexCoord2f(float_x, float_yb);

glVertex3f(points[x][y+1][0], points[x][y+1][1], points[x][y+1][2]);

glTexCoord2f(float_xb, float_yb);

glVertex3f(points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2]);

glTexCoord2f(float_xb, float_y);

glVertex3f(points[x+1][y][0], points[x+1][y][1], points[x+1][y][2]);

}

}

glEnd();// Konec kreslenφ Φtverc∙

P°i sudΘm vykreslenφ v po°adφ p°esuneme sou°adnice v poli do sousednφch sou°adnic a tφm p°esuneme i vlnu o kousek vedle. Cel² prvnφ sloupec (vn∞jÜφ cyklus) postupn∞ uklßdßme do pomocnΘ prom∞nnΘ. Potom o kousek p°esuneme vlnu jednoduch²m p°i°azenφm ka₧dΘho prvku do sousednφho a nakonec p°i°adφme ulo₧enou hodnotu okraje na opaΦn² konec obrßzku. Tφm vznikß dojem, ₧e kdy₧ mizφ jedna vlna, okam₧it∞ zaΦφnß vznikat novß, ale programov∞ je to konec tΘ starΘ :-] ZjednoduÜen∞ °eΦeno mßme jen jednu vlnu, kterß se po opuÜt∞nφ obrßzku p°esouvß na zaΦßtek. Nakonec vynulujeme wiggle_count, abychom udr₧eli animaci v chodu.

if (wiggle_count == 2)// Pro snφ₧enφ rychlosti pohybu

{

for (y = 0; y < 45; y++)// Prochßzφ hodnoty na y

{

hold=points[0][y][2];// Ulo₧φ kraj vlny

for (x = 0; x < 44; x++)// Prochßzφ hodnoty na x

{

points[x][y][2] = points[x+1][y][2];// P°i°azenφ do sousednφho prvku

}

points[44][y][2]=hold;// Ulo₧en² kraj bude na druhΘ stran∞

}

wiggle_count = 0;// Nulovßnφ poΦφtadla vykreslovßnφ

}

wiggle_count++;// Inkrementace poΦφtadla

Aktualizujeme rotaci a ukonΦφme funkci.

xrot+=0.3f;

yrot+=0.2f;

zrot+=0.4f;

return TRUE;

}

Zkompilujte a spus¥te program. Z jednΘ strany byste m∞li vid∞t hezkou vlnφcφ se bitmapu po nßslednΘm natoΦenφ z∙stane pouze drßt∞n² model.

napsal: Bosco
p°elo₧il: Michal Turek - Woq

ZdrojovΘ k≤dy

Lekce 11

<<< Lekce 10 | Lekce 12 >>>