2019年1月20日日曜日

スクリーン座標からワールド座標に変換

Unityのcinemachineの機能で、Aimの位置をスクリーン座標でオフセット出来る機能があり、これをMotionBuilderで実現出来ないか開発中です。その開発途中で知りえた、ワールド座標をスクリーン座標に変換する方法と、その逆でスクリーン座標をワールド座標に変換する方法を備忘録的に記しておきます。

基本的なことはYMMTWORKさんのサイトを参考にさせていただき勉強途中で躓いた箇所も含めて記載します。
ワールド座標をスクリーン座標に変換するには以下の流れです。
参考にさせていただいてるサイトではワールド座標変換もありますが、バーテックス情報を利用したい時はワールド座標変換も必要ですが、MotionBuilderで実装する時にはオブジェクトのワールド座標(グローバル座標)が取得出来るので今回は省いていきます。
で、ワールド座標にあるオブジェクトをまずはビュー(カメラ)座標変換します。これはイメージとしてカメラの子供にした時のローカルのTrans座標を算出することです。
ここで必要になってくるのは、カメラ本体Trans座標、注視点Trans座標、カメラのUpベクターTrans座標です。これら3つを使ってカメラのローカル軸を算出していきます。


ビュー座標変換

ビュー変換はカメラを原点に戻してZプラス方向に向け姿勢を戻します。その時に戻したTransやRotationも対象オブジェクトに反映します。
ようは対象オブジェクトをカメラの子供にしたときのローカル座標を算出しています。

プロジェクション座標変換

ビュー座標変換された座標を使って、プロジェクション座標変換をします。
プロジェクション座標変換は、カメラからの見た範囲を正規化した座標位置を算出するイメージです。


プロジェクション座標変換された空間のことをクリップ空間というらしいです。この空間は、-1<=X<=1、-1<=Y<=1、0<=Z<=1の範囲収まるようになります。ちなみに、Z=0のときはnear値、Z=1の時はfarの値になります。



スクリーン座標変換

プロジェクション座標変換された座標を使ってスクリーン座標変換します。

この計算結果で得られるXとYがスクリーン上の座標となります。
計算のイメージ図

参考にさせていただいてるサイトと少し違うのは、スクリーン座標の原点が画面中央にあることです。なんでかよくわからないですが(笑)、MotionBuilder上ではそれでも問題なさそうでした。


補足として、スクリーン座標からワールド座標に変換したいときは、スクリーン座標に対して、スクリーン座標変換の逆行列を掛けて、プロジェクション座標変換の逆行列を掛けて、ビュー座標変換の逆行列を掛けるという順番で計算すればワールド座標が求まります。

あと、私が行列の基本が出来ていなかったため躓いた点として、同次座標です。
座標を1つ上の次元で表現する方法で、ωの値が1になるようにx、y、zをωで割らないといけないことです。