$30 off During Our Annual Pro Sale. View Details »

趣味開発で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

    View Slide

  2. / 14
    VMagicMirror (VMM)とは
    VRMのアバターが動かせるWindows向けソフト。 web / BOOTH
    ・カスタム表情を含めた、表情を動かすための設定項目がある
    ・VRoid SDKに対応し、VRoid HubのモデルがDLできる
    ・目線の動きや揺れものの制御で多少Hackが入っている
    VRM 1.0モデル対応とは
    従来のモデル形式だったVRM 0.xモデルのみを扱える状態から、
    VRM 1.0のモデルも読み込んで動かせる状態に移行すること
    2

    View Slide

  3. / 14
    VRM 1.0対応 in VMM
    3
    揺れもの
    表情
    ボーン操作
    LookAt
    ロードAPI
    VRoid SDK
    利用規約UI追加
    設定ファイルの
    互換性確保
    やる 良い感じ エンバグ対策

    View Slide

  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

    View Slide

  5. / 14
    (補足) ロード直後にやること
    自前でランタイム制御のタイミングを制御する
    instance.UpdateType = Vrm10Instance.UpdateTypes.None;
    実際のアップデート: 別スクリプト(ScriptExecutionOrder定義済)でやる
    class Vrm10InstanceUpdater : MonoBehaviour {
    void LateUpdate() => instance.Runtime.Process ();
    }
    理由: VMMはScriptExecutionOrderパズルしてる処理が随所にあるため…
    通常は自動のアップデートでも大丈夫らしい
    5

    View Slide

  6. / 14
    良い感じ(1/4) 揺れもの
    ・VMMには「風」という機能がある
    ・揺れもの(SpringBone)のgravityにノイズ的な値を加算して実現
    ・UniVRM v0.106.0でgravityの追加項だけ指定できるAPIが追加された
    →追加項に風の成分を入れればOK。
    風エフェクトのためのAPIと言っても過言ではない
    デフォルト
    + 風の成分
    = 合力
    デフォルト
    風エフェクトの処理イメージ
    ※UniVRMのSpringBone実装はVRM 1.0でJobベースになった
    (たぶん昔のより速そう) (知らんけど)
    6

    View Slide

  7. / 14
    良い感じ(2/4): 表情 (理想編)
    表情を制御するAPI
    ・旧: VRMBlendShapeProxy.(Accumulate | Apply)
    ・新: VRM10Instance.Runtime.Expression.SetValue
    表情の種類(口パク、喜怒哀楽など)を表す型
    ・旧: BlendShapeKey
    ・新: ExpressionKey
    関数とデータだけ変えれば良いんだ、ラクだな~
    7

    View Slide

  8. / 14
    良い感じ(2/4): 表情 (現実編)
    関数とデータだけ変えれば良いんだ、ラクだな~
    そんなことはない
    VRM 0.x向け実装はAccumulate()→Apply()という
    関数の呼び出し順序が前提の設計になっている
    →単に関数だけ差し替えると正しく動かない
    結局、VRM0.x向けのクラスである
    VRMBlendShapeProxy風に動く自作クラスを
    挟んで一時的に凌いだ
    (追加)BlendShapeAccumulator
    Runtime.Expression
    ほかのコード群
    ExpressionKey, Value
    Dict
    毎フレーム1回呼ぶ
    毎フレーム沢山呼ぶ
    これ
    8

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  13. / 14
    エンバグ対策: 設定ファイル互換性
    設定ファイルではBlendShape名をVRM 0.x相当の名称でI/Oしておくように実装
    →VRM 1.0対応では何かしら重大バグが起こる前提でダウングレード時の懸念を減らした
    13

    View Slide

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

    獏星
    制作・解説
    14

    View Slide