概要
Three-VRMでプリセットの表情ではなく、パーツごとに組み合わせた表情(眉毛、目、口などでそれぞれ異なった表情にする)を反映させてみます。プリセットの表情は特に設定なしに使うことができますが、パーツごとに変える場合はCustom Expressionとしての登録が必要となります。
Unityなどでブレンドシェイプを作成することで実現する方法もあるみたいですが(試してませんが)、ここでは、JavaScriptの実行時にプログラム的に設定し使用します。
動作確認
- VRoidStudio 1.29. 1 -- VRMファイルのエクスポート
- Three-VRM 3.1.2
- Firefox 131
実装
プリセットの使用
Three-VRMでブラウザ上でVRMを非常に簡単に扱うことができますが、expressionManager
経由で表情を反映させることができます。以降のコードでは、変数vrm
はVRM
オブジェクトとします。VRMファイルの読み込みはThree-VRMのサンプルスクリプト等を参照してください。ここで扱うコードはVRMオブジェクトがある前提です。
Three-VRM 2.0.0より前はblendShapeProxy
でしたが、2.0.0以降はexpressionManager
経由で表情を操作するようです。
// プリセット名の確認
vrm.expressionManager.expressionMap
// Object { happy: {…}, angry: {…}, sad: {…}, relaxed: {…}, surprised: {…}, aa: {…}, ih: {…}, ou: {…}, ee: {…}, oh: {…}, … }
// プリセットの使用
vrm.expressionManager.setValue("relaxed", 0.8);
vrm.expressionManager.setValue()
はプリセットだけではなく、今回登録するCustom Expressionにも使うのですが、登録する前はプリセットしかありません。
カスタム表情の追加
上記のようにプリセットの表情(happy, angry, sad, relaxed, surprisedおよび口の形)はそのまま使えるのですが、VRoidStudioのようにそれぞれのパーツの表情を組み合わせたいことは多いと思います。その場合、VRMExpression
オブジェクトを作成し、expressionManager.registerExpression()
を使って追加登録します。
なお、この部分はThree-VRM 3.1.2のpackages/three-vrm-core/src/expressions/VRMExpressionLoaderPlugin.ts
の143行目付近のコードを参考にしています。そこで表情の登録をしているので、一連の流れを追えばさらに詳細が理解できると思います。
// カスタム表情の追加登録
const expressionName = "smile"; // 表情の登録名
const targetName = "Fcl_MTH_Fun"; // 反映させるターゲット
const targetWeight = 0.8; // ウェイト
const expression = new VRMExpression(expressionName);
vrm.scene.add(expression);
// MorphTargetBind.primitivesに登録するのはFaceグループのSkinnedMesh
const primitives = [...vrm.scene.getObjectByName("Face").children];
// FaceグループのSkinnedMesh#morphTagetDictionaryから、目的のmorphTargetIndexを得る
// FaceグループにはFace_(merged)などのSkinnedMeshが登録されている
const morphTargetDictionary = vrm.scene.getObjectByName("Face").children[0].morphTargetDictionary;
// バインドする
// 他のパーツも足していくことができる
expression.addBind(
new VRMExpressionMorphTargetBind({
primitives,
index: morphTargetDictionary[targetName],
weight: targetWeight,
})
);
// Expressionを登録する(customExpressionMapに追加される)
vrm.expressionManager.registerExpression(expression);
このコード片では、Fcl_MTH_Fun
すなわち、口の「楽しい」にウェイトをかけています。VRMExpression
を初期化する際に渡す名前でexpressionManager.customExpressionMap
に登録されます(ここではsmile
)。ここではFcl_MTH_Fun
のみをaddBind()
していますが、addBind()
は複数できるので、例えばFcl_BRW_Fun
、Fcl_EYE_Spread
などを組み合わせることができます。使用できるターゲット名は、このコード中のvrm.scene.getObjectByName("Face").children[0].morphTargetDictionary
で得ることができます。
登録した表情を使うのはプリセットと同様です。
vrm.expressionManager.setValue("smile", 1.0);
このようにすることで、様々な表情を簡単に作ることができます。
参考
- GitHub Three-VRM
- https://github.com/pixiv/three-vrm
- Examplesに簡単な使い方コードがあるのでまずはそこから
- GitHub Three-VRM VRMExpressionLoaderPlugin.ts:143
- VRM1.0でランタイム実行時にカスタムクリップを追加できるようにする
- VRM仕様 VRMC_vrm: expression