現在のモデルビュー行列からカメラからの距離を取得するには?

本物のページはこちら→camera

カメラの向いている向きのベクトルを取得する

つまり注視点-カメラ位置のベクトルのことである。

(裏ワザ★)ビュー行列の3行目で取り出す方法

CVector viewVec(-viewMatrix[2],-viewMatrix[6],-viewMatrix[10],0.0);

しかも、ベクトルの長さ1という正規化された状態でとれてしまうのだ!べんりーー
これは注視点-カメラ位置の正規化と全く同じ結果になります。
how to convert modelview matrix to gluLookAt parameters?

ローカル座標におけるカメラ位置を取得する

理論的に正しい方法

モデルビュー行列の逆行列に(0,0,0,1)を掛け算する

理論的に正しいが、計算コストが最もかかる。
もっと簡単にやるには、次の方法が有効

モデルビューの逆行列の3列目にマイナス1をかける

モデルビュー行列の逆行列に(0,0,0,1)を掛け算して求める方法と常に同じ結果になる。
w=1の時だけ有効らしい。
つまり、

modelviewInv[12],modelviewInv[13],modelviewInv[14]

ということ

カメラ位置の取得の仕方final
modelview

3列目説

モデルビューの3列目(つまり平行移動成分)にマイナスをかけたもの(スケール行列がかかってないときだけ有効である

モデルビュー行列の逆行列に(0,0,0,1)を掛け算して求める方法(実装の仕方)

現在のモデルビュー行列の取得

display関数にて

glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);

ローカル座標でのカメラ座標を知るには?

ここでいうローカル座標とは、物体の中心が原点になるような座標の事。
カメラ座標の原点(0,0,0,1)にモデルビューの逆行列を掛け算する

(1)
\begin{pmatrix} 0&4&8&12\\ 1&5&9&13\\ 2&6&10&14\\ 3&7&11&15\\ \end{pmatrix} \begin{pmatrix} 0\\ 0\\ 0\\ 1.0\\ \end{pmatrix}
  1. ワールド座標での頂点=modelMatrix*ローカル座標の頂点
  2. ワールド座標での頂点と、カメラの初期位置(0,0,-6)との距離を計算

これを最適化すると、結局求めたい結果は

(2)
\begin{pmatrix} 12\\ 13\\ 14\\ 15\\ \end{pmatrix}

逆行列成分の(12,13,14,15)なのだということがわかる。これで無駄な掛け算の演算が減りますね!
逆行列を得る

サンプルコード

gModelView.LoadIdentity();
    gModelView.gluLookAt(0,0,gZoom, 0,0,0, 0,1,0);//gZoom初期値は-5
    gModelView.MultMatrix(&rotation);
    gModelViewProj.gluPerspective(gFovy,gRatio,3,1000);
    gModelViewProj.MultMatrix(&gModelView);
    gIniCam.Create(0,0,0,1.0);
    gModelView.ConvetToInverseMatrix(&gInvModelView);//モデルビュー行列を逆行列にする
    gInvModelView.MultVector(&gIniCam,&gLocalCoordCam);

QuickSortRenderingCheckより

[quicksort]のページにあるQuickSortRenderingCheckというプログラムから抜粋。

CMatrix modelCmatrix(modelMatrix);
    modelCmatrix.transpose();
    modelCmatrix.invert();
        CVector vecView(0,0,0,1);
        vecView=modelCmatrix*vecView;        
        vecView.getv(camera);
        Vec3 cameraVec=Vec3((float)camera[0],(float)camera[1],(float)camera[2]);
        for(int i=0;i<blockNum*blockNum*blockNum;i++){
            blockSorting[i][1]=    debugBlock[(int)blockSorting[i][0]].setDistanceFromCamera(cameraVec);    
        //前フレームで並びかえた結果を使って、だいぶちらつきが減った!!
        }//printf("distance=%.3f\n",debugBlock[63].distanceFromCamera);
//centerVecが必要
float Block::setDistanceFromCamera(Vec3 camera){
    Vec3 distanceVec=camera-(this->blockCenterPoint);//this->blockCenterPoint.print();
 
    this->distanceFromCamera=distanceVec.length();//100倍しないとほとんど差がでないから
    if(this->distanceFromCamera==0.0f)printf("中心点を設定してください。視点からの距離が計算できません\n");
    //printf("%.3f\n",this->distanceFromCamera);
 
    return this->distanceFromCamera;
}

関連事項

違う角度から見た図を載せる…..取得したカメラ位置があってるかどうか視覚的に確認する。
Extracting camera position from a ModelView Matrix

ベクトルだけなら、あ行列の、2,6,10成分、という説もある

CVector viewVec(-modelviewMatrix[2],-modelviewMatrix[6],-modelviewMatrix[10],0.0);

これは長さ1
カメラ位置の取得の仕方final

現在のモデルビュー行列の取得

display関数にて

glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);

ローカル座標でのカメラ座標を知るには?

ここでいうローカル座標とは、物体の中心が原点になるような座標の事。
カメラの初期位置(0,0,0,1)にモデルビューの逆行列を掛け算する

(3)
\begin{pmatrix} 0&4&8&12\\ 1&5&9&13\\ 2&6&10&14\\ 3&7&11&15\\ \end{pmatrix} \cdot \begin{pmatrix} x\\ y\\ z\\ 1.0\\ \end{pmatrix}
  1. ワールド座標での頂点=modelMatrix*ローカル座標の頂点
  2. ワールド座標での頂点と、カメラの初期位置(0,0,-6)との距離を計算

逆行列を得る

サンプルコード

gModelView.LoadIdentity();
    gModelView.gluLookAt(0,0,gZoom, 0,0,0, 0,1,0);//gZoom初期値は-5
    gModelView.MultMatrix(&rotation);
    gModelViewProj.gluPerspective(gFovy,gRatio,3,1000);
    gModelViewProj.MultMatrix(&gModelView);
    gIniCam.Create(0,0,0,1.0);
    gModelView.ConvetToInverseMatrix(&gInvModelView);//モデルビュー行列を逆行列にする
    gInvModelView.MultVector(&gIniCam,&gLocalCoordCam);

QuickSortRenderingCheckより

[quicksort]のページにあるQuickSortRenderingCheckというプログラムから抜粋。

CMatrix modelCmatrix(modelMatrix);
    modelCmatrix.transpose();
    modelCmatrix.invert();
        CVector vecView(0,0,0,1);
        vecView=modelCmatrix*vecView;        
        vecView.getv(camera);
        Vec3 cameraVec=Vec3((float)camera[0],(float)camera[1],(float)camera[2]);
        for(int i=0;i<blockNum*blockNum*blockNum;i++){
            blockSorting[i][1]=    debugBlock[(int)blockSorting[i][0]].setDistanceFromCamera(cameraVec);    
        //前フレームで並びかえた結果を使って、だいぶちらつきが減った!!
        }//printf("distance=%.3f\n",debugBlock[63].distanceFromCamera);
//centerVecが必要
float Block::setDistanceFromCamera(Vec3 camera){
    Vec3 distanceVec=camera-(this->blockCenterPoint);//this->blockCenterPoint.print();
 
    this->distanceFromCamera=distanceVec.length();//100倍しないとほとんど差がでないから
    if(this->distanceFromCamera==0.0f)printf("中心点を設定してください。視点からの距離が計算できません\n");
    //printf("%.3f\n",this->distanceFromCamera);
 
    return this->distanceFromCamera;
}

頂点シェーダ上でカメラベクトルを取得

vec4 p = gl_ModelViewMatrix * gl_Vertex;  // 頂点位置
vec3 cam =normalize(p.xyz / p.w);          // 視線ベクトル

関連事項

違う角度から見た図を載せる…..取得したカメラ位置があってるかどうか視覚的に確認する。

サポートサイト Wikidot.com