なんか頭の中が滅茶苦茶になってしまったので途中経過だけ貼り付けておきます。
イメージとしてはGL2DVertexクラスのDrawメソッドに引数としてGLTextureクラスを入れたらそのポリゴンにテクスチャが貼られ、
nullをいれたらポリゴンだけ表示されるイメージ
(GL2DVertexクラス)
コード:
]
//ポリゴンの生成、更新、描画を簡単にさせるためのクラス
package jp.denpa.tomy.opengl_es.wrap;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class GL2DVertex {
public Vector2 center; //中心座標
public Vector2 size; //ポリゴンサイズ
public float rad; //回転角度(radian)
private GL10 gl10;
private float a,r,g,b;
public void Init(GL10 gl){ //初期化
//色の初期設定
a=1.0f;
r=1.0f;
g=1.0f;
b=1.0f;
gl10=gl;
float uv[] = {
1,0, //左上
1,1, //右上
0,1, //右下
0,0, //左下
};
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);
}
public void SetUV(int cx,int cy,int nx,int ny,boolean turn){ //UV座標セット(cx,cy=分割数。 nx,ny=描画番号 ※左上原点でお考えください)
float w = 1.0f/cx;
float h = 1.0f/cy;
float left = w * nx;
float top = h * (ny+1);
float right = w * (nx+1);
float bottom= h * ny;
if(turn==true){ //反転フラグがtrueの時の処理
float tu=right;
right=left;
left=tu;
}
float uv[] = { //UV座標
left,bottom, //左下
left,top, //左上
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); //ストリームに登録
}
public void SetColor(float A,float R,float G,float B){ //色の設定
a=A;r=R;g=G;b=B;
}
public void SetPos(){ //座標の更新(確定) //あとで回転の計算も入れる
float left = ((center.x - size.x / 2)/ (float) MainRenderer.screenW) * 2.0f - 1.0f;
float top = ((center.y - size.y / 2)/ (float) MainRenderer.screenH) * 2.0f - 1.0f;
float right = left + ((float)size.x / (float)MainRenderer.screenW) * 2.0f;
float bottom = top + ((float)size.y / (float)MainRenderer.screenH) * 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.glVertexPointer(3,GL10.GL_FLOAT,0,fb); //OpenGL ESに頂点バッファを関連付ける(コピーではないことに注意)
}
public void Draw(GLTexture gltex){ //描画
if(gltex == null){
gl10.glColor4f(r, g, b, a);
gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY); //頂点バッファの成分を切り替えている(有効化)
gl10.glDrawArrays(GL10.GL_TRIANGLE_FAN,0,4); //描画
gl10.glDisableClientState(GL10.GL_VERTEX_ARRAY); //頂点バッファの成分を切り替えている(無効化)
}else{
gl10.glEnable(GL10.GL_TEXTURE_2D); //テクスチャの有効化
gltex.SetTex();
gl10.glColor4f(r, g, b, a);
gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY); //頂点バッファの成分を切り替えている(有効化)
gl10.glDrawArrays(GL10.GL_TRIANGLE_FAN,0,4); //描画
gl10.glDisableClientState(GL10.GL_VERTEX_ARRAY); //頂点バッファの成分を切り替えている(無効化)
gl10.glDisable(GL10.GL_TEXTURE_2D); //テクスチャの無効化
}
}
}
(GLTextureクラス)
コード:
package jp.denpa.tomy.opengl_es.wrap;
import javax.microedition.khronos.opengles.GL10;
import jp.denpa.tomy.games.MyView;
import jp.denpa.tomy.games.R;
//import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
//テクスチャ管理クラス(1枚単位)
class GLTexture {
// private Context context; //このクラスでContextからgetResoucesするとエラーのち強制終了
private Bitmap bitmap;
private int textureName;
private GL10 gl10;
//テクスチャの読み込み
public void LoadTexture(GL10 gl,Resources res,int id){
gl10=gl;
//テクスチャに関する処理---------------------------------------
bitmap = BitmapFactory.decodeResource(res, id);
int[] buffers = new int[1];
//texture夜のメモリを指定数確保
gl10.glGenTextures(1,buffers,0);
//テクスチャ名を保存する
textureName = buffers[0];
}
public void SetTex(){
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();
}
//開放処理
public void Release(){}
}
(実装はこんな感じ MyRendererクラス)
コード:
package jp.denpa.tomy.opengl_es.wrap;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import jp.denpa.tomy.games.MyView;
import jp.denpa.tomy.games.R;
//OpenGL の Rendererに関するクラス メインループもここでする(←?)
public class MainRenderer implements GLSurfaceView.Renderer{
private GL2DVertex test = new GL2DVertex();
private GL2DVertex test2 = new GL2DVertex();
private GLTexture tex1 = new GLTexture();
private GLTexture tex2 = new GLTexture();
enum FlameNo{
START_INIT,
START_MAIN,
MENU_INIT, //メニュー準備
MENU_MAIN, //メニュー処理
GAME_INIT, //ゲーム準備
GAME_MAIN, //ゲーム処理
RESULT_INIT, //ゲーム終了時の得点表示
RESULT_MAIN, //ゲーム終了時の得点表示
}
private Context context;
static FlameNo gameFlg = FlameNo.START_INIT; //ゲームフラグ
static int screenW; //スクリーン座標
static int screenH;
public MainRenderer(Context ctext){
context=ctext;
}
private int textureName;
//サーフェイス作成時の処理(サーフェイスが生成される際・または再生成される際に呼ばれる)
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglconfing){
//⑦背景色
gl10.glClearColor(1.0f,1.0f,1.0f,1.0f);
// ディザを無効化
gl10.glDisable(GL10.GL_DITHER);
// 深度テストを有効に
gl10.glEnable(GL10.GL_DEPTH_TEST);
//テクスチャ機能ON
// gl10.glEnable(GL10.GL_TEXTURE_2D);
//透明可能に
gl10.glEnable(GL10.GL_ALPHA_TEST);
//ブレンド可能に
gl10.glEnable(GL10.GL_BLEND);
//色のブレンド方法
gl10.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);
}
//画面上のどの領域を使用するかの設定、あとポリゴン色とかの設定(サーフェイスのサイズ変更時に呼ばれる)
@Override
public void onSurfaceChanged(GL10 gl10, int w,int h ){
gl10.glViewport(0, 0, w, h);
screenW = w;
screenH = h;
//テクスチャに関する処理---------------------------------------
// Bitmap bitmap = BitmapFactory.decodeResource(context.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();
}
//毎フレーム描画処理
@Override
public void onDrawFrame(GL10 gl10){
//背景塗りつぶし----------------------------------
gl10.glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
gl10.glClear(GL10.GL_COLOR_BUFFER_BIT);
//end---------------------------------------------
tex1.LoadTexture(gl10, context.getResources(), R.drawable.image_512);
tex2.LoadTexture(gl10, context.getResources(), R.drawable.image_128);
test.center=new Vector2(50,50);
test.size=new Vector2(100,100);
test.Init(gl10);
//test.SetUV(2, 2, 1, 1, false); //成功
test.SetPos();
test.Draw(tex2);
test2.center=new Vector2(300,300);
test2.size=new Vector2(100,100);
test2.Init(gl10);
test2.SetUV(2, 2, 1, 0, false); //成功
test2.SetPos();
test2.Draw(null);
}
}