Kurz: Vytvoření 3D modelu klavíru
V předchozím kurzu v sérii jsme nastavili webovou stránku obsahující Babylon.js scénu s kamerou a kontrolkou. V tomto kurzu budeme vytvářet a přidávat do scény model klavíru.
V tomto kurzu se naučíte, jak:
- Vytváření, umístění a slučování sítí
- Vytvoření klávesy pro piano z krabicových sítí
- Import 3D modelu klavírního rámu
Než začnete
Ujistěte se, že jste prošli předchozím kurzem v sérii a jste připraveni pokračovat v přidávání do kódu.
index.html
<html>
<head>
<title>Piano in BabylonJS</title>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="scene.js"></script>
<style>
body,#renderCanvas { width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script type="text/javascript">
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
createScene(engine).then(sceneToRender => {
engine.runRenderLoop(() => sceneToRender.render());
});
// Watch for browser/canvas resize events
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
scene.js
const createScene = async function(engine) {
const scene = new BABYLON.Scene(engine);
const alpha = 3*Math.PI/2;
const beta = Math.PI/50;
const radius = 220;
const target = new BABYLON.Vector3(0, 0, 0);
const camera = new BABYLON.ArcRotateCamera("Camera", alpha, beta, radius, target, scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 0.6;
const xrHelper = await scene.createDefaultXRExperienceAsync();
return scene;
}
Začínáme
Začněme tím, že vytvoříte jednoduchou klávesovou klávesnici, která má tuto strukturu:
Na tomto obrázku je 7 bílých kláves a 5 černých kláves, z nichž každá je označená názvem poznámky. Úplná klávesová klávesnice s 88 klávesami obsahuje 7 úplných opakování tohoto výběru kláves (označovaných také jako registr) a 4 další klávesy. Každý registr má dvojnásobnou frekvenci oproti předchozímu rejstříku. Například frekvence rozteče C5 (což znamená poznámku C v pátém rejstříku) je dvojnásobná od C4, frekvence rozteče D5 je dvojnásobná od D4 a tak dále.
Vizuálně vypadá každý registr úplně stejně jako jiný, takže můžeme začít zkoumáním toho, jak vytvořit jednoduchou klávesovou klávesnici s tímto výběrem kláves. Později najdeme způsob, jak rozšířit rozsah na 88 kláves s plnými klávesovými klávesy.
Vytvoření jednoduché klávesy pro piano
Poznámka
I když je možné najít předem vytvořené 3D modely klavírních klávesnic z online zdrojů a importovat je na naši webovou stránku, v tomto kurzu sestavíme klávesnici od začátku, abychom umožnili maximální přizpůsobení a ukázali, jak lze 3D modely vytvářet prostřednictvím Babylon.js.
Než začneme vytvářet nějaké sítě pro sestavení klávesnice, všimněte si, že každá černá klávesa není dokonale zarovnaná uprostřed dvou bílých kláves kolem a ne každá klávesa má stejnou šířku. To znamená, že musíme vytvořit a umístit síť pro každý klíč zvlášť.
U bílých kláves můžeme zjistit, že každá bílá klávesa se skládá ze dvou částí: (1) dolní část pod černými klávesami a (2) horní část vedle černých kláves. Tyto dvě části mají různé rozměry, ale jsou poskládány dohromady, aby kréta plně bílý klíč.
Tady je kód pro vytvoření jediného bílého klíče pro poznámku C (zatím si nedělejte starosti s přidáním do scene.js ):
const whiteKeyBottom = BABYLON.MeshBuilder.CreateBox("whiteKeyBottom", {width: 2.3, height: 1.5, depth: 4.5}, scene); const whiteKeyTop = BABYLON.MeshBuilder.CreateBox("whiteKeyTop", {width: 1.4, height: 1.5, depth: 5}, scene); whiteKeyTop.position.z += 4.75; whiteKeyTop.position.x -= 0.45; // Parameters of BABYLON.Mesh.MergeMeshes: // (arrayOfMeshes, disposeSource, allow32BitsIndices, meshSubclass, subdivideWithSubMeshes, multiMultiMaterials) const whiteKeyV1 = BABYLON.Mesh.MergeMeshes([whiteKeyBottom, whiteKeyTop], true, false, null, false, false); whiteKeyV1.material = whiteMat; whiteKeyV1.name = "C4";
Zde jsme vytvořili dvě krabicové sítě, jednu pro spodní část a druhou pro horní část bílé klávesy. Potom upravíme pozici horní části tak, aby se naskládaly na spodní část, a přesuneme ji směrem doleva, aby zůstal prostor pro sousední černý klíč (C#).
Nakonec byly tyto dvě části sloučeny pomocí funkce MergeMeshes , aby se stala jednou úplnou bílou klávesou. Toto je výsledná síť, kterou tento kód vytvoří:
Vytvoření černé klávesy je jednodušší. Vzhledem k tomu, že všechny černé klávesy mají tvar krabice, můžeme vytvořit černý klíč pouhým vytvořením krabicové mřížky s černou barvou StandardMaterial.
Poznámka
Vzhledem k tomu, že výchozí barva sítě je světle šedá, která se podobá bílé, tento kurz neobsahuje kroky pro přidání bílého barevného materiálu k bílým klávesám. Pokud byste ale chtěli pravou, jasně bílou barvu na bílých klávesách, můžete si ho přidat sami.
Tady je kód pro vytvoření černého klíče V jazyce C# (nebojte se ho přidat do scene.js ):
const blackMat = new BABYLON.StandardMaterial("black"); blackMat.diffuseColor = new BABYLON.Color3(0, 0, 0); const blackKey = BABYLON.MeshBuilder.CreateBox("C#4", {width: 1.4, height: 2, depth: 5}, scene); blackKey.position.z += 4.75; blackKey.position.y += 0.25; blackKey.position.x += 0.95; blackKey.material = blackMat;
Černý klíč vytvořený tímto kódem (spolu s předchozí bílou klávesou) by vypadal takto:
Jak vidíte, vytvoření každého klíče může vést k mnoha podobným kódům, protože musíme zadat každou z jejich dimenzí a umístění. V další části se pokusíme proces vytváření zefektivnit.
Efektivní vytvoření jednoduché klávesnice pro piano
I když má každá bílá klávesa trochu jiný tvar, všechny je možné vytvořit kombinací horní a dolní části. Pojďme implementovat obecnou funkci, která vytvoří a umístí libovolnou bílou klávesu.
Přidejte následující funkci do scene.jsmimo funkci
createScene()
:const buildKey = function (scene, parent, props) { if (props.type === "white") { /* Props for building a white key should contain: note, topWidth, bottomWidth, topPositionX, wholePositionX, register, referencePositionX As an example, the props for building the middle C white key would be {type: "white", note: "C", topWidth: 1.4, bottomWidth: 2.3, topPositionX: -0.45, wholePositionX: -14.4, register: 4, referencePositionX: 0} */ // Create bottom part const bottom = BABYLON.MeshBuilder.CreateBox("whiteKeyBottom", {width: props.bottomWidth, height: 1.5, depth: 4.5}, scene); // Create top part const top = BABYLON.MeshBuilder.CreateBox("whiteKeyTop", {width: props.topWidth, height: 1.5, depth: 5}, scene); top.position.z = 4.75; top.position.x += props.topPositionX; // Merge bottom and top parts // Parameters of BABYLON.Mesh.MergeMeshes: (arrayOfMeshes, disposeSource, allow32BitsIndices, meshSubclass, subdivideWithSubMeshes, multiMultiMaterials) const key = BABYLON.Mesh.MergeMeshes([bottom, top], true, false, null, false, false); key.position.x = props.referencePositionX + props.wholePositionX; key.name = props.note + props.register; key.parent = parent; return key; } }
V tomto bloku kódu jsme vytvořili funkci s názvem
buildKey()
, která sestaví a vrátí bílý klíč, pokudprops.type
je"white"
. Identifikací typu klíče v parametruprops
můžeme vytvořit černé i bílé klíče ve stejné funkci pomocí příkazu if-.Parametry jsou
buildKey()
:- scene: scéna, ve které je klíč
- nadřazený: nadřazený objekt sítě (to nám umožňuje seskupit všechny klíče do jednoho nadřazeného objektu)
- rekvizit: vlastnosti klíče, který bude sestaven
Bílý
props
klíč bude obsahovat následující položky:- type: "white"
- name: název poznámky, kterou klíč představuje.
- topWidth: šířka horní části
- bottomWidth: šířka dolní části
- topPositionX: x-position of the top part vzhledem k dolní části
- wholePositionX: x pozice celé klávesy vzhledem ke koncovému bodu registru (pravý okraj klíče B).
- register: zaregistrujte, ke kterému klíč patří (číslo mezi 0 a 8)
- referencePositionX: souřadnice x koncového bodu registru (používá se jako referenční bod).
wholePositionX
Oddělením areferencePositionX
jsme schopni inicializovatprops
parametry potřebné k vytvoření konkrétního typu klíče (např. C) v rámci libovolného registru a potom přidatregister
do areferencePositionX
props
při vytváření tohoto klíče v konkrétním registru (např. C4, C5).Podobně můžeme také napsat obecnou funkci pro vytvoření černé klávesy. Pojďme funkci rozšířit,
buildKey()
aby zahrnovala tuto logiku:const buildKey = function (scene, parent, props) { if (props.type === "white") { /* Props for building a white key should contain: note, topWidth, bottomWidth, topPositionX, wholePositionX, register, referencePositionX As an example, the props for building the middle C white key would be {type: "white", note: "C", topWidth: 1.4, bottomWidth: 2.3, topPositionX: -0.45, wholePositionX: -14.4, register: 4, referencePositionX: 0} */ // Create bottom part const bottom = BABYLON.MeshBuilder.CreateBox("whiteKeyBottom", {width: props.bottomWidth, height: 1.5, depth: 4.5}, scene); // Create top part const top = BABYLON.MeshBuilder.CreateBox("whiteKeyTop", {width: props.topWidth, height: 1.5, depth: 5}, scene); top.position.z = 4.75; top.position.x += props.topPositionX; // Merge bottom and top parts // Parameters of BABYLON.Mesh.MergeMeshes: (arrayOfMeshes, disposeSource, allow32BitsIndices, meshSubclass, subdivideWithSubMeshes, multiMultiMaterials) const key = BABYLON.Mesh.MergeMeshes([bottom, top], true, false, null, false, false); key.position.x = props.referencePositionX + props.wholePositionX; key.name = props.note + props.register; key.parent = parent; return key; } else if (props.type === "black") { /* Props for building a black key should contain: note, wholePositionX, register, referencePositionX As an example, the props for building the C#4 black key would be {type: "black", note: "C#", wholePositionX: -13.45, register: 4, referencePositionX: 0} */ // Create black color material const blackMat = new BABYLON.StandardMaterial("black"); blackMat.diffuseColor = new BABYLON.Color3(0, 0, 0); // Create black key const key = BABYLON.MeshBuilder.CreateBox(props.note + props.register, {width: 1.4, height: 2, depth: 5}, scene); key.position.z += 4.75; key.position.y += 0.25; key.position.x = props.referencePositionX + props.wholePositionX; key.material = blackMat; key.parent = parent; return key; } }
Černá klávesa
props
pro obsahuje následující položky:- type: "black"
- name: název poznámky, kterou klíč představuje.
- wholePositionX: x-position celého klíče vzhledem ke koncovému bodu registru (pravý okraj klíče B)
- register: zaregistrujte, ke kterému klíč patří (číslo mezi 0 a 8)
- referencePositionX: souřadnice x koncového bodu registru (používá se jako referenční bod).
Vytvoření
props
černé klávesy je mnohem jednodušší, protože vytvoření černé klávesy zahrnuje pouze vytvoření rámečku a šířka každého černého klíče a pozice z jsou stejné.Teď, když máme efektivnější způsob vytváření kláves, inicializujeme pole, které ukládá
props
pro každou klávesu, která odpovídá poznámce v registru, a pak zavolámebuildKey()
funkci s každou z nich, abychom vytvořili jednoduchou klávesnici ve 4. registru.Vytvoříme také TransformNode s názvem
keyboard
, který bude fungovat jako nadřazený prvek všech kláves pro klavír. Vzhledem k tomu, že jakákoli změna pozice nebo škálování použitá u nadřazeného objektu by se použila i na podřízené položky, umožní nám seskupit klíče tímto způsobem a pak je škálovat nebo přesouvat jako celek.Do funkce připojte následující řádky
createScene()
kódu:const keyParams = [ {type: "white", note: "C", topWidth: 1.4, bottomWidth: 2.3, topPositionX: -0.45, wholePositionX: -14.4}, {type: "black", note: "C#", wholePositionX: -13.45}, {type: "white", note: "D", topWidth: 1.4, bottomWidth: 2.4, topPositionX: 0, wholePositionX: -12}, {type: "black", note: "D#", wholePositionX: -10.6}, {type: "white", note: "E", topWidth: 1.4, bottomWidth: 2.3, topPositionX: 0.45, wholePositionX: -9.6}, {type: "white", note: "F", topWidth: 1.3, bottomWidth: 2.4, topPositionX: -0.55, wholePositionX: -7.2}, {type: "black", note: "F#", wholePositionX: -6.35}, {type: "white", note: "G", topWidth: 1.3, bottomWidth: 2.3, topPositionX: -0.2, wholePositionX: -4.8}, {type: "black", note: "G#", wholePositionX: -3.6}, {type: "white", note: "A", topWidth: 1.3, bottomWidth: 2.3, topPositionX: 0.2, wholePositionX: -2.4}, {type: "black", note: "A#", wholePositionX: -0.85}, {type: "white", note: "B", topWidth: 1.3, bottomWidth: 2.4, topPositionX: 0.55, wholePositionX: 0}, ] // Transform Node that acts as the parent of all piano keys const keyboard = new BABYLON.TransformNode("keyboard"); keyParams.forEach(key => { buildKey(scene, keyboard, Object.assign({register: 4, referencePositionX: 0}, key)); })
Jak jste si asi všimli, v tomto bloku kódu umisťujeme všechny klíče vzhledem k počátku mezery.
Tady je kód, který scene.js zatím obsahuje:
const buildKey = function (scene, parent, props) { if (props.type === "white") { /* Props for building a white key should contain: note, topWidth, bottomWidth, topPositionX, wholePositionX, register, referencePositionX As an example, the props for building the middle C white key would be {type: "white", note: "C", topWidth: 1.4, bottomWidth: 2.3, topPositionX: -0.45, wholePositionX: -14.4, register: 4, referencePositionX: 0} */ // Create bottom part const bottom = BABYLON.MeshBuilder.CreateBox("whiteKeyBottom", {width: props.bottomWidth, height: 1.5, depth: 4.5}, scene); // Create top part const top = BABYLON.MeshBuilder.CreateBox("whiteKeyTop", {width: props.topWidth, height: 1.5, depth: 5}, scene); top.position.z = 4.75; top.position.x += props.topPositionX; // Merge bottom and top parts // Parameters of BABYLON.Mesh.MergeMeshes: (arrayOfMeshes, disposeSource, allow32BitsIndices, meshSubclass, subdivideWithSubMeshes, multiMultiMaterials) const key = BABYLON.Mesh.MergeMeshes([bottom, top], true, false, null, false, false); key.position.x = props.referencePositionX + props.wholePositionX; key.name = props.note + props.register; key.parent = parent; return key; } else if (props.type === "black") { /* Props for building a black key should contain: note, wholePositionX, register, referencePositionX As an example, the props for building the C#4 black key would be {type: "black", note: "C#", wholePositionX: -13.45, register: 4, referencePositionX: 0} */ // Create black color material const blackMat = new BABYLON.StandardMaterial("black"); blackMat.diffuseColor = new BABYLON.Color3(0, 0, 0); // Create black key const key = BABYLON.MeshBuilder.CreateBox(props.note + props.register, {width: 1.4, height: 2, depth: 5}, scene); key.position.z += 4.75; key.position.y += 0.25; key.position.x = props.referencePositionX + props.wholePositionX; key.material = blackMat; key.parent = parent; return key; } } const createScene = async function(engine) { const scene = new BABYLON.Scene(engine); const alpha = 3*Math.PI/2; const beta = Math.PI/50; const radius = 220; const target = new BABYLON.Vector3(0, 0, 0); const camera = new BABYLON.ArcRotateCamera("Camera", alpha, beta, radius, target, scene); camera.attachControl(canvas, true); const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene); light.intensity = 0.6; const keyParams = [ {type: "white", note: "C", topWidth: 1.4, bottomWidth: 2.3, topPositionX: -0.45, wholePositionX: -14.4}, {type: "black", note: "C#", wholePositionX: -13.45}, {type: "white", note: "D", topWidth: 1.4, bottomWidth: 2.4, topPositionX: 0, wholePositionX: -12}, {type: "black", note: "D#", wholePositionX: -10.6}, {type: "white", note: "E", topWidth: 1.4, bottomWidth: 2.3, topPositionX: 0.45, wholePositionX: -9.6}, {type: "white", note: "F", topWidth: 1.3, bottomWidth: 2.4, topPositionX: -0.55, wholePositionX: -7.2}, {type: "black", note: "F#", wholePositionX: -6.35}, {type: "white", note: "G", topWidth: 1.3, bottomWidth: 2.3, topPositionX: -0.2, wholePositionX: -4.8}, {type: "black", note: "G#", wholePositionX: -3.6}, {type: "white", note: "A", topWidth: 1.3, bottomWidth: 2.3, topPositionX: 0.2, wholePositionX: -2.4}, {type: "black", note: "A#", wholePositionX: -0.85}, {type: "white", note: "B", topWidth: 1.3, bottomWidth: 2.4, topPositionX: 0.55, wholePositionX: 0}, ] // Transform Node that acts as the parent of all piano keys const keyboard = new BABYLON.TransformNode("keyboard"); keyParams.forEach(key => { buildKey(scene, keyboard, Object.assign({register: 4, referencePositionX: 0}, key)); }) const xrHelper = await scene.createDefaultXRExperienceAsync(); return scene; }
Výsledná klávesnice by vypadala takto:
Rozšíření na klavír s 88 klávesy
V této části rozšíříme použití funkcí pro vytváření kláves a vygenerování plné 88 klávesové klávesnice.
Jak už bylo zmíněno dříve, plná klávesová klávesnice s 88 klávesami obsahuje 7 opakovaných registrů a 4 další poznámky. 3 z těchto dodatečných poznámek jsou v registru 0 (levý konec klávesnice) a 1 je v registru 8 (pravý konec klávesnice).
Nejprve budeme pracovat na sestavení 7 úplných opakování přidáním další smyčky kolem smyčky, kterou jsme napsali dříve. Předchozí smyčku pro
buildKey()
funkci nahraďte následujícím kódem:// Register 1 through 7 var referencePositionX = -2.4*14; for (let register = 1; register <= 7; register++) { keyParams.forEach(key => { buildKey(scene, keyboard, Object.assign({register: register, referencePositionX: referencePositionX}, key)); }) referencePositionX += 2.4*7; }
V této smyčce sestavíme klíče pro registr 1 až 7 a pokaždé, když přejdeme k dalšímu registru, zvýšíme referenční pozici.
V dalším kroku vytvoříme zbývající klíče. Přidejte do
createScene()
funkce následující fragment kódu:// Register 0 buildKey(scene, keyboard, {type: "white", note: "A", topWidth: 1.9, bottomWidth: 2.3, topPositionX: -0.20, wholePositionX: -2.4, register: 0, referencePositionX: -2.4*21}); keyParams.slice(10, 12).forEach(key => { buildKey(scene, keyboard, Object.assign({register: 0, referencePositionX: -2.4*21}, key)); }) // Register 8 buildKey(scene, keyboard, {type: "white", note: "C", topWidth: 2.3, bottomWidth: 2.3, topPositionX: 0, wholePositionX: -2.4*6, register: 8, referencePositionX: 84});
Všimněte si, že klávesa nejvíce vlevo a pravá klávesa klavírní klávesnice nezapadají do rozměrů rekvizit definovaných v
keyParams
(protože nejsou vedle černé klávesy na okraji), takže musíme definovat novýprops
objekt pro každou z nich, abychom mohli určit jejich speciální tvar.Vytvořená klávesnice by měla po provedení změn vypadat takto:
Přidání rámu pro klavír
Scéna vypadá trochu divně, v prostoru je jen klávesnice. Pojďme přidat rámeček klavíru kolem klávesnice, abychom vytvořili vzhled standup piano.
Podobně jako jsme vytvořili klávesy, můžeme také vytvořit rámeček umístěním a kombinováním skupiny krabicových sítí.
Tuto výzvu však necháme pro vás, abyste si to vyzkoušeli sami a použili BABYLON. SceneLoader.ImportMesh k importu předem vytvořené sítě ze standup piano frame. Připojte tuto část kódu k
createScene()
:// Transform node that acts as the parent of all piano components const piano = new BABYLON.TransformNode("piano"); keyboard.parent = piano; // Import and scale piano frame BABYLON.SceneLoader.ImportMesh("frame", "https://raw.githubusercontent.com/MicrosoftDocs/mixed-reality/docs/mixed-reality-docs/mr-dev-docs/develop/javascript/tutorials/babylonjs-webxr-piano/files/", "pianoFrame.babylon", scene, function(meshes) { const frame = meshes[0]; frame.parent = piano; });
Všimněte si, že opět vytváříme nadřazený
TransformNode
objekt s názvempiano
, který seskupí klávesnici a rámeček dohromady jako celek. To výrazně usnadní přesunutí nebo škálování celého klavíru, pokud bychom to někdy potřebovali.Po importu rámce si všimněte, že klávesnice leží v dolní části rámce (protože souřadnice kláves y jsou ve výchozím nastavení na hodnotě 0). Zvedněme klávesnici, aby se vešla do standup rámu klavíru:
// Lift piano keys keyboard.position.y += 80;
Vzhledem k tomu
keyboard
, že je nadřazená všechny klavírní klávesy, můžeme všechny klavírní klávesy zvednout jednoduše tak, že změníme pozicikeyboard
y pro .Konečný kód scene.js by měl vypadat takto:
const buildKey = function (scene, parent, props) { if (props.type === "white") { /* Props for building a white key should contain: note, topWidth, bottomWidth, topPositionX, wholePositionX, register, referencePositionX As an example, the props for building the middle C white key would be {type: "white", note: "C", topWidth: 1.4, bottomWidth: 2.3, topPositionX: -0.45, wholePositionX: -14.4, register: 4, referencePositionX: 0} */ // Create bottom part const bottom = BABYLON.MeshBuilder.CreateBox("whiteKeyBottom", {width: props.bottomWidth, height: 1.5, depth: 4.5}, scene); // Create top part const top = BABYLON.MeshBuilder.CreateBox("whiteKeyTop", {width: props.topWidth, height: 1.5, depth: 5}, scene); top.position.z = 4.75; top.position.x += props.topPositionX; // Merge bottom and top parts // Parameters of BABYLON.Mesh.MergeMeshes: (arrayOfMeshes, disposeSource, allow32BitsIndices, meshSubclass, subdivideWithSubMeshes, multiMultiMaterials) const key = BABYLON.Mesh.MergeMeshes([bottom, top], true, false, null, false, false); key.position.x = props.referencePositionX + props.wholePositionX; key.name = props.note + props.register; key.parent = parent; return key; } else if (props.type === "black") { /* Props for building a black key should contain: note, wholePositionX, register, referencePositionX As an example, the props for building the C#4 black key would be {type: "black", note: "C#", wholePositionX: -13.45, register: 4, referencePositionX: 0} */ // Create black color material const blackMat = new BABYLON.StandardMaterial("black"); blackMat.diffuseColor = new BABYLON.Color3(0, 0, 0); // Create black key const key = BABYLON.MeshBuilder.CreateBox(props.note + props.register, {width: 1.4, height: 2, depth: 5}, scene); key.position.z += 4.75; key.position.y += 0.25; key.position.x = props.referencePositionX + props.wholePositionX; key.material = blackMat; key.parent = parent; return key; } } const createScene = async function(engine) { const scene = new BABYLON.Scene(engine); const alpha = 3*Math.PI/2; const beta = Math.PI/50; const radius = 220; const target = new BABYLON.Vector3(0, 0, 0); const camera = new BABYLON.ArcRotateCamera("Camera", alpha, beta, radius, target, scene); camera.attachControl(canvas, true); const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene); light.intensity = 0.6; const keyParams = [ {type: "white", note: "C", topWidth: 1.4, bottomWidth: 2.3, topPositionX: -0.45, wholePositionX: -14.4}, {type: "black", note: "C#", wholePositionX: -13.45}, {type: "white", note: "D", topWidth: 1.4, bottomWidth: 2.4, topPositionX: 0, wholePositionX: -12}, {type: "black", note: "D#", wholePositionX: -10.6}, {type: "white", note: "E", topWidth: 1.4, bottomWidth: 2.3, topPositionX: 0.45, wholePositionX: -9.6}, {type: "white", note: "F", topWidth: 1.3, bottomWidth: 2.4, topPositionX: -0.55, wholePositionX: -7.2}, {type: "black", note: "F#", wholePositionX: -6.35}, {type: "white", note: "G", topWidth: 1.3, bottomWidth: 2.3, topPositionX: -0.2, wholePositionX: -4.8}, {type: "black", note: "G#", wholePositionX: -3.6}, {type: "white", note: "A", topWidth: 1.3, bottomWidth: 2.3, topPositionX: 0.2, wholePositionX: -2.4}, {type: "black", note: "A#", wholePositionX: -0.85}, {type: "white", note: "B", topWidth: 1.3, bottomWidth: 2.4, topPositionX: 0.55, wholePositionX: 0}, ] // Transform Node that acts as the parent of all piano keys const keyboard = new BABYLON.TransformNode("keyboard"); // Register 1 through 7 var referencePositionX = -2.4*14; for (let register = 1; register <= 7; register++) { keyParams.forEach(key => { buildKey(scene, keyboard, Object.assign({register: register, referencePositionX: referencePositionX}, key)); }) referencePositionX += 2.4*7; } // Register 0 buildKey(scene, keyboard, {type: "white", note: "A", topWidth: 1.9, bottomWidth: 2.3, topPositionX: -0.20, wholePositionX: -2.4, register: 0, referencePositionX: -2.4*21}); keyParams.slice(10, 12).forEach(key => { buildKey(scene, keyboard, Object.assign({register: 0, referencePositionX: -2.4*21}, key)); }) // Register 8 buildKey(scene, keyboard, {type: "white", note: "C", topWidth: 2.3, bottomWidth: 2.3, topPositionX: 0, wholePositionX: -2.4*6, register: 8, referencePositionX: 84}); // Transform node that acts as the parent of all piano components const piano = new BABYLON.TransformNode("piano"); keyboard.parent = piano; // Import and scale piano frame BABYLON.SceneLoader.ImportMesh("frame", "https://raw.githubusercontent.com/MicrosoftDocs/mixed-reality/docs/mixed-reality-docs/mr-dev-docs/develop/javascript/tutorials/babylonjs-webxr-piano/files/", "pianoFrame.babylon", scene, function(meshes) { const frame = meshes[0]; frame.parent = piano; }); // Lift the piano keyboard keyboard.position.y += 80; const xrHelper = await scene.createDefaultXRExperienceAsync(); return scene; }
Teď bychom měli mít standup piano, které vypadá takto: