ビジネス向けのアプリケーションでは
余り使われる事が無い3Dグラフィックスですが、
使いこなすことが出来れば、面白い技術なのではないでしょうか。
余り使われる事が無い3Dグラフィックスですが、
使いこなすことが出来れば、面白い技術なのではないでしょうか。
3Dプログラミングの概念などはちょっと置いておいて、
「Androidで3Dを描画するには最低限何を書けばいいの?」
という所に着目して、説明をしたいと思います。
「Androidで3Dを描画するには最低限何を書けばいいの?」
という所に着目して、説明をしたいと思います。
新規Androidプロジェクトを作成したと仮定します。
その後、必要なクラスファイルは以下の三つだけです。
その後、必要なクラスファイルは以下の三つだけです。
・MainActivity.java
・TriangleRenderer.java
・Triangle.java
・TriangleRenderer.java
・Triangle.java
Eclipseで作成するとこんな感じになります。
パッケージ分けはやらなくても全然OKです。
パッケージ分けはやらなくても全然OKです。
早速、コードにいってみましょう。
MainActivity.java
- public class MainActivity extends Activity {
- private GLSurfaceView mGLSurfaceView;
- private TriangleRenderer tr = null;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //GLSurfaceViewを取得
- mGLSurfaceView = new GLSurfaceView(this);
- // Rendererを作成
- tr = new TriangleRenderer();
- //GLSurfaceViewにRendererを設定
- mGLSurfaceView.setRenderer(tr);
- setContentView(mGLSurfaceView);
- }
- @Override
- protected void onResume() {
- super.onResume();
- mGLSurfaceView.onResume();
- }
- @Override
- protected void onPause() {
- super.onPause();
- mGLSurfaceView.onPause();
- }
- }
TriangleRenderer.java
- public class TriangleRenderer implements GLSurfaceView.Renderer {
- private Triangle mTriangle;
- private int size = 0x10000;
- public TriangleRenderer() {
- mTriangle = new Triangle(0 , size);
- }
- public void onDrawFrame(GL10 gl) {
- //画面をクリア
- gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
- // モデルビューの行列を用いて作業する事を指定する。
- gl.glMatrixMode(GL10.GL_MODELVIEW);
- gl.glLoadIdentity(); // 現在選択されている行列に単位行列をロードする。
- //移動(初期カメラ位置
- gl.glTranslatef(0, 0, -3.0f);
- //頂点アレイを設定
- gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- //カラーアレイを設定
- gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
- //カリングの設定
- gl.glFrontFace(GL10.GL_CW);
- //三角形を描画
- mTriangle.draw(gl);
- }
- /**
- * OpenGLの透視投影の描画領域が変更された時の設定
- */
- @Override
- public void onSurfaceChanged(GL10 gl, int width, int height) {
- /**
- * OpenGLが表示に使う長方形領域を設定します。
- * (x,y)が表示領域の左上の座標、(w,h)が表示領域の幅と高さになります。
- */
- gl.glViewport(0, 0, width, height);
- // 透視投影(遠近投影法)の行列を指定する。
- float ratio = (float) width / height;
- gl.glMatrixMode(GL10.GL_PROJECTION);
- // 現在選択されている行列に単位行列をロードする。
- gl.glLoadIdentity();
- /**
- * ビューボリューム(視体積)を指定します。
- * 引数は視体積の左、右、下、上、近クリップ面、遠クリップ面の座標を定義
- */
- gl.glFrustumf(-ratio, ratio, -1, 1, 1, 100);
- }
- /**
- * OpenGLの初期設定
- */
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- /**
- * DITHERをオフにします。
- * DITHERとは量子化の誤差を最小にするべく
- * サンプルデータに意図的に追加される誤った信号・データのこと。
- */
- gl.glDisable(GL10.GL_DITHER);
- // OpenGLにスムージングを設定
- gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
- // 背景色
- gl.glClearColor(1,1,1,1);
- //スムースシェーディング:平面のポリゴンを曲面に見せかける処理。
- gl.glShadeModel(GL10.GL_SMOOTH);
- /**
- * 多角形に影を付けるには、各多角形の前後関係を決定する必要がある。
- * これをするのが、デプステストです。
- * このデプステストを有効にします。
- */
- gl.glEnable(GL10.GL_DEPTH_TEST);
- }
- }
Triangle.java
- public class Triangle {
- private IntBuffer mVertexBuffer;
- private IntBuffer mColorBuffer;
- private ByteBuffer mIndexBuffer;
- public Triangle(int p , int size){
- int one = 0x10000;
- //座標リスト
- int vertices[] = {
- p - size , p , p + size, // 左下
- p + size , p , p + size, // 右下
- p , p + size , p , // 上
- };
- //頂点色
- int colors[] = {
- 0 , 0, 0, one,
- 0 , 0, 0, one,
- 0 , 0, 0, one,
- };
- //頂点の描画順インデックス
- byte indices[] = {
- 0, 1, 2,
- };
- //バイトバッファにそれぞれのリストを登録
- ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
- vbb.order(ByteOrder.nativeOrder());
- mVertexBuffer = vbb.asIntBuffer();
- mVertexBuffer.put(vertices);
- mVertexBuffer.position(0);
- ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
- cbb.order(ByteOrder.nativeOrder());
- mColorBuffer = cbb.asIntBuffer();
- mColorBuffer.put(colors);
- mColorBuffer.position(0);
- mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
- mIndexBuffer.put(indices);
- mIndexBuffer.position(0);
- }
- //描画
- public void draw(GL10 gl){
- gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
- gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
- gl.glDrawElements(GL10.GL_TRIANGLES, 3, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
- }
- }
これだけでもう3Dが出来ています。
早速実行してみましょう。
早速実行してみましょう。
期待通りに黒い三角形が描画されていますね。
さて、何故このような黒い三角形が描けたのか?
解説していきます。
解説していきます。
まず注目すべきは、Triangle.javaです。
Triangle.javaのこの部分で頂点と色を決めています。
(分かりやすいように修正しています。)
Triangle.javaのこの部分で頂点と色を決めています。
(分かりやすいように修正しています。)
- 引数p = 0 , size = 0x10000;
- //座標リスト
- int vertices[] = {
- -size , 0 , size, // 左下
- size , 0 , size, // 右下
- 0 , size , 0 , // 上
- };
- //頂点色
- int colors[] = {
- 0 , 0, 0, one,
- 0 , 0, 0, one,
- 0 , 0, 0, one,
- };
int vertices[]が頂点です。
三次元の頂点は(x軸 , y軸 , z軸)の三つの点で指定します。
よって、
三次元の頂点は(x軸 , y軸 , z軸)の三つの点で指定します。
よって、
- int vertices[] = {
- // (左下x座標 , 左下y座標 , 左下z座標)
- -size , 0 , size,
- // (右下x座標 , 右下y座標 , 右下z座標)
- size , 0 , size,
- // (上x座標 , 上y座標 , 上z座標)
- 0 , size , 0 ,
- }
ただのint型の配列ですが、実はこのような意味があります。
こうして見ると分かりやすいのですが、実は上の点は
奥に傾いているため、45度斜めに描画されています。
こうして見ると分かりやすいのですが、実は上の点は
奥に傾いているため、45度斜めに描画されています。
色も同様です。が、RGBAのため、最後にalpha値を指定するため、
配列4つで一点になります。
配列4つで一点になります。
- //頂点色
- int colors[] = {
- // (左下Red , 左下Green , 左下Blue , 左下Alpha)
- 0 , 0, 0, one,
- // (右下Red , 右下Green , 右下Blue , 右下Alpha)
- 0 , 0, 0, one,
- // (上Red , 上Green , 上Blue , 上Alpha)
- 0 , 0, 0, one,
- };
このようになります。試しに
上部だけ真っ赤にしてみましょう
上部だけ真っ赤にしてみましょう
- //頂点色
- int colors[] = {
- // (左下Red , 左下Green , 左下Blue , 左下Alpha)
- 0 , 0, 0, one,
- // (右下Red , 右下Green , 右下Blue , 右下Alpha)
- 0 , 0, 0, one,
- // (上Red , 上Green , 上Blue , 上Alpha)
- one , 0, 0, one,
- };
これで上だけ赤になるはずです。
実行してみましょう。
実行してみましょう。
おお、赤くなってますね。
期待通りです。
期待通りです。
では、次に3Dであることを
認識するためにこの三角形をグルグルと
回してみましょう。
今度はTriangleRenderer.javaを編集します。
といってもすることは少ないです。
認識するためにこの三角形をグルグルと
回してみましょう。
今度はTriangleRenderer.javaを編集します。
といってもすることは少ないです。
TriangleRenderer.java
- float mView = 0.0f; ←追加
- public void onDrawFrame(GL10 gl) {
- //画面をクリア
- gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
- // モデルビューの行列を用いて作業する事を指定する。
- gl.glMatrixMode(GL10.GL_MODELVIEW);
- gl.glLoadIdentity(); // 現在選択されている行列に単位行列をロードする。
- //移動(初期カメラ位置
- gl.glTranslatef(0, 0, -3.0f);
- //頂点アレイを設定
- gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- //カラーアレイを設定
- gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
- //gl.glRotatef(mView , 0, 1, 0); //横回転 ←追加
- //gl.glRotatef(mView , 1, 0, 0); //縦回転 ←追加
- //カリングの設定
- gl.glFrontFace(GL10.GL_CW);
- //三角形を描画
- mTriangle.draw(gl);
- mView += 1.2f; ←追加
- }
回転はコメントアウトしてあるので、片方ずつ外して
動作を確かめてみてください。
もちろん、同時に動かすのもアリだと思います。
動作を確かめてみてください。
もちろん、同時に動かすのもアリだと思います。
これで凄くザックリですが説明を終わります。
本当はまだまだ解説し足りません。
もし、これで3Dに興味を持った方は、
OpenGLについて調べてみては如何でしょうか?
本当はまだまだ解説し足りません。
もし、これで3Dに興味を持った方は、
OpenGLについて調べてみては如何でしょうか?
このプログラムを元に、
複数の三角形を書いてみたり、
三角形から四角形に変えてみたりしてみてください。
回転操作をフリック化してみたりするのもいいですね。
複数の三角形を書いてみたり、
三角形から四角形に変えてみたりしてみてください。
回転操作をフリック化してみたりするのもいいですね。
0 件のコメント:
コメントを投稿