Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Dalam tutorial sebelumnya dalam seri ini, kami telah menyiapkan halaman web yang berisi adegan Babylon.js dengan kamera dan lampu. Dalam tutorial ini, kita akan membangun dan menambahkan model piano ke dalam adegan.
Dalam tutorial ini, Anda akan belajar cara:
- Membuat, memposisikan, dan menggabungkan jala
- Membangun keyboard piano dari jala kotak
- Mengimpor model 3D dari bingkai piano
Sebelum Anda mulai
Pastikan Anda telah melalui tutorial sebelumnya dalam seri dan siap untuk terus menambahkan ke kode.
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;
}
Memulai
Mari kita mulai dengan membuat keyboard piano sederhana yang memiliki struktur ini:
Dalam gambar ini, ada 7 kunci putih dan 5 kunci hitam, masing-masing diberi label dengan nama catatan. Keyboard piano 88-key lengkap berisi 7 pengulangan penuh dari pilihan tombol ini (juga disebut register) dan 4 tombol tambahan. Setiap register memiliki frekuensi ganda dari register sebelumnya. Misalnya, frekuensi pitch C5 (yang berarti catatan C di register kelima) dua kali lipat dari C4, frekuensi pitch D5 dua kali lipat dari D4, dan sebagainya.
Secara visual, setiap register terlihat persis sama dengan yang lain, sehingga kita dapat mulai dengan menyelidiki cara membuat keyboard piano sederhana dengan pilihan kunci ini. Nantinya, kita dapat menemukan cara untuk memperluas cakupan ke keyboard piano lengkap 88-key.
Membangun keyboard piano sederhana
Catatan
Meskipun dimungkinkan untuk menemukan model keyboard piano 3D yang dibuat sebelumnya dari sumber online dan mengimpornya ke halaman web kami, kami akan membangun keyboard dari awal dalam tutorial ini untuk memungkinkan penyesuaian maksimum dan untuk menampilkan bagaimana model 3D dapat dibuat melalui Babylon.js.
Sebelum kita mulai membuat jala untuk membangun keyboard, perhatikan bahwa setiap tombol hitam tidak selaras dengan sempurna di tengah-tengah dua tombol putih di sekitarnya, dan tidak setiap tombol memiliki lebar yang sama. Ini berarti bahwa kita harus membuat dan memposisikan jala untuk setiap kunci satu per satu.
Untuk kunci putih, kita dapat melakukan pengamatan bahwa setiap kunci putih terdiri dari dua bagian: (1) bagian bawah di bawah kunci hitam dan (2) bagian atas di samping kunci hitam. Kedua bagian memiliki dimensi yang berbeda tetapi ditumpuk bersama-sama untuk mengkremasi kunci putih penuh.
Berikut adalah kode untuk membuat satu kunci putih untuk catatan C (jangan khawatir tentang menambahkannya ke dalamscene.js belum):
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";
Di sini kita membuat dua jala Kotak , satu untuk bagian bawah dan satu untuk bagian atas kunci putih. Kami kemudian memodifikasi posisi bagian atas untuk menumpuknya di atas bagian bawah dan memindahkannya ke arah kiri untuk meninggalkan ruang bagi kunci hitam tetangga (C#).
Akhirnya, kedua bagian ini digabungkan menggunakan fungsi MergeMeshes untuk menjadi satu kunci putih lengkap. Ini adalah jala yang dihasilkan yang akan dihasilkan kode ini:
Membuat kunci hitam lebih sederhana. Karena semua kunci hitam berbentuk kotak, kita dapat membuat kunci hitam hanya dengan membuat jala kotak dengan StandardMaterial berwarna hitam.
Catatan
Karena warna jala default adalah abu-abu muda yang menyerupai putih, tutorial ini tidak menyertakan langkah-langkah untuk menambahkan bahan warna putih ke tombol putih. Namun, jangan ragu untuk menambahkan bahan sendiri jika Anda ingin warna putih yang benar dan cerah pada tombol putih.
Berikut adalah kode untuk membuat kunci hitam C# (jangan khawatir tentang menambahkan ini ke scene.js juga):
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;
Kunci hitam yang dihasilkan oleh kode ini (bersama dengan kunci putih sebelumnya) akan terlihat seperti ini:
Seperti yang Anda lihat, membuat setiap kunci dapat menghasilkan banyak kode serupa karena kita harus menentukan masing-masing dimensi dan posisinya. Mari kita coba membuat proses pembuatan lebih efisien di bagian berikutnya.
Membangun keyboard piano sederhana secara efisien
Meskipun setiap tombol putih memiliki bentuk yang sedikit berbeda satu sama lain, semuanya dapat dibuat dengan menggabungkan bagian atas dan bagian bawah. Mari kita terapkan fungsi generik untuk membuat dan memposisikan kunci putih apa pun.
Tambahkan fungsi di bawah ini ke scene.js, di
createScene()
luar fungsi :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; } }
Dalam blok kode ini, kami membuat fungsi bernama
buildKey()
, yang membangun dan mengembalikan kunci putih jikaprops.type
adalah"white"
. Dengan mengidentifikasi jenis kunci dalam parameterprops
, kita dapat membuat kunci hitam dan kunci putih dalam fungsi yang sama dengan mencabangkan menggunakan pernyataan if.Parameternya
buildKey()
adalah:- scene: adegan tempat kunci berada
- induk: induk jala (ini memungkinkan kita untuk mengelompokkan semua kunci bersama-sama ke satu induk)
- props: properti kunci yang akan dibangun
props
untuk kunci putih akan berisi item berikut:- type: "white"
- nama: nama catatan yang diwakili kunci
- topWidth: lebar bagian atas
- bottomWidth: lebar bagian bawah
- topPositionX: posisi x bagian atas relatif terhadap bagian bawah
- wholePositionX: x-position dari seluruh kunci relatif terhadap titik akhir register (tepi kanan kunci B).
- register: daftarkan bahwa kunci tersebut milik (angka antara 0 dan 8)
- referencePositionX: koordinat x titik akhir register (digunakan sebagai titik referensi).
Dengan memisahkan
wholePositionX
danreferencePositionX
, kita dapat menginisialisasiprops
parameter yang diperlukan untuk membuat jenis kunci tertentu (misalnya C) dalam register apa pun, dan kemudian menambahkan danregister
referencePositionX
ke saat membuat kunci tersebutprops
dalam register tertentu (misalnya C4, C5).Demikian pula, kita juga dapat menulis fungsi generik untuk membuat kunci hitam. Mari kita perluas fungsi untuk menyertakan logika tersebut
buildKey()
: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; } }
props
untuk kunci hitam berisi item berikut:- jenis: "hitam"
- nama: nama catatan yang diwakili kunci
- wholePositionX: x-position dari seluruh kunci relatif terhadap titik akhir register (tepi kanan kunci B)
- register: daftarkan bahwa kunci tersebut milik (angka antara 0 dan 8)
- referencePositionX: koordinat x titik akhir register (digunakan sebagai titik referensi).
props
untuk membuat kunci hitam jauh lebih sederhana karena membuat kunci hitam hanya melibatkan pembuatan kotak, dan lebar dan posisi z setiap kunci hitam sama.Sekarang kita memiliki cara yang lebih efisien untuk membuat kunci, mari kita inisialisasi
props
array yang menyimpan untuk setiap kunci yang sesuai dengan catatan dalam register, dan kemudian memanggilbuildKey()
fungsi dengan masing-masing dari mereka untuk membuat keyboard sederhana di register ke-4.Kami juga akan membuat TransformNode bernama
keyboard
untuk bertindak sebagai induk dari semua kunci piano. Karena setiap perubahan posisi atau penskalakan yang diterapkan pada induk juga akan diterapkan pada anak-anak, mengelompokkan kunci dengan cara ini akan memungkinkan kita untuk menskalakan atau memindahkannya secara keseluruhan.Tambahkan baris kode berikut dalam
createScene()
fungsi :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)); })
Seperti yang mungkin telah Anda perhatikan, dalam blok kode ini kami menempatkan semua kunci relatif terhadap asal ruang.
Berikut adalah kode yang scene.js berisi sejauh ini:
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; }
Seperti inilah tampilan keyboard yang dihasilkan:
Memperluas ke piano 88-key
Di bagian ini, mari kita perluas penggunaan fungsi pembuatan kunci untuk menghasilkan keyboard piano 88 tombol penuh.
Seperti disebutkan sebelumnya, keyboard piano 88 tombol penuh berisi 7 register berulang dan 4 catatan lainnya. 3 dari catatan tambahan tersebut ada di register 0 (ujung kiri keyboard), dan 1 ada di register 8 (ujung kanan keyboard).
Pertama-tama kami akan bekerja membangun 7 pengulangan penuh dengan menambahkan perulangan tambahan di sekitar perulangan yang kami tulis sebelumnya. Ganti perulangan sebelumnya untuk
buildKey()
fungsi dengan kode berikut:// 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; }
Dalam perulangan ini, kami membangun kunci untuk register 1 sampai 7 dan meningkatkan posisi referensi setiap kali kami beralih ke register berikutnya.
Selanjutnya, mari kita buat kunci lainnya. Tambahkan cuplikan berikut ke
createScene()
fungsi :// 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});
Perhatikan bahwa kunci paling kiri dan kunci paling kanan keyboard piano tidak cocok dengan dimensi alat peraga yang ditentukan di
keyParams
(karena tidak di samping tombol hitam di tepi), jadi kita perlu menentukan objek baruprops
bagi masing-masing dari mereka untuk menentukan bentuk khusus mereka.Keyboard yang dihasilkan akan terlihat seperti ini setelah perubahan dilakukan:
Menambahkan bingkai piano
Adegan terlihat sedikit aneh hanya dengan keyboard mengambang di ruang. Mari kita tambahkan bingkai piano di sekitar keyboard untuk membuat tampilan piano standup.
Mirip dengan cara kita membuat kunci, kita juga dapat membuat bingkai dengan memposisikan dan menggabungkan sekelompok jala kotak.
Namun, kami akan meninggalkan tantangan itu bagi Anda untuk mencoba sendiri dan menggunakan BABYLON. SceneLoader.ImportMesh untuk mengimpor jala buatan sebelumnya dari bingkai piano standup. Tambahkan bagian kode ini ke
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; });
Perhatikan bahwa kita, sekali lagi, membuat induk
TransformNode
bernamapiano
untuk mengelompokkan keyboard dan bingkai bersama-sama secara keseluruhan. Ini akan membuat bergerak atau menskalakan seluruh piano jauh lebih mudah jika kita perlu melakukannya.Setelah bingkai diimpor, perhatikan bahwa keyboard berbaring di bagian bawah bingkai (karena koordinat y tombol berada di 0 secara default). Mari angkat keyboard agar pas dengan bingkai piano standup:
// Lift piano keys keyboard.position.y += 80;
Karena
keyboard
adalah induk dari semua kunci piano, kita dapat mengangkat semua kunci piano hanya dengan mengubah posisikeyboard
y .Kode akhir scene.js akan terlihat seperti ini:
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; }
Sekarang kita harus memiliki piano standup yang terlihat seperti ini: