Brief | Kurzbeschreibung
Write a program that presents an ever-changing, imaginative “landscape.” Populate your landscape with features that are suitable for your concept: trees, buildings, vehicles, animals, people, food items, body parts, hairs, seaweed, space junk, zombies, etc.
Give consideration to the depth of variation in your landscape: after how much time does your landscape become predictable? How might you forestall this as long as possible? How can you generate a landscape that is both coherent and engaging?
Consider: foreground, middle-ground, and background “layers”; variation at the macro-scale, meso-scale, and micro-scale; natural and human-made features; utopia, dystopia, and heterotopia; the immersive use of motion parallax; and the potential for surprise through the placement of infrequent features.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Schreiben Sie ein Programm, das eine sich ständig verändernde, imaginative „Landschaft“ präsentiert. Füllen Sie Ihre Landschaft mit Elementen, die zu Ihrem Konzept passen: Bäume, Gebäude, Fahrzeuge, Tiere, Menschen, Nahrungsmittel, Körperteile, Haare, Seetang, Weltraumschrott, Zombies usw.
Berücksichtigen Sie die Tiefe der Variation in Ihrer Landschaft: Nach welcher Zeit wird Ihre Landschaft vorhersehbar? Wie können Sie dies so lange wie möglich verhindern? Wie können Sie eine Landschaft erzeugen, die sowohl kohärent als auch fesselnd ist?
Denken Sie an: Vordergrund-, Mittelgrund- und Hintergrund-Ebenen; Variation im Makro-, Meso- und Mikromaßstab; natürliche und vom Menschen geschaffene Elemente; Utopie, Dystopie und Heterotopie; den immersiven Einsatz von Bewegungsparallaxe; sowie das Potenzial für Überraschungen durch die Platzierung seltener Elemente.
Learning Objectives | Lernziele
• Apply principles of generative design to terrain, scenery, and worlds of the imagination
• Bias randomness to carefully regulate probabilities
• Carry out a metadesign process
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
• Wenden Sie die Prinzipien des generativen Designs auf Gelände, Szenerien und imaginäre Welten an
• Beeinflussen Sie Zufälligkeit, um Wahrscheinlichkeiten sorgfältig zu steuern
• Führen Sie einen Metadesign-Prozess durch
Variations | Variationen
• Populate your landscape with one or more of the “three verticals” (people, trees, and buildings): according to Jungian psychology, these are the defining psychological features of landscapes.
• Pay attention to the manner in which the landscape moves past the “camera.” For example, it might appear to scroll by (as if you were looking out the window of a train); or approach from a first-person point of view (as if you were driving, or riding a roller coaster), or slide underneath (as if you were looking out of a glass-bottomed airplane). Consider a moving or even roving camera, capable of rotation as well as translation.
• Depict an outside scene, an interior one (such as objects on a conveyor belt), or an altogether dreamlike one.
• Experiment with 3D (as in noise terrains); 2D (as in side-scrolling video games); “2.5D” layered spaces; orthographic views; or even nonlinear, non-Cartesian geometries.
• Give consideration to sound and the possibility for audiovisual synchronicities (as in Guitar Hero).
• Make an autonomous creature, vehicle, or other character traverse your landscape.
• Implement features in your landscape that grow, evolve, or erode over time.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
• Füllen Sie Ihre Landschaft mit einem oder mehreren der „drei Vertikalen“ (Menschen, Bäume und Gebäude): Nach der jungianischen Psychologie sind dies die definierenden psychologischen Merkmale von Landschaften.
• Achten Sie darauf, wie die Landschaft an der „Kamera“ vorbeizieht. Zum Beispiel könnte sie vorbeiscrollen (als würden Sie aus dem Fenster eines Zuges schauen); aus der Ich-Perspektive erscheinen (als würden Sie fahren oder eine Achterbahn fahren) oder darunter hindurchgleiten (als würden Sie aus einem Flugzeug mit Glasboden schauen). Berücksichtigen Sie eine bewegliche oder sogar umherwandernde Kamera, die sowohl drehen als auch verschieben kann.
• Stellen Sie eine Außenszene, eine Innenszene (z. B. Objekte auf einem Förderband) oder eine völlig traumartige Szene dar.
• Experimentieren Sie mit 3D (wie bei Rauschlandschaften); 2D (wie in Side-Scrolling-Videospielen); „2,5D“-Schicht-Räumen; orthografischen Ansichten; oder sogar nichtlinearen, nichtkartesischen Geometrien.
• Berücksichtigen Sie Ton und die Möglichkeit für audiovisuelle Synchronitäten (wie in Guitar Hero).
• Lassen Sie eine autonome Kreatur, ein Fahrzeug oder eine andere Figur Ihre Landschaft durchqueren.
• Implementieren Sie Funktionen in Ihrer Landschaft, die über die Zeit wachsen, sich entwickeln oder erodieren.
Making it Meaningful | Bedeutung schaffen
We are a migrant species, instilled with a wanderlust that continually clamors for new horizons. Before the modern era of mobility, landscape paintings were often the primary means by which people could visualize faraway lands and mentally escape to them.
Today, eight-year-olds trade “seeds” for favored Minecraft worlds, and procedurally generated environments have become commonplace in video games, where the algorithmic production of novel landscapes is an economic necessity for inexhaustible play. For the meta-designer and artist-programmer, there is assuredly something godlike about calling forth world upon world. It is probably not a coincidence that the first all-CGI sequence in a feature film depicted the synthesis of an entire planet, in the triumphant “Genesis Sequence” of Star Trek II (1982).
Generative design systems, whether used to create faces, landscapes, creatures, or chairs, define seemingly infinite possibility spaces.
Pay heed, however, to what Kate Compton calls the “10,000 Bowls of Oatmeal Problem”: “I can easily generate 10,000 bowls of plain oatmeal, with each oat being in a different position and different orientation, and mathematically speaking they will all be completely unique. But the user will likely just see a lot of oatmeal.”
As Compton indicates, the challenge and opportunity of meta-design is in architecting systems whose results offer perceptual uniqueness, and are thus meaningfully distinct.
This assignment asks you to bring forth a world from your imagination. Alternatively, you may create an accurate computational representation of a very real place—and generate “more” of it.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Wir sind eine wandernde Spezies, geprägt von einem Fernweh, das ständig nach neuen Horizonten verlangt. Vor der modernen Ära der Mobilität waren Landschaftsgemälde oft das Hauptmittel, um sich ferne Länder vorzustellen und gedanklich dorthin zu entfliehen.
Heute tauschen achtjährige Kinder „Samen“ für ihre bevorzugten Minecraft-Welten, und prozedural generierte Umgebungen sind in Videospielen alltäglich geworden, wobei die algorithmische Erzeugung neuer Landschaften eine wirtschaftliche Notwendigkeit für unerschöpfliches Spiel ist. Für den Meta-Designer und Künstler-Programmierer gibt es zweifellos etwas Gottähnliches daran, Welt um Welt hervorzurufen. Es ist wahrscheinlich kein Zufall, dass die erste vollständig CGI-erstellte Sequenz in einem Spielfilm die Synthese eines gesamten Planeten darstellte – in der triumphalen „Genesis Sequence“ von Star Trek II (1982).
Generative Design-Systeme, egal ob sie zur Erstellung von Gesichtern, Landschaften, Kreaturen oder Stühlen verwendet werden, definieren scheinbar unendliche Möglichkeitsräume.
Achten Sie jedoch auf das, was Kate Compton das „10.000-Schalen-Haferbrei-Problem“ nennt: „Ich kann leicht 10.000 Schalen normalen Haferbreis erzeugen, wobei jeder Haferkorn an einer anderen Position und in einer anderen Orientierung liegt, und mathematisch gesehen sind sie alle völlig einzigartig. Aber der Benutzer wird wahrscheinlich nur viel Haferbrei sehen.“
Wie Compton zeigt, besteht die Herausforderung und Chance des Meta-Designs darin, Systeme zu entwickeln, deren Ergebnisse wahrnehmbar einzigartig und somit sinnvoll unterscheidbar sind.
Diese Aufgabe fordert Sie auf, eine Welt aus Ihrer Vorstellungskraft hervorzubringen. Alternativ können Sie eine genaue computergestützte Darstellung eines realen Ortes erstellen – und „mehr“ davon generieren.
Example Projects | Beispielprojekte
Kristyn Janae Solie’s Lonely Planets
Kristyn Janae Solie’s Lonely Planets (2013) is a stylized 3D terrain that shifts between minimalism and psychedelia. The work was created for Casey Reas’s undergraduate course, Live Cinema through Creative Coding.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Kristyn Janae Solie’s Lonely Planets
Kristyn Janae Solies Lonely Planets (2013) ist ein stilisiertes 3D-Gelände, das zwischen Minimalismus und Psychedelik wechselt. Das Werk wurde für Casey Reas’ Bachelor-Kurs Live Cinema through Creative Coding erstellt.
Everest Pipkin – Mirror Lake
Everest Pipkin generates barren flowerpot landscapes in Mirror Lake (2015), a poetic and mysterious browser experience.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Everest Pipkin – Mirror Lake
Everest Pipkin erzeugt karge Blumentopf-Landschaften in Mirror Lake (2015), einer poetischen und geheimnisvollen Browser-Erfahrung.
“Fractional noise” mountains
“Fractional noise” mountains (c. 1982), developed by Benoît Mandelbrot and Richard F. Voss at IBM, were a landmark in mathematical terrain synthesis.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
„Fractional Noise“-Berge
Die „Fractional Noise“-Berge (ca. 1982), entwickelt von Benoît Mandelbrot und Richard F. Voss bei IBM, stellten einen Meilenstein in der mathematischen Geländesynthese dar.
Jared Tarbell – Substrate
In Jared Tarbell’s classic Substrate (2003), simulated urban tectonics arise from elementary principles of accretion, branching, and feedback.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Jared Tarbell – Substrate
In Jared Tarbells Klassiker Substrate (2003) entstehen simulierte urbane Tektoniken aus grundlegenden Prinzipien von Akkretion, Verzweigung und Rückkopplung.
Research | Recherche
No Man´s Sky
No Man’s Sky is a procedurally generated space exploration game that allows players to discover and interact with billions of unique planets. Each world features diverse landscapes, flora, fauna, and weather systems, creating an endless and immersive exploration experience. The game exemplifies how generative design can produce coherent yet unpredictable environments.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
No Man’s Sky ist ein prozedural generiertes Weltraumerkundungsspiel, das es den Spielern ermöglicht, Milliarden einzigartiger Planeten zu entdecken und zu interagieren. Jeder Planet weist vielfältige Landschaften, Flora, Fauna und Wettersysteme auf, wodurch ein endloses und immersives Erkundungserlebnis entsteht. Das Spiel zeigt beispielhaft, wie generatives Design kohärente, aber unvorhersehbare Umgebungen schaffen kann.
Refik Anadol – Living Architecture: Gehry
The media artist Refik Anadol presents an audiovisual installation at the Guggenheim Museum Bilbao that translates Frank Gehry’s iconic forms into AI-generated landscapes. The installation uses real-time data and machine learning to create dynamic, constantly changing environments that make the architecture itself appear alive.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Der Medienkünstler Refik Anadol präsentiert im Guggenheim Museum Bilbao eine audiovisuelle Installation, die die ikonischen Formen von Frank Gehry in KI-generierte Landschaften übersetzt. Die Installation nutzt Echtzeit-Daten und maschinelles Lernen, um dynamische, sich ständig verändernde Umgebungen zu schaffen, die die Architektur selbst lebendig erscheinen lassen.
Nat Sarkissian – Sunset from the Bluffs
San Diego-based artist Nat Sarkissian creates generative artworks that represent nature as a system. Projects like Sunset from the Bluffs combine algorithmically generated landscapes with a hand-drawn, pastel-like style reminiscent of colored pencil drawings. These works reflect Sarkissian’s exploration of natural forms and his creative process, emphasizing the underlying structures and patterns of nature rather than simply depicting static scenery.
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Der in San Diego ansässige Künstler Nat Sarkissian erschafft generative Kunstwerke, die die Natur als System darstellen. Projekte wie Sunset from the Bluffs kombinieren algorithmisch erzeugte Landschaften mit einem handgezeichneten, pastellartigen Stil, der an Buntstiftzeichnungen erinnert. Diese Arbeiten reflektieren Sarkissians Auseinandersetzung mit natürlichen Formen und seiner kreativen Prozessgestaltung.
Tool #1: Processing
Übung A – Shapes
Im ersten Schritt wurde mit Processing ein 3 × 3 Raster aus identischen Kacheln erstellt. Jede Kachel misst 200 × 200 Pixel und enthält eine Komposition aus geometrischen Formen: ein zentraler Kreis, vier kleine Quadrate an den Ecken sowie verbindende Linien. Die Anordnung demonstriert Grundprinzipien der Wiederholung und Musterbildung in der generativen Gestaltung. Das Ergebnis ist ein klar strukturiertes, schwarz-weißes Raster.
Übung B – Color
Im zweiten Schritt wurde das Raster weiterentwickelt, indem Farben hinzugefügt wurden. Die Hintergrundfläche jeder Kachel erhielt eine lila Füllung. Die großen Kreise in der Mitte wurden gelb, während die kleinen Quadrate an den Ecken nun hellgrün erscheinen. Die Verbindungs-Knotenpunkte zwischen den Kacheln sind rot gefärbt. Diese farbige Ausarbeitung verleiht dem Muster eine freundlichere und lebendigere Optik und zeigt den Einsatz von background(), stroke() und fill() in Processing.
Übung C – Interaction
Im dritten Schritt wurde das Raster interaktiv gestaltet. Mithilfe der mouseX- und mouseY-Werte in Processing verändert sich die Größe des zentralen Kreises in jeder Kachel dynamisch, abhängig von der aktuellen Mausposition. So entsteht eine direkte Verbindung zwischen Maus-Interaktion und visueller Erscheinung des Rasters.
Übung D – Condition
Bei gedrückter Maustaste wird immer die Farbe des Quadratfelds im Raster geändert, über dem sich der Mauszeiger gerade befindet. So reagiert jeweils die aktuell ausgewählte Fläche direkt auf den Klick und passt ihr Aussehen dynamisch an.
Code
void setup() {
size(600, 600);
background(0);
frameRate(60);
}
void draw() {
for (int i = 0; i < 4; i = i+1) {
for (int j = 0; j < 4; j = j+1) {
stroke(0);
if(mousePressed && mouseX > width/3*i && mouseX < width/3*(i+1) && mouseY > height/3*j && mouseY < height/3*(j+1)){
fill(frameCount%60*255/60, frameCount%30*255/60, frameCount%120*255/60);
}else{
fill(189, 173, 234);
}
rect(width/6*(2*i), height/6*(2*j), height/3, height/3);
fill(166, 38, 57);
ellipse(width/3*i, height/3*j, width/24, height/24);
for(int k = 0; k < 4; k = k+1){
fill(143, 184, 222);
rect(width/6*(2*i)+width/12, height/6*(2*j)+height/12, height/6, height/6);
rectMode(CENTER);
fill(221, 232, 185);
rect(width/6*(2*i)+width/12, height/6*(2*j)+height/12, height/16, height/16);
rect(width/6*(2*i)+3*width/12, height/6*(2*j)+height/12, height/16, height/16);
rect(width/6*(2*i)+width/12, height/6*(2*j)+3*height/12, height/16, height/16);
rect(width/6*(2*i)+3*width/12, height/6*(2*j)+3*height/12, height/16, height/16);
rectMode(CORNER);
}
noStroke();
fill(mouseX*255/600,mouseY*255/600,255-mouseX*255/600);
ellipse(width/3*i+width/6, height/3*j+width/6, mouseX/7, mouseY/7);
}
}
stroke(0);
}
Tool #2: Laser
Erstellung
Im ersten Schritt wurde mit Processing ein 10 × 10-Raster aus individuellen Kacheln erzeugt. Jede Kachel besteht aus mindestens sechs geometrischen Grundformen (Rechteck, Kreis, Dreieck), die zufällig parametrisiert und innerhalb der Kachel platziert werden. Es wird darauf geachtet, dass keine Form über den Rand hinausgeht. Pro Kachel wird eine der sechs Formen zufällig vollständig schwarz gefüllt und dadurch von laser komplett ausgeschnitten. Die übrigen erscheinen nur als graue Konturen. So entsteht eine klare, reduzierte Formsprache und ein rasterbasiertes, aber variantenreiches Muster.
Lasercut
Im letzten Schritt wird die fertige SVG-Datei am Lasercutter im X Lab verarbeitet. Die klaren, grafischen Muster der einzelnen Kachelsegmente übertragen sich präzise auf das physische Material.
Code:
import processing.svg.*
int cols = 10;
int rows = 10;
int tileSize = 60; // Größe einer Kachel
boolean exportSVG = true; // auf false setzen, wenn du nur anzeigen willst
void setup() {
size(600, 600);
noLoop();
strokeWeight(2);
if (exportSVG) {
beginRecord(SVG, „laser_output_inverted.svg“); // Export-Datei im Sketch-Ordner
}
}
void draw() {
background(255); // Weißer Hintergrund (invertiert)
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
drawTile(x * tileSize, y * tileSize, tileSize);
}
}
if (exportSVG) {
endRecord();
println(„SVG-Datei exportiert: laser_output_inverted.svg“);
}
}
void drawTile(float x, float y, float s) {
pushMatrix();
translate(x, y);
int n = 6;
int blackIndex = int(random(n)); // eine zufällige Form pro Kachel wird voll schwarz gefüllt
// Arrays zum Zwischenspeichern der Form-Parameter
int[] shapeType = new int[n]
float[] w = new float[n]
float[] h = new float[n]
float[] px = new float[n]
float[] py = new float[n]
float[] gray = new float[n]
float margin = s * 0.1;
// Parameter generieren
for (int i = 0; i < n; i++) {
w[i] = random(s * 0.1, s * 0.8);
h[i] = random(s * 0.1, s * 0.8);
px[i] = random(margin, s - w[i] - margin);
py[i] = random(margin, s - h[i] - margin);
shapeType[i] = int(random(3));
gray[i] = random(10, 254); // neue Helligkeit (nicht ganz weiß oder schwarz)
}
// Zuerst alle nicht-schwarzen Formen zeichnen
for (int i = 0; i < n; i++) {
if (i == blackIndex) continue;
noFill();
stroke(gray[i]);
if (shapeType[i] == 0) {
rect(px[i], py[i], w[i], h[i]);
} else if (shapeType[i] == 1) {
ellipse(px[i] + w[i] / 2, py[i] + h[i] / 2, w[i], h[i]);
} else if (shapeType[i] == 2) {
triangle(px[i], py[i], px[i] + w[i], py[i], px[i] + w[i] / 2, py[i] + h[i]);
}
}
// Dann die schwarze, gefüllte Form zuletzt zeichnen (liegt oben)
fill(0);
stroke(0);
int i = blackIndex;
if (shapeType[i] == 0) {
rect(px[i], py[i], w[i], h[i]);
} else if (shapeType[i] == 1) {
ellipse(px[i] + w[i] / 2, py[i] + h[i] / 2, w[i], h[i]);
} else if (shapeType[i] == 2) {
triangle(px[i], py[i], px[i] + w[i], py[i], px[i] + w[i] / 2, py[i] + h[i]);
}
popMatrix();
}
#Lötübung
Im Rahmen der dritten Übung entstand ein Mandala aus elektronischen Komponenten wie Widerständen, Kondensatoren und LEDs sowie Silberdraht. Als Vorlage für das Löten wurde zunächst ein Mandala-Design digital entwickelt und auf Papier gebracht. Die einzelnen Bauteile wurden mit Draht verbunden und auf einem schwarzen Karton (150 × 150 mm) arrangiert und befestigt. Da keine ausgebauten Komponenten verfügbar waren, wurden einfache Arduino-Teile verwendet. Das Ergebnis ist eine geometrisch strukturierte, symmetrische Komposition, die die Verbindung von Elektronik und Gestaltung anschaulich zeigt.
Analog ↔ Digital
Technischer Aufbau & Code
Das Projekt besteht aus einem Arduino Uno, vier Tastern und vier LEDs in den Farben Rot, Gelb, Grün und Blau.
Der Arduino-Code liest in jedem Loop-Durchlauf alle vier Pins aus. Wird ein Taster gedrückt, sendet der Arduino einmalig einen String wie B0, B1, B2 oder B3 über die serielle Schnittstelle an Processing. Die dazugehörige LED leuchtet solange der Button gedrückt gehalten wird.
In Processing läuft das eigentliche Spiel. Die serielle Verbindung wird über Serial.list() hergestellt und empfängt die Button-Signale via serialEvent(). Das Spiel generiert eine zufällige Farbreihenfolge, zeigt diese visuell als pulsierende Quadranten auf dem Bildschirm an und wartet anschließend auf die Eingabe des Spielers über die physischen Buttons. Score, Level, Win/Lose-Overlays und ein Leaderboard mit 3-Buchstaben-Kürzel sind vollständig implementiert.
Video
Spielablauf
Der Spieler startet das Spiel durch Drücken eines beliebigen Buttons. Processing zeigt daraufhin eine Farbreihenfolge an – die Quadranten auf dem Bildschirm leuchten nacheinander in der entsprechenden Farbe auf. Nach der Sequenz ist der Spieler an der Reihe: er muss die gezeigte Reihenfolge durch Drücken der physischen Buttons wiederholen. Jeder Tastendruck lässt die zugehörige LED aufleuchten und sendet das Signal an Processing. Ist die Eingabe korrekt, steigt das Level und die Sequenz wird um eine Farbe verlängert. Bei einem Fehler erscheint ein Game-Over-Overlay, der Spieler gibt ein 3-Buchstaben-Kürzel ein und landet auf dem Leaderboard. Von dort kann mit einem erneuten Tastendruck neu gestartet werden.
Digital ↔ Analog
Technischer Aufbau & Code
Das Projekt besteht aus einem Arduino Uno und einem Servo-Motor. Der Servo zeigt physisch auf eine von vier Farben – Rot, Gelb, Grün und Blau – die auf einer Skala von links nach rechts angeordnet sind. Die Winkel dafür sind auf 22°, 68°, 113° und 158° gesetzt. Im Ruhezustand fährt der Servo auf 90° (Mittelposition).
Processing steuert den Servo über serielle Befehle: S0–S3 bewegen den Servo zur entsprechenden Farbe, S-1 setzt ihn zurück in die Mitte. Die Sequenz wird in updateShowSequence() schrittweise abgearbeitet – mit showHold und showPause als einstellbare Timing-Parameter. Nach der gesamten Sequenz fährt der Servo in die Mitte zurück und der Spieler ist an der Reihe.
Die Spiellogik in Processing ist identisch zum Button-Projekt aufgebaut – gleicher Startscreen, gleiche Zustandsmaschine mit STATE_START, STATE_SHOW_SEQUENCE, STATE_PLAYER_INPUT, STATE_WIN, STATE_LOSE und STATE_LEADERBOARD. Die Eingabe erfolgt hier jedoch per Mausklick auf die Farbquadranten im Processing-Fenster, mit Hover-Highlighting als visuellem Feedback.
Der Spieler startet das Spiel per Mausklick auf den Startscreen. Der Servo fährt von der Mittelposition aus nacheinander auf die Farben der generierten Sequenz, der physische Pfeil zeigt dabei direkt auf die jeweilige Farbe. Der Spieler beobachtet die Bewegungen und merkt sich die Reihenfolge. Nach Abschluss der Sequenz kehrt der Servo in die Mitte zurück und Processing wechselt in den Eingabemodus. Nun klickt der Spieler die Farben in der richtigen Reihenfolge auf dem Bildschirm an – korrekte Klicks werden mit einem kurzen Aufleuchten des Quadranten bestätigt. Bei vollständig richtiger Eingabe steigt das Level und die Sequenz wird länger. Ein Fehler führt zum Game-Over-Screen mit Namenseingabe und Leaderboard-Eintrag.
Projekt
Technischer Aufbau
Das System besteht aus drei miteinander kommunizierenden Komponenten. Eine Webcam erfasst kontinuierlich die Hand des Nutzers und übergibt die Bilddaten an ein Python-Skript, das mithilfe von MediaPipe die Handlandmarks in Echtzeit erkennt. Aus der relativen Position der Fingerglieder wird die aktuelle Geste klassifiziert und zusammen mit der normalisierten Handposition als UDP-Paket an die Processing-Applikation gesendet. Processing übersetzt diese Daten in Interaktionen auf einem hexagonalen 3D-Terrain. Parallel dazu empfängt ein Arduino über eine serielle Verbindung den aktuellen Modus und aktiviert die entsprechende LED als physisches Feedback.
Gestenübersicht
Die Interaktion basiert auf vier intuitiven Handgesten, die jeweils einen terraformenden Eingriff in die Landschaft steuern. Eine zur Kamera geöffnete Handfläche lässt Berge entstehen. Wird die Handfläche von der Kamera abgewandt, entsteht Wasser. Ein ausgestreckter Zeigefinger bei eingeklappten restlichen Fingern aktiviert den Vegetationsmodus und macht Bäume, Kiefern und Felsen sichtbar. Eine geballte Faust schließlich triggert den Stadtmodus, in dem Wolkenkratzer, Häuser und Hütten abhängig von der Terrainhöhe platziert werden.
Entwicklungsprozess
Phase 1: Hexagonales Grid
Den Ausgangspunkt bildet ein flaches hexagonales Raster, das kreisförmig zu einer Inselform beschnitten wird. Jedes Tile ist ein einfaches Hexagon-Prisma ohne Höheninformation. Erste Experimente mit Farbgebung und Kameraperspektive legen die grundlegende Ästhetik des Projekts fest.
Phase 2: Dynamisches Terrain
Im zweiten Schritt erhält jedes Tile eine interpolierte Höhe, die durch Mauseingabe beeinflusst werden kann. Ein Einflussradius um den Cursor hebt benachbarte Tiles sanft an oder senkt sie ab. Farbgradienten, von Grün über Grau bis Weiß, visualisieren automatisch die Höhenzonen Grasland, Fels und Schnee.
Phase 3: Assets & Vegetation
Auf dem Terrain werden prozedural 3D-Assets platziert: Laubbäume, Kiefern, Felsen, Baumstämme und Stümpfe. Sie erscheinen und verschwinden abhängig von Terrainhöhe und aktivem Modus. Ergänzt werden sie durch Stadtstrukturen, Wolkenkratzer zweier Typen, Häuser und Hütten, die sich je nach Höhe des Untergrunds automatisch anpassen.
Phase 4: Hand-Tracking & physisches Feedback
In der finalen Phase ersetzt ein gestenbasiertes Eingabesystem die Maussteuerung. MediaPipe erkennt vier Gesten in Echtzeit und sendet Position sowie Modus per UDP an Processing. Ein Kalibrierungssystem kompensiert Kamerawinkel und Verzerrung. Ein Arduino empfängt den aktiven Modus seriell und aktiviert die zugehörige LED – offene Hand weiß für Berge, blau für Wasser, grün für Vegetation, gelb für Stadt.
Video-Showcase
Relevante Code-Auszüge
Hexagonales Grid — Inselform
void buildGrid() {
float w = sqrt(3) * r;
float h = 1.5 * r;
float maxRadius = islandRadius;
int rowIndex = 0;
for (float z = -maxRadius; z boolean offset = (rowIndex % 2 != 0);
for (float x = -maxRadius; x float px = x + (offset ? w * 0.5 : 0);
if (px*px + pz*pz tiles.add(new HexTile(px, pz, r));
}
}
rowIndex++;
}
}
Tiles werden in einem hexagonalen Raster angeordnet. Ungerade Zeilen werden um eine halbe Breite versetzt. Der kreisförmige Clipping-Test (px²+pz² ≤ r²) schneidet das Grid zu einer Inselform zu.
Terrain-Einflussradius & Tool-Logik
float influenceR = 35;
for (HexTile t : grid.tiles) {
float dist = sqrt(dx*dx + dz*dz);
if (dist < influenceR) {
float k = 1.0 - (dist / influenceR);
if (toolMode == 1) { // Berge
float target = k * 250;
t.targetHeight = max(target, t.currentHeight);
} else if (toolMode == -1) { // Wasser
t.targetHeight = -5;
} else if (toolMode == 2) { // Vegetation
t.vegetationVisible = true;
t.vegetationLifetime = int(60 * 10);
} else if (toolMode == 3) { // Stadt
t.isCity = true;
// Skyscraper-Chance abhängig von Höhe
if (h < 30) chance = 0.4;
else if (h < 80) chance = 0.10;
}
}
}
Der Cursor beeinflusst alle Tiles in einem Radius von 35 Einheiten. Der Faktor k (1 = Zentrum, 0 = Rand) sorgt für eine weiche, kegelförmige Wirkung. Gebäudewahrscheinlichkeit sinkt mit der Terrainhöhe.
UDP-Empfang in Processing
void readHandData() {
byte[] buf = new byte[9]
DatagramPacket packet = new DatagramPacket(buf, buf.length);
udpSocket.receive(packet);
ByteBuffer bb = ByteBuffer.wrap(buf).order(ByteOrder.nativeOrder());
float nx = bb.getFloat(); // X-Position (4 Byte)
float ny = bb.getFloat(); // Y-Position (4 Byte)
byte mode = bb.get(); // Gesten-Modus (1 Byte)
handX = nx; handY = ny;
handActive = true;
if (useHandTracking) toolMode = (int) mode;
}
Processing empfängt ein 9-Byte UDP-Paket: zwei Floats für die normalisierte Handposition (0–1) und ein Byte für den aktuellen Gesten-Modus. Timeout nach 1ms setzt handActive = false.
Gestenerkennung in Python
def get_gesture(lm, handedness_label):
if is_fist(lm): return 3 # Stadt
if is_pointing(lm): return 2 # Vegetation
if is_palm_facing_camera(lm, handedness_label):
return 1 # Berge
else: return -1 # Wasser
# Handfläche zur Kamera: Kreuzprodukt von Daumen- und Kleinfinger-Vektor
def is_palm_facing_camera(lm, handedness_label):
cross_z = v1x * v2y - v1y * v2x
if handedness_label == „Right“: return cross_z < 0
else: return cross_z > 0
Die Geste wird durch geometrische Tests bestimmt. Faustdetektion vergleicht Fingerspitzen-Distanz mit MCP-Distanz zur Handwurzel. Die Handflächenorientierung berechnet das Vorzeichen des 2D-Kreuzprodukts, gespiegelt je nach Händigkeit.
Arduino LED-Feedback
void loop() {
if (Serial.available() > 0) {
char cmd = Serial.read();
digitalWrite(PIN_BERGE, LOW);
digitalWrite(PIN_WASSER, LOW);
digitalWrite(PIN_VEGETATION, LOW);
digitalWrite(PIN_STADT, LOW);
if (cmd == 'B') digitalWrite(PIN_BERGE, HIGH);
else if (cmd == 'N') digitalWrite(PIN_WASSER, HIGH);
else if (cmd == 'V') digitalWrite(PIN_VEGETATION, HIGH);
else if (cmd == 'C') digitalWrite(PIN_STADT, HIGH);
}
}
Der Arduino empfängt ein einzelnes Zeichen über Serial und schaltet die entsprechende LED. Alle vier LEDs werden zuerst ausgeschaltet, dann nur die zugehörige aktiviert. Ein einfaches, zuverlässiges Zustandsmodell.