モデルビュー行列からカメラのパラメータを計算する.
modelview matrix は model に作用する matrix も含んでいるので,シーンがスケール,移動,回転されていたりするとその効果が含まれている.これをmatrixの情報のみを使って分離する方法はない.そこで,ここではシーンに対するtransformation matrix は Identity matrix, つまり全てはカメラの効果としてカメラのパラメータを抽出する.もし,シーンに対する効果が分離されているようなレンダラと OpenGL レンダラを併用する場合には,この transformationmatrix を undo する必要がある.modelview matrix は以下のような成分になっている.この成分の詳しいことに関しては私の以前の blog(http://shitohichiumaya.blogspot.de/2011/01/what-matrix-glulookat-generates-1.html)を参照のこと.
[xxyxzx0xyyyzy0xzyzzz0−(→x⋅→e)−(→y⋅→e)−(→z⋅→e)1]
4行を a,b,cで置きかえるとこの行列は以下のように書ける.
[xxyxzx0xyyyzy0xzyzzz0abc1]
この行列には既にカメラの basis があるので,問題は視点の位置である.これは4行の1-3列だけを取り出して行列表示する.(ここでは行列とベクトルをカラムベクトル表示 →x,→y,→z,→eしている.)
[→x→y→z][→e]=[abc]
であるから,
[→e]=[→x→y→z]−1[abc]
が視点の位置となる.従ってプログラムの実装例は以下のようになる(C++).
/// get camera parameters from /// the OpenGL modelview matrix /// /// \param[out] eyepos eye position /// \param[out] viewdir viewing directio /// \param[out] updir up direction vector void gl_get_camera_parameters_from_modelview_matrix( Vector3d & eyepos, Vector3d & viewdir, Vector3d & updir) { GLdouble mat[16]; glGetDoublev(GL_MODELVIEW_MATRIX, mat); Vector3d xdir(0.0, 0.0, 0.0); Vector3d ydir(0.0, 0.0, 0.0); Vector3d zdir(0.0, 0.0, 0.0); xdir[0] = mat[0]; ydir[0] = mat[1]; zdir[0] = mat[2]; xdir[1] = mat[4]; ydir[1] = mat[5]; zdir[1] = mat[6]; xdir[2] = mat[8]; ydir[2] = mat[9]; zdir[2] = mat[10]; // This is a, b, c components. Vector3d bvec(-mat[12], -mat[13], -mat[14]); Matrix33d basis_mat(xdir[0], xdir[1], xdir[2], ydir[0], ydir[1], ydir[2], zdir[0], zdir[1], zdir[2]); // This matrix should not be singular. // invert() gives matrix inverse. basis_mat.invert(); eyepos = basis_mat * bvec; viewdir = -zdir; updir = ydir; } ここでも簡単のためにエラーチェックをしていないが,個人的にはいくつかのassertion はしておきたい.
Comments
Post a Comment