„Számítógépes grafika házi feladat tutorial” változatai közötti eltérés

Rohamcsiga (vitalap | szerkesztései)
Rohamcsiga (vitalap | szerkesztései)
Hozzáadtam a mátrix stack részt
3. sor: 3. sor:
{{Vissza|Számítógépes_grafika_és_képfeldolgozás}}
{{Vissza|Számítógépes_grafika_és_képfeldolgozás}}


Ez a tutorial nem helyettesíti az órán leadott tananyagot, de sokat segíthet a házi megírásában, ha esetleg nem volt időd órára járni, vagy valamelyik előadás nem volt teljesen világos. A leírás célja, hogy segítsen az alapvető buktatók elkerülésében, valamint választ adjon az évről-évre a listán újra és újra elhangzó kérdésekre.
Ez a tutorial alapvetően azt hivatott elmagyarázni, hogy hogyan kell az OpenGL-t használni. Ebből adódóan még minimális kitérőt se tesz a házik mögött álló elméleti háttér kifejesére, csak abba ad segítséget, hogy hogyan oldd meg a házidat. A háziknak pont az a célja, hogy az órán elsajátított elméletet gyakorolni tudd, így ha az elémlet ismerete nélkül vágsz neki a házinak, az lehet, hogy sikerülni fog, de a tárgy szempontjából semmi értelme nem lesz... Ez a tutorial nem helyettesíti az órán való jelenlétet.


'''Az oldalról kódot a saját házidba átemelni TILOS! Még ha pár sornyi kódról is van szó, gépeld be szépen magadtól, addig is gyakorlod a dolgot. Meg persze nem is érdemes másolgatni, mert csak borzolod vele a plágiumkereső idegeit, és sokban ronthat az esélyeiden az aláírás megszerzésére'''
'''Az oldalról kódot a saját házidba átemelni TILOS! Még ha pár sornyi kódról is van szó, gépeld be szépen magadtól, addig is gyakorlod a dolgot. Meg persze nem is érdemes másolgatni, mert csak borzolod vele a plágiumkereső idegeit, és sokban ronthat az esélyeiden az aláírás megszerzésére'''
336. sor: 336. sor:
</div>
</div>
- Egyáltalán nem intuitív, az origó a (7.817, 3.185) pontba kerül, és a két tengely nagyítása 2.084 és 2.43. Ezeknek az értékeknek semmi köze a kódban szereplő konstansokhoz!! <br/> <br/>
- Egyáltalán nem intuitív, az origó a (7.817, 3.185) pontba kerül, és a két tengely nagyítása 2.084 és 2.43. Ezeknek az értékeknek semmi köze a kódban szereplő konstansokhoz!! <br/> <br/>
* Tanulság: általában az eltolás - forgatás - nagyítás sorrendet szeretjük. Ez nem jelenti azt, hogy más sorrendnek ne lenne értelme, vagy egy konkrét problémának ne lehetne egyszerűbb megoldása másmilyen sorrendet használva.
* A probléma ami felmerül, hogy a transzformációk hatása permanens, azaz, ha egyszer elforgattad a világot, akkor az úgy marad, amíg vissza nem forgatod. Tehát ha egy objektum kirajzolása miatt akarsz hasznáni egy transzformációt akkor a rajzolás után azt mindenképpen, mindig vissza is kell csinálnod. De mi van ha egy összetett objektum kirajzolásához akár több száz transzformáció is kellet? Akkor a végén az összeset egybe vissza kell csinálni? Nincs erre jobb megoldás? A válasz természetesen az, hogy van, ez a megoldás a matrix stack.
=== Matrix stack ===
* Az OpenGL két függvényt ad amivel a matrix stack-et használhatjuk:
** <code> glPushMatrix(); </code>
*** A jelenleg aktív mátrixot (<code> GL_PROJECTION </code> vagy  <code> GL_MODELVIEW </code> ) elmenti annak a stackjébe.
** <code> glPopMatrix(); </code>
*** A jelenleg aktív mátrix stackjéből a legutóbb elmentett mátrixot visszaáálítja. A következő glPopMatrix() mátrix az az előtt elentett mátrixot állítja vissza.
* Megjegyzések:
** A <code> GL_MODELVIEW </code> stack mélysége legalább 32, a GL_PROJECTION mátrix-é pedig legalább 2.
*** Ez azt jelenti, hogy lehet, hogy nálad mindkét érték tízszer ekkora, de ha hordozható kódot akarsz írni, ekkor ennél nagyobb számokat nem feltételezhetsz.
*** Overflow / Underflow esetén a mátrix értéke meghatározatlan lesz.
* Pl:
<br/> <syntaxhighlight lang="c">
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix(); {
glRotatef(90, 0, 0, 1);
rajzolas(); // A rajzolaskor a világ el van forgatva
} glPopMatrix();
rajzolas2(); // It a világ már nincs elforgatva.
</syntaxhighlight> <br/>
* A matrix stack hierarchikusan felépülő testek rajzolását nagy mértékben megkönnyíti.
** Hierarhikus test pl: az emberi kéz.
*** Ha a felkarod elforgatod a vállad körül, akkor azzal az alkarod a csuklód és az ujjaid elmozdulnak. Minden izület transzformációja befolyásolja az összes csontot, ami belőle nő ki, és az összes csontot, ami a belőle kinövő csontokból nő ki, rekurzívan. Ha ezt manuálisan akarnánk leprogramozni, egy olyan fát kéne felépítenünk az izületekből, ahol a gyerekek száma változó. Ez nem lehetelen, de is kifejezetten izgalmas, viszont a matrix stack segítségével ez nagyon egyszerűen megoldhaó.
*** Pszeudó kóddal, feltételezve, hogy origó középpontú, egység hosszú, x-el párhuzamos főtengelyű hengert tudunk rajzolni a "henger kirajzolása" utasítással:
<pre>
glPushMatrix(); {
  váll körüli forgatás
  felkar hosszának a felével eltolás az x tengely mentén
  glPushMatrix(); {
    nagyítás a felkar méreteivel
    henger kirajzolása
  } glPopMatrix();
  felkar hosszának a felével eltolás az x tengely mentén
  könyök körüli forgatás
  alkar hosszának a felével eltolás az x tengely mentén
  glPushMatrix(); {
    nagyítás a alkar méreteivel
    henger kirajzolása
  } glPopMatrix();
  alkar hosszának a felével eltolás az x tengely mentén
  kéz kirajzolása
} glPopMatrix();
</pre>
* Sajnos ezt 2D-be nem lehet jól megmutatni, ezért kivételesen az ehhez kapcsolódó példaprogram 3D-s lesz.
** Technikailag a 3D rajzolást rábízzuk a glut-ra.
*** Kizárólag a <code> glutSolidCube() </code> függvényt fogjuk használni.
*** Ez a függvény - nem meglepő módón - egy [http://pastebin.com/HJKcgBsA kockát rajzol ki]:
<div style="text-align:left;margin:0px auto;">
http://i.imgur.com/PA2A3eQ.png
</div><br/>
* Ezt felhasználva a példaprogram: [http://pastebin.com/a3XtuCVh Robot kar]
** A program irányítása:
*** 'q' - Ujjak szétnyitása, 'a' - Ujjak összezárása
*** 'w' - Alkar felemelése, 's' - Alkar lehajtása
*** 'e' - Felkar felemelése, 'd' - Felkar lehajtása
*** 'r' - Az alap forgatása jobbra, 'f' - Az alap forgatása balra
<br/> <syntaxhighlight lang="c">
struct Vector {
  float x, y, z;
  Vector(float x, float y, float z) : x(x), y(y), z(z) { }
  void glTranslatef() { ::glTranslatef(x, y, z); }
  void glRotatef(float angle) { ::glRotatef(angle, x, y, z); }
  void glScalef() { ::glScalef(x, y, z); }
};
Vector x_axis(1, 0, 0), y_axis(0, 1, 0), z_axis(0, 0, 1);
Vector pos_crate(0, 0, -5), pos_left_base(1, 0, 0), pos_right_base(-1, 0, 0), scale_base(1, 1, 3),
      pos_main_arm(0, 0, -2), scale_main_arm(1, 1, 4), pos_lower_arm(0, 0, -1.5f),
      scale_lower_arm(0.7f, 0.7f, 3.0f), scale_wrist(1, 1, 1), pos_left_finger(0.5f, -1.0f, 0.0f),
      pos_right_finger(-0.5f, -1.0f, 0.0f), scale_finger(0.2f, 1.0f, 0.2f);
float rot_base = 0, rot_main_arm = 70, rot_lower_arm = -60,
      rot_finger = 20, rot_finger_relative = 20;
void onDisplay() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix(); {
    y_axis.glRotatef(rot_base);
    // Jobb oldali alap
    glPushMatrix(); {
      pos_right_base.glTranslatef();
      scale_base.glScalef();
      glutSolidCube(1.0f);
    } glPopMatrix();
   
    // Bal oldali alap
    glPushMatrix(); {
      pos_left_base.glTranslatef();
      scale_base.glScalef();
      glutSolidCube(1.0f);
    } glPopMatrix();
    x_axis.glRotatef(rot_main_arm);
    pos_main_arm.glTranslatef();
    // Felkar
    glPushMatrix(); {
      scale_main_arm.glScalef();
      glutSolidCube(1.0f);
    } glPopMatrix();
    pos_main_arm.glTranslatef();
    x_axis.glRotatef(rot_lower_arm);
    pos_lower_arm.glTranslatef();
    // Alkar
    glPushMatrix(); {
      scale_lower_arm.glScalef();
      glutSolidCube(1.0f);
    } glPopMatrix();
    pos_lower_arm.glTranslatef();
    // Csukló
    glPushMatrix(); {
      scale_wrist.glScalef();
      glutSolidCube(1.0f);
    } glPopMatrix();
    // Jobb 'ujj'
    glPushMatrix(); {
      z_axis.glRotatef(-rot_finger);
      glTranslatef(0, pos_right_finger.y, 0);
      glPushMatrix(); {
        glTranslatef(pos_right_finger.x, 0, 0);
        z_axis.glRotatef(-rot_finger_relative);
        scale_finger.glScalef();
        glutSolidCube(1.0f);
      } glPopMatrix();
      pos_right_finger.glTranslatef();
      z_axis.glRotatef(rot_finger_relative);
      scale_finger.glScalef();
      glutSolidCube(1.0f);
    } glPopMatrix();
    // Bal 'ujj'
    glPushMatrix(); {
      z_axis.glRotatef(rot_finger);
     
      glTranslatef(0, pos_left_finger.y, 0);
      glPushMatrix(); {
        glTranslatef(pos_left_finger.x, 0, 0);
        z_axis.glRotatef(rot_finger_relative);
        scale_finger.glScalef();
        glutSolidCube(1.0f);
      } glPopMatrix();
      pos_left_finger.glTranslatef();
      z_axis.glRotatef(-rot_finger_relative);
      scale_finger.glScalef();
      glutSolidCube(1.0f);
    } glPopMatrix();
  } glPopMatrix();
  // Láda
  glPushMatrix(); {
    pos_crate.glTranslatef();
    glutSolidCube(1.0f);
  } glPopMatrix();
  glutSwapBuffers();
}
</syntaxhighlight> <br/>
Az eredménye:
<div style="text-align:left;margin:0px auto;">
http://i.imgur.com/tpAuxBa.gif
</div>


== Régi wikiről áthozott rész, frissitésre szorul ==
== Régi wikiről áthozott rész, frissitésre szorul ==