OpenGL v Delphi 5



Pohyb a rotace objektu

Příklad a zdroják ke stažení (463k)

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:.

cube.jpg(6 kb)

Pro načítání objektů a jejich vykreslování si vytvoříme tyto datové typy
type
  TPoint3d=record    //struktura pro 3D bod
    x: TGLFloat;    //bod x
    y: TGLFloat;    //bod y
    z: TGLFloat;    //bod z
end;


type
  TGLObject=record    //struktura objektu
  vers: integer;    //počet vrcholů
  points: array of TPoint3d;    //vrchol je složen z bodu x, y, z
end;
Vytvoříme si objekt typu TGLObject
var
  cube1: TGLObject;    //objekt cube1
A budeme volat proceduru pro načtení objektu ze souboru cube.txt
procedure LoadAllObjects;    //načti objekty
begin
  cube1 := LoadObject('objects/cube.txt', cube1);    //načti hodnoty uložené v souboru cube.txt a předej je objektu cube1
end;
Funkce pro načítání vypadá takto
function LoadObject(name: string; k: TGLObject): TGLObject;    //načti objekt se souboru (name)
var
  i: integer;    //cyklus
  filein: TextFile;    //soubor, který budeme číst
  ver: integer;    //počet vrcholů objektu, pomocná proměnná
  rx,ry,rz: TGLFloat;    //X, Y, Z pozice vrcholů objektu, pomocná proměnná
  Vertices: string[9];    //string o velikosti 10 znaků (Vertices:)
begin  AssignFile(filein, name);    //spoj proměnnou filein se souborem name
  try    //zkus otevřít soubor
    Reset(filein);    //otevři soubor pro čtení
    Readln(filein,  Vertices, ver);    //přečti první řádku, načti string o délce 10 znaků, aby jsi přeskocil string Vertices: a načti počet vrcholů ver
    SetLength(k.points, ver);    //nastav velikost dynamického pole bodů points

    for i := 0 to ver-1 do begin  //cykluj podle počtu vrcholů
      Readln(filein, rx, ry, rz);    //přečti další řádku a načti hodnoty X, Y, Z
      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
    end;
    finally    //a nakonec
      CloseFile(filein);    //zavři soubor
    end;

  result := k;    //vrať funkci hodnoty všech vrcholů objektu

end;
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í.
procedure TForm1.InitWindow;
begin
  ...
  ...
    ////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////
  ...
  ...
end;
Ještě, než začneme vykreslovat objekt, vypočítáme si pohyb a rotaci.
var
  angle: TPoint3d;    //úhel rotace objektu
  translate: TPoint3d;    //pozice objektu
  direction: TPoint3d;    //směr pohybu objektu
  start: boolean=true;    //pomocná proměnná pro načítání základních hodnot při startu aplikace


procedure TranRotCube;
begin
    //začátek výpočtu pohybu objektu
    if (start) then     //jestliže probíhá první otočka cyklu
    begin
      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
    end;

    if ((translate.x >= 3) or (translate.x <= -3)) then  //jetliže X pozice objektu přesáhne hodnoty 3 nebo -3
    begin
        direction.x := -direction.x;    //otoč směr pohybu X
    end;
    translate.x := translate.x + (0.01 * direction.x);    //přičti 0.01 pozici X, podle směru pohybu X

    if ((translate.y >= 2) or (translate.y <= -2)) then    //jetlize Y pozice objektu přesáhne hodnoty 2 nebo -2
    begin
        direction.y := -direction.y;    //otoč směr pohybu Y
    end;
    translate.y := translate.y + (0.01 * direction.y);    //přičti 0.01 pozici Y, podle směru pohybu Y

    if ((translate.z >= -6) or (translate.z <= -20)) then    //jetliže Z pozice objektu přesáhne hodnoty -6 nebo -20
    begin
        direction.z := -direction.z;    //otoč směr pohybu Z
    end;
    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) then    //jestliže je úhel větší, než 360 stupňů
    begin
      angle.x := angle.x -360;    //odečti 360 stupňů
    end;

    angle.y := angle.y + 1;    //přičti úhel Y rotace
    if (angle.y >= 360) then    //jestliže je úhel větší, než 360 stupňů
    begin
      angle.y := angle.y -360;    //odečti 360 stupňů
    end;

    angle.z := angle.z + 1.5;    //přičti úhel Z rotace
    if (angle.z >= 360) then    //jestliže je úhel větší, než 360 stupňů
    begin
      angle.z := angle.z -360;    //odečti 360 stupňů
    end;
    //konec výpočtu rotace objektu
end;
A nakonec budeme vykreslovat objekt v nekonečné smyčce.
procedure DrawCube;    //vykresli krychli
begin
    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)
end;
V této proceduře 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

Stejný tutorial pro C++ najdete zde


2D Textura Výpočet FPS a plynulé animace




Home