AR.jsでWebARしてみる(9) Detection

10 min読了の目安(約9500字TECH技術記事

はじめに

WebARで分かったことメモしていく

参考

Detection (detection.html)を勉強する

デモ

  • 以下の環境で動作を確認
    • iOS 13.7 Safari
    • Android 9 Chrome
    • Windows10 Firefox 81.0.1

ソース

参考で紹介したサイトのDetection (detection.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>

let markerVisible = { "redMarker": false, "yellowMarker": false, "blueMarker": false };

AFRAME.registerComponent('registerevents', {
    init: function () 
    {
        let marker = this.el;
        marker.addEventListener('markerFound', function() {
            markerVisible[ marker.id ] = true;
            // console.log( markerVisible );
        });
        marker.addEventListener('markerLost', function() {
            markerVisible[ marker.id ] = false;
            // console.log( markerVisible );
        });
    }
});

AFRAME.registerComponent('loop', 
{   
    init: function()
    {
        this.box = document.querySelector("#theBox");
    },
    tick: function (time, deltaTime) 
    {
        // for convenience
        let mv = markerVisible, r = "redMarker", y = "yellowMarker", b = "blueMarker";
        
        if ( mv[r] && mv[y] && mv[b] )
            this.box.setAttribute("color", "#654321");
        else if ( mv[r] && mv[y] && !mv[b] )
            this.box.setAttribute("color", "#FF8800");
        else if ( mv[r] && !mv[y] && mv[b] )
            this.box.setAttribute("color", "purple");
        else if ( mv[r] && !mv[y] && !mv[b] )
            this.box.setAttribute("color", "red");
        else if ( !mv[r] && mv[y] && mv[b] )
            this.box.setAttribute("color", "green");
        else if ( !mv[r] && mv[y] && !mv[b] )
            this.box.setAttribute("color", "yellow");
        else if ( !mv[r] && !mv[y] && mv[b] )
            this.box.setAttribute("color", "blue");
        else // if ( !mv[r] && !mv[y] && !mv[b] )
            this.box.setAttribute("color", "gray");
    }
});
</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="pattern" url="data/kanji.patt" id="baseMarker">
        <a-box id="theBox"
               position="0 0.5 0"
               color = "white"
               material="src:#grid; transparent: true; opacity: 0.90;">
        </a-box>
    </a-marker>
    
    <a-marker type="barcode" value="0" id="redMarker" registerevents>
        <a-plane position="0 0 0" 
                 rotation="-90 0 0"
               material="color: red">
        </a-plane>
    </a-marker>

    <a-marker type="barcode" value="1" id="yellowMarker" registerevents>
        <a-plane position="0 0 0" 
                 rotation="-90 0 0"
               material="color: yellow">
        </a-plane>
    </a-marker>

    <a-marker type="barcode" value="2" id="blueMarker" registerevents>
        <a-plane position="0 0 0" 
                 rotation="-90 0 0"
               material="color: blue">
        </a-plane>
    </a-marker>
    
    <a-entity camera></a-entity>
    <a-entity loop></a-entity>
    
</a-scene>
</body>
</html>

確認したこと

処理の流れ

3つの変数が false/true に切り替わり、その組み合わせにより立方体の色が決まる。3つの値は、a-markerタグのIDと同じ値にしておき、ARマーカーと連動するように工夫してる。

let markerVisible = { "redMarker": false, "yellowMarker": false, "blueMarker": false };

マーカーを認識したときにここの処理が実行される。認識したマーカーIDと連動した変数の値がtrue になる

marker.addEventListener('markerFound', function() {/*省略*/});

認識していたマーカーが消えたときにここの処理が実行される。認識したマーカーIDと連動した変数の値がfalse になる

marker.addEventListener('markerLost', function() {/*省略*/});

赤,黄,青色の板を表示するARマーカー

<a-marker type="barcode" value="0" id="redMarker" registerevents></a-marker>
<a-marker type="barcode" value="1" id="yellowMarker" registerevents></a-marker>
<a-marker type="barcode" value="2" id="blueMarker" registerevents></a-marker>

3つのマーカーは、githubmarkers\barcodesにある

応用してみた

canvasタグに色を塗り、それを立方体のテクスチャにして、同じことやってみた。

ソースはこれ

<!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 = { "redMarker": false, "yellowMarker": false, "blueMarker": false };

AFRAME.registerComponent('registerevents', {
    init: function () 
    {
        let marker = this.el;

        marker.addEventListener('markerFound', function() {
            markerVisible[ marker.id ] = true;
            // console.log( markerVisible );
        });

        marker.addEventListener('markerLost', function() {
            markerVisible[ marker.id ] = false;
            // console.log( markerVisible );
        });
    }
});

AFRAME.registerComponent('loop', 
{   
    init: function()
    {
        this.canvas = document.querySelector("#myCanvas");
        this.canvas.width = 512;
        this.canvas.height = 512;
        this.context = this.canvas.getContext('2d');
        this.coreAreaColer   = "gray";
        this.redAreaColer    = "red";
        this.yellowAreaColer = "yellow";
        this.blueAreaColer   = "blue";
        this.redPos = 10;
        this.yellowPos = 10;
        this.bluePos = 10;
    },
    
    tick: function (time, deltaTime) 
    {
        let mv = markerVisible, r = "redMarker", y = "yellowMarker", b = "blueMarker";

        if ( mv[r] && mv[y] && mv[b] ){
            this.coreAreaColer = "#654321";
            this.redPos    = 196;
            this.yellowPos = 196;
            this.bluePos   = 196;
        }else if ( mv[r] && mv[y] && !mv[b] ){
            this.coreAreaColer = "#FF8800";
            this.redPos    = 196;
            this.yellowPos = 196;
            this.bluePos   = 266;
        }else if ( mv[r] && !mv[y] && mv[b] ){
            this.coreAreaColer = "purple";
            this.redPos    = 196;
            this.yellowPos = 266;
            this.bluePos   = 196;
        }else if ( mv[r] && !mv[y] && !mv[b] ){
            this.coreAreaColer = "red";
            this.redPos    = 196;
            this.yellowPos = 266;
            this.bluePos   = 266;
        }else if ( !mv[r] && mv[y] && mv[b] ){
            this.coreAreaColer = "green";
            this.redPos    = 266;
            this.yellowPos = 196;
            this.bluePos   = 196;
        }else if ( !mv[r] && mv[y] && !mv[b] ){
            this.coreAreaColer = "yellow";
            this.redPos    = 266;
            this.yellowPos = 196;
            this.bluePos   = 196;
        }else if ( !mv[r] && !mv[y] && mv[b] ){
            this.coreAreaColer = "blue";
            this.redPos    = 266;
            this.yellowPos = 266;
            this.bluePos   = 196;
        }else{
            this.coreAreaColer = "gray";
            this.redPos    = 266;
            this.yellowPos = 266;
            this.bluePos   = 266;
        }

        this.context.fillStyle = this.coreAreaColer;   this.context.fillRect(0,0,  512,512);
        this.context.fillStyle = "#252525";            this.context.fillRect(101,186,  190,70);
        this.context.fillStyle = "#050505";            this.context.fillRect(101,256,  190,70);
        this.context.fillStyle = this.redAreaColer;    this.context.fillRect(111,this.redPos, 50,50);
        this.context.fillStyle = this.yellowAreaColer; this.context.fillRect(171,this.yellowPos, 50,50);
        this.context.fillStyle = this.blueAreaColer;   this.context.fillRect(231,this.bluePos, 50,50);

        let material = this.el.getObject3D("mesh").material;
        if(!material.map){
            reutrn;
        }else{
            material.map.needsUpdate = true;
        }
    }
});

</script>

<a-scene embedded vr-mode-ui="enabled: false;" arjs="debugUIEnabled: false; detectionMode: mono_and_matrix; matrixCodeType: 3x3;">
    <a-assets>
        <canvas id="myCanvas"></canvas>
	</a-assets>
    <a-marker type="pattern" url="data/kanji.patt" id="baseMarker" cubeObject>
        <a-box id="theBox"
               position="0 0.5 0"
               material="src:#myCanvas; transparent: true; opacity: 0.80;"
               loop>
        </a-box>
    </a-marker>
    
    <a-marker type="barcode" value="0" id="redMarker" registerevents>
        <a-plane position="0 0 0" 
                 rotation="-90 0 0"
               material="color: red">
        </a-plane>
    </a-marker>

    <a-marker type="barcode" value="1" id="yellowMarker" registerevents>
        <a-plane position="0 0 0" 
                 rotation="-90 0 0"
               material="color: yellow">
        </a-plane>
    </a-marker>

    <a-marker type="barcode" value="2" id="blueMarker" registerevents>
        <a-plane position="0 0 0" 
                 rotation="-90 0 0"
               material="color: blue">
        </a-plane>
    </a-marker>
    <a-entity camera></a-entity>
</a-scene>
</body>
</html>