Dat.GUI

Když ve Three.js něco vytváříme, tak často třeba ze začátku nevíme kam přesně na scéně umístit objekty, jaké jim nastavit hodnoty některých vlastností jejich materiálů, a tak podobně. Mohli bychom experimentovat s různými hodnotami přímo v kódu, ale to může být dost velká otrava. Proto je lepší pro tento účel použít nějakou knihovnu, která nám tyto hodnoty umožní dynamicky měnit přímo na stránce. Existuje na to více knihoven, ale mi se naučíme používat dat.GUI.

Co je dat.GUI

Dat.GUI je knihovna pro vytváření grafického uživatelské rozhraní pro měnění hodnot proměnných v JavaScriptu. Umožňuje nám vytvořit si takový panel, který se zobrazí v pravé horní části stránky a umístit do něj inputy pro měnění některých hodnot v našem kódu. Už jste se s tím vlastně setkali u některých interaktivních ukázek, které se na tomto webu nacházejí. Hlavní účel dat.GUI je ale pro debugování a experimentování s hodnotami bez toho aniž bychom něco museli měnit v kódu. Je to pro nás tedy takový nástroj pro vývoj.

Startovní kód

Abychom měli něco, na čem si můžeme dat.GUI vyzkoušet, tak je tu pro vás opět připraven startovní kód. Vytvořte si tedy pomocí startovního kódu z části o Webpacku nový projekt a do JavaScript souboru vložte kód, který ukazuje následující ukázka. Tento kód jen vytváří scénu, přidává do ní pár objektů, zajišťuje aby se canvas roztáhl přes celé okno prohlížeče a spouští animační smyčku pro renderování scény každý frame.

import './style.css';
import * as THREE from 'three';

// vytvoření scény
const scene = new THREE.Scene();

// vytvoření plochy
const plane = new THREE.Mesh(
    new THREE.PlaneGeometry(10, 10),
    new THREE.MeshBasicMaterial({ color: 0xdedede })
);
plane.rotation.x = -Math.PI * 0.5;
scene.add(plane);

// vytvoření kostky
const cube = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshBasicMaterial({ color: 0x78E8FA })
);
cube.position.y = 0.5;
scene.add(cube);

// vytvoření koule
const sphere = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 12, 8),
    new THREE.MeshBasicMaterial({ color: 0xFAB278 })
);
sphere.position.y = 0.5;
sphere.position.z = -1.5;
sphere.position.x = -1.5;
scene.add(sphere);

// vytvoření kamery
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// napozicování kamery
camera.position.y = 2;
camera.position.z = 3;
// nastavení aby se kamera dívala na souřadnice [0, 0, -1]
camera.lookAt(0, 0, -1);
// přidání kamery do scény
scene.add(camera);

// vytvoření rendereru
const renderer = new THREE.WebGLRenderer({
    canvas: document.getElementById("WebGLCanvas")
});
// nastavení rozměrů canvasu a pixel ratio
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

// přidání event listeneru pro změnu velikosti okna
window.addEventListener("resize", () => {
    // změnění poměru stran kamery
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    // změnění rozměrů canvasu a pixel ratio
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});

// tato funkce je volána každý frame
function tick() {
    renderer.render(scene, camera);
}

// nastavení animační smyčky
// - funkce tick se bude volat každý frame
renderer.setAnimationLoop(tick);

Abychom se zbavili defaultních marginů nebo paddingů, tak si ještě zkopírujte CSS kód z následující ukázky a vložte si jej do CSS souboru.

*, *::before, *::after {
    padding: 0;
    margin: 0;
}

body {
    overflow: hidden;
}

Po spuštění aplikace byste měli vidět vyrenderovanou scénu. Na té si dat.GUI vyzkoušíme.

Instalace dat.GUI

Než můžeme dat.GUI použít, tak si jej samozřejmě musíme nainstalovat. Můžeme jej nainstalovat pomocí NPM jako jakýkoliv jiný balíček.

npm install dat.gui --save

Po instalaci si můžeme dat.GUI naimportovat do našeho JavaScript souboru. Následující ukázka ukazuje, jak to můžeme udělat.

import './style.css';
import * as THREE from 'three';
import * as dat from 'dat.gui';

/* ... */

Použití dat.GUI

K použití dat.GUI si musíme nejdříve vytvořit panel, do kterého potom umístíme různé inputy pro měnění hodnot v kódu. Ten vytvoříme vytvořením instance třídy GUI.

/* ... */

// vytvoření dat.GUI panelu
const gui = new dat.GUI();

Panel by se nám měl automaticky přidat na stránku. Po spuštění aplikace by jste měli v pravém horním rohu vidět zatím jen tlačítko s nápisem "close controls", jelikož v panelu ještě nemáme žádné inputy. Po kliknutí na tlačítko se vám text tlačítka změní na "open controls" a pokud bychom v panelu měli nějaké inputy, tak by se skryly. Celý panel (zatím jen tlačítko) můžete skrývat/odkrývat pomocí klávesy H.

Číselný input

Do panelu můžeme přidat inputy pro změnu hodnot v kódu pomocí metody add. Té jako parametr předáváme objekt u kterého chceme měnit hodnotu nějaké vlastnosti, řetězec představující název vlastnosti a volitelně můžeme nastavit také minimální a maximální nastavitelnou hodnotu a krok po kterém se bude hodnota měnit. Poslední tři parametry je ale lepší nastavovat zřetězením metod min, max a step, protože se to potom lépe čte.

V naší scéně si třeba můžeme pomocí dat.GUI zkusit měnit pozici kostky na ose X. Následující ukázku ukazuje, jak pro tuto operaci přidáme do panelu input.

/* ... */

// přidání inputu pro měnění pozice kostky na ose X
gui.add(cube.position, "x").min(-4.5).max(4.5).step(0.01);

Nyní byste v panelu měli vidět vytvořený input, pomocí kterého můžete ve scéně posouvat kostku na ose X.

Input, který jsme si teď ukázali, je input pro číselné hodnoty. Existuje ale více typů inputů pro různé typy hodnot. Postupně si některé ukážeme.

Input pro barvu

Pokud chceme pomocí dat.GUI měnit například barvu objektů, tak můžeme. Slouží k tomu input pro výběr barvy, který si můžeme do panelu přidat pomocí metody addColor. Jelikož jsou ale ve Three.js barvy reprezentovány pomocí třídy Color, tak je jejich měnění přes dat.GUI o něco složitější. Pro změnu barvy si budeme muset vytvořit pomocný objekt, který bude ukládat hodnotu barvy a po změně inputu se hodnota z tohoto pomocného objektu aplikuje jako barva objektu. Uděláme to tak, že za metodu addColor zřetězíme metodu onChange, která nám umožňuje předat funkci, která se spustí po změně inputu. V této funkci tedy z pomocného objektu vezmeme hodnotu barvy a nastavíme ji jako barvu objektu. Myslím že v následující ukázce to pochopíte lépe.

/* ... */

// pomocný objekt pro změnu barvy
const debugObject = {
    cubeColor: 0x78E8FA
}

// přidání inputu pro změny barvy kostky
gui.addColor(debugObject, "cubeColor").onChange(() => {
    // změnění barvy materiálu kostky
    cube.material.color.set(debugObject.cubeColor);
});

Po spuštění aplikace by vám v panelu měl přibýt input pro změnu barvy, pomocí kterého můžete kostce měnit barvu.

Checkbox input

Pokud chceme pomocí dat.GUI měnit boolean hodnoty (true|false), tak je to jednoduché. Pro vytvoření inputu, který nám umožňuje přepínat mezi true a false stačí metodě add předat objekt u kterého chceme měnit nějakou vlastnost obsahující true nebo false a název této vlastnosti. V našem příkladu bychom například mohli chtít měnit jestli je kostka viditelná nebo ne.

/* ... */

// přidání checkbox inputu
gui.add(cube, "visible");

Teď byste pomocí checkbox inputu, který se vám v panelu zobrazí, měli být schopni nastavovat, jestli je kostka viditelná nebo ne.

Select input

Pro výběr z několika možností si můžeme vytvořit select input. Vytvoříme jej tak, že metodě add předáme objekt u kterého chceme měnit nějakou vlastnosti, název této vlastnosti a jako třetí parametr pole hodnot, ze kterých můžeme vybírat. V našem příkladu můžeme třeba kouly posouvat na ose X dle výběru nějakých hodnot. Následující ukázka ukazuje, jak bychom to mohli udělat.

/* ... */

// přidání select inputu
gui.add(sphere.position, "x", [-1.5, 0, 1.5]);

Po spuštění aplikace si můžete vybírat pozici koule ze tří možností.

Pojmenovávání inputů

Jak jste si mohli všimnout, tak máme v našem panelu dva inputy stejně pojmenované. Pokud chceme, tak můžeme jejich název změnit zřetězením metody name, které předáme jaký by měl mít input název. V našem kódu si můžeme třeba změnit název inputu pro výběr pozice koule, jak ukazuje následující ukázka.

/* ... */

// přidání select inputu
gui.add(sphere.position, "x", [-1.5, 0, 1.5]).name("x pozice koule");

Input pro výběr pozice koule by po spuštění aplikace měl být pojmenovaný jako "x pozice koule".

Více si již o dat.GUI knihovně neřekneme. To co jste se o ní v této části naučili by vám pro její používání ve vlastních projektech mohlo stačit. Pokud byste ale chtěli, tak se vždy o dat.GUI můžete dozvědět více sami. Zde je API dokumentace dat.GUI. V příští části se podíváme na různé geometrie, které nám Three.js umožňuje vytvořit.