Používáme gluUnProject()

Potřebujete transformovat pozici myši na souřadnice v OpenGL scéně a nevíte si rady? Pokud ano, jste na správném místě.

Vytvoříme jednoduchou funkci, která provede všechny potřebné operace. Předávat se jí budou dvě celá čísla definující pozici v okně a výstupem budou tři čísla x, y, z pozice ve scéně. Co všechno budeme potřebovat:

Jak tedy na ně?

1. Viewport pozice a velikost

Potřebujeme nagrabovat informace o aktuálním viewportu. Konkrétně se jedná o počáteční x a y souřadnice spolu se s jeho šířkou a výškou. Pro tuto operaci poslouží OpenGL funkce glGetIntegerv().

GLint viewport[4];// Paměť pro viewport

glGetIntegerv(GL_VIEWPORT, viewport);// Získání viewportu

Pole viewport bude po provedení příkazu obsahovat následující informace.

2. Modelview matice

Jakmile máme informace o viewportu, můžeme se pustit do získávání informací o modelview matici, která určuje, jak jsou koordináty OpenGL primitiv transformovány do viditelných souřadnic. Překl.: V modelview matici je uloženo nastavení kamery (např. translace a rotace).

GLdouble modelview[16];// Paměť pro modelview matici

glGetDoublev(GL_MODELVIEW_MATRIX, modelview);// Získání modelview matice

3. Projekční matice

Dále potřebujeme získat projekční matici, která transformuje vertexy v souřadnicích očí do ořezávacích koordinátů. Překl.: Projekční matice se používá pro nastavení perspektivní nebo pravoúhlé projekce.

GLdouble projection[16];// Paměti pro projekční matici

glGetDoublev(GL_PROJECTION_MATRIX, projection);// Získání projekční matice

4. Pozice v okně

Poté, co jsme toto všechno udělali, můžeme nagrabovat souřadnice v okně. V našem případě se zajímáme o pozici myši.

POINT mouse;// Bude ukládat x a y souřadnice myši

GetCursorPos(&mouse);// Grabování souřadnic myši

ScreenToClient(hWnd, &mouse);// Souřadnice v klientské oblasti okna

GLfloat winX, winY, winZ;// Bude ukládat x, y, a z souřadnice

winX = (float)mouse.x;// X pozice myši

winY = (float)mouse.y;// Y pozice myši

Střed souřadnicového systému [0; 0] se ve Windows nachází vlevo nahoře, zatímco u OpenGL je vlevo dole.

winY = (float)viewport[3] - winY;// Odečte aktuální y pozici myši od výšky obrazovky.

Jistě jste si všimli, že nám chybí hodnota na ose z...

glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);// Získání z pozice

5. Získání OpenGL souřadnic kurzoru

Vše, co nám ještě zbývá udělat, je vypočítat finální hodnoty na OpenGL osách.

GLdouble posX, posY, posZ;// Bude obsahovat výsledné hodnoty

gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);// Transformace do OpenGL souřadnic

Pomocí právě získaných znalostí můžeme napsat C/C++ funkci, která z pozice myši v okně vypočítá OpenGL souřadnice.

CVector3 GetOGLPos(int x, int y)

{

GLint viewport[4];

GLdouble modelview[16];

GLdouble projection[16];

GLfloat winX, winY, winZ;

GLdouble posX, posY, posZ;

glGetDoublev(GL_MODELVIEW_MATRIX, modelview );

glGetDoublev(GL_PROJECTION_MATRIX, projection);

glGetIntegerv(GL_VIEWPORT, viewport);

winX = (float)x;

winY = (float)viewport[3] - (float)y;

glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);

gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);

return CVector3(posX, posY, posZ);

}

A ještě jednou, tentokrát v Delphi...

function GetOGLPos(X, Y: Integer): T3D_Point;

var

viewport: array [1..4] of Integer;

modelview: array [1..16] of Double;

projection: array [1..16] of Double;

winZ: Single;

begin

glGetDoublev(GL_MODELVIEW_MATRIX, @modelview);

glGetDoublev(GL_PROJECTION_MATRIX, @projection);

glGetIntegerv(GL_VIEWPORT, @viewport);

Při testování jsem objevil, že pokud se v Delphi rovná y hodnota nule, vrací se nedefinovaná hodnota.

if (Y = 0) then Y := 1;

glReadPixels(X, -Y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, @winZ);

gluUnProject(X, viewport[4]-Y, winZ, @modelview, @projection, @viewport, Result[1], Result[2], Result[3]);

end;

Tak to bude vše. Myslím, že to ani nebolelo...

napsal: Luke Benstead <Lukerd84 (zavináč) lycos.co.uk>
přeložil: Přemysl Jaroš <xzf (zavináč) seznam.cz>

Anglický originál článku lze najít na adrese http://nehe.gamedev.net/data/articles/article.asp?article=13.

Zdrojové kódy