Zylinder

Aus DGL Wiki
Version vom 21. März 2012, 15:29 Uhr von Openglerf (Diskussion | Beiträge) (Vorraus -> Voraus)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Allgemein

Der folgende Code zeichnet einen Zylinder in einem Würfel der Kantenlänge 2. Dadurch lassen sich beim Zeichnen die Positionskoordinaten auch direkt für die Normalen des Zylinders nutzen. Der Körper des Zylinders sowie die Endkappen werden mit der aktuell gebundene Textur gezeichnet. Will man jede der Flächen mit einer anderen Textur versehen, so muss diese zwischen den einzelnen Abschnitten gewechselt werden.

Verwendete Typen

Type
  TVector3f = Record
    x, y, z  : Single;
  End;

Parameter

Der einzige Parameter n der Prozedur bestimmt die Anzahl der Unterteilungen des Zylinders. Die Größe des Objektes wird durch ein vorangehendes glScalef festgelegt, welches als Parameter jeweils die Radien des Objektes in den verschiedenen Koordinatenachsen enthält.

Procedure

Procedure DrawCylinder(n : Byte);
Const
  Two_PI  = PI * 2;
  Half_PI = PI / 2;
Var
  i          : Integer;
  vect       : TVector3f;
  SinCosData : Array of Extended;
Begin
  If n < 4 then exit;
  If n = 4 then DrawCube;  //Ein Zylinder mit 4 Seiten ist ein Würfel - falls es jemanden interessiert *gg*

  glEnable(GL_NORMALIZE);  //Aktiviere GL_NORMALIZE damit die Normalen nach dem glScale auch die richtige Länge haben

  //Berechne die Sinus- und Cosinus-werte einmalig im Voraus
  SetLength(SinCosData, (n+1)*2);
  for i := 0 to n do
    SinCos(i/n * Two_PI, SinCosData[i*2], SinCosData[i*2+1]);

  glBegin(GL_QUAD_STRIP);
  for i := 0 to n do
  begin
    vect.x := SinCosData[i*2];
    vect.z := SinCosData[i*2+1];
    vect.y := 1;

    glTexCoord2f(i/n, 0);
    glNormal3f(vect.x, 0, vect.z);
    glVertex3fv(@vect);

    vect.y := -1;

    glTexCoord2f(i/n, 1);
    glNormal3f(vect.x, 0, vect.z);
    glVertex3fv(@vect);
  end;
  glEnd;

  //Zeichnen der oberen Endkappe
  glBegin(GL_TRIANGLE_FAN);
  vect.y := 1;
  glNormal3f(0, 1, 0);
  glTexCoord2f(0.5, 0.5);
  glVertex3f(0, 1, 0);
  for i := 0 to n do
  begin
    vect.x := SinCosData[i*2];
    vect.z := SinCosData[i*2+1];
    glTexCoord2f(vect.x*0.5 + 0.5, vect.z*0.5 + 0.5);
    glVertex3fv(@vect);
  end;
  glEnd;

  //Zeichnen der unteren Endkappe
  glBegin(GL_TRIANGLE_FAN);
  vect.y := -1;
  glNormal3f(0, -1, 0);
  glTexCoord2f(0.5, 0.5);
  glVertex3f(0, -1, 0);
  for i := n downto 0 do
  begin
    vect.x := SinCosData[i*2];
    vect.z := SinCosData[i*2+1];
    glTexCoord2f(0.5 - vect.x*0.5, vect.z*0.5 + 0.5);
    glVertex3fv(@vect);
  end;
  glEnd;

  glDisable(GL_NORMALIZE);
End;


Beispiel Aufruf

Einen Zylinder mit der Höhe 3 und dem Radius 4 zeichnet man mit der Prozedur wie folgt:

glPushMatrix;             //Sichere die Matrix
glTranslatef(0, 1.5, 0);  //Verschiebe den Mittelpunkt des Zylinders an die Position (0 | 1.5 | 0)
glScalef(4, 3 / 2, 4);    //Die Höhe wird halbiert, da bei glScale die radien des Objektes stehen sollen
DrawCylinder(16);         //Zeichne den Zylinder mit 16 Unterteilungen
glPopMatrix;              //Setzte die Matrix auf den Ausgangszustand zurück