gluPerspectiveの概念図は上記のようになる.(画像はSource:unknownとして出回っている画像だが,公式赤本OpenGL Programming Guideが出展)
gluPerspective関数は,
- カメラの画角(fovy)
- 描画する最近の距離,描画する最遠の距離
- 画面のアスペクト比
のパラメータからなる.概念図の染められている領域が透視図法によって描画される.
/* 3DGraphicsWithPerspectiveProjection_1.c */
#ifdef __APPLE__
#include <OpenGL/opengl.h>
#include <OpenGL/glu.h> //gluというのが新しく追加されたよ
#include <GLUT/glut.h>
#else
#include <GL/gl.h>
#include <GL/glu.h> //gluというのが新しく追加されたよ
#include <GL/glut.h>
#endif
//あらかじめ描画する座標を2次元配列として作っておく
double myTriangle1[3][3] = {
{0.8, 0.1, 0.0},
{-0.3, -0.2, 0.0},
{0.4, -0.8, 0.0}};
double myTriangle2[3][3] = {
{0.5, 0.0, 0.0}, //Z座標は0とする
{-0.5, -0.3, 0.9},
{0.2, -0.4, 0.8}};
float cameraPosZ = 1.0;
void display(void){
//背景を塗りつぶす
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//隠面消去指定をする(ちゃんと後ろにあるものは隠れるようにする)
glEnable(GL_DEPTH_TEST);
//投影変換モードへ入る
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); //投影変換の変換行列を単位行列で初期化
//gluPerspective()を実行することで透視変換を指定する.
//引数はカメラの視野角(度数,ここでは120度),アスペクト比(ここでは4:3),
//見える範囲でカメラから一番近い距離,見える範囲でカメラから一番遠い距離,となる.
gluPerspective(120.0, 1.333333, 0.1, 1000000.0);
glMatrixMode(GL_MODELVIEW); //視野変換・モデリング変換モードへ
glLoadIdentity(); //視野変換・モデリング変換の変換行列を単位行列で初期化
//カメラの位置を指定
float cameraPosX = 0.0; //カメラの位置
float cameraPosY = 0.0;
//cameraPosZ はtimer関数によって随時更新されていく
float cameraCenterX = 0.0; //カメラが見る座標
float cameraCenterY = 0.0;
float cameraCenterZ = 0.0;
float cameraAngleX = 0.0; //カメラの位置とカメラが見る座標の線分上で
float cameraAngleY = 1.0; //カメラの「上」を定義する.
float cameraAngleZ = 0.0; //通常はYだけ1にしておけば良い
gluLookAt(cameraPosX, cameraPosY, cameraPosZ,
cameraCenterX, cameraCenterY, cameraCenterZ,
cameraAngleX, cameraAngleY, cameraAngleZ);
//------ここから下でモデル・オブジェクトの描画をする-----------------
glPushMatrix(); //ここからglPopMatrix()までひとまとまりとする.
//これから描く色を指定する(RGBA)
glColor4f(1.0, 0.0, 0.0, 0.0);
//Teapotを描画する.
glutSolidTeapot(0.5);
glPopMatrix();
glPushMatrix();//また新たにひとまとまりの描画を行う.
//これから描画するモデルは回転させますよ,という命令.
//引数は,回転する角度,残り三つが原点からそのポイントまでを回転軸とするx, y, z
glRotatef(60, 1.0, 1.0, 1.0);
//新たに線の色を指定する
glColor4f(0.0, 1.0, 0.0, 0.0);
//あらかじめ作っておいた頂点配列を描画する.
glBegin(GL_LINE_LOOP);
for(int i=0; i<3; i++){
glVertex3d(myTriangle1[i][0], myTriangle1[i][1], myTriangle1[i][2]);
}
glEnd();
glPopMatrix();
glPushMatrix();
//新たに色を指定する
glColor4f(0.0, 0.0, 1.0, 0.0);
//今度は塗りつぶす三角形
glBegin(GL_TRIANGLES);
for(int i=0; i<3; i++){
glVertex3d(myTriangle2[i][0], myTriangle2[i][1], myTriangle2[i][2]);
}
glEnd();
glPopMatrix();
//-----------モデルの描画ここまで-------------------
glutSwapBuffers();
}
void resize(int windowWidth, int windowHeight) {
glViewport(0, 0, windowWidth, windowHeight); //ウインドウ全体に表示
}
void timer(int value){
cameraPosZ += 0.01;
glutPostRedisplay();
glutTimerFunc(100, timer, 0);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640, 480);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
//GLUT_DEPTHを指定することで,Z軸が使える様になる.
glutCreateWindow("3DGraphicsWithPerspectiveProjection_1");
glutDisplayFunc(display);
glutReshapeFunc(resize); //関数resizeをコールバックに設定
//黒で塗りつぶす指定をする
glClearColor(0.0, 0.0, 0.0, 0.0);
glutTimerFunc(100, timer, 0);
//メインループ開始
glutMainLoop();
return 0;
}