じゅころぐAR/VR

AR/VRメインのブログ。時々ドローン。

A-Frameでnav meshを使う

WebVRフレームワークのA-Frameは、HTML/JavaScriptで記述でき、様々なコンポーネントを組み合わせて使うことで簡単にマルチプラットフォーム向けのVRコンテンツが作成できます。

便利な機能がまとめてincludeできるaframe-extrasを眺めていたところ、nav meshによる移動を扱うコンポーネントを見つけたため、試しに実装してみました。

概要

READMEを見ると、aframe-extrasのnav-meshコンポーネントは内部でPatrolJSを利用しているようです。 A-Frameはthree.jsを内包しているため、three.js向けのプラグインが活用しやすくなっています。

nav meshの作成方法を含む詳しい使い方は、以下の記事に書かれています。

medium.com

Blenderを使ってnav meshを作成し、glTFでエクスポートしてA-Frameで使うようです。

nav meshの作成

参考記事に倣って、Blenderで作成します。

適当にオブジェクトを結合してシーンに配置した後、以下の手順を行うとNavmeshが追加されます。

  • 画面上部メニューで"Blenderゲーム"モードに変更
  • 画面右のパネルで"Scene"を選択
  • nav meshの対象となるオブジェクトを選択
  • パラメータを調整して、ナビゲーションメッシュを構築

f:id:jyuko49:20171123232658p:plain

glTFでエクスポート

作成したNavmeshをA-Frameで利用するため、エクスポートします。

glTF(GL Transmission Format)は、OpenGLと親和性が高く、通信とロードを効率化した3Dフォーマットです。WebGLベースで3Dデータをネットワーク経由で配布するWebVRに適したフォーマットと言われています。

BlenderからglTFでエクスポートするにはアドオンを追加する必要があります。 Blenderのアドオン一覧には表示されていないため、下記のGithubからダウンロードします。

github.com

複数ファイルで構成されているアドオンのため、BlenderのUIでファイルから追加を行なってもアドオン一覧に表示されません。 対応としては、PC内でBlenderのアドオンが保存されているフォルダを探して、"io_scene_gltf2"を丸ごとコピーしてからBlenderを再起動するとアドオンが表示され、有効にできます。

f:id:jyuko49:20171124014438p:plain

アドオンの追加は以下の記事が参考になりました。 qiita.com

アドオンが有効になったらNavmeshを選択した状態で、"ファイル" > "エクスポート" > "glTF 2.0 (.gltf)"でエクスポートできます。

Navmeshを作成する際は"Export selected only"にチェックしないと、元のメッシュごとエクスポートしてしまいます。

f:id:jyuko49:20171124014716p:plain

エクスポートに成功すると、.gltfと.binの2ファイルが同じ階層に作成されているはずです。

navmesh.gltfの確認

エクスポートしたglTFのnav meshが正しく作成されているかは、glTF Viewerで確認できます。

gltf-viewer.donmccurdy.com

無料で使えるWebのビューアで.gltfと.binの2ファイルをまとめてドラッグ&ドロップすればOKです。

f:id:jyuko49:20171124002810p:plain

A-Frameでの実装

サンプルとして70行程度のHTMLファイル1つで記述しました。

移動先を決定する処理は元記事のJavaScriptをそのまま利用、移動するエージェントはglTFではなくa-mmdMMDフォーマットを使っています。

ポイントとして、nav meshオブジェクトに"nav-mesh"属性、エージェントに"nav-controller"属性を付けます。

移動先の変更はclickイベント発生時のスクリプトで制御しています。"nav-controller"にdestinationをセットした上で、activeをtrueにして移動を開始させています。

const ctrlEl = el.sceneEl.querySelector('[nav-controller]');
ctrlEl.setAttribute('nav-controller', {
  active: true,
  destination: e.detail.intersection.point
 });

動作確認

実装例ではgdgde妖精sMMDを利用しており、商用利用・再配布がNGです。

権利的にパブリックなサーバにはアップできないため、apachectlでMac上にWebサーバを起動し、ifconfigコマンドでIPアドレス(192.168.0.XXX)を調べてローカル接続しています。

マテリアルをセットしていないのでメッシュが黒いのは気にしないでください。

カメラを向けた方向でカーソルを固定すると、視線によるclickイベントが発生し、その地点にキャラクターが移動します。 Physicsは利用していないためコンテンツのロード時はキャラクターが宙に浮いた状態で、最初の移動でnav meshとの接地面まで降りてきてくれました。

まとめ

Blenderでnav meshを作成、glTFでエクスポートすることで、A- Frameでnav meshに基づいた移動が実現できました。 nav meshに関しては、glTF以外での動作は確認できておらず、単純にplaneを配置して"nav-mesh"属性を付与しただけでは、移動のパスが見つけられませんでした。 移動させるエージェント(キャラクター)や表示用のシーンオブジェクトは、他の3Dフォーマットも利用できそうです。

事前にBlenderで作成する手間はあるものの、やり方を覚えてしまえば簡単に作れます。 シーンを構成するデータと合わせて配信して、シーン内の移動を制御する用途なら十分使えそうです。