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 zezadu 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 přední strany byste měli vidět hezkou vlnící se bitmapu a po následném natočení z ní zůstane pouze drátěný model.
napsal: Bosco <bosco4 (zavináč) home.com>
přeložil: Michal Turek - Woq <WOQ (zavináč) seznam.cz>