こんにちは、カシカでエンジニアのインターンをしております、石飛と申します。

今回はVRMモデルを表示する簡単なwebアプリを作る方法を解説します。 VRMを表示し、カメラのコントロール、モーションの変更、表情の変更の 基本的なコントロールができるWEBアプリの作っていきます。

やりたいこと

VRMとは人型アバターモデルのためのファイルフォーマットです。

実際のデータはニコニ立体などから入手することができます。 今回の例でもこのサイトに公開されているニコニ立体ちゃんを利用します。

公式のガイドに従えば、Unity、Blender、Maya等の標準的なCG開発環境でVRM形式のデータを読み込むことができます。

ですが、今回はwebブラウザでVRMデータを表示することを目的とします。

実際に作ったアプリのスクリーンショットを下に示しています。 VRMデータを読み込んで表示することはもちろん、カメラを移動して様々な方向からモデルを観察することができます。 また、VRMモデルの操作として、表情の変更やFBX形式のモーションデータの適用も可能です。

完成版イメージ

(完成版のイメージと主な機能)

主なソフトウェア

作るとはいってもJavaScript系の既存ソフトウェアを組合わせるだけで、簡単な機能はすぐに実現できます。

ここでは、今回の用途において要となるNode.jsthree-vrmの概要を説明します。

具体的な環境構築の方法はこちらの記事を参考にしてください。

Node.js

JavaScriptの実行環境としてNode.jsを利用します。

Node.jsがどういうものなのかについては、こちらの記事でわかりやすく解説されています。 端的に言えば、ローカルで完結した環境でWebアプリを開発できるようにするものです。

Node.jsではnpmというパッケージ管理ツールを使うことになります。 上の記事の受け売りですが、知っている人には「Pythonにおけるpip、Rubyにおけるgem(RubyGems)、Debianにおけるapt、MacにおけるHomebrew、Rustにおけるcargo」と考えればすぐに理解できるかと思います。

なので次に説明するthree-vrmも

$ npm i @pixiv/three-vrm

のようにして、npmコマンドでインストールします。

three-vrm

JavaScriptで3DCGを描画するためのライブラリとしてThree.jsがよく知られています。 このThree.jsでVRMモデルを扱えるようにしたライブラリがthree-vrmであり、pixivがオープンソースで公開しています。

three-vrmのページからリンクが張られているexamplesでは、VRMの基本的な操作を扱ったデモがまとめられています。 今回はこれらデモを参考にしてアプリケーションに機能を追加します。

ビューワの実装

先述の通りにこちらの記事に従って環境構築すると、正面を向いたモデルがブラウザで確認できるかと思います。

srcフォルダ内にあるindex.tsを編集してから

$ npm run build
$ npm run start

ビルド・実行し直すことで機能を追加できます。

編集にあたってthree-vrmのexamplesを参考にすると述べましたが、具体的には各デモに対応するhtmlファイルのscriptブロックを参照します。

カメラのコントロール

Three.jsの機能を用いることで、マウスドラッグによる視点操作が容易に実装できます。

こちらはデモのbasicを参考にしましょう。OrbitControlsをインポートし、シーン設定時にcontrolを生成していることが分かります。

// camera controls
const controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = true;
controls.target.set( 0.0, 1.0, 0.0 );
controls.update();

これだけでは視点の移動がわかりにくいので、ついでにシーンにグリッドと軸を追加します。

// helpers
const gridHelper = new THREE.GridHelper( 10, 10 );
scene.add( gridHelper );

const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );

モーションの適用

デモのhumanoidAnimationを参考にmixamoからダウンロードしたFBX形式のモーションを適用します。 他のデモと異なり、humanoidAnimationだけは同じ階層にhtmlファイルはなく、専用のフォルダが用意されていることに注意してください。

このフォルダ内のmain.jsは、loadFBXを介してloadMixamoAnimationを呼び出しています。 自身の環境でも同様にloadFBXが実行されるように編集しましょう。

特に注目すべきは

window.addEventListener( 'drop', function ( event )

の部分です。 これはフィールドにファイルをドロップした際に呼ばれるものであり、main.jsではファイルのタイプによってloadFBXかloadVRMが実行されるようになっています。

うまくいくとドラッグアンドドロップしてモーションを適用することができます。また、再度ドロップすればモーションが更新されます。

タイムスケールスライダの追加

Three.jsに含まれるlil-gui.module.min.jsを利用することでGUIを追加できます。スライダでモーションの再生速度を変更できるようにしましょう。 humanoidAnimation/main.jsの以下の部分でGUIを追加しています。

// gui
const gui = new GUI();

const params = {
	timeScale: 1.0,
};

gui.add( params, 'timeScale', 0.0, 2.0, 0.001 ).onChange( ( value ) => {
	currentMixer.timeScale = value;
} );

GUIというオブジェクトに、paramsに属するtimeScaleを操作するようなスライダを追加する、というような操作をしています。 また、スライダの値が変化したときに、数値をcurrentMixer.timeScaleに代入するようにしています。

ただし、currentMixerはグローバル変数であり、loadFBX実行時にTHREE.AnimationMixerのインスタンスが代入されるようになっています。

タイムスケールスライダ

(タイムスケールスライダ)

表情の操作

続いてデモのexpressionsを参考に表情を操作してみましょう。

変数currentVRMにVRMデータが設定されている場合、表情の変更は以下のようにして実現できます。

currentVRM.expressionManager.setValue([表情パラメタ], [値])

表情パラメタのリストについてはこちらのページで確認できます。

expressions.htmlではanimateという関数内で

// tweak expressions
const s = Math.sin( Math.PI * clock.elapsedTime );
currentVrm.expressionManager.setValue( 'aa', 0.5 + 0.5 * s );
currentVrm.expressionManager.setValue( 'blinkLeft', 0.5 - 0.5 * s );

として、口と目を開閉させています。

さらに表情をスライダで変更できるようにしてみましょう。 paramsにhappyを追加したうえで以下のようにしてGUIにスライダを追加します。

gui.add( params, 'happy', 0.0, 1.0, 0.001).onChange((value) => {
    currentVrm.expressionManager.setValue('happy', value);
});

値が変更した際にはexpressionManager.setValueで表情パラメタの値が即座に変更されるようになっています。

表情の変化

(スライダによる表情の操作)

まとめ

Node.jsとthree-vrmによってVRMをブラウザで表示する方法を説明しました。

three-vrmでは通常のVRMの機能を活用できるようなライブラリが揃っているうえにデモが用意されているので、開発はしやすいようです。

他のデモで行われている目線の移動やボーンの操作なども簡単に追加できますし、データの入出力関係も色々できそうです。

株式会社カシカでは社員募集しています! リクルートページ

VRM開発に興味がある方はぜひお問い合わせください。 お問い合わせページ

参考文献