LoginSignup
12
3

More than 5 years have passed since last update.

アッチの世界を覗く射影行列 (Projection Matrix)

Last updated at Posted at 2016-01-20

アッチの世界を覗きたい

アッチの世界を覗ける窓を作ってみた (ニコニコ動画)

この動画を見てからずっと私もアッチの世界を覗いてみたいと思っていました。
最近は顔認識の精度も良くなってきたので何もWiiリモコンを使わずともHead Trackingはある程度できます。
しかし3DCGに疎い私はどういう変換を行ったらアッチの世界をリアルに見せられるのかがわかりませんでした。

...そう、今日までは。

考えてみるとすごくアホみたいなことなんですが、「↑の動画に似たことをやりたいけど3DCGとかよくわからないしとりあえず頭の座標にカメラオブジェクトの座標を合わせてやってみよう」というふうにやってコレジャナイ感に苛まれた方が結構な数いるのではないかと思います。

結論から言うと問題はカメラの配置やVR空間の変換ではなくカメラそのもの、具体的にはカメラが使う射影行列を変える必要がありました。

あっちの世界を覗く射影行列

以下がその魔法の行列です。
window_projection_matrix.gif
※ (1/21 追記) 以前の行列に間違いがありました、正しくは以上のようになります。

x, y, zはそれぞれカメラのx, y, z座標に対応します。
w, hは画面の幅と高さに対応します。
これで、VR空間内の原点を中心に画面の大きさと同じ領域を画面に映し出すことができます。
72dpiのディスプレイではVR空間内の2834.6456693pxが1メートルに対応します。

実装 (JavaScript)

THREE.WindowCamera (JSFiddle)

WindowCameraという名前のthree.jsで使えるカメラを作ったので使ってみてください。
一つ難点はrenderer.render(scene, camera);を呼ぶ前にcamera.updateProjectionMatrix()を呼ばないといけないこと。これはパフォーマンス上の影響は小さいはずなので追々修正するつもりです。
WindowCamera.js (Gist)
WindowCamera.js (Raw)

同じ行列を使えばOpenGLだろうとなんだろうと同じ現象を再現できるはずです。

計算方法

ここを参考にしています。
カメラの座標を(0, 0, 0)から(x, y, z)へ、near平面の中心を原点(0, 0, 0)にし幅と高さをそれぞれw, hに置き換えて計算するとおおむね以上のような結果になります(一部都合がいいように変更しています)。

12
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
3