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