読者です 読者をやめる 読者になる 読者になる

Android 1.6 + OpenGL ES 1.0に触れてみた。

Android OpenGL

社長に「お前は3Dやゲームプログラミング(グラフィック周り)もわからんのか!だからお前はアホなのだぁぁぁ!(意訳」とよく言われるので、ちったあOpenGL ESでも触ってみようかと思って本を買ってきた。

OpenGL ES 2.0 プログラミングガイド
Aaftab Munshi Dan Ginsburg Dave Shreiner アフタブ・ムンシ ダン・ギンズバーグ デーブ・シュライナー
ピアソンエデュケーション
売り上げランキング: 10311
おすすめ度の平均: 5.0
5 お勧めです

国内で発売されているAndroid端末が基本的に1.6なので、OpenGL ES 2.0ではなく1.0なんだけど、まぁ動かないものはググればいいかなぁということで。

とりあえず巻末の付録FにAndroid用のサンプルコードが掲載されていたので写経してみた。

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.MotionEvent;

public class HelloActivity extends Activity {
    private GLSurfaceView mView;
    private MyRenderer mRenderer;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mView = new GLSurfaceView(this);
        mRenderer = new MyRenderer();
        mView.setRenderer(mRenderer);
        setContentView(mView);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        mView.onPause();
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        mView.onResume();
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // タップすると表示色をトグルする
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            mView.queueEvent(new Runnable() {
                @Override
                public void run() {
                    mRenderer.toggleColor();
                }
            });
        }  
        return true;
    }

    private class MyRenderer implements GLSurfaceView.Renderer {
        private FloatBuffer mQuad;
        private boolean mColorRed = true;
        private boolean mLastColorRed = false;
        
        public MyRenderer() {
            float[] vertices = {
                -0.5f, -0.5f, 0.0f,
                 0.5f, -0.5f, 0.0f,
                -0.5f,  0.5f, 0.0f,
                 0.5f,  0.5f, 0.0f
            };
            
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length*4);
            byteBuffer.order(ByteOrder.nativeOrder());
            
            mQuad = byteBuffer.asFloatBuffer();
            mQuad.put(vertices);
            mQuad.position(0);
        }
        
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            GLU.gluOrtho2D(gl, -1.0f, 1.0f, -1.0f, 1.0f);
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            if (width > height) // ランドスケープ
                gl.glViewport((width - height) / 2, 0, height, height);
            else                // ポートレート
                gl.glViewport(0, (height - width) / 2, width, width);
        }

        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
            
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
            
            // 3.6秒で1回転
            gl.glRotatef((SystemClock.uptimeMillis() % 3600) * 0.1f, 0, 0, 1.0f);
            
            if (mColorRed != mLastColorRed) {
                if (mColorRed)
                    gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // 赤
                else
                    gl.glColor4f(0.0f, 1.0f, 0.0f, 1.0f); // 緑
                mLastColorRed = mColorRed;
            }
            
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mQuad);
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        }

        public void toggleColor() {
            mColorRed = ! mColorRed;
        }
    }
}

動かすとこんなんが表示される。
f:id:terurou:20100719185837p:image