If you're seeing this message, it means we're having trouble loading external resources on our website.

Wenn du hinter einem Webfilter bist, stelle sicher, dass die Domänen *. kastatic.org und *. kasandbox.org nicht blockiert sind.

Hauptinhalt

3D-Formen generieren

Jetzt haben wir also einen Würfel, aber was machen wir, wenn wir seine Position oder Größe verändern wollen? Oder wenn wir einen rechteckigen Quader oder mehrere Quader zeichnen wollen? Mit unserem aktuellen Code müssten wir die Knotenpunkte einzeln ändern, was wirklich anstrengend wäre. Wir bräuchten im Prinzip eine einfache Methode, einen Quader mit einer bestimmten Position und bestimmten Dimensionen zu erzeugen. Anders gesagt, bräuchten wir eine Funktion, die eine Position und Dimensionen in einem Array von Knotenpunkten und Flächen einander zuordnet.

Einen Quader definieren

Ein Quader hat drei Dimensionen: Breite, Höhe und Tiefe:
Er hat auch eine Position im dreidimensionalen Raum, was sechs Parameter ergibt. Es gibt unterschiedliche Möglichkeiten, die Position des Quaders im Raum zu definieren: wir könnten seine Mitte definieren oder eine Ecke. Ersteres ist wahrscheinlich gebräuchlicher, aber Letzteres ist einfacher anzuwenden.
Unsere Funktion muss sowohl das Array für die Knotenpunkte als auch für die Kanten zurückgeben. Eine Art, zwei Variablen zurückzugeben, ist es, die Variablen in ein Objekt zu packen, mit einem Index für nodes (Knoten) und einem für edges (Kanten). Beachte, dass man prinzipiell jeden String zum Benennen der Variable verwenden kann - ich finde es aber einfacher, das gleiche Wort zu verwenden.
// Zeichne einen Quader mit Knotenpunkt bei (x, y, z)
// mit Breite w, Höhe h und Tiefe d.
var createCuboid = function(x, y, z, w, h, d) {
   var nodes = [];
   var edges = [];
   var shape = { 'nodes': nodes, 'edges': edges };
   return shape;
};
Wenn wir diese Funktion verwenden würden, um einen Quader zu zeichnen, würden wir auf den ersten Knotenpunkt folgendermaßen zugreifen:
var shape = createCuboid(0, 0, 0, 100, 160, 50);
var node0 = shape.nodes[0];
Dies setzt node0 auf den ersten Wert im Array nodes. Im Moment gibt es allerdings keine Werte in den Arrays für Knotenpunkte (nodes) oder Kanten (edges).
Wir definieren die Knotenpunkte als jede Kombination einer Position mit oder ohne entsprechende Dimension. Kanten werden genau wie zuvor definiert (außer dass ich sie alle zusammen definiere anstatt jede Kante einzeln). Beachte, dass man bei dieser Funktion negative Dimensionen für den Quader festlegen kann.
var createCuboid = function(x, y, z, w, h, d) {
   var nodes = [[x, y, z ], [x, y, z+d], [x, y+h, z ], [x, y+h, z+d], [x+w, y, z ], [x+w, y, z+d], [x+w, y+h, z ], [x+w, y+h, z+d]];

   var edges = [[0, 1], [1, 3], [3, 2], [2, 0], [4, 5], [5, 7], [7, 6], [6, 4], [0, 4], [1, 5], [2, 6], [3, 7]];

   return { 'nodes': nodes, 'edges': edges};
};
Wir können dann auf die folgende Art einen Quader mit der Breite 100, Höhe 160 und Tiefe 50 sowie einem Knotenpunkt am Ursprung anlegen:
var shape = createCuboid(0, 0, 0, 100, 160, 50);
Da unser vorheriger Code nur globale Variablen für nodes und edges referenziert, müssen wir die Eigenschaften unseres Objekts in diesen globalen Variablen speichern:
var nodes = shape.nodes; var edges = shape.edges;
Hier unten kannst du den kompletten Code sehen.

Mit mehreren Formen arbeiten

Wir können Formen mit unterschiedlichen Dimensionen anlegen - was machen wir also, wenn wir mehr als eine brauchen? Immer wenn wir eine variable Anzahl von etwas brauchen, ist ein Array nützlich. Legen wir also ein Array von Formen an.
var shape1 = createCuboid(-120, -20, -20, 240, 40, 40);
var shape2 = createCuboid(-120, -50, -30, -20, 100, 60);
var shape3 = createCuboid( 120, -50, -30, 20, 100, 60);
var shapes = [shape1, shape2, shape3];
Jetzt müssen wir die Anzeige- und Drehungsfunktionen so ändern, dass sie mit einem Objektarray funktionieren. Ändere am Anfang den Code so, dass in einer for-Schleife, die alle Objekte durchläuft, die Kanten aller Objekte angezeigt werden.
// Zeichne Kanten
stroke(edgeColor);
for (var shapeNum = 0; shapeNum < shapes.length; shapeNum++) {
   var nodes = shapes[shapeNum].nodes;
   var edges = shapes[shapeNum].edges;
   for (var e = 0; e < edges.length; e++) {
      var n0 = edges[e][0];
      var n1 = edges[e][1];
      var node0 = nodes[n0];
      var node1 = nodes[n1];
      line(node0[0], node0[1], node1[0], node1[1]);
   }
}
Und dann füge eine ähnliche for-Schleife zur Anzeige der Knotenpunkte ein:
// Zeichne Knotenpunkte
fill(nodeColor);
noStroke();
for (var shapeNum = 0; shapeNum < shapes.length; shapeNum++) {
   var nodes = shapes[shapeNum].nodes;
   for (var n = 0; n < nodes.length; n++) {
      var node = nodes[n]; ellipse(node[0], node[1], nodeSize, nodeSize);
   }
}
Wir könnten jeder der Drehungsfunktionen eine ähnliche for-Schleife hinzufügen, eine flexiblere Lösung wäre aber meiner Meinung nach, das Array von Knotenpunkten an jede der Funktionen weiterzugeben - so können wir Formen unabhängig voneinander drehen. Dann würde die Funktion rotateZ3D() beispielsweise so aussehen:
var rotateZ3D = function(theta, nodes) { ... };
Wenn wir jetzt die Maus zum Drehen verwenden, müssen wir für jede einzelne Funktion die Formen mittels Schleifen durchlaufen und die Funktion aufrufen:
mouseDragged = function() {
   var dx = mouseX - pmouseX;
   var dy = mouseY - pmouseY;
   for (var shapeNum = 0; shapeNum < shapes.length; shapeNum++) {
      var nodes = shapes[shapeNum].nodes;
      rotateY3D(dx, nodes);
      rotateX3D(dy, nodes);
   }
};
Achte darauf, alle anderen Aufrufe von Drehungsfunktionen zu entfernen, die keine Knotenpunkte eingeben. Unten kannst du den kompletten Code sehen.

Willst du an der Diskussion teilnehmen?

Noch keine Beiträge.
Verstehst du Englisch? Klick hier, um weitere Diskussionen auf der englischen Khan Academy Seite zu sehen.