Upgrade to Pro — share decks privately, control downloads, hide ads and more …

趣味開発でVRM1.0モデルに対応した話

 趣味開発でVRM1.0モデルに対応した話

Baku_Dreameater

December 08, 2022
Tweet

More Decks by Baku_Dreameater

Other Decks in Programming

Transcript

  1. / 14 趣味開発で VRM1.0モデルに 対応した話 2022/12 獏星(ばくすたー) / @baku_dreameater 1

  2. / 14 VMagicMirror (VMM)とは VRMのアバターが動かせるWindows向けソフト。 web / BOOTH ・カスタム表情を含めた、表情を動かすための設定項目がある ・VRoid

    SDKに対応し、VRoid HubのモデルがDLできる ・目線の動きや揺れものの制御で多少Hackが入っている VRM 1.0モデル対応とは 従来のモデル形式だったVRM 0.xモデルのみを扱える状態から、 VRM 1.0のモデルも読み込んで動かせる状態に移行すること 2
  3. / 14 VRM 1.0対応 in VMM 3 揺れもの 表情 ボーン操作

    LookAt ロードAPI VRoid SDK 利用規約UI追加 設定ファイルの 互換性確保 やる 良い感じ エンバグ対策
  4. / 14 ロードAPI etc. ロード関数: VRM10.LoadBytesAsync(byte[], …) ・VRoid SDKはモデルロード関数を↑に差し替えれば大体動く ・ロードしたアバターを保持する型:

    VRM10Instance ・ロード完了後はVRM 0.xと1.0の区別がつかないが、 メタデータ取得時には判別できる →VRM 0.xと1.0ではモデル規約UIを切り替える UIを切り替えるモチベ (の例): VRM0.xには「政治・宗教利用の許可/不許可」設定はない →無いものは無いので、旧表記にしたほうが実態に合う VRM 0.x 規約(as-is) VRM 1.0 規約(追加) 4
  5. / 14 (補足) ロード直後にやること 自前でランタイム制御のタイミングを制御する instance.UpdateType = Vrm10Instance.UpdateTypes.None; 実際のアップデート: 別スクリプト(ScriptExecutionOrder定義済)でやる

    class Vrm10InstanceUpdater : MonoBehaviour { void LateUpdate() => instance.Runtime.Process (); } 理由: VMMはScriptExecutionOrderパズルしてる処理が随所にあるため… 通常は自動のアップデートでも大丈夫らしい 5
  6. / 14 良い感じ(1/4) 揺れもの ・VMMには「風」という機能がある ・揺れもの(SpringBone)のgravityにノイズ的な値を加算して実現 ・UniVRM v0.106.0でgravityの追加項だけ指定できるAPIが追加された →追加項に風の成分を入れればOK。 風エフェクトのためのAPIと言っても過言ではない

    デフォルト + 風の成分 = 合力 デフォルト 風エフェクトの処理イメージ ※UniVRMのSpringBone実装はVRM 1.0でJobベースになった (たぶん昔のより速そう) (知らんけど) 6
  7. / 14 良い感じ(2/4): 表情 (理想編) 表情を制御するAPI ・旧: VRMBlendShapeProxy.(Accumulate | Apply)

    ・新: VRM10Instance.Runtime.Expression.SetValue 表情の種類(口パク、喜怒哀楽など)を表す型 ・旧: BlendShapeKey ・新: ExpressionKey 関数とデータだけ変えれば良いんだ、ラクだな~ 7
  8. / 14 良い感じ(2/4): 表情 (現実編) 関数とデータだけ変えれば良いんだ、ラクだな~ そんなことはない VRM 0.x向け実装はAccumulate()→Apply()という 関数の呼び出し順序が前提の設計になっている

    →単に関数だけ差し替えると正しく動かない 結局、VRM0.x向けのクラスである VRMBlendShapeProxy風に動く自作クラスを 挟んで一時的に凌いだ (追加)BlendShapeAccumulator Runtime.Expression ほかのコード群 ExpressionKey, Value Dict<ExpressionKey, Value> 毎フレーム1回呼ぶ 毎フレーム沢山呼ぶ これ 8
  9. / 14 良い感じ(2/4): 表情 (補足) ~表情排他~ VRM 1.0: 表情の排他設定が追加されてる ・各表情に「この表情の適用中は口パク

    / 目パチしない(or 弱める)」という指定ができる VRM 0.x: ロードすると、表情は全て排他しない設定扱い 例:Happy (旧: JOY)に目閉じモーフが入ってても、Happy/Blinkを同時実行できる 方針: いったん排他設定は信用しないのが簡単 例: Happyの表情を適用中は、アプリ側でBlinkやLipSyncを止める ※VRM 0.x向けアプリでは既にそういう実装が入っているはず ただし、実際には真のVRM 1.0モデルの場合ガード処理を避ける方が見栄えが良い →VRM 1.0の普及前には対策したい… 9
  10. / 14 良い感じ(3/4) ボーン (理想編) 前提: ・VRM 0.x: ボーンのローカル軸はTポーズ状態で全てワールドXYZ軸に揃う ・VRM

    1.0: ボーンのローカル軸は元データの軸のまま UniVRMの機能: ・モデルのロード直後、VRM 0.x相当の仮想ボーンを生成してAnimatorを差し替える ・実態はVRM10Instance.Runtime.ControlRig ・Animator.GetBoneTransformすると真のボーンの代わりに仮想ボーンが拾える ・仮想ボーン姿勢に基づいて、(Eye以外の)ボーンが毎フレーム更新 つまりどういうこと?: ・普通にAnimator.GetBoneTransform(…).localRotation = …; で勝手に良い感じになる! ・最高! 10
  11. / 14 良い感じ(3/4) ボーン (現実編) 腕がねじれる!!!Humanoid AnimationとIKの併用で発生 助けて貰いました in :

    https://github.com/vrm-c/UniVRM/issues/1923 FinalIKで、FBBIK (FullBodyBipedIK)の使い方に問題があった ・詳細はissue先を参照 ・要はIKに対して肩~肘~手首の曲げ方向のヒントを入れると安定する (VRIKとかでは元々やってそう = VRIKだと再現しない) ※ちなみに上記issueの回答適用後も 従来版よりアバターの腕が捻れやすいです。 原因は絶賛調査中… 謎骨折の現場 VRM1.0対応をやめたく なった最大の要因 11
  12. / 14 良い感じ(4/4) LookAt ・VRM 0.x: VRMLookAt ・VRM 1.0: VRM10Instance.Runtime.Gaze

    ・VMMの場合: 独自処理で目ボーン or 目BlendShapeを制御 ・独自処理のモチベ: 目閉じ制御など △: Animator.GetBoneTransform(…) →仮想ボーンの目が取得できるが、手元だとココをいじっても動かず ※VMMではScriptExecutionOrderをいじりすぎてるせいかも… 〇: VRM10Instance.Runtime.ControlRig.Bones[…].ControlTarget →仮想ボーンではない、モデルのホンモノの目ボーンを取得する Animatorベースでうまく行かない場合でも動く 独自処理の例: 目閉じで目線を下げる →LookAt(Gaze)では表現しきれない 12
  13. / 14 エンバグ対策: 設定ファイル互換性 設定ファイルではBlendShape名をVRM 0.x相当の名称でI/Oしておくように実装 →VRM 1.0対応では何かしら重大バグが起こる前提でダウングレード時の懸念を減らした 13

  14. / 14 まとめ: VRM 1.0対応 やるだけ • ロードAPI / VRoid

    SDK → やるだけ • モデルの利用規約UIを作る → やるだけ (項目は多い) 良い感じ • 揺れもの → 簡単 • 表情 → APIの互換性に注意 • ボーン → そこそこバグる +まだバグってます • LookAt → 凝ってる場合は要注意 エンバグ対策 • 設定ファイル互換性 → 備えよう 終 獏星 制作・解説 14