Eye trackingの実装【VRChat技術情報】
こっち見んなモーフからの脱却
VRChat日本ユーザーの間では自作アバターの作成が盛んなのですが、ほとんどの人がVRChatのアイトラッキング(Eye tracking)を実装できていないです。(あるいはわざとかも知れないけれど)ほとんどが目を凹面にしてだまし絵を利用したアイトラッキングなのではないでしょうか。
原因はアイトラッキングに関する日本語の記事が全くないことが原因と思われます。
英語のチュートリアル動画などはあるのですが、英語なので重要なポイントを聞き落としやすく、どこかしらでつまずいていることが多いようです。
私もここでつまずいていたのですが、今回フレンド(VRCID:MIYASE)さんの協力を得て実装方法を理解できたので、この記事にまとめます。
VRC SDKはいかんせんブラックボックスの性格が強いため、手探りで実装しています。必要な工程と認識していた物が蛇足だったり、偶然実装成功している部分もあると思います。以下の情報はいろいろ試しながら追記、修正する予定です。この記事を参考にして実装した際に問題が発生した場合、新しい情報に繋がる可能性があります。コメント欄やツイッターのリプライで報告して頂けるとありがたいです。
アイトラッキング周りの機能概要
・瞳の挙動
・まぶたの挙動
まず、この機能はHumanoidのリグを前提としているため、Generic等のアバターには恐らく対応していないことに注意。
瞳の挙動は相対するアバターがいた場合に相手から見てこちらに視線を向けているように瞳が動く。この挙動はボーンの回転で表現している。瞳の可動範囲はVRC SDKの固定値なので設定不可能。破綻する場合*1は瞳のボーンの支点を前後させたりウェイトペイントで対応する。
まぶたの挙動は顔のシェイプキーで表現している。これを実装すると自動で瞬きをするようになる。また、瞳の挙動と連動していて、瞳を下に向ければ上まぶたが、上に向ければ下まぶたが窄まり、より自然な目の挙動に近づけやすい。ただしこの瞬きは少し頻度が高すぎるのと、だからといって頻度を調整できるわけでは無いので、気にくわない場合はあえて使わない選択肢もある。
必要なモデルデータの様式
以下に3Dモデルに必要な様式、設定をまとめる。とりあえずアイトラッキングのテストまではこの記事通りに実装して、不必要な物は後に調整するという形にした方が問題の切り分けがしやすくオススメ。3Dモデルの編集はBlenderを想定している。
- ボーン名称をVRChatに対応させる(追記:リップシンク用のメッシュの名前も)
- まばたき用のシェイプキーを用意
- 瞳のボーンの配置
- ウェイトペイント
上記4工程がモデルデータの様式を揃えるのに必要。
ただしこれにはBlender無償プラグインの「cats-blender-plugin」を利用して自動で処理する方法もあり、手順はあっとさん(https://twitter.com/aaattttttooo)から情報提供されている。
①cats-blender-pluginを導入する
②EyeTrackingの項目があるのでそれをつかう
※瞳のウェイトを塗る。事前に用意した目のボーンとEyeTrackingで自動生成されるボーンの両方に1.0で。
私はこれでアイトラッキングできてますよ!— あっと@みんなきのこになるVRChat (@aaattttttooo) July 25, 2018
ただ、私の環境で上手く変換が通らずボーン意図した向きにならないために瞳の軌道が弧を描いてしまう問題が解決できず、まだ詳細の説明はできない。環境やプラグインのバージョンによるのかもしれないので試してみて通るようなら下記の工程をスキップできる。
また、以下のリンクで配布されているUnityのエディタ拡張で自動でアイトラッキングの動作条件を満たすアプリが配布されている。
上手く通らなかった場合、手作業で実装したい場合は以下。
1.ボーン名称をVRChatに対応させる(追記:リップシンク用のメッシュの名前も)
Humanoidのアバターのボーンの名称とリップシンクのシェイプキーが格納されたメッシュの名称はVRC SDKで検出するために特定の名称が設定されている模様。
理屈の上ではリグの設定時に右目左目のボーンを設定すれば動きそうだけど、これでは動かない。
上の画像は駄目。瞳のボーンの名称が適当なので動かない。
全身のボーンを正しい名前にする必要はなく、右目と左目に繋がるボーンを最低限名前を揃えれば良い。
念のためアーマチュアの名称から順に
Armature
┗Hips
┗Spine
┗Chest
┗Neck
┗Head
┣LeftEye
┗RightEye
(┗、┣はボーンの親子関係を示す記号なので無視すること)
10/2追記
100の人 さん(@esperecyan)からの情報で条件が確定。
以上のボーン構造は、実際に利用するアーマチュアのオブジェクトである必要は無く、VRCSDKが同様のオブジェクト構造があることのみを条件にアイトラッキングの有無を決定している。つまり、以上を無視したボーン構造のアバターの場合でも、空のオブジェクトを作成し同様の構造をアバターのルート直下に配置すればよい。
アルファベット大文字小文字も関係するのでコピペするなどして正しく命名する。半角/全角スペースが紛れ込むケースも多いので注意。
8/31追記
リップシンクの表情のシェイプキーが格納されているメッシュ(多くの場合顔、あるいは顔を含む体全体など)の名前を
Body
にする。このメッシュの名称がBodyでなくともリップシンクは動作するものの、アイトラッキングを動作させたい場合はこの名称も揃えなければVRC SDKがアイトラッキング用のシェイプキーを認識できない。その結果、リップシンクのみでアイトラッキングは動作しないアバターになってしまう。また、このBodyメッシュはアバターのルート直下に配置しなければならない。
以上、目のボーンまでのボーンの名前とリップシンク用のメッシュの名前全てが一致していないと、アイトラッキングは動作しない。
2.まばたき用のシェイプキーを用意
Bodyメッシュに用意するシェイプキーは4つ。VRC SDKでは口パクのシェイプキーとセットで扱われるため、ひとつのオブジェクトの中にまぶたと口のメッシュが入っている必要がある。まつげがある場合も当然同様。瞳のメッシュは別でも良い。
VRC SDKにはまばたきのシェイプキーを指定する項目はなく、以下に示す特定の名称のシェイプキーをVRC SDKが自動で検出して適用する。
vrc.blink_left
vrc.blink_right
vrc.lowerlid_left
vrc.lowerlid_right
シェイプキーの並び順が最も重要なので、必ず画像の順になるように並び替えること。並び替えは対象のシェイプキーを選択した状態で画像右下の△と▽ボタン。
FF外から失礼します。ちょうど先日フレンドとアイトラッキングについて検証していたので情報提供を。
— あお@ニコ生with麦ちゃ (@aocha_tkt) September 1, 2018
瞬き用シェイプの名前ですが、こちらは指定のモノでなくても良いようです。
位置の方が重要で、上から順番に適用されている模様でした。 pic.twitter.com/dbiLEuM7b9
それぞれのシェイプキーの挙動は
vrc.blink_left:
左目のまばたき。上まぶたと下まぶたの挙動を表現したもの。このシェイプキーだけでまばたきを表現するので上まぶただけの挙動でないことに注意。
vrc.blink_right:
右目のまばたき。上まぶたと下まぶたの挙動を表現したもの。このシェイプキーだけでまばたきを表現するので上まぶただけの挙動でないことに注意。
vrc.lowerlid_left:
左目の下まぶたのすぼまり。いぶかしむような目つきを表現したり、瞳を上に動かした時などに連動して動く。
vrc.lowerlid_right:
右目の下まぶたのすぼまり。いぶかしむような目つきを表現したり、瞳を上に動かした時などに連動して動く。
まばたきを実装したくない場合は同名のシェイプキーを作成、頂点を見えない範囲で移動させる挙動にする。Basis(ベース)から一切頂点を移動させてないシェイプキーはUnityに移行する際に最適化されて削除されてしまうため、何かしら頂点を移動させる必要がある。作成済みのシェイプキーの値を0.001など微少に適用させたものを設定すれば良い。
編集モード、Aキー押下するなどして頂点を全選択した状態で、
画面下のツールバーの「メッシュ」→「頂点」→「任意のシェイプキーを選択部に合成」
あるいは「Ctrl+V」→「任意のシェイプキーを選択部に合成」
これで指定したシェイプキーを任意の値でブレンドできる。
まばたきをアニメーションやアニメーションオーバーライドで実装したい場合は、同様に頂点がほとんど動かないシェイプキーを作成したあと、別名でまばたきのシェイプキーを作成して実装すること。(一つのシェイプキーを複数のコンポーネントから利用するとシェイプキーが機能しなくなり頂点が動かなくなるため)
3.瞳のボーンの配置
上図を参照。
緑色に着色された6角形のメッシュが瞳。
ボーンのヘッドの位置が目玉の回転軸にあたる。このときボーンの姿勢が重要で、垂直方向を向いている必要がある。(Blender上だとZ軸方向と平行)長さなどは特に指定があるかなど詳細は不明だが、図のモデルは動くので各設定値を参考にすると良い。
フリーハンドでボーンを垂直に立てた場合、ボーンの姿勢のパラメータのうちロールが180度とか90度、あるいは適当な値になることがあるので、編集モードでロールの値を0度に指定すること。ここに角度がついているとVRChatに実装後に0度に戻る動きをするため、白目になったりロンドンとパリを同時に睨むことになる。
ボーンの設定。親のボーンは「Head」、回転を継承、スケールを継承、ローカル位置にチェック、接続は外してOK(配置の関係上外さないとやりようがないとは思う)
4.ウェイトペイント
当然それぞれの瞳のウェイトはLeftEyeとRightEyeで1.0に指定するのは当然として、少し特殊だがHeadでも両瞳のウェイトを1.0に指定する。
こうすることで瞳が動きすぎるのを抑制することができる。
VRC SDKでは瞳の可動範囲を指定できないため、アニメ調のキャラでほとんどの場合瞳が動きすぎて目からはみ出したりする。頭側のウェイトを塗ることで瞳の移動を抑えることができるのでこのような設定にしている。瞳と頭のウェイトの値を変更することで微調整も可能。(例:Headのウェイトは1.0のまま、Left/RightEyeのウェイトを0.2に設定してさらに動きを押さえる。)
ちなみに、ブレンダー上でLeft/RightEyeのロール±30°程度が目の左右移動の最大角度なので、±30°の状態で瞳が目から飛び出さないようにウェイトを調整するとよい。
以上で3Dモデルのデータ様式はVRChatでアイトラッキングを利用できるようになった。次にVRC SDK。つまりUnity上での設定を説明する。
VRChatへの実装(Unity - VRC SDK)
主なポイントは3つ。順に説明する。
1.リグの生成、確認
通常通り、fbxファイルをインポートした後にHumanoidリグを適用する工程。
Headの位置にあるLeft EyeとRight Eyeが正しく指定されているかチェックする。誤っている場合は指定し直す。
2.VRC_Avatar Descriptor、リップシンクの設定
通常通り、リグを設定したfbxファイルをシーンに追加し、VRC SDKのコンポーネント「VRC_Avatar Descriptor」を追加する。
そして表示される2つのコンポーネントのうち「VRC_Avatar Descriptor(Script)」の「Lip Sync」の項目を「Viseme Blend Shape」に指定する。
すると下にリップシンクに使うメッシュとシェイプキーの指定項目が現れるので、まぶたと口パクのシェイプキーが入った”Body”メッシュを指定する。メッシュの名前がBodyでないとアイトラッキングが動作しないので、ここで指定するメッシュの名称は必ずBodyにする。必要ならリネームすること。
リップシンク用のシェイプキーを選ぶときに、シェイプキーの一覧が表示されるので、このときまばたき用のシェイプキーが正しくインポートされているか確認すること。正しくインポートされていれば先ほど作成した4つのシェイプキーが表示される。
このときまばたき用のシェイプキーを指定する項目は存在しない。上述したが、特定の名称のシェイプキーを自動でまばたき用のシェイプキーとして適用するようになっているため、メッシュに特定の名前のシェイプキーが存在すればよい。
3.VRC_Avatar Descriptor、View Positionの設定
View PositionはVRChat上での一人称カメラの位置を指定する物なので、一見アイトラッキングに関係が無いように思えるが、配置によっては悪影響を及ぼすため注意が必要。
目と目の間。具体的には正面から見て右瞳と左瞳の中心を繋いだ線と、正中線が交わる位置にView Positionを指定すること。
これが上下にずれると常にView Positonの方向に瞳の位置がずれるようになる*2。アイトラッキング自体は動作するものの想定通りの動作から遠ざかる可能性がある。
Z方向の位置はVRChat公式のガイドにもあるように皮膚に少し食い込む程度に近づけること。これは単純にZの値が0から離れるほどカメラの挙動が悪化するのと、だからといってメッシュの奥に配置すると視界が悪化することのトレードオフの解。
以上で全て完了。
あとはアップロードすればアイトラッキングが実装できるはず。
情報求む
VRC SDKはブラックボックスなので、以上の実装は手探りで動作確認したものです。
この通りの設定にしても動作しなかった場合、コメントやツイッターのリプライで教えて頂けると不明な点が少しずつ解明していくと思います。
私のほうでもアバターに実装しながら細かいところの挙動を確認していきながら追記していく予定なので、そのような情報がありましたら教えてくださると嬉しいです。