強火で進め

このブログではプログラム関連の記事を中心に書いてます。

(Mac・iPhone)頂点配列を使った三角形の描画

OpenGLでは前回行った様な glBegin() 〜 glEnd() での描画方法の他に頂点配列を使った描画方法があります。

なお、iPhone(OpenGL ES)では glBegin() 〜 glEnd() 形式の描画は対応していません、今回紹介する頂点配列で描画する必要が有ります。

Macで頂点配列を使った三角形の描画

ソースコードこちらです。こちらを表示しながら読み進めて下さい。

頂点配列はその名前の通り、「頂点情報を持った配列を指定して描画」します。前回のこの頂点情報は

glBegin(GL_TRIANGLES);
{
glVertex3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
}

この様に置き換わります。データは「X、Y、Z座標」、「X、Y、Z座標」と順番に指定します。

const GLfloat triangleVertices[] = {
0.0, 1.0, 0.0,
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
};

次に glVertexPointer() コマンドで頂点配列のポインタを指定します。
引数は先頭から順番に

  • 使用する頂点数(2の場合はX,Y座標、3の場合はX,Y,Z座標を配列で準備します)
  • データの型
  • オフセット(配列のどの部分から使用するかを指定)
  • 実際に頂点情報を格納した配列へのポインタ

glVertexPointer(3, GL_FLOAT, 0, triangleVertices);

頂点配列の使用はデフォルトでは無効になっているので以下のコマンドで有効にします。

glEnableClientState(GL_VERTEX_ARRAY);

実際のレンダリングは glDrawArrays() コマンドで行います。
引数は先頭から順番に

  • プリミティブの種類。glBeing() コマンドで指定するものと同様の値。GL_TRIANGLES、GL_TRIANGLE_FANなど
  • glVertexPointer() で指定した配列のどの位置から使用するかを指定。0の場合、先頭から使用する。
  • 上記、指定位置からいくつ使用するかを指定。ここでは3を指定しているのですべてのデータを使用します。

glDrawArrays(GL_TRIANGLES, 0, 3);

iPhoneで頂点配列を使った三角形の描画

先に説明した様にiPhoneでは glBegin() 〜 glEnd() の形式での描画はできません。そのためiPhoneのサンプルはここからはじまります。

ソースコードこちらです。こちらを表示しながら読み進めて下さい。

まず、iPhoneOpenGL ESを使用する場合は「iPhone OS」グループ内の「Application」-「OpenGL ES Application」を選択します。

こちらのテンプレートを使った場合、OpenGL ES関連のフレームワークなどは既に追加された状態プロジェクトが生成されます。

そのためMacのときに行ったようなフレームワークの追加を行う必要ありません。

逆に生成時には既に「四角形が回転するプログラム」として生成されているため少々、プログラムに修正を行い、合わせて「三角形の描画」変更を行います。

具体的な修正部分はとしては「1回しかしなくてい良い処理が何度も呼ばれている部分の修正」となります。

(1) EAGLView.h の以下の部分の下に

    NSTimeInterval animationInterval;

以下の初期化フラグ用の変数を追加します。このフラグにより一度しか呼ばなくて良い処理が何度も呼ばれるのを防ぎます。

    NSTimeInterval animationInterval;
	
    BOOL initFlag;

また、セットアップ処理を別のメソッドに分離するので setupView の宣言を以下の位置に追加します。

- (void)startAnimation;
- (void)stopAnimation;
- (void)setupView;
- (void)drawView;

(2) EAGLView.m の initWithCoder:coder の上、辺りに init を追加し、フラグをNOとします。

- (id)init {
    if ((self = [super init])) {
		initFlag = NO;
    }
	return self;
}

//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder {

(3) drawView から初期化処理を分離し、 setupView に記述します。

- (void)setupView {
    glViewport(0, 0, backingWidth, backingHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);
	
	// クリア色の設定
    glClearColor(0.0f, 0.0f, 0.0f, 1.0);
	// 頂点配列の設定
    glVertexPointer(3, GL_FLOAT, 0, triangleVertices);
	// 頂点配列の有効化
    glEnableClientState(GL_VERTEX_ARRAY);
}

- (void)drawView {
    [EAGLContext setCurrentContext:context];
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

	if(!initFlag) {
		[self setupView];
		initFlag = YES;
	}

    glClear(GL_COLOR_BUFFER_BIT);
    
    glDrawArrays(GL_TRIANGLES, 0, 3);
    
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

ところどころiPhoneOpenGL ES特有の記述もありますがメインの描画部分に関してMac向けOpenGLと同様の記述ができることが確認できるかと思います。

iPhoneの場合、Macの画面に比べて縦長であるため上部に多少空間があります。

iPhone3Dプログラミング講座の一覧はこちら