OpenGL 視点を変える gluLookAt

シェーディング関係は、こんなもんでOKでしょう。次に視点を変えることをやってみようと思う。3DCGでの視点は、仮想空間の中の「仮想カメラの位置」。カメラの位置や、向きを変えることでダイナミックな動画を作ることができる。
gluLookAt
今までは、視点位置は変えずに、モデルの方を移動させてカメラに収まるようにしてきた。今回は、ちゃんと視点を設定してみることにしよう。カメラ位置を設定するのは、gluLookAtを使うのが便利。
PROJECTIONマトリックスを選択している状態で、glTranslatefやglRotatefで視点を移動、回転させることもできるのではあるが、何かと「ややこしい」。ただでさえ、座標値がx,y,zの3つもあるのに、「カメラの向き」を軸周りの回転で考えてやらないといけない。紙に書いてもそれは2次元でしかないので、基本、頭の中で「ぐりぐり」するしかない。X-Y平面だけ紙に書くという手もあるか。
BlenderとかのCGレンダリングソフトで、カメラを操作するのも、トレーニングにはいいかも知れない。
さて、それはさておき、便利なgluLookAtを使った方が視点(カメラ位置)の設定は簡単にできる。といってもgluLookAtには引数がたくさんある。あーんめんどくさい。
視点位置座標
まず、最初の3つの引数は、視点位置の指定。x,y,zで指定する(OpenGLのインスタンスは引数から除いて説明している)。
今、モデルの方をz軸方向に移動しているので、これをやめて、zの移動量を0にする。xの値は左右にずらす必要があるので、そのまま。
視点の位置をz軸で3にする。モデルを-3していたので、逆にカメラの方を+3にして同じように表示できるようにする、といった作戦である。
視点位置は、デフォルトで0,0,0なので、最初の3つの引数は、0,0,3とする。
注視点位置座標
次に、「注視点」のx,y,z座標をgluLookAtの引数で設定する。注視点というのは、カメラの向いている方向を示すための座標値。視点から注視点に向かうベクトルがカメラの向きとなる。
視点位置が、0,0,3。ここからモデルの存在する方向にカメラを向けたいので、注視点は0,0,0とする。これでうまくいくはず。
カメラの上向きベクトル
最後に、カメラの上方向を指定するベクトルを指定する。通常は、Y軸のプラスが上方向だが、逆立ちしてみたり、横になったりするかも知れないので、このパラメータがある。とりあえず、普通に0,1,0でOKであろう。

// カメラ位置を設定
GLU.gluLookAt(gl, 0, 0, 3, 0, 0, 0, 0, 1, 0);

さて、どこで設定すればよいかというと、動画にすることをにらんで、固定ではあるが、onDrawFrameで設定してしまおう。

@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// カメラ位置を設定
GLU.gluLookAt(gl, 0, 0, 3, 0, 0, 0, 0, 1, 0);
// ライティングをON
gl.glEnable(GL10.GL_LIGHTING);
// 光源を有効にして位置を設定
gl.glEnable(GL10.GL_LIGHT0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightpos, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, red, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, blue, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, yellow, 0);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glPushMatrix();		// マトリックス記憶
//gl.glTranslatef(1, 0, -3);
gl.glTranslatef(1, 0, 0);
gl.glRotatef(angle, 0, 1, 0);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, gray, 0);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, gray, 0);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, gray, 0);
gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 80f);
gl.glShadeModel(GL10.GL_FLAT);
model.draw(gl);
gl.glPopMatrix();		// マトリックスを戻す
// ふたつめの描画
gl.glPushMatrix();		// マトリックス記憶
//gl.glTranslatef(-1, 0, -3);
gl.glTranslatef(-1, 0, 0);
gl.glRotatef(angle, 0, 1, 0);
gl.glCullFace(GL10.GL_BACK);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, gray, 0);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, gray, 0);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, gray, 0);
gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 80f);
// スムースシェーディング
gl.glShadeModel(GL10.GL_SMOOTH);
model.draw(gl);
gl.glPopMatrix();		// マトリックスを戻す
angle += 0.5;			// 回転角度は最後に計算
}

とここまでやって表示させてみたのではあるが、前回と何も変わっていない。
違いがわかるように、視点位置をずらしてみたのが、以下の動画である。

GLU.gluLookAt(gl, 2, 1, 2, 0, 0, 0, 0, 1, 0);


三角形がぐるぐる回っているが、これはモデルの方を回転させている。視点を移動させているわけではない。
タッチパネルのスライドで視点移動する例は以下。
Androidアプリ開発 OpenGL 視点をスクロール(スライド)で操作する
その前にデプステストを読んだ方がよいですよ。

投稿者プロフィール

asai
asai
システムエンジニア
喋れる言語:日本語、C言語、SQL、JavaScript