|
|
Dnes se podíváme na to, jak se pohybovat ve scéně vytvořené v OpenGL. Tento malý tutoriál bude rozdělen do dvou částí. První část bude obsahovat kontrolu pohybu pomocí klávesnice (= pohyb vpřed, couvání a úkroky do obou směrů, což je dynamická část pohybu) a druhá část se bude zabývat pohybem pomocí myši (= otáčení pohledu do všech směrů, což je statická část pohybu).
Pro tuto část programů jsem zvolil několik proměnných pro uchování nezbytných dat. Neříkám, že je to jediná možná cesta, ani že je to ta nejlepší, je to jen moje cesta.
Budeme si tedy hlídat polohu kamery a směr jejího pohledu. Pro toto použijeme:
GLdouble pozice[3]={0.0, 0.0, 7.0};
GLdouble smerPohledu[3]={0.0, 0.0, -1.0};
bool kameraVlevo, kameraVpravo, kameraDopredu, kameraDozadu;
Pozice je vybrána náhodně, ale směr pohledu je podle ní upraven tak, aby mířil do středu scény. Pro uchování pozice a směru pohledu použiji tříprvkové pole, kde první prvek pole je hodnota na ose X, druhý na Y a třetí na Z. Dále jsem si nadefinoval proměnné typu bool pro uchování, zda se má kamera pohybovat či nikoliv (vysvětleno později).
V display funkci poté použijeme kód ve formátu:
gluLookAt(
pozice[0], pozice[1], pozice[2],
pozice[0]+smerPohledu[0], pozice[1]+smerPohledu[1], pozice[2]+smerPohledu[2],
0.0, 1.0, 0.0
);
Funkce gluLookAt má následující parametry:
void gluLookAt(
GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ,
GLdouble centerX, GLdouble centerY, GLdouble centerZ,
GLdouble upX, GLdouble upY, GLdouble upZ );
Kde eyeX, eyeY, eyeZ jsou jednotlivé souřadnice pozice kamery. CenterX, centerY, centerZ je vektor mířící ke středu pozorování. A nakonec upX, upY, upZ je vektor natočení kamery (douho jsem nechápal smysl tohoto vektoru, ale jde jen o to, zda má být kamera narovno, nebo má ležet, či být nakloněna pod jiným úhlem).
Při výše zvolených hodnotách tedy bude funkce gluLookAt vypadat:
void gluLookAt(0, 0, 7, 0, 0, 6, 0, 1, 0);
Nyní k jednotlivých klávesám. Pro rozeznání stisku a puštění klávesy použijeme dvě funkce již definované v knihovně GLUT:
glutKeyboardFunc(myKeys);
glutKeyboardUpFunc(myUpKeys);
Pozn.: Pokud bychom chtěli zaznamenávat stisk speciálních kláves, jako jsou šipky, použili bychom funkce:
glutSpecialFunc(mySpecialKeys);
glutSpecialUpFunc(mySpecialUpKeys);
Jejímiž jedinými parametry jsou odkazy na funkce, kde si ošetříme stisk jednotlivých kláves. Fuknce budou vypadat následnovně:
void myKeys(unsigned char key, int x, int y){
switch (key) {
case 'a':
case 'A': kameraVlevo = true;
break;
case 'd':
case 'D': kameraVpravo = true;
break;
case 'w':
case 'W': kameraDopredu = true;
break;
case 's':
case 'S': kameraDozadu = true;
break;
}
}
void myUpKeys(unsigned char key, int x, int y){
switch (key) {
case 'a':
case 'A': kameraVlevo = false;
break;
case 'd':
case 'D': kameraVpravo = false;
break;
case 'w':
case 'W': kameraDopredu = false;
break;
case 's':
case 'S': kameraDozadu = false;
break;
}
}
Vstupními parametry těchto dvou funkcí jsou vždy: parametr key, což je zmáčknutá/uvolněná klávesa, Dalšími dvěma parametry jsou pozice myši v našem okně při zmáčknutí/uvolnění klávesy.
Nyní přejdeme k timer funkci. Vždy budeme kontrolovat, zda není aktivní některá bool proměnná pro pohyb kamery (aktivní se myslí, že má hodnotu true).
Nejlépe se to jistě vysvětlí na ukázce:
void update(int value) {
if (kameraDopredu){
pozice[0] += smerPohledu[0]*DELKA_KROKU;
pozice[1] += smerPohledu[1]*DELKA_KROKU;
pozice[2] += smerPohledu[2]*DELKA_KROKU;
}
if (kameraDozadu){
pozice[0] -= smerPohledu[0]*DELKA_KROKU;
pozice[1] -= smerPohledu[1]*DELKA_KROKU;
pozice[2] -= smerPohledu[2]*DELKA_KROKU;
}
if (kameraVpravo){
pozice[0] -= smerPohledu[2]*DELKA_KROKU;
pozice[2] += smerPohledu[0]*DELKA_KROKU;
}
if (kameraVlevo){
pozice[0] += smerPohledu[2]*DELKA_KROKU;
pozice[2] -= smerPohledu[0]*DELKA_KROKU;
}
glutPostRedisplay();
//zavolani Timer funkce pro hodnotu 50 milisekund
glutTimerFunc(50, update, value);
}
Konstanta DELKA_KROKU zde zastupuje hodnotu, o kterou chceme posunout naši kameru (v našem případu) každých 50 milisekund.
Při zmáčknutí w dojde ke změně hodnoty u kameraDopredu. V tomto případu se každých 50 milisekund zvětší pozice kamery o délku kroku vynásobenou směrem pohledu pro každou ze tří souřadnic (x, y, z). Pro kameru dozadu je to stejné, ale odečítá se vždy DELKA_KROKU vynásobená příslušným směrem pohledu. Úkrok vpravo a vlevo je skoro stejné jako pohyb dopředu a dozadu, pouze otočen o 90°.
Pozn.: Uvádím zde i změnu „y“ souřadnice při pohybu dopředu a dozadu pro druhou část tutoriálu, kde se budeme již otáčet pomocí myši i nahoru a dolů.
Na konci timer funkce nesmíme zapomenout zavolat ještě funkci glutPostRedisplay(), která nám zavolá display funkci pro překreslení obrazu s novými hodnotami.
Poté už jen znova zavolat timer funkci.
Štítky: c++, kamera, OpenGL, pohyb
Zaachi blog využívá WordPress MU a běží na Blog.zive.cz. Vytvořte si svůj vlastní blog
Sledování přes RSS: články
a komentáře
Partnerská sekce pro IT profesionály:
Microsoft TechNet/MSDN