11.07.2015 Aufrufe

c't magazin für computer technik 24/2013 - since

c't magazin für computer technik 24/2013 - since

c't magazin für computer technik 24/2013 - since

MEHR ANZEIGEN
WENIGER ANZEIGEN
  • Keine Tags gefunden...

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

Know-how I OpenGL ESEin texturiertesPrisma mit drei,sechs und zwölfSeiten zeigt dieAnnäherung anden Zylinder.spiel durch Rundungsfehler einschleichenkönnen.Zu dem Zylinder kommt man über einen2D-Kreis, den man "hochzieht": Statt diePunkte auf der Kreislinie direkt zu verbinden,erzeugt man einen weiteren Punkt in derdritten Dimension weiter oben. Dadurch entstehtein Zackenmuster, das sich um einenKreis herumwickelt. Die Methode build() derKlasse GLCylinder zeigt, wie das geht (siehe dasListing aufS. 213).Mit den vorbereiteten Daten sieht dasZeichnen in der Methode GLCylinder.draw() dannin etwa wie folgt aus:gl.glEnableClientState(GL 1 O.GL_ VERTEX_ARRAY);gl.glVertexPointer(3, GL 10.GL_FLOAT, 0, vertexßuffer);gl.glDrawArrays(GL 1 O.GL_ TRIANGLE_STRIP, 0,vertexßuffer.capacity() I 3);vertexßuffer .rewind();Die Funktion glEnableClientState() stellt den Zeichenkontextso ein, dass das Zeichnen vonPunkten aus einem Array überhaupt erstmöglich wird. Welches Array die zu zeichnendenEckpunkte enthält, bestimmt glVertex­Pointer(). Der obige Aufruf besagt, dass dreiKoordinaten (x, y, z) vom Typ float einen einzelnenEckpunkt ergeben und die Eckpunktedirekt hintereinander im Array vertexßuffer gespeichertsind.vertexßuffer ist vom Typ Floatßuffer. Diese Klasseunterhält einen Cursor, der angibt, welchesElement des Puffers zuletzt bearbeitetwurde. Darum setzt die Methode draw() diesenCursor mit rewind() zurück, sodass dasnächste Zeichenkommando wieder an derAnfangsposition des Puffers anfängt.Je enger die gezeichneten Eckpunkte aufdem Kreis liegen, der so erzeugt wird, destoeher sieht das Ganze nach einem Zylinderaus. Die Fläche, die jeweils vier Punkte (zweiDreiecke) beschreiben, nennt man auchFaces (Oberflächen). Im Beispiel-Code kannman die Anzahl der zu generierenden Facesdem Konstruktor von GLCylinder mitgeben.MittendrinIn OpenGL ES steht der Betrachter (fallsnichts anderes angegeben ist) im Ursprungeines Koordinatensystems, dessen x-Achsenach rechts, y-Achse nach oben und z-Achseaus der Zeichenebene heraus verläuft; derBetrachter blickt dabei in Richtung der negativenz-Achse. Um den Zylinder, dessenGrundriss hier in der x/z-Ebene liegt, vonschräg oben zu betrachten, muss man denBetrachter relativ zum Zylinder bewegen.Wie in OpenGL üblich, geschieht dies, indemman die ganze Weit um den Betrachterherum bewegt. ln GLRenderer.onDrawFrame() wirdhierfür bei jedem Zeichnen eines Frames Folgendesausgeführt:gl.glMatrixMode(GL 10.GL_MODELVIEW);gl.glloadldentity();gl.glT ranslatef(O, 0, -7);gl.glRotatef(tilt, 1, 0, 0);gl.glRotatef(yaw, 0, 1, 0);cylinder.draw(gl);Das manipuliert zunächst die Modei-View­Matrix, die die Position und Orientierungzwischen dem Betrachter und dem betrachtetenModell festlegt. Die mit glloadldentity()geladene Einheitsmatrix, die dem oben beschriebenenNormalfall entspricht, überschreibteine eventuell vorhandene andereMatrix. Soll der Betrachter nun vor dem Modellstehen, kann man das erreichen, indemman die gesamte zu zeichnende Welt überglTranslate() in z-Richtung nach hinten versetzt.Außerdem wird der Zylinder um tilt Grad umseine x-Achse gedreht sowie um yaw Grad umseine y-Achse.Der nächste Schritt belegt den Zylindermit einer Textur, macht also quasi aus demZylinder eine mit dem Panoramabild beklebteLitfaßsäule.LitfaßsäuleDazu muss man erstmal die Textur in denSpeicher laden. Das geschieht in der MethodeGLCylinder.setTexture() (siehe Listing unten).glGenTextures() weist dem Texturpuffer eineKennung zu, unter der man die Textur späterreferenzieren kann (Zeile S). Die Funktion erlaubtdas Erzeugen von beliebig vielenNummern mit einem Aufruf. ln diesem Beispielreicht eine einzige. Das Zuweisen derTextur zu einer ID ist in diesem Beispiel deshalbeigentlich nicht nötig. Mögliche spätereErweiterungen des Programms auf mehrereTexturen würden das Erstellen und Zuordneneiner ID dann aber sehr wohl erfordern.Die Verwendung dieser Nummer im Aufrufvon glBindTexture() (Zeile 6) besagt, dassOpenGL ES die soeben erzeugte Textur beimZeichnen heranziehen soll.Dies klingt zuerst einmal seltsam, weil janoch kein Bild geladen wurde. Die gerade aktiveTextur ist aber schon von Anfang an vorhanden,ihr ist lediglich noch kein Bild zugeordnet.Die Zuordnung holt der folgendeAufrufvon GLUtils.texlmage2D() nach (Zeile 7).Nun muss man noch das Verhalten fürden Fall definieren, dass das Bild kleiner odergrößer als das Original dargestellt werdensoll. Dies übernimmt die Funktion glTexParameterx()(Zeilen 8-9). Die Parameter GL_TEXTURE_MIN_FILTER und GL_TEXTURE_MAG_FILTER bestimmen,welcher Algorithmus beim Vergrößernoder Verkleinern des Bildes zum Einsatzkommt: GL_LINEAR bedeutet, dass die Pixel linearinterpoliert werden.Da das Bild nun im Grafikspeicher liegt,kann man den vom Bild belegten Hauptspeichermit recycle() freigeben.Als Nächstes muss man festgelegen, wiedie Textur auf dem Objekt erscheinen soll.Der mit Texturversehene Zylinderzeigt schon dasrichtige Bild - nunbraucht es nur nochden richtigenBlickwinkel ...1 private void setTexture(GL10 gl, Bitmap bmp) (1 ByteButter b = ByteButter.allocateDirect(lnteger.SIZEl;3 b.order(ByteOrder.nativeOrder());4 textureButfer = b.aslntBufferO;5 gl.glGenTextures(1, textureßutferl;6 gl.glßi ndTexture(GL 10. GL_TEXTURE_1D, textureButt er .get(O));7 GLUti ls.texlmage1D(GL10.GL_T EXTURE_1D, 0, bmp, 0);8 g l . gl TexPa rameterx ( GL 10. GL_T EXTURE_1D,9 GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEARl;10 g l . gl TexPa rameterx ( GL 10. GL_T EXTURE_1D,11 GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);11 bmp .recycle();13 }GLCylinder.setTexture() lädt eine Bitmap als Textur und markiertsie als aktiv. giTexPara meterx() legt fest, dass die Texturpixel beimVergrößern und Verkleinern linear interpoliert werden.214<strong>c't</strong> <strong>2013</strong>, Heft <strong>24</strong>

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!