😸
AR.jsでWebARしてみる(10) Line between two markers
はじめに
WebARで分かったことメモしていく
参考
※Line between two markers (line.html)
を勉強する
デモ
- 以下の環境で動作を確認
- iOS 13.7 Safari
- Android 9 Chrome
- Windows10 Firefox 81.0.1
ソース
参考で紹介したサイトのLine between two markers (line.html)のソース
<!doctype HTML>
<html>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script src="js/aframe.min.js"></script>
<script src="js/aframe-ar.js"></script>
<body style="margin: 0px; overflow: hidden;">
<script>
// store visibility data in object;
// can only draw line when both are visible.
let markerVisible = { m0: false, m1: false };
AFRAME.registerComponent('registerevents', {
init: function ()
{
let marker = this.el;
marker.addEventListener('markerFound', function() {
markerVisible[ marker.id ] = true;
});
marker.addEventListener('markerLost', function() {
markerVisible[ marker.id ] = false;
});
}
});
AFRAME.registerComponent('run', {
init: function()
{
this.m0 = document.querySelector("#m0");
this.m1 = document.querySelector("#m1");
this.p0 = new THREE.Vector3();
this.p1 = new THREE.Vector3();
this.geometry = new THREE.Geometry();
this.geometry.vertices.push( new THREE.Vector3(-1,-1,-1) );
this.geometry.vertices.push( new THREE.Vector3( 1, 1, 1) );
this.material = new THREE.LineBasicMaterial( {color: 0xFF0000} );
this.line = new THREE.Line( this.geometry, this.material );
let scene = document.querySelector('a-scene').object3D;
scene.add( this.line );
},
tick: function (time, deltaTime)
{
if ( markerVisible["m0"] && markerVisible["m1"] )
{
this.m0.object3D.getWorldPosition(this.p0);
this.m1.object3D.getWorldPosition(this.p1);
this.geometry.vertices[0] = this.p0;
this.geometry.vertices[1] = this.p1;
this.geometry.verticesNeedUpdate = true;
this.line.visible = true;
}
else
{
this.line.visible = false;
}
}
});
</script>
<a-scene embedded vr-mode-ui="enabled: false;" arjs="debugUIEnabled: false; detectionMode: mono_and_matrix; matrixCodeType: 3x3;">
<a-assets>
<img id="grid" src="images/border.png" />
</a-assets>
<a-marker type="barcode" value="0" id="m0" registerevents>
<a-plane position="0 0 0"
rotation="-90 0 0"
material="color: white; transparent: true; opacity: 0.10;">
</a-plane>
</a-marker>
<a-marker type="barcode" value="1" id="m1" registerevents>
<a-plane position="0 0 0"
rotation="-90 0 0"
material="color: white; transparent: true; opacity: 0.10;">
</a-plane>
</a-marker>
<a-marker type="pattern" url="data/kanji.patt" id="baseMarker" ></a-marker>
<a-entity camera></a-entity>
<a-entity run></a-entity>
</a-scene>
</body>
</html>
確認したこと
処理概要
マーカーを認識したときにtrue
、見失った場合にfalse
を設定
marker.addEventListener('markerFound',function(){markerVisible[marker.id]=true;});
marker.addEventListener('markerLost,function(){markerVisible[marker.id]=false;});
markerVisible["m0"],["m1"]
の両方がtrue
のときに線を描画し、false
だと線を見えなくする
if ( markerVisible["m0"] && markerVisible["m1"] ){ /*線を描画*/ }
else{ /*線を見えなくする*/ }
線を描画する処理はここ。object3D.getWorldPosition
でマーカーの位置(座標)を取得して、this.geometry.vertices
で線の両端の座標を設定して、geometry.verticesNeedUpdate
をtrue
にして情報更新するフラグを立てて、visible
をtrue
にしてオブジェクトを見えるようにしてる。
this.m0.object3D.getWorldPosition(this.p0); // マーカー座標を取得
this.m1.object3D.getWorldPosition(this.p1);
this.geometry.vertices[0] = this.p0; // 線の座標を設定
this.geometry.vertices[1] = this.p1;
this.geometry.verticesNeedUpdate = true; // 更新してフラグをたてる
this.line.visible = true; // 見えるようにする
imgタグは使ってない
imgタグは使ってないので削除可能
<a-assets>
<img id="grid" src="images/border.png" />
</a-assets>
線を3本にしてみた
追加した2本の線の座標設定に苦戦しました。this.geometry2.vertices[0].x
でX座標の値を設定しましたが、もっとスマートな設定方法ありそう。
<!doctype HTML>
<html>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<script src="js/aframe.min.js"></script>
<script src="js/aframe-ar.js"></script>
<body style="margin: 0px; overflow: hidden;">
<script>
let markerVisible = { m0: false, m1: false };
AFRAME.registerComponent('registerevents', {
init: function ()
{
let marker = this.el;
marker.addEventListener('markerFound', function() {
markerVisible[ marker.id ] = true;
});
marker.addEventListener('markerLost', function() {
markerVisible[ marker.id ] = false;
});
}
});
AFRAME.registerComponent('run', {
init: function()
{
this.m0 = document.querySelector("#m0");
this.m1 = document.querySelector("#m1");
this.p0 = new THREE.Vector3();
this.p1 = new THREE.Vector3();
this.geometry1 = new THREE.Geometry();
this.geometry1.vertices.push( new THREE.Vector3(-1,-1,-1) );
this.geometry1.vertices.push( new THREE.Vector3( 1, 1, 1) );
this.geometry2 = new THREE.Geometry();
this.geometry2.vertices.push( new THREE.Vector3(-1,-1,-1) );
this.geometry2.vertices.push( new THREE.Vector3( 1, 1, 1) );
this.geometry3 = new THREE.Geometry();
this.geometry3.vertices.push( new THREE.Vector3(-1,-1,-1) );
this.geometry3.vertices.push( new THREE.Vector3( 1, 1, 1) );
this.material1 = new THREE.LineBasicMaterial( {color: 0xFF00FF} );
this.material2 = new THREE.LineBasicMaterial( {color: 0x00FF00} );
this.material3 = new THREE.LineBasicMaterial( {color: 0x0000FF} );
this.line1 = new THREE.Line( this.geometry1, this.material1 );
this.line2 = new THREE.Line( this.geometry2, this.material2 );
this.line3 = new THREE.Line( this.geometry3, this.material3 );
let scene = document.querySelector('a-scene').object3D;
scene.add( this.line1 );
scene.add( this.line2 );
scene.add( this.line3 );
},
tick: function (time, deltaTime)
{
if ( markerVisible["m0"] && markerVisible["m1"] )
{
this.m0.object3D.getWorldPosition(this.p0);
this.m1.object3D.getWorldPosition(this.p1);
this.geometry1.vertices[0] = this.p0;
this.geometry1.vertices[1] = this.p1;
this.geometry1.verticesNeedUpdate = true;
this.line1.visible = true;
this.m0.object3D.getWorldPosition(this.p0);
this.m1.object3D.getWorldPosition(this.p1);
this.geometry2.vertices[0].x = this.p0.x + 0.1;
this.geometry2.vertices[0].y = this.p0.y + 0.1;
this.geometry2.vertices[0].z = this.p0.z + 0.1;
this.geometry2.vertices[1].x = this.p1.x + 0.1;
this.geometry2.vertices[1].y = this.p1.y + 0.1;
this.geometry2.vertices[1].z = this.p1.z + 0.1;
this.geometry2.verticesNeedUpdate = true;
this.line2.visible = true;
this.geometry3.vertices[0].x = this.p0.x - 0.1;
this.geometry3.vertices[0].y = this.p0.y - 0.1;
this.geometry3.vertices[0].z = this.p0.z - 0.1;
this.geometry3.vertices[1].x = this.p1.x - 0.1;
this.geometry3.vertices[1].y = this.p1.y - 0.1;
this.geometry3.vertices[1].z = this.p1.z - 0.1;
this.geometry3.verticesNeedUpdate = true;
this.line3.visible = true;
}
else
{
this.line1.visible = false;
this.line2.visible = false;
this.line3.visible = false;
}
}
});
</script>
<a-scene embedded vr-mode-ui="enabled: false;" arjs="debugUIEnabled: false; detectionMode: mono_and_matrix; matrixCodeType: 3x3;">
<a-marker type="barcode" value="0" id="m0" registerevents>
<a-plane position="0 0 0"
rotation="-90 0 0"
material="color: white; transparent: true; opacity: 0.10;">
</a-plane>
</a-marker>
<a-marker type="barcode" value="1" id="m1" registerevents>
<a-plane position="0 0 0"
rotation="-90 0 0"
material="color: white; transparent: true; opacity: 0.10;">
</a-plane>
</a-marker>
<a-marker type="pattern" url="data/kanji.patt" id="baseMarker" ></a-marker>
<a-entity camera></a-entity>
<a-entity run></a-entity>
</a-scene>
</body>
</html>
Discussion