|
Tutorial na pohyb glTranslatef() a rotaci glRotatef(). Načítání objektů ze souboru (*.txt)
|
|
|
Nejdříve si načteme objekt (krychli) ze souboru cube.txt. Soubor má tuto podobu
|
|
Vertices: 8
-1.0 -1.0 1 v0
-1.0 1.0 1 v1
1.0 -1.0 1 v2
1.0 1.0 1 v3
1.0 -1.0 -1 v4
1.0 1.0 -1 v5
-1.0 -1.0 -1 v6
-1.0 1.0 -1 v7
|
Hodnota za Vertices: nám zadává, kolik vertexů obsahuje objekt. Protože jde o krychli,
tak máme 8 vrcholů Další hodnoty jsou
X, Y, Z pozice jednotlivých vrcholů. v0 - v7 je jen informativní text,
který se nenačítá. To samé platí o textu Vertices:.
Pro načítání objektů a jejich vykreslování si vytvoříme tyto datové typy
|
|
//---------------------------------------------------------------------------
typedef struct //struktura pro 3D bod
{
GLfloat x, y, z; //bod x, y, z
} TPoint3d;
//---------------------------------------------------------------------------
typedef struct //struktura objektu
{
int verts; //počet vrcholů
TPoint3d *points; //vrchol je složen z bodu x, y, z
} TGLObject;
//---------------------------------------------------------------------------
|
Vytvoříme si objekt typu TGLObject
|
|
TGLObject cube1; //objekt cube1
|
A budeme volat funkci pro načtení objektu ze souboru cube.txt
|
|
void LoadAllObjects() //načti objekty
{
cube1 = LoadObject("objects/cube.txt", &cube1); //načti hodnoty uložené v souboru cube.txt a předej je objektu cube1
}
|
Funkce pro načítání vypadá takto
|
|
TGLObject LoadObject(char *name, TGLObject *k) //načti objekt se souboru (name)
{
//definice proměnných
int ver; //pomocná proměnná pro počet vrcholů objektu
GLfloat rx,ry,rz; //pomocna proměnna pro X, Y, Z pozici vrcholu objektu
FILE *filein; //definice souboru, který budeme číst
char oneline[255]; //definice řádku souboru s maximálně 255 znaky
//kód
if ((filein = fopen(name, "rt"))== NULL) //zkus otevřít soubor pro čtení v textovém modu "rt"
{
ShowMessage("Cannot open input file"); //jestli se to nezdaří, hoď chybovou hlášku
}
else //jinak pokračuj v práci s načteným souborem
{
ReadLine(filein,oneline); //volej funkci pro načtení řádky ze souboru
sscanf(oneline, "Vertices: %d\n", &ver); //přečti z první řádky počet vrcholů a předej ho proměnné ver
k = new TGLObject; //dynamicky alokuj pamět pro objekt (cube1)
k->points = new TPoint3d[ver]; //dynamicky alokuj pamět pro počet vrcholů objektu
k->verts = ver; //načtenou hodnotu počtu vrcholů předej vrcholům objektu
for (int i=0;i<
ver;i++) //cykluj podle počtu vrcholů
{
ReadLine(filein,oneline); //čti řádek po řádku
sscanf(oneline, "%f %f %f", &rx, &ry, &rz); //najdi v řádce tři čísla typu float a předej je hodnotám rx, ry, rz
k->points[i].x = rx; //předej bodu X (aktuálního vrcholu) hodnotu rx
k->points[i].y = ry; //předej bodu Y (aktuálního vrcholu) hodnotu ry
k->points[i].z = rz; //předej bodu Z (aktuálního vrcholu) hodnotu rz
}
fclose(filein); //zavři soubor
}
return *k; //vrať funkci hodnoty všech vrcholů objektu
}
|
Tato funkce používá pro načtení řádky ze souboru funkci
|
|
void ReadLine(FILE *f,char *s) //čti řádek ze souboru f a ukládej do řetězce s
{
do //cykluj
{
fgets(s, 255, f); //a čti znak po znaku maximálně však 255
} while ((s[0] == '/') || (s[0] == '\n')); //dokud se nedostaneš na konec řádky
return; //vrať funkci hodnotu načteného řádku
}
|
Funkce pro načítání objektů se samozřejmě provádějí jen jednou, při startu aplikace.
Při startu aplikace také musíme zapnout DEPTH buffer glEnable(GL_DEPTH_TEST);.
Pokud bychom nechali vypnutý DEPTH buffer, objekty by se vykreslovali v tom pořadí, v jakém
jsou volány, takže by se stalo, že by se zadní stěna krychle vykreslila před přední.
|
|
bool __fastcall TForm1::InitGL()
{
...
...
////sem budu zadávat funkce, které se mají provádět jen při startu aplikace////
glEnable(GL_DEPTH_TEST); //zapni hloubkový (DEPTH) buffer, aby objekty blíž ke kameře překrývali vzdálenější
LoadGLTextures(); //vytvoř textury
LoadAllObjects(); //načti objekty
////konec zadávání funkcí, které se mají provádět jen při startu aplikace////
...
...
}
|
Ještě, než začneme vykreslovat objekt, vypočítáme si pohyb a rotaci.
|
|
//definice proměnných
extern GLuint Texture[1]; //2d textura, pole s jednou texturou
extern TGLObject cube1; //objekt krychle
TPoint3d angle; //úhel rotace objektu
TPoint3d translate; //pozice objektu
TPoint3d direction; //směr pohybu objektu
bool start=true; //pomocná proměnná pro načítání základních hodnot při startu aplikace
//---------------------------------------------------------------------------
void TranRotCube() //vypočítej pohyb a rotaci
{
//začátek výpočtu pohybu objektu
if (start) //jestliže probíhá první otočka cyklu
{
direction.x = 1; //nastav směr pohybu objektu v X směru na 1
direction.y = 1; //nastav směr pohybu objektu v Y směru na 1
direction.z = 1; //nastav směr pohybu objektu v Z směru na 1
translate.z = -8; //nastav Z pozici objektu
start = false; //nastav start na false, aby při další otočce cyklu se základní hodnoty nenačítaly
}
if ((translate.x >= 3) || (translate.x <= -3)) //jetliže X pozice objektu přesáhne hodnoty 3 nebo -3
{
direction.x = -direction.x; //otoč směr pohybu X
}
translate.x = translate.x + (0.01 * direction.x); //přičti 0.01 pozici X, podle směru pohybu X
if ((translate.y >= 2) || (translate.y <= -2)) //jetliže Y pozice objektu přesáhne hodnoty 2 nebo -2
{
direction.y = -direction.y; //otoč směr pohybu Y
}
translate.y = translate.y + (0.01 * direction.y); //přičti 0.01 pozici Y, podle směru pohybu Y
if ((translate.z >= -6) || (translate.z <= -20)) //jetliže Z pozice objektu přesáhne hodnoty -6 nebo -20
{
direction.z = -direction.z; //otoč směr pohybu Z
}
translate.z = translate.z + (0.01 * direction.z); //přičti 0.01 pozici Z, podle směru pohybu Z
//konec výpočtu pohybu objektu
//začátek výpočtu rotace objektu
angle.x = angle.x + 0.5; //přičti úhel x rotace
if (angle.x >= 360) //jestliže je úhel větší, než 360 stupňů
{
angle.x = angle.x -360; //odečti 360 stupňů
}
angle.y = angle.y + 1; //přičti úhel y rotace
if (angle.y >= 360) //jestliže je úhel větší, než 360 stupňů
{
angle.y = angle.y -360; //odečti 360 stupňů
}
angle.z = angle.z + 1.5; //přičti úhel z rotace
if (angle.z >= 360) //jestliže je úhel větší, než 360 stupňů
{
angle.z = angle.z -360; //odečti 360 stupňů
}
//konec výpočtu rotace objektu
}
|
Nyní můžeme vykreslovat objekt v nekonečné smyčce.
|
|
GLvoid DrawCube(GLvoid) //vykresli krychli
{
TranRotCube(); //vypočítej pohyb a rotaci krychle
//začátek bloku OpenGL příkazu pro vykreslení objektu (krychle)
glEnable(GL_TEXTURE_2D); //zapni 2D texturování
glBindTexture(GL_TEXTURE_2D, Texture[0]); //potáhni následující objekt texturou číslo 0
glPushMatrix; //začátek prostorové matice
//posouvej a rotuj objektem (který je mezi glPushMatrix; a glPopMatrix;) podle vypočtených hodnot
glTranslatef( translate.x, translate.y, translate.z); //pohni celým objektem
glRotatef( angle.x, 1, 0, 0); //rotuj objektem v X směru
glRotatef( angle.y, 0, 1, 0); //rotuj objektem v Y směru
glRotatef( angle.z, 0, 0, 1); //rotuj objektem v Z směru
glBegin(GL_TRIANGLES); //začni vykreslovat trojúhelníky
//------------------------
//přední stěna krychle
//první trojúhelník
glTexCoord2f( 0, 0); glVertex3f( cube1.points[0].x, cube1.points[0].y, cube1.points[0].z); //levý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[1].x, cube1.points[1].y, cube1.points[1].z); //levý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[2].x, cube1.points[2].y, cube1.points[2].z); //pravý dolní vrchol textury a výsledného čtverce
//druhý trojúhelník
glTexCoord2f( 1, 1); glVertex3f( cube1.points[3].x, cube1.points[3].y, cube1.points[3].z); //pravý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[2].x, cube1.points[2].y, cube1.points[2].z); //pravý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[1].x, cube1.points[1].y, cube1.points[1].z); //levý horní vrchol textury a výsledného čtverce
//-------------------------
//pravá stěna krychle
//první trojúhelník
glTexCoord2f( 0, 0); glVertex3f( cube1.points[2].x, cube1.points[2].y, cube1.points[2].z); //levý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[3].x, cube1.points[3].y, cube1.points[3].z); //levý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[4].x, cube1.points[4].y, cube1.points[4].z); //pravý dolní vrchol textury a výsledného čtverce
//druhý trojúhelník
glTexCoord2f( 1, 1); glVertex3f( cube1.points[5].x, cube1.points[5].y, cube1.points[5].z); //pravý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[4].x, cube1.points[4].y, cube1.points[4].z); //pravý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[3].x, cube1.points[3].y, cube1.points[3].z); //levý horní vrchol textury a výsledného čtverce
//-------------------------
//zadní stěna krychle
//první trojúhelník
glTexCoord2f( 0, 0); glVertex3f( cube1.points[4].x, cube1.points[4].y, cube1.points[4].z); //levý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[5].x, cube1.points[5].y, cube1.points[5].z); //levý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[6].x, cube1.points[6].y, cube1.points[6].z); //pravý dolní vrchol textury a výsledného čtverce
//druhý trojúhelník
glTexCoord2f( 1, 1); glVertex3f( cube1.points[7].x, cube1.points[7].y, cube1.points[7].z); //pravý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[6].x, cube1.points[6].y, cube1.points[6].z); //pravý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[5].x, cube1.points[5].y, cube1.points[5].z); //levý horní vrchol textury a výsledného čtverce
//-------------------------
//levá stěna krychle
//první trojúhelník
glTexCoord2f( 0, 0); glVertex3f( cube1.points[6].x, cube1.points[6].y, cube1.points[6].z); //levý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[7].x, cube1.points[7].y, cube1.points[7].z); //levý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[0].x, cube1.points[0].y, cube1.points[0].z); //pravý dolní vrchol textury a výsledného čtverce
//druhý trojúhelník
glTexCoord2f( 1, 1); glVertex3f( cube1.points[1].x, cube1.points[1].y, cube1.points[1].z); //pravý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[0].x, cube1.points[0].y, cube1.points[0].z); //pravý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[7].x, cube1.points[7].y, cube1.points[7].z); //levý horní vrchol textury a výsledného čtverce
//-------------------------
//vrchní stěna krychle
//první trojúhelník
glTexCoord2f( 0, 0); glVertex3f( cube1.points[1].x, cube1.points[1].y, cube1.points[1].z); //levý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[7].x, cube1.points[7].y, cube1.points[7].z); //levý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[3].x, cube1.points[3].y, cube1.points[3].z); //pravý dolní vrchol textury a výsledného čtverce
//druhý trojúhelník
glTexCoord2f( 1, 1); glVertex3f( cube1.points[5].x, cube1.points[5].y, cube1.points[5].z); //pravý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[3].x, cube1.points[3].y, cube1.points[3].z); //pravý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[7].x, cube1.points[7].y, cube1.points[7].z); //levý horní vrchol textury a výsledného čtverce
//-------------------------
//spodní stěna krychle
//první trojúhelník
glTexCoord2f( 0, 0); glVertex3f( cube1.points[6].x, cube1.points[6].y, cube1.points[6].z); //levý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[0].x, cube1.points[0].y, cube1.points[0].z); //levý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[4].x, cube1.points[4].y, cube1.points[4].z); //pravý dolní vrchol textury a výsledného čtverce
//druhý trojúhelník
glTexCoord2f( 1, 1); glVertex3f( cube1.points[2].x, cube1.points[2].y, cube1.points[2].z); //pravý horní vrchol textury a výsledného čtverce
glTexCoord2f( 1, 0); glVertex3f( cube1.points[4].x, cube1.points[4].y, cube1.points[4].z); //pravý dolní vrchol textury a výsledného čtverce
glTexCoord2f( 0, 1); glVertex3f( cube1.points[0].x, cube1.points[0].y, cube1.points[0].z); //levý horní vrchol textury a výsledného čtverce
//-------------------------
glEnd(); //ukonči vykreslování trojúhelníků
glPopMatrix; //konec prostorové matice
//konec bloku OpenGL příkazu pro vykreslení objektu (krychle)
}
|
V této funkci DrawCube() konečně používáme OpenGL příkazy. Všechny předešlé funkce nemají s OpenGL nic
společného. Provádějí jen náčítání hodnot ze souboru cube.txt a výpočet pohybu a rotace.
glTranslatef( translate.x, translate.y, translate.z); - pohybuje objektem v X,Y,Z směru, podle předem vypočtených hodnot translate.x, translate.y, translate.z
glRotatef( angle.x, 1, 0, 0);
glRotatef( angle.y, 0, 1, 0);
glRotatef( angle.z, 0, 0, 1); - rotují objektem v X,Y,Z směru, podle předem vypočtených hodnot angle.x, angle.y, angle.z
glVertex3f( cube1.points[0].x, cube1.points[0].y, cube1.points[0].z);
glVertex3f( cube1.points[1].x, cube1.points[1].y, cube1.points[1].z);
glVertex3f( cube1.points[2].x, cube1.points[2].y, cube1.points[2].z);
glVertex3f( cube1.points[3].x, cube1.points[3].y, cube1.points[3].z);
glVertex3f( cube1.points[4].x, cube1.points[4].y, cube1.points[4].z);
glVertex3f( cube1.points[5].x, cube1.points[5].y, cube1.points[5].z);
glVertex3f( cube1.points[6].x, cube1.points[6].y, cube1.points[6].z);
glVertex3f( cube1.points[7].x, cube1.points[7].y, cube1.points[7].z);
- vykreslí krychli z trojúhelníků, podle načtených hodnot cube1.points[ ], ze souboru cube.txt
|
|
|
Při ukončování aplikace nesmíme zapomenout vymazat objekt z paměti.
|
|
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
...
...
...
DeleteAllObjects(); //vymaž objekty z paměti
}
//---------------------------------------------------------------------------
void DeleteAllObjects() //vymaž objekty
{
cube1 = DeleteObject(&cube1); //vymaž objekt cube1 z paměti
}
//---------------------------------------------------------------------------
TGLObject DeleteObject(TGLObject *k) //vymaž objekt z paměti
{
delete k->points; //vymaž všechny body objektu z paměti
delete k; //vymaž objekt z paměti
return *k; //vrať funkci hodnotu k
}
Home