最近、vrmという規格に興味があって調べていたところ、株式会社バーチャルキャストがBabylon.jsに対応したbabylon-vrm-loaderを公開したことを知りました。
VRM は Unity 専用じゃない!ブラウザで VRM 表示出来るものを作りました! | VirtualCast Blog
GitHub - virtual-cast/babylon-vrm-loader: glTF VRM extension Loader for babylon.js
そこで、今回はこれを元にBabylon.jsのVRモードを追加し、発売されたばかりのOculus Questで見るまでの手順を紹介します。
確認した環境
* Babylon.js 4.0.3
1. 今回使う技術分野について
1.1 VRM
ドワンゴが発表した人型3Dモデルに関する共通フォーマットです。詳細はこちらをご覧ください。
「VRM」とは? そのメリットや対応アプリなど情報まとめ | MoguraVR News - VRの「いま」を掘りだすニュースメディア
1.2 Babylon.js
Web上で3DCGの表現ができるライブラリです。
Babylon.js: Powerful, Beautiful, Simple, Open - Web-Based 3D At Its Best
参考までに、去年から色々と調べていた内容は下記の通りです。
babylonjs カテゴリーの記事一覧 - CrossRoad
2. 環境構築手順
大まかな手順は以下の通りです。
(1) babylon-vrm-loaderをビルド
(2) VRで動かすための機能を追加
(3) サーバ公開の設定
2.0 Node.js/npm/yarnのインストール
(インストール済みの方は飛ばして、2.1に進んでください)
概要、および必要な手順は以下を参照ください。
Node.js / npm をインストール (Mac環境) - Qiita
2.1 babylon-vrm-loaderをビルド
ここからソースコードを取得します。
GitHub - virtual-cast/babylon-vrm-loader: glTF VRM extension Loader for babylon.js
Readmeに沿ってターミナルから、 bash yarn build
を実行してビルド、bash yarn debug
を実行するだけです。
しかし、なぜか私の環境では大量のエラーが出てそうなりませんでした。本来ならばpackage.jsonの中に書かれたパッケージを取得して加えてくれるはずなのですが。
このあたり、まだ私のnpmに関する理解が浅いので、今回はエラーが出るたびに該当するパッケージを入れるという作業を繰り返しました。最終的にこのようなコマンドを入力することでビルドを通しました。
$ npm install --save-dev ts-loader $ npm install --save-dev typescript $ npm install --save-dev ts-lib $ npm install --save-dev @babylonjs/core $ npm install --save-dev @babylonjs/loaders $ npm install --save-dev @babylonjs/inspector $ npm install --save-dev babylon-mtoon-material $ npm install --save-dev webpack-dev-server $ npm install --save-dev webpack $ npm install --save-dev webpack-cli
最後にtsconfig.jsonの記述を1箇所修正しました。
(これはChanged js version in tsconfig.jsonでmergeいただいたので、以後は不要です )
ここまでやってから、 yarn debugとすると、webpackが起動します。Chromeなどのブラウザで
http://localhost:8080
にアクセスするとこのような画面が開きます。
画面左上に「ファイルを開く」というボタンがあるので、ここからvrmファイルを読み込みます。
手っ取り早く確認するには、株式会社ドワンゴが提供している「ニコニ立体ちゃん」がよいと思います (ダウンロードには、無料の会員登録が必要です)
「ニコニ立体ちゃん (VRM)」 / ニコニ立体 さんの作品 - ニコニ立体
これでこのような画面になります。
2.2 VRで動かすための機能を追加
babylon.jsのAPIを使います。 src/test/index.tsの一部を変更します。
//L37付近 vrmモデルを近くで見るために、カメラ位置を移動 // camera.position = new Vector3(0, 1.2, -3); camera.position = new Vector3(0, 1.2, -1.1);
//L100付近 VRモード追加とコントローラの有効化 const vrHelper = scene.createDefaultVRExperience(); //基本的にはこの1行だけでVRモードが利用可能 const leftHand = Mesh.CreateBox("",0.1, scene); leftHand.scaling.z = 2; leftHand.isVisible =false; const rightHand = Mesh.CreateBox("",0.1, scene); rightHand.scaling.z = 2; rightHand.isVisible =false; scene.onBeforeRenderObservable.add(()=>{ if(vrHelper.webVRCamera.leftController){ leftHand.position = vrHelper.webVRCamera.leftController.devicePosition.clone(); leftHand.rotationQuaternion = vrHelper.webVRCamera.leftController.deviceRotationQuaternion.clone(); } if(vrHelper.webVRCamera.rightController){ rightHand.position = vrHelper.webVRCamera.rightController.devicePosition.clone(); rightHand.rotationQuaternion = vrHelper.webVRCamera.rightController.deviceRotationQuaternion.clone(); } });
bash left/rightHand.isVisible =false;
を設定しないと、コントローラをCubeが覆ってしまいます。以前は下記のコードで透明化することで対応できました。
var leftHand = BABYLON.Mesh.CreateBox("",{height:0.1,width:0.1,depth:0.1,faceColors:(1,1,1,0)}, scene);
引用:Babylon.jsでWindows Mixed Realityヘッドセットのアプリを作る方法 - CrossRoad
しかし、今回はES6以降のjavascriptで書いたためか、あるいはBabylon.jsのメジャーバージョンが上がったためか、この方法は使えませんでした。
ここまで書くと、VRモードで動かせるようになります。
2.3 サーバ公開の設定
今回、webサーバとして動かすために、webpackというパッケージを使っています。webpackは基本設定のままだとlocalhostしかアクセスできないので、Oculus Questからアクセスするために、サーバ設定を変更します。
//webpack.config.js //最終行に以下を追加 devServer: { disableHostCheck: true }
"scripts": { //省略 "debug-lan": "webpack-dev-server --host 0.0.0.0 --config webpack.test.config.js", //省略 },
こちらを参考にさせていただきました。
webpack-dev-server に localhost 以外からアクセスできるようにする場合は host: 0.0.0.0 を指定する - 約束の地
3. 動作確認結果
2.2と2.3の修正をしたものを下記におきました。2.1のビルドについては、書いたコマンドを実行してください。
また、vrmファイルは、リポジトリの"test/vrm"と書かれたところに入れます。vrmファイル名は下記を修正してください。
// src/test/index.ts await SceneLoader.AppendAsync('./vrm/', 'vita.vrm', scene);
Oculus Questで確認しました。先ほどのリポジトリでビルドした状態で、bash yarn debug-lan
を実行するとwebpackによるサーバが起動し、Oculus Questからアクセスできます。。
- 使用したモデルのURL
ヴィータ - VRoid Hub
動画の13秒付近にコントローラが写っています。この通りコントローラは2つとも認識され、Raycastを飛ばしてオブジェクトを識別したり、ボタン操作を識別することも可能です。ただし、コントローラの3DモデルはOculus Touchです。
2019/7/21更新
使っているモジュールの1つである"lodash"にセキュリティ脆弱性がある、という警告がGithubより来ました。
脆弱性対応のため、依存関係のあるモジュールを含めてアップデートしたところ、脆弱性は消えました。しかし、vitaモデルを表示させると、服が黒くなってしまいました。
ただ、Aliciaモデルは正常に読み込めます。
vrm-loader側が新しくなることで解決する可能性があるため、申し訳ありませんが現状では保留とさせてください。
もしこのブログ記事執筆時点の環境で確認したい場合、下記のGitコミットIDを指定してください。ただし、セキュリティ脆弱性を含むため、利用は自己責任でお願いいたします。
9ba001c81611b1b3b64036e7118b9fb2fe6373c2
4. 補足
4.1 Oculus Goで動かす場合
Oculus Goでも同じソースコードで動きますが、Oculus Goのコントローラには「戻る」というボタンがないので、Sphereを選択したらexitVR()を呼ぶという処理の追加があるとよいです。
Oculus GoでBabylon.jsを使ったときに、没入型と通常VRモードを切り替える方法 - CrossRoad
具体的には、index.tsにこのようなコードを追加します。
//冒頭のimport import { ActionManager,ExecuteCodeAction} from '@babylonjs/core/Actions';
//vrHelperの宣言をした直後付近 vrHelper.enableInteractions(); vrHelper.gazeTrackerMesh = BABYLON.Mesh.CreateSphere("sphere1", 4, 0.1, scene); vrHelper.onControllerMeshLoaded.add((webVRController)=>{}); sphere.actionManager = new BABYLON.ActionManager(scene); sphere.actionManager.registerAction( new BABYLON.ExecuteCodeAction({ trigger: BABYLON.ActionManager.OnPickDownTrigger,}, function () { console.log("clicked the mesh"); vrHelper.exitVR(); scene.getEngine().exitFullscreen(); }));
4.2 参考にした関連技術のリンク
私がまだまだWeb系の勉強が足りないので備忘録のために残しておきます。
javascriptのバージョンについて
2015~2017年のECMAScript コンプリートガイド - QiitaWebpackの基本的な導入方法
ベーシックなWebpackの導入と設定 - QiitaTypescript概要、javascriptのバージョン違いや考え方など
TypeScript入門以前ガイド - mizchi's blog
私はこの記事の「ES2015 for ES5 Programmers」が一番近い感じでした。
5. おわりに
WebGLでvrmを表示する仕組みはいくつかありますが、冒頭のバーチャルキャストブログで言われているように、Babylon.jsはわりとよいと思います。Questも届いたし、新しいjavascript、Typescriptでの書き方も覚えつつあるので、引き続きvrmとBabylon.jsで色々やってみたいと思います。