GLUT

- A GLUT alapjai
- ablakok inicializálása és létrehozása
- ablakkezelés és input események kezelése
- példaprogram

A Graphics Library Utility Toolkit(GLUT)

A GLUT az OpenGL kibõvítése, amely már tartalmazza az OpenGL ablakok létrehozásához szükséges eljárásokat, így néhány sor megírásával létre tudunk hozni egy OpenGL renderelésre alkalmas ablakot. A GLUT emellet saját esemény kezelõ rendszerrel is rendelkezik, sõt olyan rutinokat is tartalmaz, amelyekkel karaktereket és magasabb szintû geometriai objektumokat, mint például gömböket, kúpokat, ikozaédereket tudunk specifikálni. A GLUT úgy egyszerûsíti le az eseménykezelést, hogy callback rutinokat rendelhetünk bizonyos eseményekhez, mint például egy billentyû, vagy a bal egérgomb lenyomása. Ezután egy main loop-ba (esemény hurok) lépünk, majd ha egy esemény történik a hurokban, akkor az ezen eseményhez rendelt callback rutinok végrehajtódnak. A GLUT ablak és képernyõ koordináták pixelekben vannak kifejezve. A képernyõ vagy ablak bal felsõ koordinátája (0, 0). Az x koordináta jobbra haladva nõ, az y koordináta pedig lefelé; ez nem egyezik meg az OpenGL koordináta rendszerével, ahol általában a bal alsó koordinátája (0, 0), de megegyezik a legelterjedtebb ablakozó rendszerek koordináta rendszerével. A GLUT-ban az egész azonosítók 1-gyel kezdõdnek, nem pedig 0-val. pl.: az ablak és a menü azonosítók, illetve a menü item indexek. A GLUT header file-ok a következõ include direktívával építhetõk be a forráskódba:

#include<GL\glut.h>

Egy ablak inicializálása és létrehozása

Egy ablak létrehozásához specifikálni kell annak tulajdonságait. Ehhez a következõ rutinokat kell alkalmazni:
void glutInit(int argc, char **argv);

a glutInit eljárást minden más GLUT eljárás elõtt kell meghívni, mert ez inicializálja a GLUT library-t.
A glutInit paraméterei megegyeznek a main függvény paramétereivel.

megj.: a glutInit függvénynek nem kötelezõ szerepelni az ablak jellemzõit beállító függvények között, de ha szerepel, akkor az összes többi elõtt kell lennie;

void glutInitDisplayMode(unsigned int mode);

a glutInitDisplayMode a képernyõ módot specifikálja (egyszeresen vagy kétszeresen pufferelt ablak, RGBA
vagy szín index mód,...)

pl.: a glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) egy egyszeresen pufferelt, RGB módban lévõ ablakot specifikál;
megj.: a glutInitDisplayMode-nak meglehetõsen sok lehetséges paramétere van (GLUT_DOUBLE, GLUT_INDEX, GLUT_STEREO, ...), de egyszerûbb programok írásához nekünk ezek közül csak néhányra lesz szükségünk. Majd késõbb látni fogjuk, hogy pl. kétszeresen pufferelt ablak (GLUT_DOUBLE) a jó minõségû animációnál lesz elengedhetetlen.

void glutInitWindowSize(int width, int height);

az ablak méreteit specifikálja pixelekben. width: szélesség, height: magasság.

pl.: a glutInitWindowSize(400, 400) egy 400x400-as ablakot specifikál

void glutInitWindowPosition(int x, int y);

az ablak bal felsõ sarkának x és y pozíciója.

pl.: a glutInitWindowPosition(100, 100) az ablak bal felsõ koordinátái a pontban lesznek

int glutCreateWindow(char *name);

megnyit egy ablakot az elõzõ rutinokban specifikált jellemzõkkel. Ha az ablakozó rendszer lehetõvé teszi, akkor a
name megjelenik az ablak fejlécén. A visszatérési érték egy egész, amely az ablak azonosítója. Ezt az értéket
használhatjuk fel az ablak kontrollálására

pl.: a glutCreateWindow("single") egy single névvel ellátott ablakot specifikál.

Ablakkezelés és input események

Miután az ablakot létrehoztuk, de még mielõtt belépünk az esemény hurokba, kijelölhetjük a callback függvényeket a következõ rutinokkal:

void glutDisplayFunc(void(*func)(void));

azt a függvényt specifikálja, amelyet akkor kell meghívni, ha az ablak tartalmát újra akarjuk rajzoltatni.

megj.: leegyszerûsítve a dolgot: a func nevû eljárásban kell definiálni azokat a dolgokat, amiket meg szeretnénk jeleníteni. Lásd a példát.

void glutReshapeFunc(void(*func)(int width, int height));

azt a függvényt specifikálja, amelyet akkor kell meghívni, ha az ablak mérete vagy pozíciója megváltozik. A
func argumentum egy függvényre mutat, amelynek két paramétere van, az ablak új szélessége és magassága.
Ha a glutReshapeFunc függvényt nem hívjuk meg vagy NULL az argumentuma, akkor egy
alapértelmezett függvény hívódik meg, amely meghívja a glViewport(0, 0, width, height) függvényt.
void glutKeyboardFunc(void(*func)(unsigned char key, int x, int y);
a függvényt specifikálja, melyet egy billentyû lenyomásakor kell meghívni. key egy ASCII karakter. Az x és y
paraméterek az egér pozícióját jelzik a billentyû lenyomásakor (ablak relatív koordinátákban).

megj.: tehát ha írunk pl. egy

void keyboard(unsigned char key, int x, int y)
{
switch(key) {
case 27:
exit(0);
break;
default:
break;
}
}

függvényt, majd ezt a függvényt átadjuk paraméterként a glutKeyboardFunc eljárásnak a következõképpen:

glutKeyboardFunc(keyboard);

akkor a programunkból az esc billentyû lenyomásakor léphetünk ki.
void glutMouseFunc(void(*func)(int button, int state, int x, int y);

a függvényt specifikálja, amely egy egér gomb lenyomásakor illetve elengedésekor hívódik meg. A button callback
paraméter a GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON illetve a GLUT_RIGHT_BUTTON egyike.
A state callback paraméter a GLUT_UP és a GLUT_DOWN szimbolikus konstansok egyike. Az x és `y` callback
paraméterek az egér pozícióját jelzik az egér esemény megtörténtekor (ablak relatív koordinátákban).
void glutPostRedisplay(void);
az érvényes ablak frissítését eredményezi.

megj.: a glutPostRedisplay eljárásra többnyire az animációkészítésnél lesz szükségünk, ugyanis ezzel az eljárással tudjuk az ablakot periodikusan frissíteni.

Példa GLUT programra

Hozzunk létre egy 200 pixel széles, és 200 pixel magas ablakot a (100, 100) pozícióban. Az ablak neve legyen firstglut.
Az ablak legyen egyszeresen pufferelt, és RGB szín módú. Rajzoljunk fekete háttérbe egy kék szakaszt (0.2, 0.2) pontból a (0.8, 0.8) pontba. A programból esc-re tudjunk kilépni.

#include<GL\glut.h>
#include<stdlib.h>
/*#include "stdafx.h"*/

void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0); // a háttér legyen fekete
glMatrixMode(GL_PROJECTION); // beállítjuk a vetítési mátrixot
glLoadIdentity(); // betöltjük az egységmátrixot
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); // vágósíkok
}

void display(void) {
glClear(GL_COLOR_BUFFER_BIT); // a képernyõ törlése
glColor3f(0.0, 0.0, 1.0); // az érvényes szín kék
glBegin(GL_LINES) {
glVertex2d(0.2, 0.2);
glVertex2d(0.8, 0.8); // az egyenes specifikálása
glEnd();
glFlush();
}

void keyboard(unsigned char key, int x, int y) {
switch(key) {
case 27:
exit(0);
break;
}
}

int main(void) {
/* int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
*/
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // egyszeresen pufferelt, RGB szín módú ablak
glutInitWindowSize(200, 200); // az ablak mérete
glutInitWindowPosition(100, 100); // az ablak pozíciója
glutCreateWindow("firstglut"); // az ablak neve
init();
glutDisplayFunc(display); // a képernyõ kezelése
glutKeyboardFunc(keyboard); // a billentyûzet kezelése
glutMainLoop(); // belépés az esemény hurokba
return 0;
}

/* ha Visual C-ben akarjuk a kódot lefordítani, akkor így fog kinézni a program*/
<-- fõoldal

.