本書サポートページの目次へ戻る
このサイトの目次へ戻る

「図形オブジェクト」のスーパークラス「MyShape」を作る:「OpenGL ESではじめる3D-CGプログラミング」関連情報

このページは、工学社刊/清水美樹著「「OpenGL ESではじめる3D-CGプログラミング」」( ISBN978-4-7775-1770-1)の付加情報です。正確な情報は、工学社開設のサポートページを御参照ください。


第8章で省略した内容

本書第8章では、三角形を表すクラス「MyTriangle」、四角形を表すクラス「MySquare」、レンダラークラス「MyOpenGLESRenderer」から切り離す作業を解説しました。
これだけで結構大変だったので、「MyTriangle」「MySquare」各クラスを洗練するところまではしませんでした。両者は、重複事項のたくさんある非効率なクラスのままで扱いました。

これをもっと洗練する例を示します。 「MyTriangle」と「MySquare」から共通部分を抜き出して、スーパークラス「MyShape」を作成します。すると、「MyTriangle」と「MySquare」は、ほぼ座標の配列だけを記述すればよいことになります。

クラスMyShape>

クラスMySquareの内容がほとんど

 クラスMyShapeの内容は、ほぼ第8-5節(150p)で解説したクラスMySquareの内容と同じです。といいましても、クラスMySquareは第8-2節で解説したクラスMyTriangleの内容を元にしていますから、ゼロから作成するのはなかなか面倒だと思います。
工学社サポートページからダウンロードできるサンプルのうち、「gles-sample/chap8-3」フォルダに入っている「MySquare.java」をもとにしてください。

「chap8-3」フォルダの「MySquare.java」と「MyShape」の違う所

 まずクラス名の宣言が「MyShape」になります。それに伴い、コンストラクタの名前もMyShape()になります。
 さらに、このコンストラクタは引数を二つ取ります。本書を通じて使われている配列「mVertexData」及び、その書き順を表す配列「mDrawOrder」にそれぞれ該当する配列です。換言すれば、これらのみがクラスMySquare及びMyTriangle に記述すべき情報になります。

 そのため、クラスMyShapeには、本書を通じて使っていたメンバー変数mVertexData, mDrawOrderは要らなくなるはずです。  しかし、クラスMyShapeに書くべきメソッドglDrawElements(第5-1節のリスト5-7(87ページ))が、メンバー変数mDrawOrderから「mDrawOrder.length」を得なければなりません。
 そこで、「配列の長さ」である「mDrawOrder.length」そのものをメンバー変数mDrawOrderLengthにします。

クラスMyShapeのコンストラクタで変更する箇所

 以上、クラスMyShapeのコンストラクタで、本書サンプルのMySquareと異なる点は以下の部分、とくに太字の部分です。
リスト1 クラスMyShapeのコンストラクタ
public MyShape(float[] vertexData, short[] drawOrder){
	mVertexBuffer = allocateFloatBuffer(vertexData.length);
	mVertexBuffer.put(vertexData).position(0);
		
	mDrawOrderBuffer = allocateShortBuffer(drawOrder.length);
    mDrawOrderBuffer.put(drawOrder).position(0);
    mDrawOrderLength=drawOrder.length;

	....あとは「gles-sample/chap8-3」の「MySquare.java」の内容と同じ

また、メソッドdraw中に書かれるglDrawElementsの引数には、新しく作ったメンバー変数mDrawOrderLengthを用います。
リスト2 クラスMyShapeのメソッドdraw中のglDrawElements
GLES20.glDrawElements(
				GLES20.GL_TRIANGLES,
				mDrawOrderLength,
				GLES20.GL_UNSIGNED_SHORT,
				mDrawOrderBuffer
		);


他は、本書で示した大量の記述が、全部「MyShape」にそのまま書かれます。

図形クラス

クラスMySquare

以上のように、図形クラスの記述のほとんどをMyShapeクラスに置いたので、これを継承するMySquareクラスは、たったこれだけになります。
パッケージ宣言だけは省略してありますので、みなさんのパッケージ名を記入してください。
なんと、インポート宣言はありません。
リスト3 クラスMySquareの全文(インポート宣言は省略)
public class MySquare extends MyShape {
	
	public MySquare(){

		super(
				new float[]{ 
					-0.6f, 0.6f, 0.0f, 0.0f, 0.6f, 0.6f, 1.0f, 
					-0.6f, -0.6f, 0.0f, 0.0f, 0.6f, 0.6f, 1.0f, 
					0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 
					0.6f, 0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f
			    }, 	//mVertexDataに相当する配列。1番目の引数。
			    new short[]{0, 1, 2, 0, 2, 3} //mDrawOrderに相当する配列。2番目の引数。
		);
	}
}


リスト3では、スーパークラスであるMyShapeのコンストラクタ(リスト1)が取る二つの引数を、MySquareのコンストラクタ中の、それもスーパークラスのコンストラクタの引数を指定する場所で、「その場で作成」して入れています。
どこかで変数名を与えておいて、引数には変数名で与えればいいのに、と思うかも知れませんが、コンストラクタの規則上できません。それは、MySquareのコンストラクタ自体は引数を取っていないからです。


クラスMyTriangle

平面の三角形がひとつだけのクラスMyTriangleについては、本書中ではずっと簡単なglDrawArraysを描画メソッドに用いてきました。しかし、MySquareとスーパークラスを共有することにしたので、こちらもクラスMyShapeに定義したglDrawElementsにデータを渡したほうがむしろ便利になります。
三角形を描くのにメソッドglDrawElementsを用いるには、素直に書き順を「0, 1, 2」にするのみです。
リスト4 クラスTriangleの全文(インポート宣言は省略)
public class MyTriangle extends MyShape {

	public MyTriangle(){
		super(
				new float[]{ 
				0.0f,  0.52f, 0.0f, 1.0f, 0.2f, 0.2f, 1.0f, 
				   -0.6f, -0.52f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 
					0.6f, -0.52f, 0.0f, 1.0f, 0.5f, 0.0f, 1.0f 
			    }, 
			    new short[]{0,1,2} //素直に書き順を示す
		);
	}
}



「レンダラークラス」の記述は変わらない

なお、「MyGLESRenderer.java」も、同じ「chap8-3」に入っているものを使用してください。こちらは変更することなくそのまま使えます。第8章で、苦労して図形クラスとレンダラークラスを分離した甲斐がありました。

これで、図8-5(152p)のような複数の図形を表示させる記述がぐっと簡単になりました。
このサイトの目次へ戻る