Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Dans le tutoriel précédent de la série, vous avez configuré une page web contenant une scène Babylon.js avec une caméra et une lumière. Dans ce tutoriel, vous allez créer et ajouter un modèle de piano à la scène.
Dans ce tutoriel, vous apprenez à effectuer les opérations suivantes :
- Créer, positionner et fusionner des maillages
- Créer un clavier de piano à partir de maillages de boîtes
- Importer un modèle 3D d’un cadre de piano
Avant de commencer
Assurez-vous que vous avez terminé le tutoriel précédent de la série et que vous êtes prêt à continuer à ajouter au code.
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;
}
Prise en main
Commençons par créer un clavier de piano simple avec cette structure :
Dans cette image, il y a sept clés blanches et cinq touches noires, chacune étiquetée avec le nom de la note. Un clavier de piano complet de 88 touches contient sept répétitions complètes de cette sélection de touches (également appelée registre) et quatre touches supplémentaires. Chaque registre a le double de la fréquence de son registre précédent. Par exemple, la fréquence de tangage de C5 (ce qui signifie que la note C dans le cinquième registre) est le double de celle de C4, la fréquence de tangage de D5 est le double de celle de D4, et ainsi de suite.
Visuellement, chaque registre ressemble exactement à un autre, donc nous pouvons commencer par examiner comment créer un clavier de piano simple avec cette sélection de touches. Plus tard, nous trouverons un moyen d’étendre l’étendue à un clavier de piano complet de 88 touches.
Créer un clavier de piano simple
Remarque
Bien qu’il soit possible de trouver des modèles 3D prédéfinis de claviers de piano à partir de sources en ligne et de les importer dans notre page web, nous allons créer le clavier à partir de zéro dans ce tutoriel pour permettre une personnalisation maximale et pour montrer comment les modèles 3D peuvent être créés via Babylon.js.
Avant de commencer à créer des maillages pour la construction du clavier, notez que chaque touche noire n’est pas parfaitement alignée au milieu des deux touches blanches qui l’entourent, et que toutes les touches n’ont pas la même largeur. Cela signifie que nous devons créer et positionner le maillage pour chaque clé individuellement.
Pour les touches blanches, nous pouvons faire une observation que chaque clé blanche est composée de deux parties : (1) la partie inférieure sous la ou les touches noires et (2) la partie supérieure en regard de la ou des touches noires. Les deux parties ont des dimensions différentes, mais sont empilées ensemble pour créer une clé blanche complète.
Voici le code permettant de créer une clé blanche unique pour la note C (ne vous inquiétez pas encore de l’ajouter à 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";Ici, nous avons créé deux maillages Box , un pour la partie inférieure et l’autre pour la partie supérieure de la clé blanche. Nous modifions ensuite la position de la partie supérieure pour l’empiler sur la partie inférieure et la déplacer vers la gauche pour laisser de l’espace pour la clé noire voisine (C#).
Enfin, ces deux parties ont été fusionnées à l’aide de la fonction MergeMeshes pour devenir une clé blanche complète. Il s’agit du maillage résultant que ce code produirait :
La création d’une clé noire est plus simple. Étant donné que toutes les touches noires sont de la forme d’une boîte, nous pouvons créer une clé noire simplement en créant un maillage de boîte avec un StandardMaterial de couleur noire.
Remarque
Étant donné que la couleur de maillage par défaut est un gris clair qui ressemble au blanc, ce tutoriel n’inclut pas d’étapes pour ajouter un matériau de couleur blanche aux touches blanches. Toutefois, n’hésitez pas à ajouter le matériau vous-même si vous souhaitez une vraie couleur blanche sur les touches blanches.
Voici le code permettant de créer la clé noire C# (ne vous inquiétez pas non plus de l’ajouter à 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;La clé noire produite par ce code (avec la clé blanche précédente) se présente comme suit :
Comme vous pouvez le voir, la création de chaque clé peut entraîner un grand nombre de codes similaires, car nous devons spécifier chacune de leurs dimensions et position. Essayons de rendre le processus de création plus efficace dans la section suivante.
Créer efficacement un clavier de piano simple
Bien que chaque clé blanche ait une forme légèrement différente les unes des autres, toutes peuvent être créées en combinant une partie supérieure et une partie inférieure. Implémentons une fonction générique pour créer et positionner n’importe quelle clé blanche.
Ajoutez la fonction ci-dessous pour scene.js, en dehors de la
createScene()fonction :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; } }Dans ce bloc de code, nous avons créé une fonction nommée
buildKey(), qui génère et retourne une clé blanche siprops.typea la valeur"white". En identifiant le type de la clé dans le paramètreprops, nous pouvons créer des clés noires et des clés blanches dans la même fonction en créant une branche à l’aide d’une instruction if.Les paramètres de
buildKey()sont les suivants :- scene : scène dans laquelle se trouve la clé
- parent : parent du maillage (cela nous permet de regrouper toutes les clés en un seul parent)
- props : propriétés de la clé qui sera générée
Le
propspour une clé blanche contient les éléments suivants :- type : « blanc »
- name : nom de la note que représente la clé
- topWidth : largeur de la partie supérieure
- bottomWidth : largeur de la partie inférieure
- topPositionX : position x de la partie supérieure par rapport à la partie inférieure
- wholePositionX : position x de l’ensemble de la clé par rapport au point de terminaison du registre (le bord droit de la clé B).
- register : inscrire à laquelle appartient la clé (un nombre compris entre 0 et 8)
- referencePositionX : coordonnée x du point de terminaison du registre (utilisé comme point de référence).
En séparant
wholePositionXetreferencePositionX, nous sommes en mesure d’initialiser lespropsparamètres nécessaires pour créer un type spécifique de clé (par exemple, C) dans n’importe quel registre, puis d’ajouterregisteretreferencePositionXà lors de lapropscréation de cette clé dans un registre spécifique (par exemple, C4, C5).De même, nous pouvons également écrire une fonction générique pour créer une clé noire. Nous allons développer la
buildKey()fonction pour inclure cette logique :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; } }Le
propspour une clé noire contient les éléments suivants :- type : « black »
- name : nom de la note que représente la clé
- wholePositionX : position x de l’ensemble de la clé par rapport au point de terminaison du registre (le bord droit de la clé B)
- register : inscrire à laquelle appartient la clé (un nombre compris entre 0 et 8)
- referencePositionX : coordonnée x du point de terminaison du registre (utilisé comme point de référence).
Le
propspour créer une clé noire est beaucoup plus simple, car la création d’une clé noire implique uniquement la création d’une boîte, et la largeur et la position z de chaque clé noire sont identiques.Maintenant que nous avons un moyen plus efficace de créer les touches, initialisons un tableau qui stocke pour
propschaque touche qui correspond à une note dans un registre, puis appelons labuildKey()fonction avec chacune d’elles pour créer un clavier simple dans le quatrième registre.Nous allons également créer un TransformNode nommé
keyboardpour agir en tant que parent de toutes les touches de piano. Étant donné que toute modification de position ou de mise à l’échelle appliquée au parent est également appliquée aux enfants, le regroupement des clés de cette façon nous permet de les mettre à l’échelle ou de les déplacer dans leur ensemble.Ajoutez les lignes de code suivantes dans la
createScene()fonction :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)); })Comme vous l’avez probablement remarqué, dans ce bloc de code, nous plaçons toutes les clés relatives à l’origine de l’espace.
Voici le code que scene.js contient jusqu’à présent :
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; }Voici à quoi ressemblerait le clavier obtenu :
Extension à un piano à 88 touches
Dans cette section, nous allons développer l’utilisation des fonctions de création de touches pour générer un clavier de piano complet de 88 touches.
Comme mentionné précédemment, un clavier de piano complet de 88 touches contient sept registres répétés et quatre autres notes. Trois de ces notes supplémentaires se trouvent dans le registre 0 (extrémité gauche du clavier) et 1 dans le registre 8 (extrémité droite du clavier).
Nous allons d’abord travailler sur la création des sept répétitions complètes en ajoutant une boucle supplémentaire autour de la boucle que nous avons écrite précédemment. Remplacez la boucle précédente pour la
buildKey()fonction par le code suivant :// 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; }Dans cette boucle, nous créons les clés du registre 1 à 7 et incrémentons la position de référence chaque fois que nous passons au registre suivant.
Ensuite, nous allons créer le reste des clés. Ajoutez l’extrait de code suivant à la
createScene()fonction :// 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});Notez que la touche la plus à gauche et la touche la plus à droite du clavier du piano ne tiennent pas dans les dimensions des accessoires définis dans
keyParams(car elles ne sont pas à côté d’une touche noire au bord), nous devons donc définir un nouvelpropsobjet pour chacun d’eux afin de spécifier leur forme spéciale.Le clavier produit doit ressembler à ceci une fois les modifications apportées :
Ajout d’un cadre de piano
La scène semble un peu étrange avec juste un clavier flottant dans l’espace. Ajoutons un cadre de piano autour du clavier pour créer l’apparence d’un piano debout.
À l’instar de la façon dont nous avons créé les clés, nous pouvons également créer le cadre en positionnant et en combinant un groupe de maillages de boîtes.
Cependant, nous allons laisser ce défi pour vous d’essayer par vous-même et d’utiliser BABYLON. SceneLoader.ImportMesh pour importer un maillage prédéfini d’un cadre de piano debout. Ajoutez ce morceau de code à
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; });Notez que nous créons à nouveau un parent
TransformNodenommépianopour regrouper le clavier et le cadre dans son ensemble. Cela rendra le déplacement ou la mise à l’échelle de l’ensemble du piano beaucoup plus facile si nous avons jamais besoin de le faire.Une fois le frame importé, notez que le clavier se trouve en bas du cadre (car les coordonnées y des touches sont à 0 par défaut). Soulevons le clavier pour qu’il s’intègre dans le cadre du piano debout :
// Lift piano keys keyboard.position.y += 80;Étant donné que
keyboardest le parent de toutes les touches de piano, nous pouvons soulever toutes les touches de piano en modifiant simplement la position y dekeyboard.Le code final de scene.js doit ressembler à ceci :
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; }Maintenant, nous devrions avoir un piano debout qui ressemble à ceci :
