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

Pokud používáš webový filtr, ujisti se, že domény: *.kastatic.org and *.kasandbox.org jsou vyloučeny z filtrování.

Hlavní obsah

Tvorba 3D tvarů

Takže teď už máme krychli, ale co když chceme změnit její pozici nebo velikost? Nebo co když chceme obdélníkový kvádr nebo několik kvádrů? S naším současným kódem bychom museli změnit každý uzel zvlášť, což by bylo otravné. Potřebovali bychom jednoduchou metodu pro vytvoření kvádru s určitou pozicí a rozměry. Jinými slovy, chceme funkci, která mapuje polohu a rozměry do pole uzlů a pole hran.

Definování kvádru

Kvádr má tři rozměry: šířku, výšku a hloubku:
Má také pozici ve 3D prostoru, čímž nám dává šest parametrů. Existuje několik způsobů, jak bychom mohli definovat polohu kvádru: mohli bychom definovat jeho střed, nebo bychom mohli definovat jeden roh. První způsob se používá častěji, ale ten druhý je dle mého názoru jednodušší na provedení.
Naše funkce musí vrátit pole uzlů i hran. Jedním ze způsobů, jak vrátit dvě proměnné, je uložit proměnné do objektu, s klíčem pro uzly nodes a klíčem pro hrany edges. Nezapomeň, k odkazování na proměnnou můžeš použít libovolný řetězec, mně ale přijde jednodušší použít stejné slovo.
// Vytvoř kvádr umístěn na (x, y, z)
// se šířkou w, výškou h, a hloubkou d.
var createCuboid = function(x, y, z, w, h, d) {
   var nodes = [];
   var edges = [];
   var shape = { 'nodes': nodes, 'edges': edges };
   return shape;
};
Pokud tuto funkci k vytvoření kvádru použijeme, můžeme přistupovat k prvnímu uzlu následovně:
var shape = createCuboid(0, 0, 0, 100, 160, 50);
var node0 = shape.nodes[0];
Tímto nastavíme node0 na první hodnotu v poli nodes. V současné době však v uzlech ani v hranách žádné hodnoty nejsou.
Uzly definujeme jako každou kombinaci polohy s nebo bez odpovídajícího rozměru. Hrany jsou definovány stejným způsobem jako dříve (s výjimkou toho, že jednotlivé hrany nedefinuji samostatně jako předtím, definuji je všechny najednou). Všimni si, že tato funkce ti umožňuje specifikovat záporné rozměry kvádru.
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};
};
Můžeme vytvořit kvádr o šířce 100, výšce 160, hloubce 50 a s jedním uzlem v počátku, jako je to následovně:
var shape = createCuboid(0, 0, 0, 100, 160, 50);
Vzhledem k tomu, že náš předchozí kód odkazuje na globální proměnné nodes a edges, musíme do nich uložit vlastnosti našeho objektu:
var nodes = shape.nodes; var edges = shape.edges;
Celý kód v jednom celku můžeš vidět níže.

Použití více tvarů

Teď už můžeme vytvářet tvary s různými rozměry, co když ale chceme více než jeden tvar? Kdykoli chceme proměnný počet věcí, hodí se nám pole, takže pojďme vytvořit pole tvarů.
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];
Nyní musíme upravit funkce zobrazení a otáčení, abychom mohli pracovat s polem objektů. Začni tím, že vložíš kód k zobrazení hran v cyklu for, který iteruje všemi tvary:
// Nakreslení hran
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]);
   }
}
A ještě podobný cyklus for pro zobrazení uzlů:
// Nakreslení uzlů
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);
   }
}
Můžeme přidat podobný cyklus for pro každou z funkcí otáčení, ale myslím si, že bude efektivnější předat pole uzlů do každé z funkcí - tak můžeme otáčet tvary nezávisle na sobě. Funkce rotateZ3D() by například vypadala takto:
var rotateZ3D = function(theta, nodes) { ... };
Když teď použijeme myš a začneme rotovat, musíme iterovat cyklus přes všechny tvary a pro každý z nich zavolat funkci:
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);
   }
};
Ujisti se, že odstraníš všechna další volání pro funkce otáčení, které nepředávají žádné uzly. Níže můžeš vidět, jak celý kód vypadá.

Chceš se zapojit do diskuze?

Zatím žádné příspěvky.
Umíš anglicky? Kliknutím zobrazíš diskuzi anglické verze Khan Academy.