Androidアプリでテクスチャの読み込みをする際にリソースの取得ができない

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
TOMY

Androidアプリでテクスチャの読み込みをする際にリソースの取得ができない

#1

投稿記事 by TOMY » 13年前

現在AndroidアプリでOpenGLESを使ったゲームを作るために
”初めてのOpenGL ES”という本を参考に勉強用のプログラムを組んでいます。
サンプルプログラムを見ながら組んでいき、テクスチャの読み込みに関する部分まで来た時に
テクスチャを読むときに必要なリソースの部分で詰まってしまいした。
Bitmap部分のgetResources()というメソッドなのですがいろいろ試してもうまくいきません。
import してもダメ。extendsとかで継承しても強制終了するか何も表示されないかのどちらかです。
javaやAndroidについてはそこまで詳しくないので手探りで進めています。
おそらく初歩的なミスではありそうですが解決につながるご助言がありましたらどうかお願いします。

以下自作プログラム

コード:

package jp.tomi.MyOpenGL_ES;
//-----------------------------------------------------------------
//OpenGL_ESを使うための下準備をここでする。あとActivityとか
//よく分からずに組んでいる部分もちらほらあります		
//-----------------------------------------------------------------
import java.nio.FloatBuffer;

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.content.*;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Bitmap.Config;
import android.graphics.Paint.Style;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.util.Log;


public class MyOpenGL_ES_BaseActivity extends Activity {

	//描画対象View
	private GLSurfaceView glSurfaceView = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        glSurfaceView = new GLSurfaceView(this);
        glSurfaceView.setRenderer(new GLRendearSurface());
        setContentView(glSurfaceView);
    }

    //Activity休止時の処理
    @Override
    protected void onPause(){
    	super.onPause();
    	glSurfaceView.onPause();
    }

    //Activity復帰時の処理
    @Override
    protected void onResume(){
    	super.onResume();
    	glSurfaceView.onResume();
    }
}





//extends 継承      implements プロトタイプ宣言みたいなもの(実装)
class GLRendearSurface  implements GLSurfaceView.Renderer {
	private int screenWidth,screenHeight;		//スクリーンサイズ
    private int textureName;					//OpenGLから割り当てられたテクスチャ名
    private int textureWidth, textureHeight;	//テクスチャサイズ

   public void log(String message) {			//ログの出力
       Log.i("GLES_SAMPLE", message);
   }
	//サーフェイス作成時の処理
	@Override
	public void onSurfaceCreated(GL10 gl10, EGLConfig eglconfing){
//		Toast.makeText(MyOpenGL_ES_BaseActivity.this,"massage",Toast.LENGTH_LONG).show();
	}

	//画面上のどの領域を使用するかの設定、あとポリゴン色とかの設定
	@Override
	public void onSurfaceChanged(GL10 gl10, int w,int h ){
		gl10.glViewport(0, 0, w, h);
		screenWidth = w;
		screenHeight= h;

		//テクスチャに関する処理---------------------------------------
		Bitmap bitmap =	BitmapFactory.decodeResource(getResources(), R.drawable.image_512);

        log("bitmap size : " + bitmap.getWidth() + " x " + bitmap.getHeight());
		gl10.glEnable(GL10.GL_TEXTURE_2D);
		int[] buffers = new int[1];
		//texture夜のメモリを指定数確保
		gl10.glGenTextures(1,buffers,0);
		//テクスチャ名を保存する
		textureName = buffers[0];

		gl10.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

		//拡大縮小時の処理を指定
		gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
		gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

		//ビットマップを廃棄
		bitmap.recycle();

	}

	private void drawQuad(GL10 gl10, int x, int y, int w, int h){
		float left =((float) x / (float) screenWidth)* 2.0f - 1.0f;
		float top  =((float) y / (float) screenHeight) * 2.0f - 1.0f;

		float right = left + ((float) w/ (float) screenWidth) * 2.0f;
		float bottom =top + ((float) h / (float) screenHeight) * 2.0f;

		//上下を反転させる
		top = -top;
		bottom = -bottom;

		//位置情報テスト----------------------------------
		float positions[] = {			//x,y,zの順に定義
				left,top,0,					//左上
				left,bottom,0,					//左下
				right,bottom,0,					//右上
				right,top,0,
		};

		//OpenGLはビッグエンディアンではなく
		//CPUごとの”ネイティブエンディアン”で数値を伝える必要がある。
		//その為Javaヒープを直接的には扱えず、
		//”Java.nio”配下のクラスへ一度値を格納する必要がある。(面倒くせぇ)
		ByteBuffer bb=ByteBuffer.allocateDirect(positions.length * 4);  //GL_ESが扱えるのはallocateDirectで確保した領域のみ
		bb.order(ByteOrder.nativeOrder());		//実行環境に合わせて最適な値を指定できるようにnativeOrderを使う
		FloatBuffer fb = bb.asFloatBuffer();	//確保したバッファをfloatに格納(新たにメモリを確保しているわけではない)
		fb.put(positions);						//バッファをfloat配列に転送(この時点でエンディアンに関する変換はもう終わっている)
		fb.position(0);							//putすると書き込み位置が一つ進められるのでpositionで最初に戻す

		gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);	//頂点バッファの成分を切り替えている(ここでは有効化)
		gl10.glVertexPointer(3,GL10.GL_FLOAT,0,fb);		//OpenGL ESに頂点バッファを関連付ける(コピーではないことに注意)
		gl10.glDrawArrays(GL10.GL_TRIANGLE_FAN,0,4);	//描画
		//end---------------------------------------------

	}

	//毎フレーム描画処理
	@Override
	public void onDrawFrame(GL10 gl10){

		//背景塗りつぶし----------------------------------
		gl10.glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
		gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);
		//end---------------------------------------------
		gl10.glColor4f(1.0f, 0, 0, 1.0f);
		drawQuad(gl10, 100,200,300,400);

		gl10.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
		drawQuad(gl10, screenWidth /2,  screenHeight /2, 256, 128);


	}

}


TOMY

Re: Androidアプリでテクスチャの読み込みをする際にリソースの取得ができない

#2

投稿記事 by TOMY » 13年前

こちらがサンプルプログラムの方になります。
こっちだと正しくgetResources()が使えるんですけどね・・・
記述忘れましたが開発環境はEclipse INDIGO 
デバッグはGalaxy s2 実機です。

以下サンプルプログラム

コード:

/**
package eaglesakura.sample.ogles;

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.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Bitmap.Config;
import android.graphics.Paint.Style;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.util.Log;

/**
 *
 */
public class OpenGLSample_1_4 extends Activity {
    /**
     * 描画対象のView
     */
    private GLSurfaceView glSurfaceView = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        glSurfaceView = new GLSurfaceView(this);

        //  必要なレンダークラスを生成する
        // ! setRenderせずに処理を継続した場合、Exceptionが投げられるため、
        // ! 必ず設定を行うこと。
        glSurfaceView.setRenderer(new GLRenderSample2());
        setContentView(glSurfaceView);
    }

    /**
     * Activity休止時の処理を行う。 この処理を行わない場合、正常に描画用スレッドが<BR>
     * 停止されない等の不具合が発生する。
     */
    @Override
    protected void onPause() {
        super.onPause();
        glSurfaceView.onPause();
    }

    /**
     * Activity復帰時の処理を行う。 この処理を行わない場合、描画用スレッドが再開されないため<BR>
     * 画面更新が出来なくなる。
     */
    @Override
    protected void onResume() {
        super.onResume();
        glSurfaceView.onResume();
    }

    /**
     * 以後のサンプルで利用するインターフェース。<BR>
     * 確保したメモリの破棄が必要になるため、インターフェース側で定義しておく。
     */
    abstract class GLRenderSampleBase implements GLSurfaceView.Renderer {
        /**
         * ログ出力を行う。
         *
         * @param message
         */
        public void log(String message) {
            Log.i("GLES_SAMPLE", message);
        }
    };

    /**
     * テクスチャの生成を行う。
     */
    class GLRenderSample1 extends GLRenderSampleBase {
        private int screenWidth, screenHeight;

        /**
         * OpenGLから割り当てられたテクスチャ名
         */
        private int texture;

        /**
         * サーフェイス作成時の処理。
         *
         * @param gl10
         * @param eglconfig
         */
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglconfig) {
        }

        /**
         * サーフェイスが変更になった。
         *
         * @param gl10
         * @param w
         *            画面横の長さ(ピクセル)
         * @param h
         *            画面縦の長さ(ピクセル)
         */
        @Override
        public void onSurfaceChanged(GL10 gl10, int w, int h) {
            gl10.glViewport(0, 0, w, h);
            screenWidth = w;
            screenHeight = h;

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image_512);

            log("bitmap size : " + bitmap.getWidth() + " x " + bitmap.getHeight());

            gl10.glEnable(GL10.GL_TEXTURE_2D);
            int[] buffers = new int[1];
            gl10.glGenTextures(1, buffers, 0); // !< テクスチャ用のメモリを指定数確保
            texture = buffers[0]; // !< テクスチャ名を保存する

            // ! テクスチャ情報の設定
            gl10.glBindTexture(GL10.GL_TEXTURE_2D, texture);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            // ! 拡大・縮小時の処理を指定する。
            // ! GL10.GL_LINEAR / GL10.GL_NEARESTで指定する。
            // ! MINは縮小時、MAGは拡大時の処理に指定する。
            // ! リニアは高品位・低速、ニアレストは低品位・高速に動作する。
            // ! これを指定しない場合、正常にテクスチャが表示されない場合がある
            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

            // ! bitmapを破棄
            bitmap.recycle();
        }

        /**
         * 指定した2D座標に四角形を描画する。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void drawQuad(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) screenWidth) * 2.0f - 1.0f, top = ((float) y / (float) screenHeight) * 2.0f - 1.0f;

            float right = left + ((float) w / (float) screenWidth) * 2.0f;
            float bottom = top + ((float) h / (float) screenHeight) * 2.0f;

            // ! 上下を反転させる
            top = -top;
            bottom = -bottom;

            // ! 位置情報
            float positions[] = {
            // ! x y z
                    left, top, 0.0f, // !< 左上
                    left, bottom, 0.0f, // !< 左下
                    right, top, 0.0f, // !< 右上
                    right, bottom, 0.0f, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(positions);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl10.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);

            gl10.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        }

        /**
         * 毎フレーム描画処理。
         *
         * @param gl10
         */
        @Override
        public void onDrawFrame(GL10 gl10) {
            gl10.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);

            // ! テクスチャ全体のUVを指定する。
            {
                // ! UV情報
                float uv[] = {
                // ! u v
                        0.0f, 0.0f, // !< 左上
                        0.0f, 1.0f, // !< 左下
                        1.0f, 0.0f, // !< 右上
                        1.0f, 1.0f, // !< 右下
                };

                // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
                // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
                ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
                bb.order(ByteOrder.nativeOrder());
                FloatBuffer fb = bb.asFloatBuffer();
                fb.put(uv);
                fb.position(0);

                gl10.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
                gl10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);
            }

            // ! 等倍で表示する
            drawQuad(gl10, 0, 0, 512, 512);

            // ! 拡大縮小して表示する
            drawQuad(gl10, screenWidth / 2, screenHeight / 2, 800, 100);
        }
    }

    /**
     * テクスチャの生成を行う。
     */
    class GLRenderSample2 extends GLRenderSampleBase {
        private int screenWidth, screenHeight;

        /**
         * OpenGLから割り当てられたテクスチャ名
         */
        private int textureName;

        private int textureWidth, textureHeight;

        /**
         * サーフェイス作成時の処理。
         *
         * @param gl10
         * @param eglconfig
         */
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglconfig) {
        }

        /**
         * サーフェイスが変更になった。
         *
         * @param gl10
         * @param w
         *            画面横の長さ(ピクセル)
         * @param h
         *            画面縦の長さ(ピクセル)
         */
        @Override
        public void onSurfaceChanged(GL10 gl10, int w, int h) {
            gl10.glViewport(0, 0, w, h);
            screenWidth = w;
            screenHeight = h;

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image_512);

            textureWidth = bitmap.getWidth();
            textureHeight = bitmap.getHeight();
            log("bitmap size : " + bitmap.getWidth() + " x " + bitmap.getHeight());

            gl10.glEnable(GL10.GL_TEXTURE_2D);
            int[] buffers = new int[1];
            gl10.glGenTextures(1, buffers, 0); // !< テクスチャ用のメモリを指定数確保
            textureName = buffers[0]; // !< テクスチャ名を保存する

            // ! テクスチャ情報の設定
            gl10.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            // ! 拡大・縮小時の処理を指定する。
            // ! GL10.GL_LINEAR / GL10.GL_NEARESTで指定する。
            // ! MINは縮小時、MAGは拡大時の処理に指定する。
            // ! リニアは高品位・低速、ニアレストは低品位・高速に動作する。
            // ! これを指定しない場合、正常にテクスチャが表示されない場合がある
            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

            // ! bitmapを破棄
            bitmap.recycle();
        }

        /**
         * 指定した2D座標に四角形を描画する。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void drawQuad(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) screenWidth) * 2.0f - 1.0f, top = ((float) y / (float) screenHeight) * 2.0f - 1.0f;

            float right = left + ((float) w / (float) screenWidth) * 2.0f;
            float bottom = top + ((float) h / (float) screenHeight) * 2.0f;

            // ! 上下を反転させる
            top = -top;
            bottom = -bottom;

            // ! 位置情報
            float positions[] = {
            // ! x y z
                    left, top, 0.0f, // !< 左上
                    left, bottom, 0.0f, // !< 左下
                    right, top, 0.0f, // !< 右上
                    right, bottom, 0.0f, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(positions);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl10.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);

            gl10.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        }

        /**
         * テクスチャの描画範囲を指定する。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void setTextureArea(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) textureWidth);
            float top = ((float) y / (float) textureHeight);

            float right = left + ((float) w / (float) textureWidth);
            float bottom = top + ((float) h / (float) textureHeight);

            // ! 位置情報
            float uv[] = {
            // ! u v
                    left, top, // !< 左上
                    left, bottom, // !< 左下
                    right, top, // !< 右上
                    right, bottom, // !< 右下
            };

            ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(uv);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);
        }

        /**
         * 毎フレーム描画処理。
         *
         * @param gl10
         */
        @Override
        public void onDrawFrame(GL10 gl10) {
            gl10.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);

            setTextureArea(gl10, 0, 0, 256, 256);
            drawQuad(gl10, 0, 0, 256, 256);

            setTextureArea(gl10, 256, 0, 256, 256);
            drawQuad(gl10, 256, 0, 256, 256);

            setTextureArea(gl10, 0, 256, 256, 256);
            drawQuad(gl10, 0, 256, 256, 256);

            setTextureArea(gl10, 256, 256, 256, 256);
            drawQuad(gl10, 256, 256, 256, 256);
        }
    };

    /**
     * テクスチャの生成を行う。
     */
    class GLRenderSample3 extends GLRenderSampleBase {
        private int screenWidth, screenHeight;

        /**
         * OpenGLから割り当てられたテクスチャ名
         */
        private int textureName;

        private int textureWidth, textureHeight;

        /**
         * サーフェイス作成時の処理。
         *
         * @param gl10
         * @param eglconfig
         */
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglconfig) {
        }

        /**
         * サーフェイスが変更になった。
         *
         * @param gl10
         * @param w
         *            画面横の長さ(ピクセル)
         * @param h
         *            画面縦の長さ(ピクセル)
         */
        @Override
        public void onSurfaceChanged(GL10 gl10, int w, int h) {
            gl10.glViewport(0, 0, w, h);
            screenWidth = w;
            screenHeight = h;

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image_512);

            textureWidth = bitmap.getWidth();
            textureHeight = bitmap.getHeight();
            log("bitmap size : " + bitmap.getWidth() + " x " + bitmap.getHeight());

            gl10.glEnable(GL10.GL_TEXTURE_2D);
            int[] buffers = new int[1];
            gl10.glGenTextures(1, buffers, 0); // !< テクスチャ用のメモリを指定数確保
            textureName = buffers[0]; // !< テクスチャ名を保存する

            // ! テクスチャ情報の設定
            gl10.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            // ! 拡大・縮小時の処理を指定する。
            // ! GL10.GL_LINEAR / GL10.GL_NEARESTで指定する。
            // ! MINは縮小時、MAGは拡大時の処理に指定する。
            // ! リニアは高品位・低速、ニアレストは低品位・高速に動作する。
            // ! これを指定しない場合、正常にテクスチャが表示されない場合がある
            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

            // ! bitmapを破棄
            bitmap.recycle();
        }

        /**
         * 色を変えて描画を行う。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void drawQuad(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) screenWidth) * 2.0f - 1.0f, top = ((float) y / (float) screenHeight) * 2.0f - 1.0f;

            float right = left + ((float) w / (float) screenWidth) * 2.0f;
            float bottom = top + ((float) h / (float) screenHeight) * 2.0f;

            // ! 上下を反転させる
            top = -top;
            bottom = -bottom;

            // ! 位置情報
            float positions[] = {
            // ! x y z
                    left, top, 0.0f, // !< 左上
                    left, bottom, 0.0f, // !< 左下
                    right, top, 0.0f, // !< 右上
                    right, bottom, 0.0f, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(positions);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl10.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);

            gl10.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        }

        /**
         * テクスチャの描画範囲を指定する。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void setTextureArea(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) textureWidth), top = ((float) y / (float) textureHeight);

            float right = left + ((float) w / (float) textureWidth);
            float bottom = top + ((float) h / (float) textureHeight);

            // ! 位置情報
            float uv[] = {
            // ! u v
                    left, top, // !< 左上
                    left, bottom, // !< 左下
                    right, top, // !< 右上
                    right, bottom, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(uv);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);
        }

        /**
         * 毎フレーム描画処理。
         *
         * @param gl10
         */
        @Override
        public void onDrawFrame(GL10 gl10) {

            gl10.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);

            /**
             * 左上
             */
            gl10.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
            setTextureArea(gl10, 0, 0, 256, 256);
            drawQuad(gl10, 0, 0, 256, 256);

            /**
             * 右上
             */
            gl10.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
            setTextureArea(gl10, 256, 0, 256, 256);
            drawQuad(gl10, 256, 0, 256, 256);

            /**
             * 左下
             */
            gl10.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
            setTextureArea(gl10, 0, 256, 256, 256);
            drawQuad(gl10, 0, 256, 256, 256);

            /**
             * 右下
             */
            gl10.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
            setTextureArea(gl10, 256, 256, 256, 256);
            drawQuad(gl10, 256, 256, 256, 256);
        }
    };

    /**
     * 文字を描画する
     */
    class GLRenderSample4 extends GLRenderSampleBase {
        private int screenWidth, screenHeight;

        /**
         * OpenGLから割り当てられたテクスチャ名
         */
        private int textureName;

        private int textureWidth, textureHeight;

        /**
         * サーフェイス作成時の処理。
         *
         * @param gl10
         * @param eglconfig
         */
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglconfig) {
        }

        /**
         * サーフェイスが変更になった。
         *
         * @param gl10
         * @param w
         *            画面横の長さ(ピクセル)
         * @param h
         *            画面縦の長さ(ピクセル)
         */
        @Override
        public void onSurfaceChanged(GL10 gl10, int w, int h) {
            gl10.glViewport(0, 0, w, h);
            screenWidth = w;
            screenHeight = h;

            /**
             * 空のビットマップを作成し、そこへ文字を書き込むことでGL上に描画を行う。
             */
            Bitmap bitmap = Bitmap.createBitmap(256, 256, Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            Paint paint = new Paint();
            paint.setColor(Color.WHITE);
            paint.setStyle(Style.FILL);
            canvas.drawColor(0);
            canvas.drawText("文字描画サンプル", 0, 15, paint);

            textureWidth = bitmap.getWidth();
            textureHeight = bitmap.getHeight();
            log("bitmap size : " + bitmap.getWidth() + " x " + bitmap.getHeight());

            gl10.glEnable(GL10.GL_TEXTURE_2D);
            int[] buffers = new int[1];
            gl10.glGenTextures(1, buffers, 0); // !< テクスチャ用のメモリを指定数確保
            textureName = buffers[0]; // !< テクスチャ名を保存する

            // ! テクスチャ情報の設定
            gl10.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

            // ! bitmapを破棄
            bitmap.recycle();

        }

        /**
         * 四角形描画を行う。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void drawQuad(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) screenWidth) * 2.0f - 1.0f, top = ((float) y / (float) screenHeight) * 2.0f - 1.0f;

            float right = left + ((float) w / (float) screenWidth) * 2.0f;
            float bottom = top + ((float) h / (float) screenHeight) * 2.0f;

            // ! 上下を反転させる
            top = -top;
            bottom = -bottom;

            // ! 位置情報
            float positions[] = {
            // ! x y z
                    left, top, 0.0f, // !< 左上
                    left, bottom, 0.0f, // !< 左下
                    right, top, 0.0f, // !< 右上
                    right, bottom, 0.0f, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(positions);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl10.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);

            gl10.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        }

        /**
         * テクスチャの描画範囲を指定する。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void setTextureArea(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) textureWidth), top = ((float) y / (float) textureHeight);

            float right = left + ((float) w / (float) textureWidth);
            float bottom = top + ((float) h / (float) textureHeight);

            // ! 位置情報
            float uv[] = {
            // ! u v
                    left, top, // !< 左上
                    left, bottom, // !< 左下
                    right, top, // !< 右上
                    right, bottom, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(uv);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);
        }

        /**
         * 毎フレーム描画処理。
         *
         * @param gl10
         */
        @Override
        public void onDrawFrame(GL10 gl10) {

            gl10.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);

            /**
             * おまけ この3行でアルファが有効になる gl10.glEnable( GL10.GL_BLEND );
             * gl10.glEnable( GL10.GL_ALPHA ); gl10.glBlendFunc(
             * GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA );
             */

            setTextureArea(gl10, 0, 0, 256, 256);
            gl10.glColor4f(1.0f, 0, 0, 1);
            drawQuad(gl10, 0, 0, 256, 256);

        }
    };

    /**
     * 複数枚のテクスチャを利用する
     */
    class GLRenderSample5 extends GLRenderSampleBase {
        private int screenWidth, screenHeight;

        /**
         * テクスチャID配列
         */
        private int[] textures = null;

        /**
         * テクスチャ幅配列
         */
        private int[] widths = null;

        /**
         * テクスチャ高さ配列
         */
        private int[] heights = null;

        private int textureWidth, textureHeight;

        /**
         * サーフェイス作成時の処理。
         *
         * @param gl10
         * @param eglconfig
         */
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglconfig) {
        }

        /**
         * サーフェイスが変更になった。
         *
         * @param gl10
         * @param w
         *            画面横の長さ(ピクセル)
         * @param h
         *            画面縦の長さ(ピクセル)
         */
        @Override
        public void onSurfaceChanged(GL10 gl10, int w, int h) {
            gl10.glViewport(0, 0, w, h);
            screenWidth = w;
            screenHeight = h;

            // ! 利用するテクスチャ数
            final int[] resources = { R.drawable.image_512, R.drawable.image_128 };

            textures = new int[resources.length];
            widths = new int[resources.length];
            heights = new int[resources.length];

            // ! テクスチャ生成
            gl10.glGenTextures(resources.length, textures, 0);
            gl10.glEnable(GL10.GL_TEXTURE_2D);

            for (int i = 0; i < resources.length; ++i) {
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resources[i]);

                widths[i] = bitmap.getWidth();
                heights[i] = bitmap.getHeight();
                log("bitmap size : " + bitmap.getWidth() + " x " + bitmap.getHeight());

                // ! テクスチャ情報の設定
                gl10.glBindTexture(GL10.GL_TEXTURE_2D, textures[i]);
                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

                gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
                gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

                // ! bitmapを破棄
                bitmap.recycle();

            }
        }

        private void setTexture(GL10 gl10, int index) {
            if (index < 0 || index >= textures.length) {
                gl10.glDisable(GL10.GL_TEXTURE_2D);
            } else {
                gl10.glEnable(GL10.GL_TEXTURE_2D);
                gl10.glBindTexture(GL10.GL_TEXTURE_2D, textures[index]);
                textureWidth = widths[index];
                textureHeight = heights[index];
            }
        }

        /**
         * 四角形描画を行う。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void drawQuad(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) screenWidth) * 2.0f - 1.0f, top = ((float) y / (float) screenHeight) * 2.0f - 1.0f;

            float right = left + ((float) w / (float) screenWidth) * 2.0f;
            float bottom = top + ((float) h / (float) screenHeight) * 2.0f;

            // ! 上下を反転させる
            top = -top;
            bottom = -bottom;

            // ! 位置情報
            float positions[] = {
            // ! x y z
                    left, top, 0.0f, // !< 左上
                    left, bottom, 0.0f, // !< 左下
                    right, top, 0.0f, // !< 右上
                    right, bottom, 0.0f, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(positions);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl10.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);

            gl10.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        }

        /**
         * テクスチャの描画範囲を指定する。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void setTextureArea(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) textureWidth), top = ((float) y / (float) textureHeight);

            float right = left + ((float) w / (float) textureWidth);
            float bottom = top + ((float) h / (float) textureHeight);

            // ! 位置情報
            float uv[] = {
            // ! u v
                    left, top, // !< 左上
                    left, bottom, // !< 左下
                    right, top, // !< 右上
                    right, bottom, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(uv);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);
        }

        /**
         * 毎フレーム描画処理。
         *
         * @param gl10
         */
        @Override
        public void onDrawFrame(GL10 gl10) {

            gl10.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);

            setTexture(gl10, 0);
            setTextureArea(gl10, 0, 0, 256, 256);
            gl10.glColor4f(1.0f, 0, 0, 1);
            drawQuad(gl10, 0, 0, 256, 256);

            setTexture(gl10, -1);
            gl10.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
            drawQuad(gl10, 100, 200, 300, 400);
        }
    };

    /**
     * テクスチャの生成を行う。
     */
    class GLRenderSample7 extends GLRenderSampleBase {
        private int screenWidth, screenHeight;

        /**
         * OpenGLから割り当てられたテクスチャ名
         */
        private int textureName;

        private int textureWidth, textureHeight;

        /**
         * サーフェイス作成時の処理。
         *
         * @param gl10
         * @param eglconfig
         */
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglconfig) {
        }

        int[] textures = null, widths = null, heights = null;

        /**
         * サーフェイスが変更になった。
         *
         * @param gl10
         * @param w
         *            画面横の長さ(ピクセル)
         * @param h
         *            画面縦の長さ(ピクセル)
         */
        @Override
        public void onSurfaceChanged(GL10 gl10, int w, int h) {
            gl10.glViewport(0, 0, w, h);
            screenWidth = w;
            screenHeight = h;

            final int[] resources = { R.drawable.image_128, R.drawable.image_512 };

            //! IDや幅・高さの格納先を確保する。
            textures = new int[resources.length];
            heights = new int[resources.length];
            widths = new int[resources.length];

            gl10.glEnable(GL10.GL_TEXTURE_2D);
            gl10.glGenTextures(resources.length, textures, 0);

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image_512);

            textureWidth = bitmap.getWidth();
            textureHeight = bitmap.getHeight();
            log("bitmap size : " + bitmap.getWidth() + " x " + bitmap.getHeight());

            gl10.glEnable(GL10.GL_TEXTURE_2D);
            int[] buffers = new int[1];
            gl10.glGenTextures(1, buffers, 0); // !< テクスチャ用のメモリを指定数確保
            textureName = buffers[0]; // !< テクスチャ名を保存する

            // ! テクスチャ情報の設定
            gl10.glBindTexture(GL10.GL_TEXTURE_2D, textureName);
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

            // ! bitmapを破棄
            bitmap.recycle();

        }

        /**
         * 色を変えて描画を行う。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void drawQuad(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) screenWidth) * 2.0f - 1.0f, top = ((float) y / (float) screenHeight) * 2.0f - 1.0f;

            float right = left + ((float) w / (float) screenWidth) * 2.0f;
            float bottom = top + ((float) h / (float) screenHeight) * 2.0f;

            // ! 上下を反転させる
            top = -top;
            bottom = -bottom;

            // ! 位置情報
            float positions[] = {
            // ! x y z
                    left, top, 0.0f, // !< 左上
                    left, bottom, 0.0f, // !< 左下
                    right, top, 0.0f, // !< 右上
                    right, bottom, 0.0f, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(positions.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(positions);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl10.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);

            gl10.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
        }

        /**
         * テクスチャの描画範囲を指定する。
         *
         * @param gl10
         * @param x
         * @param y
         * @param w
         * @param h
         */
        private void setTextureArea(GL10 gl10, int x, int y, int w, int h) {
            float left = ((float) x / (float) textureWidth), top = ((float) y / (float) textureHeight);

            float right = left + ((float) w / (float) textureWidth);
            float bottom = top + ((float) h / (float) textureHeight);

            // ! 位置情報
            float uv[] = {
            // ! u v
                    left, top, // !< 左上
                    left, bottom, // !< 左下
                    right, top, // !< 右上
                    right, bottom, // !< 右下
            };

            // ! OpenGLはビッグエンディアンではなく、CPUごとのネイティブエンディアンで数値を伝える必要がある。
            // ! そのためJavaヒープを直接的には扱えず、java.nio配下のクラスへ一度値を格納する必要がある。
            ByteBuffer bb = ByteBuffer.allocateDirect(uv.length * 4);
            bb.order(ByteOrder.nativeOrder());
            FloatBuffer fb = bb.asFloatBuffer();
            fb.put(uv);
            fb.position(0);

            gl10.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl10.glTexCoordPointer(2, GL10.GL_FLOAT, 0, fb);
        }

        /**
         * 毎フレーム描画処理。
         *
         * @param gl10
         */
        @Override
        public void onDrawFrame(GL10 gl10) {

            gl10.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);

            /**
             * 左上
             */
            gl10.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
            setTextureArea(gl10, 0, 0, 256, 256);
            drawQuad(gl10, 0, 0, 256, 256);

            /**
             * 右上
             */
            gl10.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
            setTextureArea(gl10, 256, 0, 256, 256);
            drawQuad(gl10, 256, 0, 256, 256);

            /**
             * 左下
             */
            gl10.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
            setTextureArea(gl10, 0, 256, 256, 256);
            drawQuad(gl10, 0, 256, 256, 256);

            /**
             * 右下
             */
            gl10.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
            setTextureArea(gl10, 256, 256, 256, 256);
            drawQuad(gl10, 256, 256, 256, 256);
        }
    };

}


ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: Androidアプリでテクスチャの読み込みをする際にリソースの取得ができない

#3

投稿記事 by ISLe » 13年前

getResourcesはandroid.app.Activity(正確には継承したandroid.content.Context)のメソッドなので、GLRendearSurfaceクラスを、サンプルと同じようにActivityを継承したクラスの入れ子クラスにすれば良いと思います。

独立したクラスにしたいのであれば、GLRendearSurfaceクラスのコンストラクタに引数を追加して渡すと良いと思います。


ところで雑誌等に載っているソースコードの無断転載は著作憲法違反行為ですよ。
フォーラムルールでも禁止されています。

TOMY

Re: Androidアプリでテクスチャの読み込みをする際にリソースの取得ができない

#4

投稿記事 by TOMY » 13年前

>ところで雑誌等に載っているソースコードの無断転載は著作憲法違反行為ですよ。
フォーラムルールでも禁止されています。

申し訳ありませんそこの部分をすっかり忘れていました。
本題についてはご助言を元に解決してから解決にチェックを入れさせていただきたいと思います。

TOMY

Re: Androidアプリでテクスチャの読み込みをする際にリソースの取得ができない

#5

投稿記事 by TOMY » 13年前

>getResourcesはandroid.app.Activity(正確には継承したandroid.content.Context)のメソッドなので、GLRendearSurfaceクラスを、サンプルと同じようにActivityを継承したクラスの入れ子クラスにすれば良いと思います。

>独立したクラスにしたいのであれば、GLRendearSurfaceクラスのコンストラクタに引数を追加して渡すと良いと思います。
ご助言の通りコンストラクタでResourceを引数にしたところなんとか動きました。本当にこんな初歩的な質問に答えていただきありがとうございます

閉鎖

“C言語何でも質問掲示板” へ戻る