だいぶ昔のトピックの続きですが、一応制作は進めていました。オライリーの『初めてのOpenGLES』を参考に雛形を作っていて問題が多々出てきてしまったために質問させて頂きます。
非常にワガママ身勝手ですが、案の定また制作締め切りが近づいていて、しかもこれが出来なければチーム制作の他の人の評価に影響を出してしまうため、出来れば早急にアドバイスが頂きたのでお願いします。
本題です。夏休みの頃から、オライリーの初めてのOpenGLESを参考に雛形を作って、ポリゴンの描画を簡単にする『GL2DVertex』クラスにて、radian値を入力すればその値にあわせて矩形ポリゴンが回転するという処理を入れていましたが、うまく出来ずに詰まってしまいました。そこでOpenGLに詳しい先生に相談してみたところ、glorthof関数で座標系を作っていないため、このままでは汎用性のないものになってしまうと指摘され、glorthofを使い、左上頂点のウィンドウ座標系をつくりました。しかし、今度はポリゴンの描画部分がおかしくなってしまい、その部分を解決する方法を緊急で模索しています。
問題のプログラム部分はここです。↓
//ポリゴンの生成、更新、描画を簡単にさせるためのクラス
package jp.denpa.tomy.opengl_es.wrap;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.math.*;
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; //カラー+アルファ
// 持っておきたい情報
private int useTexName; // 使用するテクスチャ番号
private boolean turnFlg; // テクスチャのUVを左右反転
//壊れることのない情報(配列定数)
private final static float[] dx={-1.0f, 1.0f, 1.0f, -1.0f};
private final static float[] dy={-1.0f, -1.0f, 1.0f, 1.0f};
//計算が分かりやすい様にする為の変数
private float[] tx = new float[4];
private float[] ty = new float[4];
public GL2DVertex(GL10 gl){
this.gl10 = gl;
}
public void Init(){ //初期化
useTexName = -1;
turnFlg = false;
rad = 0;
//色の初期設定
a=1.0f;
r=1.0f;
g=1.0f;
b=1.0f;
// 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 SetUV(int cx,int cy,int nx,int 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(turnFlg==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;
}
private void SetPos(){ //座標の更新(確定) //あとで回転の計算も入れる
float[] verX = new float[4];
float[] verY = new float[4];
//計算の簡略化用
for(int i=0;i<4;i++){
tx[i] = size.x / 2 * dx[i];
ty[i] = size.y / 2 * dy[i];
}
for(int i=0;i<4;i++){
verX[i] = (float) (tx[i] * Math.cos(rad) - ty[i] * Math.sin(rad) + center.x);
verY[i] = (float) (tx[i] * Math.sin(rad) + ty[i] * Math.cos(rad) + center.y);
}
//位置情報
float positions[] = { //x,y,zの順に定義
verX[0],verY[0],0, //左上
verX[1],verY[1],0, //右上
verX[2],verY[2],0, //右下
verX[3],verY[3],0, //左下
};
// float positions[] = { //x,y,zの順に定義
// 50,50,0, //左上
// 100,50,0, //右上
// 100,100,0, //右下
// 50,100,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に頂点バッファを関連付ける(コピーではないことに注意)
}
public void Draw(GLTexture gltex){ //描画
//ビューポート変換
gl10.glViewport(0,0,MainRenderer.screenW,MainRenderer.screenH);
//投影変換
gl10.glMatrixMode(GL10.GL_PROJECTION);
gl10.glLoadIdentity();
gl10.glOrthof(0,MainRenderer.screenW,-MainRenderer.screenH,0 , -10,10); //座標系の指定(左上原点Wndow座標系指定(ニア、ファーは0にして2D専用にしている))
// gl10.glTranslatef(-MainRenderer.screenW/2, -MainRenderer.screenH/2, 0); //座標系の原点を平行移動
//
SetPos();
// テクスチャ有り
gl10.glBindTexture(GL10.GL_TEXTURE_2D, gltex.getTexName());
gl10.glDrawArrays(GL10.GL_TRIANGLE_FAN,0,4); //描画
}
public void Draw(){
//ビューポート変換
gl10.glViewport(0,0,MainRenderer.screenW,MainRenderer.screenH);
//投影変換
gl10.glMatrixMode(GL10.GL_PROJECTION);
gl10.glLoadIdentity();
gl10.glOrthof(0,MainRenderer.screenW,-MainRenderer.screenH,0 , -10,10); //座標系の指定(左上原点Wndow座標系指定(ニア、ファーは0にして2D専用にしている))
// gl10.glTranslatef(-MainRenderer.screenW/2, -MainRenderer.screenH/2, 0); //座標系の原点を平行移動
//
//クリア色の設定
gl10.glClearColor(a,r,g,b);
SetPos();
//モデリング変換
gl10.glMatrixMode(GL10.GL_MODELVIEW);
gl10.glLoadIdentity();
gl10.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);
}
public void SetTexName(int texname) { useTexName = texname; }
public void SetTurnFlg(boolean turnflg) { turnFlg = turnflg; }
public int GetTexName() { return useTexName; }
public boolean GetTurnFlg() { return turnFlg; }
}