前回はOpenGLを動作させるためのソースを記述しました。
今回は書いたソースについて解説していきます。
まずはMainActivityから見て行きましょう。
package com.example.opengl_test;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
private MyGLView myGLView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myGLView = new MyGLView(this);
setContentView(myGLView);
}
@Override
protected void onResume() {
super.onResume();
myGLView.onResume();
}
@Override
protected void onPause() {
super.onPause();
myGLView.onPause();
}
}
AndroidアプリはこのMainActivityから始まるため、このソースは詳細な意味を覚えるよりこういうお作法とおぼえておいたほうがいいです。
そして上で強調した行はActivityからOpenGL表示用のビューを呼び出しています。
次にMyGLViewを見てみましょう。
package com.example.opengl_test;
import android.content.Context;
import android.opengl.GLSurfaceView;
public class MyGLView extends GLSurfaceView {
private MyRenderer myRenderer;
public MyGLView(Context context) {
super(context);
myRenderer = new MyRenderer();
setRenderer(myRenderer);
}
}
ここではビューにOpenGL描画用のレンダーを登録しています。
次にMyRendererを見てみましょう。
package com.example.opengl_test;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;
public class MyRenderer implements Renderer {
MyCube cube = new MyCube();
@Override
public void onDrawFrame(GL10 arg0) {
// 背景色を設定
arg0.glClearColor(0, 0, 1, 1.0f);
arg0.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
arg0.glMatrixMode(GL10.GL_MODELVIEW);
arg0.glLoadIdentity();
arg0.glTranslatef(0, 0, -3f);
arg0.glRotatef(30f, 0, 1, 0);
arg0.glRotatef(30f, 1, 0, 0);
cube.draw(arg0);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45f, (float) width / height, 1f, 50f);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
gl.glDepthFunc(GL10.GL_LEQUAL);
}
}
ここでは3つのメソッドが登場します。
上から順番に見て行きましょう。
まず一番上で登場するonDrawFrameメソッドはアプリの描画の際に繰り返し呼ばれます。
ですので描画処理は基本的にはこちらで行うことになります。
次にonSurfaceChangedメソッドについてですが、こちらは主に画面の向きが縦から横へ、
またはその逆に切り替わった時に呼ばれます。
そのため基本的な画面設定はこちらに書きます。
最後にonSurfaceCreatedメソッドについてなのですが、こちらはレンダークラスの初期化時に呼ばれます。
ではメソッドの中身を一つづつ見て行きましょう。
まずは初期化時に呼ばれるonSurfaceCreated之中身についてですが、ここでは主に描画の設定を行っています。
まず上から3つのglEnableメソッドについては3Dの描画を行う上での機能を有効化しています。
GL_DEPTH_TESTは名前の通りデプステストを、GL_LIGHTINGは光源のライティングを、GL_LIGHT0は使う光源の番号を設定しその高原を有効化しています。
最後のglDepthFuncについては深度値と深度バッファの震度を比較する関数の指定を行っています。
今回指定しているGL_LEQUALは入って来る深度値が格納された深度値以下である時に通過を設定しています。
次にonSurfaceChangedを見ていきます。
ここでは画面の設定を行っています。
まず画面の範囲を指定します。
その後画面のパースペクティブを登録し、どの端末でも同じように描画できるよう設定します。
最後にonDrawFrameを見ていきます。
まず最初の2行について見てみます。
こちらは背景色を設定しています。
次の3行についてですが、ここでは実際に指定した座標にものを描画するという設定と描画するものの移動を行っています。
次の2行は3Dオブジェクトの回転を行っています。
3Dでは行列を使って描画する物体の移動や回転を行います。
行列については詳しくは高校数学を参照してみてください。
またゲームプログラムのための3Dの書籍に乗っているのでそちらを参考にしてみください。
最後の1行については、ここで画面に四角描画しています。
でわ最後のソースの四角の描画について見てみましょう。
package com.example.opengl_test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class MyCube {
private final FloatBuffer mVertexBuffer;
public MyCube() {
float vertices[] = {
// 前
-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,
// 左
-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,
// 上
-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 };
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer = vbb.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
// Front
gl.glNormal3f(0, 0, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
// Back
gl.glNormal3f(0, 0, -1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
// Left
gl.glNormal3f(-1.0f, 0, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
// Right
gl.glNormal3f(1.0f, 0, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
// Top
gl.glNormal3f(0, 1.0f, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
// Right
gl.glNormal3f(0, -1.0f, 0);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
}
}
まずコンストラクタから見て行きましょう。
ここでは3Dの描画の座標を設定しています。
3Dは基本的にはすべて三角形で描画されます。
このことを考慮した上でソースを見て行きましょう。
3Dでは座標は(x,y,z)の3つの位置情報を指定します。
今回のソースでは四点ごとに分けてあります。
それぞれ四角形の四頂点を指定しています。
またOpenGLでは頂点情報をバッファクラスに詰めて使用します。
次はdrawメソッドを見て行きましょう
ここでは実際に頂点情報を使用して四角形を順番に描画しています。
最初の一行目では頂点配列を描画するという設定を行い、
次の一行で設定した頂点情報を渡します。
その後各四角形を描画します。
四角形を描画する二行一組については以下の様な設定を行います。
glNormal3fメソッドは光を反射する方向を指定しています。
次のglDrawArraysメソッドは頂点情報を使用して三角形を二枚描画します。
描画まず頂点情報のはじめの3つの頂点を使用し三角形を一枚描画します。
その後2番目、3番目、4番目を使用してい一枚描画します。
こうして4つの頂点情報で四角形を一枚描画ができます。
このようにして3Dの正方形が描画できます。
今回はAndroidでのOpenGLの描画の内容について説明してきました。
今後はこれらを利用してゲームの作り方的なものをかけていけたらと思いますの。
今回は、ここまで!