⛳
AR.jsでWebARしてみる(11) Cylinder between two markers
はじめに
WebARで分かったことメモしていく
参考
※Cylinder between two markers (line2.html)
を勉強する
デモ
- 以下の環境で動作を確認
- iOS 13.7 Safari
- Android 9 Chrome
- Windows10 Firefox 81.0.1
ソース
参考で紹介したサイトのCylinder between two markers (line2.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();
let geometry = new THREE.CylinderGeometry( 0.05, 0.05, 1, 12 );
geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, 0.5, 0 ) );
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( THREE.Math.degToRad( 90 ) ) );
let material = new THREE.MeshLambertMaterial( {color: 0xFF0000} );
this.cylinder = new THREE.Mesh( geometry, material );
this.cylinderGroup = document.querySelector('#cylinderGroup').object3D;
this.cylinderGroup.add( this.cylinder );
},
tick: function (time, deltaTime)
{
if ( markerVisible["m0"] && markerVisible["m1"] )
{
this.m0.object3D.getWorldPosition(this.p0);
this.m1.object3D.getWorldPosition(this.p1);
let distance = this.p0.distanceTo( this.p1 );
this.cylinderGroup.lookAt( this.p1 );
this.cylinder.scale.set(1,1,distance);
this.cylinder.visible = true;
}
else
{
this.cylinder.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-sphere radius="0.10" color="red"></a-sphere>
<!-- this group rotates the cylinder to point at marker m1 -->
<a-entity id="cylinderGroup"></a-entity>
</a-marker>
<a-marker type="barcode" value="1" id="m1" registerevents>
<a-sphere radius="0.10" color="red"></a-sphere>
</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>
確認したこと
処理概要
2つのマーカーが a-markerタグで設定されていて、両方のタグにregisterevents
とある
<a-marker type="barcode" value="0" id="m0" registerevents></a-marker>
<a-marker type="barcode" value="1" id="m1" registerevents></a-marker>
registerevents
に対しマーカーを見つけたときと見失ったときに処理が動くよう設定されている。
AFRAME.registerComponent('registerevents', {
init: function () {
let marker = this.el;
marker.addEventListener('markerFound', function() { });
marker.addEventListener('markerLost', function() { });
}
});
2つのマーカーを見つけた時にシリンダーオブジェクトの形状を変形する。"2つのマーカー間の距離をシリンダーオブジェクトの長さにする", "シリンダーオブジェクトの向きを変更する" の2つを行う。
let distance = this.p0.distanceTo( this.p1 ); //マーカー間の距離を算出
this.cylinderGroup.lookAt( this.p1 ); //シリンダーの向きを設定(*1)
this.cylinder.scale.set(1,1,distance); // シリンダーの長さを設定
this.cylinder.visible = true; // シリンダーが見えるように設定
- (*1) シリンダーの向きを設定 について
-
lookAt
で、シリンダーオブジェクトの向きを設定してる。this.p1
はもう1つのマーカーの中心ざ行のこと。つまりもう1つのマーカーに向かってシリンダーが伸びる感じになる。(へぇ~)
-
ちょっと改良してみた
棒の両端を立方体にしてみた。
ソースはこちら、立方体の向きをもう1つのマーカーに向けているのが工夫したポイント。
<!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();
let geometry = new THREE.CylinderGeometry( 0.05, 0.05, 1, 12 );
geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, 0.5, 0 ) );
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( THREE.Math.degToRad( 90 ) ) );
let material = new THREE.MeshLambertMaterial( {color: 0xFF0000} );
this.cylinder = new THREE.Mesh( geometry, material );
this.cylinderGroup = document.querySelector('#cylinderGroup').object3D;
this.cylinderGroup.add( this.cylinder );
this.cylinderGroup2 = document.querySelector('#cylinderGroup2').object3D;
},
tick: function (time, deltaTime)
{
if ( markerVisible["m0"] && markerVisible["m1"] )
{
this.m0.object3D.getWorldPosition(this.p0);
this.m1.object3D.getWorldPosition(this.p1);
let distance = this.p0.distanceTo( this.p1 );
console.log( "[debug] distance = " + distance );
this.cylinderGroup.lookAt( this.p1 );
this.cylinder.scale.set(1,1,distance);
this.cylinder.visible = true;
this.cylinderGroup2.lookAt( this.p0 );
}
else
{
this.cylinder.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-entity id="cylinderGroup">
<a-box color="blue" depth="0.2" height="0.4" width="0.2" ></a-box>
</a-entity>
</a-marker>
<a-marker type="barcode" value="1" id="m1" registerevents>
<!-- <a-sphere radius="0.10" color="red"></a-sphere> -->
<a-entity id="cylinderGroup2">
<a-box color="green" depth="0.2" height="0.2" width="0.4" ></a-box>
</a-entity>
</a-marker>
<a-entity camera></a-entity>
<a-entity run></a-entity>
</a-scene>
</body>
</html>
Discussion