理論上のCameraMatrixとProjectionMatrix
世界座標系で表された[Xw, Yw, Zw]は、カメラの外部パラメータによって[Xc, Yc, Zc]になる(カメラ座標系)。
これが、カメラの内部パラメータによって、[u, v]になる。(下の式のX,Y,ZがXw,Yw,Zw)
右辺の左の行列がCameraMatrix。
この状態だと、CameraMatrix=ProjectionMatrix。
さらに、右辺中央の外部パラメータはViewMatrix。
この式みたいにModel座標系から世界座標系の変換が必要ないのであれば(もともと世界座標系の点を考えているので)、
ModelMatrixはIdentityとしていいので(無視していいので)、ViewMatrix=ModelViewMatrix。
つまり、この式がまさに $ProjectionMatrix \times ModelViewMatrix \times position$ の状態。(vertex shaderっぽい)
実際はCameraMatrixをそのままProjectionMatrixに使えない
その理由は、レンダリングの都合上、znearとzfarという2つの平面を指定する必要があるから。
以下のサイトがProjectionMatrixについてわかりやすく記述している。
http://miffysora.wikidot.com/perspective-matrix
(このサイトでは点を行ベクトルとして扱っているので、行列は転置してある。この場合、行列は右からかける。
frustum
frustumでは、left, right, top, bottomが独立している。znear、zfarも指定する。
光学中心、焦点距離(内部パラメータ)がうまく反映されていることがわかる。
perspective
一方で、よく見るPerspective Matrixは、cx, cyを考慮してくれない。
fovとaspectだけ指定ればOKなのは、光学中心=画像中心だから。
perspectiveでは、left=-right, top=-bottomとなっている。
VRとAR
VRだけやるのであればPerspectiveはシンプルで使いやすいが、ARをやろうとして実際のカメラの内部パラメータを計測しても、perspectiveを使ったprojection matrixでは上手くいかない。(光学中心のズレが考慮されない。)
ただし、opencvなどでundistortする際に、newCameraMatrixとしてcx,cyを0にしたものを与えれば、Perspectiveが使える。
その他、カメラの内部パラメータ、外部パラメータ、歪みについては以下を参照。
http://qiita.com/RyoheiKomiyama/items/fee2105c3e9bfccde3a3