本書サポートページの目次へ戻る
このサイトの目次へ戻る
「図形オブジェクト」のスーパークラス「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)のような複数の図形を表示させる記述がぐっと簡単になりました。
このサイトの目次へ戻る