トマシープが学ぶ

Unity/VR/AR/デザイン好きのミーハー 記事内容は自分用のメモです

QuestProのアイトラッキングをVRoid(VRM)の目に反映した!!

前回QuestProのフェイストラッキングをVRMに反映するというのはやってみた

bibinbaleo.hatenablog.com

次はアイトラッキング

OVREyeGaze

OVREyeGazeというのを使う

公式リファレンス

https://developer.oculus.com/reference/unity/v60/class_o_v_r_eye_gaze/

こちらの記事通りにやってみた

note.com

こういうコンポーネント。右と左を選べる。

フェイストラッキングのと同じように許可を設定

これで動いた

TrackingModeはHeadとWorldをそれぞれ試したところ、Headだと自分の頭の位置?に追従するので常に目の前にこのオブジェクトが表示され目の動きに合わせて回転した。

Worldは原点の位置?最初自分の足元らへんに表示されて、自分が動いても追従しない。

VRMに対応

こりんさんのメモに以下のように書いてあった

手っ取り早い使い方としては、キャラクターの眼球に相当するオブジェクトにOVREyeGazeをアタッチして、EyeをそれぞれLeftとRightに設定、Apply Rotationをオンにして、Tracking ModeをHead Spaceにすると視線の向きにあわせて眼球のオブジェクトが回転します。

tech.framesynthesis.co.jp

VRoidに眼球オブジェクトはないけど、Root下のFaceeyeを回転させると目も動く

ただこのTransformは実行中外部から値を変更はできない?こうやってもダメだった

サンプルシーンではRoot下の目についてた。

これかな?Animtorを付けていて実行順の問題?

qiita.com

とりあえずAnimetorをオフにしたら動いた

OVREyeGazeスクリプト内のUpdateをLateUpdateにしたらAnimatorをオンにしても動いた。Packages内にあるとスクリプトを変えれなかったのでAssets下に置いた

 

でも頭の回転にも反応してめっちゃうごく。これ、ヘッドセットのトラッキングもしてたら別にこれでもいいのか?

公式ドキュメントを読む

https://developer.oculus.com/documentation/unity/move-eye-tracking/

サンプルで設定されていたViewpointのような「ワールド空間方向の参照フレームが必要です。通常、この基準フレームは目の前方向に設定する必要があります。これは、目のゲームオブジェクトの初期オフセットを計算するためにあります。」だって

追加した

これを追加しても特に変わらない

TarackingSpaceをWorldにしたら、頭の回転と共に目も回転することはなくなった

範囲調整

でも動く範囲がやばいので制御したい

こちらの記事では別途フィルター処理をかけたらしい

synamon.hatenablog.com

 

これで設定できないかな~と思ったが、VRMのLookAt機能を使わない限り関係なさそう?

qiita.com

すでにいい感じになってる。

ChatGPTに言って角度制限してもらうようにしてみた。確かに範囲内の値にはなるが、全然動きがない

解決!x0.2の値にする

目の可動範囲を強制的にある値の間に制限するのではなく、動きを何分の1かにしたらいい感じになった!

 



ChatGPTにOVREyeGazeを直接いじってもらった

 
 
public float rotationScaleFactor = 0.5f;
 
~~
LateUpdate内
 
        if (ApplyRotation)
        {
 
          var scaledRotation = ScaleEyeRotation(pose.orientation);
            transform.rotation = CalculateEyeRotation(scaledRotation);
        }
 
~~
 
 
private Quaternion ScaleEyeRotation(Quaternion eyeRotation)
{
    // 目の回転を Euler 角に変換
    Vector3 eyeEuler = eyeRotation.eulerAngles;

    // Euler 角を -180度から180度の範囲に正規化
    eyeEuler.x = NormalizeAngle(eyeEuler.x);
    eyeEuler.y = NormalizeAngle(eyeEuler.y);
    eyeEuler.z = NormalizeAngle(eyeEuler.z);

    // 回転をスケーリング
    eyeEuler.x *= rotationScaleFactor;
    eyeEuler.y *= rotationScaleFactor;
    eyeEuler.z *= rotationScaleFactor;

    // スケーリングされた Euler 角から Quaternion に戻す
    Quaternion scaledRotation = Quaternion.Euler(eyeEuler);
    scaledRotation.Normalize();
    return scaledRotation;
}

private float NormalizeAngle(float angle)
{
    while (angle > 180) angle -= 360;
    while (angle < -180) angle += 360;
    return angle;
}

 

値はいろいろ試したけど0.2ぐらいでよさそう。

ただ上下を見たとき、片方が逆を向く症状があって、ChatGPTに直してもらっていい感じになったのに、別のモデルで試すとまた再発した

直してもらった時

private Quaternion ScaleEyeRotation(Quaternion eyeRotation)
{
    // ...(既存のコード)

    Quaternion scaledRotation = Quaternion.Euler(eyeEuler);
    scaledRotation.Normalize();
    return scaledRotation;
}

ってやったのだが、これをもとの

    return Quaternion.Euler(eyeEuler);

にしたら、その別のモデルでは正しくなった。

なんなんだろう~

メモ:動かない

OVRBody

OVRBodyの動きを反映させたら目線が動かなくなった。

bibinbaleo.hatenablog.com

OVRBody側が送る値に上書きされている。

スクリプトの実行順を変えたら動いた。OVRBodyの動きを送っているAvatarMotionTransferよりOVREyeGazeを下にする

VRM1.0

アバターをVRM1.0にしたらまた動かなくなった。

VRMInstanceのUpdateTypeをLateUpdateからUpdateにしたら動いた