久々の投稿デス。
WebXRやろうかなと思ったのですが、手持ちのARCore対応デバイスがAndroid7.xのため試せず・・・で気分転換にWebVRをやりました。
はじめに
three.jsに関する基礎知識を持っている前提で書いているので、three.jsをさわったことがない!という方は、他の記事やサイトも合わせて読んでください。
開発環境については、以下となっております。(WiFiルータ経由でローカル通信)
- Webサーバ
- Macbook Pro
- http-server
- クライアント
- ASUS Zenfone AR
- Chrome 69
- Daydream View & Daydream Controller
three.jsでVRMを扱う
VRMLoader.jsを使って、VRMを表示させることができます。
公式のexampleは以下。
VRMはglTF2.0ベースなので、GLTFLoader.jsでも読み込みは可能です。
上記のVRMLoader.jsも内部でGLTFLoader.jsをラップしています。
UniVRMでエクスポートする
まず、VRMモデルを用意します。
今回は公式の手順に従い、FBXファイルをUniVRMでエクスポートしてみました。
VRMファイルを作ってみたい - dwango on GitHub
モデルはいつもの(クエリちゃんSDモデル)です。
手順の通り、Humanoidリグが設定されているモデルをエクスポートするだけなので簡単。
こんな感じで、three.jsで使えるようになります。
ボーンアニメーションで動かす
FBXからエクスポートしたVRMにはアニメーションが付いていないので、何もしないとTポーズのままになります。
それだと面白くないので、ボーンを使って動きを付けます。
ボーンを確認する方法として、LoadしたVRMモデルの情報をconsoleに表示させました。
var loader = new THREE.VRMLoader(); loader.load( 'SD_QUERY_01.vrm', function (vrm) { console.log(vrm); ... }
MacのWebブラウザでページを開いてconsoleを見ると、VRMの構造が確認できます。
scene内にモデルが含まれるので、sceneのchildrenを辿っていくと、SkinnedMeshが見つかるはずです。SkinnedMeshはskeletonプロパティにbonesを持っていて、このbonesを回転させれば、モデルが動きます。
ボーンアニメーションについては、カヤックさんのブログがわかりやすかったです。
とりあえず、動かしてみました。
OutlineEffect消し。ボーンアニメーション頑張れば動かせそう。 pic.twitter.com/FDapvFF2w2
— jyuko (@jyuko49) 2018年10月3日
中央にいるSDクエリちゃんの回転と首振りがボーンアニメーションです。
一方、隣でキレキレのダンスを披露しているコロちゃん(コロコロ*1 )は、元のモデルがMMDでMMDLoader.jsでVMDファイルをAnimationClipとしてLoadしています。
複雑なモーションの場合、ボーンをスクリプトで直接動かすのはつらいので、何らかの手段でAnimationClipを作った方がいいです。
three.jsのシーンをWebVRに対応させる
exampleを参考にthree.jsのシーンをVRで表示させます。
通常のスクリプトから以下の点を変更すればOKのよう。
// WebVR.jsを読み込む <script src="examples/js/vr/WebVR.js"></script> <script> renderer = new THREE.WebGLRenderer( { antialias: true } ); // rendererでVRを有効にする renderer.vr.enabled = true; // createButtonで"Enter VR"ボタンを表示する document.body.appendChild(WEBVR.createButton(renderer)); function animate() { // setAnimationFrameではなく、setAnimationLoopでループさせる renderer.setAnimationLoop(animate); render(); }; </script>
Daydreamで表示させるとこんな感じになります。
やっぱthree.js使えるの楽だな。6DoFのデバイスが欲しくなる。 pic.twitter.com/SxYVSbEveH
— jyuko (@jyuko49) 2018年10月8日
Daydreamコントローラーを使う
Gamepad Extensionsを有効化する
three.jsのexamplesでは、renderer.vr.getController()
でDaydreamコントローラーの情報が取れているのですが、ローカルで実行すると動きませんでした。
GoogleのDevelopers Guideによると、ChromeブラウザでGamepad API 拡張機能を有効にしないと動かないようです。 Adding Input to a WebVR Scene | Web Fundamentals | Google Developers
Chromeブラウザのアドレスバーにchrome://flags
と入力して、設定画面を開き、"Gamepad Extensions"、"WebXR Gamepad Support"をEnabled(有効)にすると動くようになります。
Ray Inputで代用する
開発者向けであれば、上記の設定を行えばいい話ですけど、一般のユーザに自身のデバイスでデモを体験させたいときなど、設定を変えてもらうのはちょっと手間です。
代案として、先程のGoogleの記事に記載されていたRay Inputであれば、拡張機能の設定なしに動きます。
Daydream(モバイルVR)の場合、オブジェクト選択に使うRayがコントローラーの向きに関わらず、視点の中心になりました。
click等はDaydreamコントローラーの操作がイベントとして取れます。
空間内の移動を実装する
three.jsで移動を実装する場合、cameraオブジェクトのposition、rotationを操作すれば視点が変わり、プレイヤーが移動しているように見えます。
ただ、WebVRの場合はcameraがVRデバイスと連動するため、cameraのプロパティを直接操作しても視点が変わりません。
// three.jsでは移動するけど、WebVRだと動かない・・・ camera.position.z -= 0.1;
これの解決策として、cameraの親オブジェクトを作ってあげて、camera直接ではなく親オブジェクトの方を動かすと位置が変わります。
// Object3Dでplayerを作り、cameraを親子関係にする var player; player = new THREE.Object3D(); scene.add(player); player.add(camera); // playerを動かすとcameraも動いて視点が変わる player.position.z -= 0.1;
playerの移動をコントローラー入力のイベントに連動させれば、3DoFデバイスでも空間上の前進、後退くらいは実現できます。
Daydreamコントローラー認識してclickで移動ができるようになった。 pic.twitter.com/OBjxd8GyMQ
— jyuko (@jyuko49) 2018年10月12日
まとめ
今回の内容でthree.jsのシーンをWebVR対応させ、キャラクター(VRM)を表示させて、コントローラーで入力や移動を行うところまで実装できました。
若干の差異はあれど、通常のthree.jsとほぼ変わらないので、元々three.jsをやっていた人なら簡単にVR開発ができます。
three.jsの場合、シーン構成からアニメーションまですべてスクリプトで完結する点とライブラリ・サンプルが豊富という点で、UnityやUEにはない安心感がありますね。(圧倒的ホームグラウンド感!)
Webなので、ネットワークを介したコンテンツの共有が楽ですし、VR内でのWebブラウジングからスムーズにVRコンテンツに移行できるので、安価なVRデバイスが普及していけば用途も広がりそうな感じはします。
*1:gdgd妖精sのBD特典モデル(Copyright (c) 2013 gdgd妖精s(ぐだぐだフェアリーーーズ), 2代目gdgd妖精s)、改造可・再配布・商用利用不可