image image


Pulsierende Wellen mit Processing.py

Manchmal stellt man fest, daß die Welt nicht nur aus Kisten und Kugeln besteht, sondern daß man auch andere, komplexere dreidimensionale Formen in Processing.py, dem Python-Mode von Processing, programmieren möchte. Diese fügt man in der Regel aus Gittern (Meshes) zusammen, bewährt haben sich Gitter aus Drei- oder aus Vierecken. Diese kann man sowohl im zwei-, wie auch im dreidimensionalen in Processing aus Vertizes zusammenbauen. Ich habe das mal am Beispiel einer pulsierenden, dreidimensionalen Welle, die auf einem mathematischen Algorithmus beruht, nachprogrammiert1. Doch zuerst einmal ein Video mit dem fertigen Ergebnis:

Zuerst einmal habe ich einige Konstanten definiert und dann im setup() nur die Fenstergröße festgelegt:

ringWidth = 0.04
ringSteps = 8.0
maxi = 240

def setup():
    size(600, 400, P3D)

Die eigentliche Programmlogik beherbergt die Funktion draw(). Hier wird erst einmal die Hintergrundfarbe definiert, das Licht eingeschaltet (ohne Beleuchtung seht Ihr im dreidimensionalen Raum von Processing nichts) und dann der Ursprung des Koordinatensystems für die x-Achse in die Mitte des Fensters und für die y-Achse in das untere Viertel des Fensters transformiert.

def draw():
    background(108, 131, 163)
    
    lights()
    translate(width/2, 3*height/8.0)
    rotateX(radians(55))
    scale(height/2.0, height/2.0)

Das Rotieren der x-Achse um 55 Grad füllt das Fenster vollständig aus, nette Ansichten erhaltet Ihr aber auch, wenn Ihr die x-Achse um 20 Grad (rotateX(radians(20))) oder um 85 Grad (rotateX(radians(84))) rotiert. Im ersten Fall seht Ihr die Funktion von oben, im zweiten Fall von der Seite schräg von unten und so könnt Ihr beobachten, wie sich die Spitze der Welle auch nach unten durchschlägt.

Die Funktion ist sehr »schlank«, ohne die scale()-Funktion seht Ihr nur einen Strich. Daher wurde sie in x- und y-Richtung fensterfüllend ausgehnt.

Das eigentliche Zeichnen erledigt die Processing.py-eigene with-Konstruktion:

    with beginShape(QUAD_STRIP):
        i = -ringSteps
        while i < maxi:
            r0 = ringWidth*(i*1.0/ringSteps)
            r1 = r0 + ringWidth
            if r0 < 0.0:
                r0 = 0.0
            theta = i*(TWO_PI/ringSteps)
            makeVertex(r0, theta)
            makeVertex(r1, theta)
            i += 1

Die Vertizes sollen rechteckige Streifen sein (QUAD_STRIP) und die eigentlich Funktion soll in Polarkoordinaten mit rho und theta berechnet werden. Von rho werden zwei Werte (r0 und r1) berechnet, während theta für beide Werte gleich bleibt.

Die Berechnung und das Zeichnen des Gebildes wird in der Funktion makeVertex() erledigt:

def makeVertex(r, theta):
    x = r*cos(theta)
    y = r*sin(theta)
    z = 100*exp(-3*r*r)*cos((r*2*TWO_PI) - (frameCount/50.0))
    fill(163, 143, 109)
    stroke(0)
    strokeWeight(0.01)
    vertex(x, y, z)

In den ersten beiden Zeilen wird die Ebene von Polarkoordinaten in kartesischen Koordinaten transformiert und in der dritten Zeile findet die Berechnung der Wellenfunktion statt. Hier ist der Ort, wo Ihr für eigene Experimente ansetzen könnt. Ändert einzelne Werte der Wellenfunktion und schaut nach, wie sich das auf das Ergebnis auswirkt.

Da sich – zumindest in meinem Processing 3.3.7 – das scale() auch auf die Liniendicke auswirkte, mußte ich das Gewicht der Gitterlinien mit strokeWeigt(0.01) auf einen sehr kleinen Wert setzen. Ansonsten bekam ich nämlich nur sehr, sehr dicke, schwarze Gitterlinien zu sehen, die die eigentliche Welle fast vollständig bedeckten.

beginShape() kann mit diversen Parametern aufgerufen werden, die Einfluß darauf haben, wie die Vertizes gezeichnet werden. Die wichtigsten davon sind:

  • POINTS zeichnet nur die einzelnen Eck-Punkte der Vertizes.
  • LINES zeichnet einzelne Linien, die aber nicht zu geschlossenen Polygonen zusammengeführt werden.
  • TRIANGLES zeichnet einzelne Dreiecke, die ebenfalls keine geschlossene Fläche bilden.
  • TRIANGLE_STRIP zeichnet ein Mesh aus Dreiecken.
  • QUADS zeichnet einzelne Vierecke. Auch diese Vierecke bilden keine geschlossene Fläche.
  • QUAD_STRIP zeichnet ein Mesh aus Vierecken, wie in unserem obigen Programm.

Setzt diese Parameter doch im Sketch einfach einmal einmal ein, um ihre Auswirkungen kennenzulernen. Ihr werdet interessante Dinge sehen2.

Wird beginShape() ohne Parameter aufgerufen werden und soll die entstehende Fläche mit einer Füllfarbe gefüllt werden, so muß am Ende zwingend ein endShape(CLOSE) aufgerufen werden. In diesem Falle ist die elegante with-Konstruktion leider nicht möglich.

Zum Schluß noch einmal wie gewohnt das vollständige Programm zum Nachprogrammieren und Nachvollziehen:

ringWidth = 0.04
ringSteps = 8.0
maxi = 240

def setup():
    size(600, 400, P3D)

def draw():
    background(108, 131, 163)
    
    lights()
    translate(width/2, 3*height/8.0)
    rotateX(radians(55))
    scale(height/2.0, height/2.0)

    with beginShape(QUAD_STRIP):
        i = -ringSteps
        while i < maxi:
            r0 = ringWidth*(i*1.0/ringSteps)
            r1 = r0 + ringWidth
            if r0 < 0.0:
                r0 = 0.0
            theta = i*(TWO_PI/ringSteps)
            makeVertex(r0, theta)
            makeVertex(r1, theta)
            i += 1

def makeVertex(r, theta):
    x = r*cos(theta)
    y = r*sin(theta)
    z = 100*exp(-3*r*r)*cos((r*2*TWO_PI) - (frameCount/50.0))
    fill(163, 143, 109)
    stroke(0)
    strokeWeight(0.01)
    vertex(x, y, z)
  1. Den Algorithmus habe ich in dem wunderbaren Buch »Processing for Visual Artists – How to Create Expressive Images and Interactive Art« von Andrew Glassner (Seiten 101-103) gefunden und (mit einigen Änderungen) von Java nach Python portiert.

  2. Bei Points müßt Ihr allerdings das strokeWeight() heraufsetzten, zum Beispiel auf 0.1, um überhaupt etwas zu sehen.


(Kommentieren) 

image image



Über …

Der Schockwellenreiter ist seit dem 24. April 2000 das Weblog digitale Kritzelheft von Jörg Kantel (Neuköllner, EDV-Leiter, Autor, Netzaktivist und Hundesportler — Reihenfolge rein zufällig). Hier steht, was mir gefällt. Wem es nicht gefällt, der braucht ja nicht mitzulesen. Wer aber mitliest, ist herzlich willkommen und eingeladen, mitzudiskutieren!

Alle eigenen Inhalte des Schockwellenreiters stehen unter einer Creative-Commons-Lizenz, jedoch können fremde Inhalte (speziell Videos, Photos und sonstige Bilder) unter einer anderen Lizenz stehen.

Der Besuch dieser Webseite wird aktuell von der Piwik Webanalyse erfaßt. Hier können Sie der Erfassung widersprechen.

Diese Seite verwendet keine Cookies. Warum auch? Was allerdings die iframes von Amazon, YouTube und Co. machen, entzieht sich meiner Kenntnis.


Werbung


Werbung


image  image  image
image  image  image


image