AR.jsのドキュメント にはA-Frame用を使ったコードが記載されているのですが、Three.jsを使った実装も検証します。
結論
先に結論を書いておきます。
A-Frame を使っても Three.js を使ってもイメージトラッキングの実装は可能でした。
ただし、現時点では実戦で使用するのはちょっと厳しいかな。という印象です。
- AFrameでもThree.jsでも実装可能
- どちらもマーカーに対するARオブジェクトの位置が安定しない(かなりガクガクする)
- THREEx.ArSmoothedControls は使用できない
- PCとスマホでARオブジェクトの表示位置がかなりズレる
A-Frameを使ったサンプル
Three.jsを使ったサンプル
Three.jsでの実装
マーカーを使った実装をちょっと変更するだけでOKかと思いきや、微妙なはまりどころがあったので、コメントで補足しておきます。
ソースコード
index.html(全文)
<html> <head> <title>three.js + ar.js</title> <meta name="viewport" content="width=device-width, viewport-fit=cover, shrink-to-fit=no" /> <style> * { margin: 0; padding: 0; } .wrapper { position: relative; overflow: hidden; } </style> </head> <body> <div class="wrapper"> <canvas></canvas> </div> <script src="https://unpkg.com/three@0.127.0/build/three.min.js"></script> <script src="https://raw.githack.com/AR-js-org/AR.js/3.3.3/three.js/build/ar-nft.js"></script><!--❶ イメージトラッキング用のスクリプトに変更--> <script> const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector('canvas'), antialias: true, alpha: true }); const camera = new THREE.PerspectiveCamera(); const scene = new THREE.Scene(); const markerRoot = new THREE.Group(); const arToolkitContext = new THREEx.ArToolkitContext({ detectionMode: 'mono' }); const arToolkitSource = new THREEx.ArToolkitSource({ sourceType: 'webcam' }); const arMarkerControls = new THREEx.ArMarkerControls(arToolkitContext, camera, { type: 'nft', // 'nft'に変更 descriptorsUrl : 'marker/filename', // ❷ https://carnaux.github.io/NFT-Marker-Creator/ で作成 changeMatrixMode: 'cameraTransformMatrix' }); renderer.setSize(window.innerWidth, window.innerHeight); scene.add(camera); // ❸ カメラをシーンに追加 window.addEventListener('resize', handleResize, { passive: true }); window.addEventListener('arjs-nft-loaded', (evt) =>{ console.log(evt); }); arToolkitContext.init(() => { camera.projectionMatrix.copy(arToolkitContext.getProjectionMatrix()); }); arToolkitSource.init(() => { document.querySelector('.wrapper').appendChild(arToolkitSource.domElement); setTimeout(() => handleResize(), 400); }); scene.visible = false; scene.add(markerRoot); const cube = new THREE.Mesh( new THREE.BoxGeometry(100, 100, 100), // ❹ 大きめに設定 new THREE.MeshNormalMaterial() ); cube.position.set(0, 0, 0); // ❹ 一旦、原点に表示 markerRoot.add(cube); renderer.setAnimationLoop((delta) => { if (arToolkitSource.ready) { arToolkitContext.update(arToolkitSource.domElement); } scene.visible = camera.visible; // ❺ 自力で表示・非表示を切り替える renderer.render(scene, camera); }); function handleResize() { if (arToolkitSource.ready) { arToolkitSource.onResize(); arToolkitSource.copySizeTo(renderer.domElement); } renderer.setPixelRatio(window.devicePixelRatio); } </script> </body> </html>
解説
❶ スクリプトの変更
https://raw.githack.com/AR-js-org/AR.js/3.3.3/three.js/build/ar.js から https://raw.githack.com/AR-js-org/AR.js/3.3.3/three.js/build/ar-nft.js に変更します。
❷ fset・fset3・isetの作成
https://carnaux.github.io/NFT-Marker-Creator/ にトラッキングしたい画像をアップして、fset・fset3・isetをダウンロードします。
- filename.fset
- filename.fset3
- filename.iset
の3つのファイルが生成されるので、descriptorsUrlには3つのファイルを収納されているディレクトリと、filenameを記述します。
❸ カメラの追加
マーカー型のARの場合は、カメラをシーンに追加せずとも動作するのですが、イメージトラッキングの場合は必須でした。
❹ オブジェクトの大きさ・ポジション
オブジェクトが小さすぎると目視での確認が困難なので、大きめに表示します。
公式のexample でもポジションをダイナミック(model.position.z = -100)に設定しています。
また、ポジションに関しては example だと、nft.detailの幅・高さ・dpiを元に設定しているのですが、
window.addEventListener('arjs-nft-init-data', function(nft) { console.log(nft); var msg = nft.detail; model.position.y = (msg.height / msg.dpi * 2.54 * 10)/2.0; //y axis? model.position.x = (msg.width / msg.dpi * 2.54 * 10)/2.0; //x axis? });
?がついていること、exampleでもPC、スマホでオブジェクトの位置が大きくずれることから、一旦、原点(0,0,0)に設定しました。
❺ シーンの表示非表示を切り替える
マーカー型だと自動で行われる処理ですが、イメージトラッキングの場合、自力で表示・非表示の切り替えが必要でした。
DEMO
こちらにイメージトラッキングのサンプルをアップしました。
本の表紙をトラッキングできるか試したかったので、下記の画像を認識するように設定しています。
また、もしも 手元に帯付きの本 がある場合は、実物の本も認識するはずです。