▼Androidメモ▼
3Dモデルの読み込み


OpenGL ES 1.0で3Dモデルの読み込みを行うプログラムを作成する。
HelloGL10_21.png

3Dモデルファイル
以下の2つのファイルをプロジェクトのassetsに配置。
objファイルの書式はこちら
mltファイルの書式はこちら

ソースコード
GL10ModelEx1.java
package net.npaka.gl10modelex1;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

//3Dモデルの読み込み
public class GL10ModelEx1 extends Activity {
private GLSurfaceView glView;

//アクティビティ生成時に呼ばれる
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);

//GLサーフェイスビューの生成
glView=new GLSurfaceView(this);
glView.setRenderer(new GLRenderer(this));
setContentView(glView);
}

//アクティビティレジューム時に呼ばれる
@Override
public void onResume() {
super.onResume();
glView.onResume();
}

//アクティビティポーズ時に呼ばれる
@Override
public void onPause() {
super.onPause();
glView.onPause();
}
}

GLRenderer.java
package net.npaka.gl10modelex1;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import net.npaka.gles.GLES;
import net.npaka.gles.ObjLoader;
import net.npaka.gles.Object3D;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;

//レンダラー
public class GLRenderer implements
GLSurfaceView.Renderer {
//システム
private float aspect;//アスペクト比
private int angle; //回転角度

//モデル
private Object3D model=new Object3D();

//コンストラクタ
public GLRenderer(Context context) {
GLES.context=context;
}

//サーフェイス生成時に呼ばれる
@Override
public void onSurfaceCreated(GL10 gl10,EGLConfig eglConfig) {
GLES.gl=(GL11)gl10;

//デプステストの有効化
gl10.glEnable(GL10.GL_DEPTH_TEST);

//光源色の有効化
gl10.glEnable(GL10.GL_LIGHTING);
gl10.glEnable(GL10.GL_LIGHT0);

//光源色の指定
gl10.glLightfv(GL10.GL_LIGHT0,GL10.GL_AMBIENT,
new float[]{0.2f,0.2f,0.2f,1.0f},0);
gl10.glLightfv(GL10.GL_LIGHT0,GL10.GL_DIFFUSE,
new float[]{0.7f,0.7f,0.7f,1.0f},0);
gl10.glLightfv(GL10.GL_LIGHT0,GL10.GL_SPECULAR,
new float[]{0.9f,0.9f,0.9f,1.0f},0);

//モデルの読み込み
try {
model.figure=ObjLoader.load("droid.obj");
} catch (Exception e) {
android.util.Log.e("debug",e.toString());
for (StackTraceElement ste:e.getStackTrace()) {
android.util.Log.e("debug"," "+ste);
}
}
}

//画面サイズ変更時に呼ばれる
@Override
public void onSurfaceChanged(GL10 gl10,int w,int h) {
//ビューポート変換
gl10.glViewport(0,0,w,h);
aspect=(float)w/(float)h;
}

//毎フレーム描画時に呼ばれる
@Override
public void onDrawFrame(GL10 gl10) {
//画面のクリア
gl10.glClearColor(1.0f,1.0f,1.0f,1.0f);
gl10.glClear(GL10.GL_COLOR_BUFFER_BIT|
GL10.GL_DEPTH_BUFFER_BIT);

//射影変換
gl10.glMatrixMode(GL10.GL_PROJECTION);
gl10.glLoadIdentity();
GLU.gluPerspective(gl10,
45.0f, //Y方向の画角
aspect, //アスペクト比
0.01f, //ニアクリップ
100.0f);//ファークリップ

//光源位置の指定
gl10.glMatrixMode(GL10.GL_MODELVIEW);
gl10.glLoadIdentity();
gl10.glLightfv(GL10.GL_LIGHT0,GL10.GL_POSITION,
new float[]{5.0f,5.0f,5.0f,0.0f},0);

//ビュー変換
GLU.gluLookAt(gl10,
0,0.8f,5.0f, //カメラの視点
0,0.8f,0.0f, //カメラの焦点
0.0f,1.0f,0.0f);//カメラの上方向

//モデル変換
gl10.glRotatef(angle++,0,1,0);

//モデルの描画
model.draw();
}
}

モデル変換用ライブラリ
読み込んだ3Dモデルにモデル変換を適用するクラス郡を用意。
クラス名 説明
Object3D モデル変換を適用する3Dモ デル。
形状データ(Figure)とモデル変換のベクトル(Vector3D)を保持。
Vector3D 3要素のベクトル。
加算、減算、内積、外積、正規化といった計算メソッドを保持。

Object3D.java
package net.npaka.gles;
import java.util.ArrayList;
import javax.microedition.khronos.opengles.GL10;

//3Dオブジェクト
public class Object3D {
public Figure figure; //フィギュア
public Vector3 position=new Vector3(); //位置
public Vector3 rotate =new Vector3(); //回転
public Vector3 scale =new Vector3(1,1,1);//拡縮
public ArrayList<Object3D> childs=new ArrayList<Object3D>();//子

//描画
public void draw() {
GL10 gl=GLES.gl;
gl.glPushMatrix();
gl.glTranslatef(position.x,position.y,position.z);
gl.glRotatef(rotate.z,0,0,1);
gl.glRotatef(rotate.y,0,1,0);
gl.glRotatef(rotate.x,1,0,0);
gl.glScalef(scale.x,scale.y,scale.z);
figure.draw();
for (int i=0;i<childs.size();i++) childs.get(i).draw();
gl.glPopMatrix();
}
}

Vector3.java
package net.npaka.gles;

//3要素ベクトル
public class Vector3 {
public float x=0.0f;//X座標
public float y=0.0f;//Y座標
public float z=0.0f;//Z座標

//コンストラクタ
public Vector3() {
}

//コンストラクタ
public Vector3(float x,float y,float z) {
set(x,y,z);
}

//コンストラクタ
public Vector3(Vector3 origin) {
set(origin);
}

//値の指定
public void set(Vector3 origin) {
x=origin.x;
y=origin.y;
z=origin.z;
}

//値の指定
public void set(float x,float y,float z) {
this.x=x;
this.y=y;
this.z=z;
}

//内積の計算
public float dot(Vector3 v) {
return (x*v.x)+(y*v.y)+(z*v.z);
}

//内積の計算
public float dot(float x,float y,float z) {
return (this.x*x)+(this.y*y)+(this.z*z);
}

//外積の計算
public Vector3 cross(Vector3 v,Vector3 result) {
result.set((y*v.z)-(z*v.y),(z*v.x)-(x*v.z),(x*v.y)-(y*v.x));
return result;
}

//外積の計算
public void cross(float x,float y,float z) {
set((this.y*z)-(this.z*y),(this.z*x)-(this.x*z),(this.x*y)-(this.y*x));
}

//和の計算
public void add(Vector3 v0,Vector3 v1) {
x=v0.x+v1.x;
y=v0.y+v1.y;
z=v0.z+v1.z;
}

//差の計算
public void sub(Vector3 v0,Vector3 v1) {
x=v0.x-v1.x;
y=v0.y-v1.y;
z=v0.z-v1.z;
}

//ベクトルの長さの取得
public float length() {
return (float)Math.sqrt((double)((x*x)+(y*y)+(z*z)));
}

//ベクトルの長さの正規化
public void normalize() {
final float len=length();
x/=len;
y/=len;
z/=len;
}

//値の比較
@Override
public boolean equals(Object o) {
Vector3 v=(Vector3)o;
return v.x==x && v.y==y && v.z==z;
}
}


3Dモデル読み込み用ライブラリ
3Dモデルを読み込むクラス郡を用意。
クラス名 説明
ObjLoader OBJファイルを読み込む ローダー。
ファイル名を指定し、Figureオブジェクトを取得。
GLES GLライブラリ全体で利用す る変数とメソッドを保持。
Figure 読み込み跡の形状データ。
メッシュ郡とマテリアル郡を保持。
Mesh メッシュ。
頂点バッファとインデックスバッファとマテリアルを保持。


GLObject OpenGLで bind/unbindを行うオブジェクト。
VertexBuffer/IndexBuffer/Material/Textureの親。
VertexBuffer
頂点バッファ。
IndexBuffer
インデックスバッファ。
Material マテリアル。
テクスチャとマテリアル色を保持。
Texture テクスチャ

ObjLoader.java
package net.npaka.gles;
import java.io.DataInputStream;
import java.util.ArrayList;
import java.util.HashMap;

//OBJローダー
public class ObjLoader {
//ロード
public static Figure load(String path) throws Exception {
DataInputStream in=new DataInputStream(
GLES.context.getAssets().open(path));

//頂点バッファとインデックスバッファ
ArrayList<float[]> positions=new ArrayList<float[]>();
ArrayList<float[]> normals =new ArrayList<float[]>();
ArrayList<float[]> uvs =new ArrayList<float[]>();
ArrayList<float[]> vertexs =new ArrayList<float[]>();
ArrayList<short[]> indexs =new ArrayList<short[]>();

//メッシュとマテリアル
ArrayList<Mesh> meshs=new ArrayList<Mesh>();
HashMap<String,Material> materials=new HashMap<String,Material>();

//パース
Material material=null;
boolean meshFlag=false;
String line=in.readLine();

while (line!=null) {
String[] word=line.split(" ",0);

//MTLファイルの読み込み
if (word[0].equals("mtllib")) {
loadMtl(materials,word[1]);
}
//マテリアル
else if (word[0].equals("usemtl")) {
material=materials.get(word[1]);
}
//頂点
else if (word[0].equals("v")) {
float[] position=new float[]{
Float.parseFloat(word[1]),
Float.parseFloat(word[2]),
Float.parseFloat(word[3])
};
positions.add(position);
}
//UV
else if (word[0].equals("vt")) {
float[] uv=new float[]{
Float.parseFloat(word[1]),
1.0f-Float.parseFloat(word[2])
};
uvs.add(uv);
}
//法線
else if (word[0].equals("vn")) {
float[] normal=new float[]{
Float.parseFloat(word[1]),
Float.parseFloat(word[2]),
Float.parseFloat(word[3])
};
normals.add(normal);
}
//インデックス
else if (word[0].equals("f")) {
meshFlag=true;
short[] index=new short[word.length-1];
for (int i=0;i<index.length;i++) {
String[] w=word[i+1].split("/",0);
index[i]=(short)addVertex(vertexs,
positions.get(Integer.parseInt(w[0])-1),
uvs.get(Integer.parseInt(w[1])-1),
normals.get(Integer.parseInt(w[2])-1));
}
indexs.add(index);
}
//メッシュの生成
else if (meshFlag) {
meshFlag=false;
Mesh mesh=new Mesh();
mesh.vertexBuffer=new VertexBuffer(vertexs);
mesh.indexBuffer =new IndexBuffer(indexs);
mesh.material =material;
meshs.add(mesh);
}
line=in.readLine();
}
in.close();

//フィギュアの生成
Figure figure=new Figure();
figure.materials=materials;
figure.meshs=meshs;
return figure;
}

//頂点の追加
private static int addVertex(ArrayList<float[]> vertexs,
float[] position,float[] uv,float[] normal) {
float[] vertex=new float[3+2+3];
System.arraycopy(position,0,vertex,0,3);
System.arraycopy(uv,0,vertex,3,2);
System.arraycopy(normal,0,vertex,3+2,3);

//既存の頂点
for (int i=0;i<vertexs.size();i++) {
float[] v=vertexs.get(i);
int j=0;
for (;j<8;j++) {
if (v[j]!=vertex[j]) break;
}
if (j==8) return i;
}

//新規の頂点
vertexs.add(vertex);
return vertexs.size()-1;
}

//MTLの読み込み
public static void loadMtl(HashMap<String,Material> materials,
String path) throws Exception {
DataInputStream in=new DataInputStream(
GLES.context.getAssets().open(path));
Material material=null;
materials.clear();
String line=in.readLine();
while (line!=null) {
String[] word=line.split(" ",0);
//マテリアル名
if (word[0].equals("newmtl")) {
material=new Material();
materials.put(word[1],material);
}
//環境光
else if (word[0].equals("Ka")) {
material.ambient=new float[]{
Float.parseFloat(word[1]),
Float.parseFloat(word[2]),
Float.parseFloat(word[3]),
1.0f};
}
//拡散光
else if (word[0].equals("Kd")) {
material.diffuse=new float[]{
Float.parseFloat(word[1]),
Float.parseFloat(word[2]),
Float.parseFloat(word[3]),
1.0f};
}
//鏡面光
else if (word[0].equals("Ks")) {
material.speculer=new float[]{
Float.parseFloat(word[1]),
Float.parseFloat(word[2]),
Float.parseFloat(word[3]),
1.0f};
}
//鏡面反射角度
else if (word[0].equals("Ns")) {
material.shininess=new float[]{
Float.parseFloat(word[1])};
}
//テクスチャ
else if (word[0].equals("map_Kd")) {
material.texture=Texture.createTextureFromAsset(word[1]);
}
line=in.readLine();
}
in.close();
}
}

GLES.java
package net.npaka.gles;
import javax.microedition.khronos.opengles.GL11;
import android.content.Context;

//GLES
public class GLES {
public static GL11 gl; //GL
public static Context context;//コンテキスト
}

Figure.java
package net.npaka.gles;
import java.util.ArrayList;
import java.util.HashMap;

//フィギュア
public class Figure {
public HashMap<String,Material> materials;//マテリアル群
public ArrayList<Mesh> meshs; //メッシュ群

//描画
public void draw() {
for (Mesh mesh:meshs) mesh.draw();
}
}

Mesh.java
package net.npaka.gles;

//メッシュ
public class Mesh {
public VertexBuffer vertexBuffer;//頂点バッファ
public IndexBuffer indexBuffer; //インデックスバッファ
public Material material; //マテリアル

//描画
public void draw() {
material.bind();
vertexBuffer.bind();
indexBuffer.draw();
vertexBuffer.unbind();
material.unbind();
}
}

GLObject.java
package net.npaka.gles;

//GLオブジェクト(VertexBuffer/IndexBuffer/Material/Textureの親)
public abstract class GLObject {

//破棄時に呼ばれる
@Override
protected void finalize() throws Throwable {
super.finalize();
dispose();
}

//バインド
public abstract void bind();

//アンバインド
public abstract void unbind();

//解放
public abstract void dispose();
}

VertexBuffer.java
package net.npaka.gles;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

//頂点バッファ
public class VertexBuffer extends GLObject {
private int vertexBufferId;//頂点バッファID

//コンストラクタ
public VertexBuffer(ArrayList<float[]> vertexs) {
float[] vertexArray=new float[8*vertexs.size()];
for (int i=0;i<vertexs.size();i++) {
float[] vertex=vertexs.get(i);
System.arraycopy(vertex,0,vertexArray,8*i,8);
}
GL11 gl=GLES.gl;
int count=vertexArray.length/8;
int[] bufferIds=new int[1];
GLES.gl.glGenBuffers(1,bufferIds,0);
vertexBufferId=bufferIds[0];
FloatBuffer fb=ByteBuffer.allocateDirect(8*4*count).
order(ByteOrder.nativeOrder()).asFloatBuffer();
fb.put(vertexArray);
fb.position(0);
gl.glDisable(GL10.GL_CULL_FACE);
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER,vertexBufferId);
gl.glBufferData(GL11.GL_ARRAY_BUFFER,fb.capacity()*4,
fb,GL11.GL_STATIC_DRAW);
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER,0);
}

//バインド
@Override
public void bind() {
GL11 gl=GLES.gl;
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER,vertexBufferId);
gl.glVertexPointer(3,GL10.GL_FLOAT,8*4,0);
gl.glTexCoordPointer(2,GL10.GL_FLOAT,8*4,3*4);
gl.glNormalPointer(GL10.GL_FLOAT,8*4,5*4);
}

//アンバインド
@Override
public void unbind() {
GL11 gl=GLES.gl;
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER,0);
}

//破棄
@Override
public void dispose() {
if (vertexBufferId!=0) {
GLES.gl.glDeleteBuffers(1,new int[]{vertexBufferId},0);
vertexBufferId=0;
}
}
}

IndexBuffer.java
package net.npaka.gles;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

//インデックスバッファ
public class IndexBuffer extends GLObject {
private int indexBufferId; //インデックスバッファID
private int indexBufferSize;//インデックスバッファサイズ

//コンストラクタ
public IndexBuffer(ArrayList<short[]> indexs) {
short[] indexArray=new short[3*indexs.size()];
for (int i=0;i<indexs.size();i++) {
short[] index=indexs.get(i);
System.arraycopy(index,0,indexArray,3*i,3);
}
int[] bufferIds=new int[1];
GLES.gl.glGenBuffers(1,bufferIds,0);
indexBufferId=bufferIds[0];
bind();
ShortBuffer sb=ByteBuffer.allocateDirect(indexArray.length*2).
order(ByteOrder.nativeOrder()).asShortBuffer();
sb.put(indexArray);
sb.position(0);
indexBufferSize=indexArray.length;
GL11 gl=GLES.gl;
gl.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER,
sb.capacity()*2,sb,GL11.GL_STATIC_DRAW);
unbind();
}

//描画
public void draw() {
GL11 gl=GLES.gl;
gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER,indexBufferId);
gl.glDrawElements(GL10.GL_TRIANGLES,indexBufferSize,GL10.GL_UNSIGNED_SHORT,0);
gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER,0);
}

//バインド
@Override
public void bind() {
GL11 gl=GLES.gl;
gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER,indexBufferId);
}

//アンバインド
@Override
public void unbind() {
GL11 gl=GLES.gl;
gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER,0);
}

//解放
@Override
public void dispose() {
if (indexBufferId!=0) {
GLES.gl.glDeleteBuffers(1,new int[]{indexBufferId},0);
indexBufferId=0;
}
}
}

Material.java
package net.npaka.gles;
import javax.microedition.khronos.opengles.GL10;

//マテリアル
public class Material extends GLObject {
public Texture texture; //テクスチャ
public float[] ambient =new float[4];//環境光
public float[] diffuse =new float[4];//拡散光
public float[] speculer =new float[4];//鏡面光
public float[] shininess=new float[1];//鏡面反射角度

//バインド
@Override
public void bind() {
GL10 gl=GLES.gl;
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_AMBIENT,ambient,0);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_DIFFUSE,diffuse,0);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_SPECULAR,speculer,0);
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,GL10.GL_SHININESS,shininess,0);
if (texture!=null) texture.bind();
}

//アンバインド
@Override
public void unbind() {
if (texture!=null) texture.unbind();
}

//破棄
@Override
public void dispose() {
if (texture!=null) {
texture.dispose();
texture=null;
}
}
}

Texture.java
package net.npaka.gles;
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

//テクスチャ
public class Texture extends GLObject {
public int textureId;//テクスチャID
public int width; //幅
public int height; //高さ

//バインド
@Override
public void bind() {
GL10 gl=GLES.gl;
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textureId);
}

//アンバインド
@Override
public void unbind() {
GL10 gl=GLES.gl;
gl.glDisable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D,0);
}

//解放
@Override
public void dispose() {
if (textureId!=0) {
GLES.gl.glDeleteTextures(0,new int[]{textureId},0);
textureId=0;
}
}

//テクスチャの生成
public static Texture createInstance(Bitmap bmp) {
Texture result=new Texture();
GL11 gl=GLES.gl;
int[] bufferIds=new int[1];
gl.glGenTextures(1,bufferIds,0);
result.textureId=bufferIds[0];
result.width=bmp.getWidth();
result.height=bmp.getHeight();
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D,result.textureId);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bmp,0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D,0);
return result;
}

//テクスチャの生成
public static Texture createTextureFromAsset(
String assetFileName) throws IOException {
InputStream in=GLES.context.getAssets().open(assetFileName);
Bitmap bmp=BitmapFactory.decodeStream(in);
Texture result=Texture.createInstance(bmp);
bmp.recycle();
in.close();
return result;
}
}

2D描画用ライブラリ

2D描画のクラス郡を用意。
クラス名 説明
Graphics 2D描画のクラス。

Graphics.java
package net.npaka.gles;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;

//2Dグラフィックス
public class Graphics {
public int screenW; //画面幅
public int screenH; //画面高さ
private FloatBuffer vertexBuffer;//頂点バッファ
private FloatBuffer uvBuffer; //UVバッファ

//コンストラクタ
public Graphics(int screenW,int screenH) {
this.screenW=screenW;
this.screenH=screenH;

//頂点バッファの生成
float[] vertexs={
-1.0f, 1.0f,0.0f,//頂点0
-1.0f,-1.0f,0.0f,//頂点1
1.0f, 1.0f,0.0f,//頂点2
1.0f,-1.0f,0.0f,//頂点3
};
vertexBuffer=makeFloatBuffer(vertexs);

//UVバッファの生成
float[] uvs={
0.0f,0.0f,//左上
0.0f,1.0f,//左下
1.0f,0.0f,//右上
1.0f,1.0f,//右下
};
uvBuffer=makeFloatBuffer(uvs);
}

//2D描画の設定
public void setup2D() {
GL10 gl=GLES.gl;

//頂点配列の有効化
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

//デプステストと光源の無効化
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glDisable(GL10.GL_LIGHTING);
gl.glDisable(GL10.GL_LIGHT0);

//ブレンドの指定
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);

//射影変換
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glColor4f(1.0f,1.0f,1.0f,1.0f);
gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,uvBuffer);
}

//イメージの描画
public void drawImage(Texture texture,int x,int y) {
drawImage(texture,x,y,texture.width,texture.height);
}

//イメージの描画
public void drawImage(Texture texture,int x,int y,int w,int h) {
drawImage(texture,x,y,w,h,0,0,texture.width,texture.height);
}

//イメージの描画
public void drawImage(Texture texture,int dx,int dy,int dw,int dh,
int sx,int sy,int sw,int sh) {
GL10 gl=GLES.gl;
//ウィンドウ座標を正規化デバイス座標に変換
float tw=(float)sw/(float)texture.width;
float th=(float)sh/(float)texture.height;
float tx=(float)sx/(float)texture.width;
float ty=(float)sy/(float)texture.height;

//前処理
texture.bind();

//テクスチャ行列の移動・拡縮
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glLoadIdentity();
gl.glTranslatef(tx,ty,0.0f);
gl.glScalef(tw,th,1.0f);

//ウィンドウ座標を正規化デバイス座標に変換
float mx=((float)dx/(float)screenW)*2.0f-1.0f;
float my=((float)dy/(float)screenH)*2.0f-1.0f;
float mw=((float)dw/(float)screenW);
float mh=((float)dh/(float)screenH);

//モデルビュー行列の移動・拡大縮小
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(mx+mw,-(my+mh),0.0f);
gl.glScalef(mw,mh,1.0f);

//四角形の描画
gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);

//後処理
texture.unbind();
}

//float配列をFloatBufferに変換
private FloatBuffer makeFloatBuffer(float[] array) {
FloatBuffer fb=ByteBuffer.allocateDirect(array.length*4).order(
ByteOrder.nativeOrder()).asFloatBuffer();
fb.put(array).position(0);
return fb;
}
}


−戻る−