OpenGLで立方体を表示する

スクリーンショット_070713_105440_AM

OpenGLで立方体を表示するプログラムを作成します。

まず以下の記事を参考にして、OnCreateとOnDestroyを記述します。

>>OpenGLの初期設定

視点の設定

そして、3Dの場合は見る視点を設定する必要があります。

この視点はウインドウのサイズにしたがって設定するので、OnSize関数に以下のように記述します。

void CTestView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: ここにメッセージ ハンドラー コードを追加します。
	CClientDC dc(this);

	::wglMakeCurrent(dc.GetSafeHdc(),m_hGLRC);

	::glViewport(0,0,cx,cy);

	::glMatrixMode(GL_MODELVIEW);
	::glLoadIdentity();
	::gluLookAt(2.5,2.5,2.5,0.0,0.0,0.0,0.0,1.0,0.0);

	::glMatrixMode(GL_PROJECTION);
	::glLoadIdentity();
	::gluPerspective(45.0,(double)cx/(double)cy,0.1,100.0);

	::wglMakeCurrent(NULL,NULL);
}

視点の設定の流れは以下のようになります。

  1. 視覚の大きさの設定
  2. カメラの位置と方向の設定
  3. 透視投影の設定

視覚の大きさの設定

OnSizeでは、はじめにglViewpointにより視覚の大きさの設定をしています。

void glViewport(GLint x,GLint y,GLsizei width,GLsizei height)

(x,y)でウインドウの左下の座標を設定します。

(width,height)でウインドウの幅と高さを設定しています。

カメラの位置の方向の設定

ウインドウの大きさが決まったら、カメラの位置や方向を設定します。

そこで用いる関数がgluLookAt関数です。

void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz)

とても引数が長いですが、基本的には3つのベクトル

  1. カメラの位置(eyex,eyey,eyez)
  2. 注視点(centerx,centery,centerz)
  3. 上方向(upx,upy,upz)

を設定しているだけです。カメラの位置はその名の通り、カメラの座標です。ゲームで言ったら主人公の位置を設定します。注視点は目線の位置です。カメラの位置から注視点の方向に視線が設定されます。最後の上方向は、カメラの上方向を設定します。たとえば、(0,0,1)と設定すれば、Z方向が上方向になります。別に、視線に対して垂直にする必要はありません。

透視投影の設定

ウインドウやカメラの位置と視線を設定しただけでは、

  1. ウインドウを視線上のどの位置に設定すればいいか
  2. どこまでを投影すればいいか

を設定する必要があります。これらの設定をするのがgluPerspectiveです。

void gluPerspective(GLdouble y,GLdouble aspect,GLdouble near,GLdouble far)

yは視野角です。角度で設定します。45なら視点から上下45度の範囲が見えるようになります。

aspectはアスペクト比でウインドウの幅を高さで割った値を設定します。これにより左右にどれくらいの範囲を見えるかを設定できます。

nearはカメラから視点方向に向けてどの距離にウインドウを置くかを設定します。

farはどの範囲までの物質を表示するかを設定します。

立方体の描写

立方体の描写はOnDrawに書きます。

コードは以下のようになります。

void CTestView::OnDraw(CDC* pDC)
{
	CTestDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: この場所にネイティブ データ用の描画コードを追加します。
	GLfloat vertices [8][3]=
	{
		{-0.5f,-0.5f,0.5f},
		{0.5f,-0.5f,0.5f},
		{0.5f,0.5f,0.5f},
		{-0.5f,0.5f,0.5f},
		{0.5f,-0.5f,-0.5f},
		{-0.5f,-0.5f,-0.5f},
		{-0.5f,0.5f,-0.5f},
		{0.5f,0.5f,-0.5f}
	};

	::wglMakeCurrent(pDC->GetSafeHdc(),m_hGLRC);

	::glEnable(GL_DEPTH_TEST);
	::glEnable(GL_CULL_FACE);

	::glClearColor(0.0f,0.0f,0.25f,1.0f);
	::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//色の設定
	::glColor3f(1.0f,1.0f,0.0f);

	//立方体の描写
	::glBegin(GL_POLYGON);
		::glVertex3fv(vertices[0]);
		::glVertex3fv(vertices[1]);
		::glVertex3fv(vertices[2]);
		::glVertex3fv(vertices[3]);
	::glEnd();

	::glBegin(GL_POLYGON);
		::glVertex3fv(vertices[4]);
		::glVertex3fv(vertices[5]);
		::glVertex3fv(vertices[6]);
		::glVertex3fv(vertices[7]);
	::glEnd();

	::glBegin(GL_POLYGON);
		::glVertex3fv(vertices[1]);
		::glVertex3fv(vertices[4]);
		::glVertex3fv(vertices[7]);
		::glVertex3fv(vertices[2]);
	::glEnd();

	::glBegin(GL_POLYGON);
		::glVertex3fv(vertices[5]);
		::glVertex3fv(vertices[0]);
		::glVertex3fv(vertices[3]);
		::glVertex3fv(vertices[6]);
	::glEnd();

	::glBegin(GL_POLYGON);
		::glVertex3fv(vertices[3]);
		::glVertex3fv(vertices[2]);
		::glVertex3fv(vertices[7]);
		::glVertex3fv(vertices[6]);
	::glEnd();

	::glBegin(GL_POLYGON);
		::glVertex3fv(vertices[1]);
		::glVertex3fv(vertices[0]);
		::glVertex3fv(vertices[5]);
		::glVertex3fv(vertices[4]);
	::glEnd();

	::glBegin(GL_POLYGON);
		::glVertex3fv(vertices[0]);
		::glVertex3fv(vertices[1]);
		::glVertex3fv(vertices[2]);
		::glVertex3fv(vertices[3]);
	::glEnd();

	::glBegin(GL_POLYGON);
		::glVertex3fv(vertices[0]);
		::glVertex3fv(vertices[1]);
		::glVertex3fv(vertices[2]);
		::glVertex3fv(vertices[3]);
	::glEnd();

	::wglMakeCurrent(NULL,NULL);

}

画面をクリアする

はじめに

::glEnable(GL_DEPTH_TEST);

::glEnable(GL_CULL_FACE);

により「zバッファ法」による「陰面消去」と「背面消去」を有効にします。そして、

::glClearColor(0.0f,0.0f,0.25f,1.0f);

で画面をクリアする色を設定して

::glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

で画面をクリアします。

 

立方体をかく

あとはglBegin(GL_POLYGON)で面を描写します。

今回は四角形の面を描写するのでglVertex3fvで頂点を設定しています。

頂点の設定は

  • glVertex3f(GLfloat x,GLfloat y,GLfloat z);
  • glVertex3fv(GLfloat* vertex);

で行います。glVertex3fは一点ごと指定して、glVertex3fvは3点を一度に配列で設定します。

今回は配列で頂点の位置を設定しています。

実行結果

プログラムを実行すると以下のようになります。

スクリーンショット_070713_105440_AM

今回の場合は面で設定した色がそのまま表示されているので、すべて黄色になっています。

光の散乱を設定すれば3次元ぽく見えるようになります。

それについてはまた説明します。

著者:安井 真人(やすい まさと)