はじめに
音楽まったくやってない人って楽器ひくことにちょっとしたあこがれないですか?
私はそんな一人です、楽器ひいてみたい。
ということで、かくかくしかじかあってマトリョミン作ることにしました。前回は、音を奏でるテルミン(風)までを作りました。今回は、見た目をマトリョーシカにしていきます。
完成デモ
できたマトリョミン(風)はこちら。ARで見た目をマトリョーシカにしていて、奏でる音階に合わせてマトリョーシカの表情が変わります。
テルミンを内蔵するマトリョーシカ、その名もマトリョミン。マトリョミン風の楽器をIoTで作ってみる。
— suo-takefumi (@zsipparu) December 20, 2020
ステップ(7) ARで見た目をマトリョーシカにするの完成
よし!マトリョミン風の楽器できた!#Matryomin #protoout #AFrame #ARjs #obniz pic.twitter.com/QPn6TUzLzU
距離センサーとスピーカーで音を奏でて、かつARと連携する仕組みを作る
前回は、距離センサーとスピーカーで奏でる音を制御しましたが、今回はさらにARとも連携させます。ARは、A-FrameとAR.jsを使いました。
前回LEGOで組み立てたテルミン(風)に、LEGO互換パーツ化したARマーカーを付けます。
※LEGO互換ARマーカーの作り方はこちらで紹介しています
→レジンでLEGO互換パーツを自作したい!その(1)
制御スクリプトはこちら
前回にちょっと追加で制御スクリプトが作れると思っていたのですが、甘かった。obniz x A-Frame x AR.js 連携の情報が見つからなくて結局自作しました(ちょっと苦戦しました)。
<!doctype HTML>
<html>
<script src="https://unpkg.com/obniz@3.10.1/obniz.js"></script>
<script src="js/aframe.min.js"></script>
<script src="js/aframe-ar.js"></script>
<body style="margin: 0px; overflow: hidden;">
<script>
let obnizConnectFlg = 0;
let hcsr04;
let speaker;
let glNo = 0;
let updateFlg=0;
const SCALELENGTH = 15;
const STARTCOUNT = 5;
const CYCLEVAL = 500;
const scaleArr = new Array();
const dispArr = new Array();
scaleArr.push(0); dispArr.push("無(近)");
scaleArr.push(262); dispArr.push("ド");
scaleArr.push(294); dispArr.push("レ");
scaleArr.push(330); dispArr.push("ミ");
scaleArr.push(349); dispArr.push("ファ");
scaleArr.push(392); dispArr.push("ソ");
scaleArr.push(440); dispArr.push("ラ");
scaleArr.push(494); dispArr.push("シ");
scaleArr.push(523); dispArr.push("ド(高)");
scaleArr.push(0); dispArr.push("無(遠)");
const OBNIZ_ID = 'xxxx-xxxx'; // お持ちのObniz ID を設定
const obniz = new Obniz(OBNIZ_ID);
obniz.onconnect = async function() {
hcsr04 = obniz.wired("HC-SR04", {gnd:0, echo:1, trigger:2, vcc:3});
speaker = obniz.wired("Speaker",{"signal":10, "gnd":11});
obnizConnectFlg = 1;
}
AFRAME.registerComponent('canvas-texture', {
init: function()
{
this.canvas = document.querySelector("#myCanvas");
this.canvas.width = 595;
this.canvas.height = 842;
this.context = this.canvas.getContext('2d');
this.x = 200;
this.y = 100;
this.dx = 5;
this.dy = 3;
this.image = ["00.png","01.png","02.png","03.png","04.png","05.png","06.png","07.png","08.png","09.png"];
this.imgSrc = "";
this.dtsum = 0;
this.distance = 0;
this.updateFlg = 0;
},
update: function(){
let material = this.el.getObject3D("mesh").material;
const chara = new Image();
console.log("glNo = " + glNo + ", this.image[ glNo ] = " + this.image[ glNo ]);
chara.src = "images/" + this.image[ glNo ];
chara.onload = () => {
this.context.drawImage(chara, 0, 0);
if (!material.map)
return;
else
material.map.needsUpdate = true;
};
},
tick: function(t, dt)
{
this.dtsum += dt;
if( this.dtsum >= CYCLEVAL ){
this.dtsum = 0;
if(obnizConnectFlg == 1){
this.obniz();
}
}
},
obniz: function(){
hcsr04.measure(function(distance){
console.log("distance = " + distance);
updateFlg = 1;
const tmpNo = Math.floor( distance / SCALELENGTH ) - STARTCOUNT;
if(tmpNo < 0){
glNo = 0;
}else if(tmpNo >= 9){
glNo = 9;
}else if( !isNaN(tmpNo) ){
glNo = tmpNo;
}else{
glNo = 9;
}
speaker.play( scaleArr[ glNo ] );
updateFlg = 1;
});
if( updateFlg == 1){
updateFlg = 0;
this.update();
}
}
});
</script>
<a-scene embedded vr-mode-ui="enabled: false;" arjs="debugUIEnabled: false;">
<a-assets>
<canvas id="myCanvas"></canvas>
</a-assets>
<a-marker type="pattern" url="data/hiro.patt">
<a-plane
width="2" height="2.82"
position="0 0 0"
rotation="-90 0 0"
material="src: #myCanvas; transparent: true; opacity: 0.95;"
canvas-texture
></a-plane>
</a-marker>
<a-entity camera></a-entity>
</a-scene>
</body>
</html>
イラストの準備
描いたマトリョーシカのイラストは全10種類。
9種類はこちら
テルミンを内蔵するマトリョーシカ、その名もマトリョミン。マトリョミン風の楽器をIoTで作ってみる。
— suo-takefumi (@zsipparu) December 20, 2020
ステップ(6) マトリョーシカのイラスト完成#Matryomin #protoout pic.twitter.com/uRynpctFMp
10枚目がこれ。距離が近すぎたらこのイラストが表示されます。
さいごに
アドベントカレンダーに参加したくて、マトリョミン(風)の楽器を作りました。obnizとA-Frame,AR.jsの連携が思ったより難しかったですが、無事つくれてよかった。