自分の腕を伸ばしきってもアバタの腕が伸びきらないとき(又はその逆)の対処法の原理

2020年12月11日金曜日

VR アバタ 技術 原理

t f B! P L


 前置き

こんにちはTOKIです

プログラムの原理的な部分について解説します

まだ読んでない人は前回を読んでからの方が良いと思います

今回の話は前提としてFinal IKを用いた場合の話なのですが
もしかしたら別のIKシステムやまったく別の問題にも使えるかも...?

御託はここまで

原理

そもそもSteamVR(VIVEやValve)のトラッキング座標はどう処理されている?

ベースステーションを用いたトラッキング方法は
HTC Vive Lighthouse Chaperon tracking system Explained

に紹介されているように同期フラッシュと左右,上下方向の光の走査の受信タイミングで行われており
ベースステーションに対する角度から位置を推定しています

Unity上でCameraRigを配置するとCameraRigのScaleに合わせてHMDやController,TrackerがCameraRig原点に対する相対位置で配置されます
なのでCamera (head)(Camera (eye)の親階層)やController (right),Controller (left)の親階層のScaleが変更されるとCameraRig原点からの相対距離が変化します
こんな感じ

何が問題になるか

Final IKはあくまでターゲットに合わせてアバタを動かすものなので
上記のことがややこしい問題を起こします

まずやりたいこととして自分の腕を伸ばしきるタイミングと
アバタの腕が伸びきるタイミングを一致させることなのですが
アバタは身長と両手を広げた時の幅が一致しないことがあり
身長のスケールに合わせても腕を横にした時に
アバタの腕が伸びきらない(もしくはその逆)という事が生じます
また肩幅の比率も多々違うので腕を前にした時にも
アバタの腕が伸びきらない(もしk(ry)という事が生じます

じゃあCameraRigのScaleに各軸別の値を入れよう
という事をしようとしても
といった問題が生じます

1つ目の問題についてはCameraRigのScaleをいじらずに
Camera (head)とController (right OR left)に
それぞれ別の新しい親階層を作り
そこにScaleを入れればいいと思うわけですが
そうすると原点からの相対距離にScaleがかけられるので
HMDとControllerの間にズレが生じていきます
(しかも原点から離れるとズレが大きくなる)
こんな感じで...

2つ目の問題に対してはこのままではどうしようもありません

解決法

上記の問題はControllerが
原点に対する距離で計算されるのが原因であるため
Final IKのターゲットとなる位置を
HMDに対する相対距離で計算できるようにすれば解決します
しかし実際にはControllerが止まっていて
HMDが動くこともあるので
アバタのUpperChestを基準に計算します
(ただしY軸方向は地面を基準)

計算自体は下図のように座標変換をおこなった後に
Scale変換をおこない元の座標系に戻すだけです

この時身体の前,横方向で
かけるScaleを変えたいので回転もおこないます
またUnityは左手座標系なのでそこだけ注意します
XZ座標系をUW座標系に変換

ここまで考えればあとは数学的な計算をプログラムで書くだけです

という事で
プログラムの原理的な部分はこんな感じでした
これはTrackerを使う時などにも応用が利くかもしれません


なにかあればコメントください

ではではノシ

QooQ