AndroidのOpenGL ESで変換行列


とりあえず変換行列を使った平行移動とスケール変換だけ作った。
あとは回転だけなんだけどこれはクオータニオンを使うべきなのか。


というかオイラー角だとしてもクオータニオンだとしてもめんどくさそうだ。


あとMatrix3Dというクラスを作ってみたがあんまりうまく作れてない。


以下よくわかりにくい動作画面とソース。
http://screencast.com/t/NDXZ9WeRTMc

ソース

DisplayObject3D.java

package net.swelt.android.opengltest;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;

public class DisplayObject3D {
	protected IntBuffer mVertexBuffer;
	protected IntBuffer mColorBuffer;
	protected IntBuffer mTransformBuffer;
	protected ByteBuffer mIndexBuffer;
	private int x = 0;
	private int y = 0;
	private int z = 0;
	private boolean visible = true;
	private boolean picking = true;
	private String name = "";
	protected float scaleX = 1.0f;
	protected float scaleY = 1.0f;
	protected float scaleZ = 1.0f;	
	protected Matrix3D transform = new Matrix3D();
	protected boolean transformDirty = true;
	
	public void update() {
		if( transformDirty ) updateTransform();
	}
	
	public void draw(GL10 gl) {
		gl.glVertexPointer(3, GL10.GL_FIXED, 0, mTransformBuffer);
		gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
		gl.glDrawElements(GL10.GL_TRIANGLES, mIndexBuffer.capacity(), GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
	}
	
	public void reset() {
		x = 0;
		y = 0;
		z = 0;
		scaleX = 1.0f;
		scaleY = 1.0f;
		scaleZ = 1.0f;
		
		transformDirty = true;
	}
	
	public void move(int x, int y, int z) {
		this.x = x;
		this.y = y;
		this.z = z;
		
		transformDirty = true;
	}
	
	public void translate(int x, int y, int z) {
		this.x += x;
		this.y += y;
		this.z += z;
		
		transformDirty = true;
	}
	
	public int getX() { return x; };
	public int getY() { return y; };
	public int getZ() { return z; };

	public void setX(int x) {
		this.x = x;
		
		transformDirty = true;
	}
	
	public void setY(int y) {
		this.y = y;
		
		transformDirty = true;
	}
	
	public void setZ(int z) {
		this.z = z;
		
		transformDirty = true;
	}
	//-----scale
	public float getScale() { return scaleX; };
	public float getScaleX() { return scaleX; };
	public float getScaleY() { return scaleY; };
	public float getScaleZ() { return scaleZ; };
	
	public void setScale(float scale) {
		scaleX = scaleY = scaleZ = scale;
		
		transformDirty = true;
	}
	
	//-----visibility
	public boolean getVisibility() { return visible; };	
	public void setVisibility(boolean visible) {
		this.visible = visible;
	}
	
	//-----picking
	public boolean getPicking() { return picking; };	
	public void setPicking(boolean picking) {
		this.picking = picking;
	}
	
	//-----name
	public String getName() { return name; };
	public void setName(String name) {
		this.name = name;
	}
		
	//-----transform
	public void updateTransform() {
		Matrix3D transform = new Matrix3D(Matrix3D.IDENTITY);
		transform.set(41, x);
		transform.set(42, y);
		transform.set(43, z);
		
		Matrix3D scaleM = new Matrix3D();
		scaleM.set(11, scaleX);
		scaleM.set(22, scaleY);
		scaleM.set(33, scaleZ);
		scaleM.set(44, 1.0f);
		
		this.transform.calc(transform, scaleM);
		
		Matrix3D vertexM = new Matrix3D();
		Matrix3D r = new Matrix3D();
		vertexM.set(14, 1.0f);
		for( int i = 0; i < mVertexBuffer.capacity(); i += 3 ) {
			vertexM.set(11, (float)mVertexBuffer.get(i));
			vertexM.set(12, (float)mVertexBuffer.get(i+1));
			vertexM.set(13, (float)mVertexBuffer.get(i+2));
						
			r.calc(vertexM, this.transform);
			
			mTransformBuffer.put(i, (int)r.get(11));
			mTransformBuffer.put(i+1, (int)r.get(12));
			mTransformBuffer.put(i+2, (int)r.get(13));;
		}
		
		transformDirty = false;
	}
	
	//-----string
	public String toString() {
		String s;
		
		s = "x:" + x + " y:" + y + " z:" + z + "\n";
		s += "scaleX:" + scaleX + "\nscaleY:" + scaleY + "\nscaleZ:" + scaleZ + "\n";
		
		return s;
		
	}
}


Matrix3D.java

package net.swelt.android.opengltest;

public class Matrix3D {
	public static float[] IDENTITY = {1.0f, 0, 0, 0,
									  0, 1.0f, 0, 0,
									  0, 0, 1.0f, 0,
									  0, 0, 0, 1.0f};
	
	private float n11 = 0;
	private float n12 = 0;
	private float n13 = 0;
	private float n14 = 0;
	private float n21 = 0;
	private float n22 = 0;
	private float n23 = 0;
	private float n24 = 0;
	private float n31 = 0;
	private float n32 = 0;
	private float n33 = 0;
	private float n34 = 0;
	private float n41 = 0;
	private float n42 = 0;
	private float n43 = 0;
	private float n44 = 0;
	
	public Matrix3D() {		
	}
	
	public Matrix3D(float[] ar) {
		set(ar);
	}
	
	public float get(int index) {
		switch( index ) {
		case 11: return n11;
		case 12: return n12;
		case 13: return n13;
		case 14: return n14;
		case 21: return n21;
		case 22: return n22;
		case 23: return n23;
		case 24: return n24;
		case 31: return n31;
		case 32: return n32;
		case 33: return n33;
		case 34: return n34;
		case 41: return n41;
		case 42: return n42;
		case 43: return n43;
		case 44: return n44;
		}
		return 0;
	}
	
	public void set(int index, float n) {
		switch( index ) {
		case 11: n11 = n; break;
		case 12: n12 = n; break;
		case 13: n13 = n; break;
		case 14: n14 = n; break;
		case 21: n21 = n; break;
		case 22: n22 = n; break;
		case 23: n23 = n; break;
		case 24: n24 = n; break;
		case 31: n31 = n; break;
		case 32: n32 = n; break;
		case 33: n33 = n; break;
		case 34: n34 = n; break;
		case 41: n41 = n; break;
		case 42: n42 = n; break;
		case 43: n43 = n; break;
		case 44: n44 = n; break;
		}		
	}
	
	public void set(float[] ar) {
		if( ar.length >= 12 ) {
			n11 = ar[0]; n12 = ar[1]; n13 = ar[2]; n14 = ar[3];
			n21 = ar[4]; n22 = ar[5]; n23 = ar[6]; n24 = ar[7];
			n31 = ar[8]; n32 = ar[9]; n33 = ar[10]; n34 = ar[11];
			n41 = ar[12]; n42 = ar[13]; n43 = ar[14]; n44 = ar[15];
		}		
	}
	
	public float[] get() {
		return new float[] {n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44};
	}

	public void calc(Matrix3D a, Matrix3D b) {
		float[] m1 = a.get();
		float[] m2 = b.get();
		float[] r = new float[m1.length];
		
		for( int j = 0; j < 4; ++ j ) {
			for( int i = 0; i < 4; ++ i ) {
				int n = 4*j;
				r[n+i] = m1[n]*m2[i]+m1[n+1]*m2[4+i]+m1[n+2]*m2[8+i]+m1[n+3]*m2[12+i];
			}
		}
		
		set(r);
	}

	//-----string
	public String toString() {
		String s;
		
		s = "" + n11 + "," + n12 + "," + n13 + "," + n14 + "\n";
		s += "" + n21 + "," + n22 + "," + n23 + "," + n24 + "\n";
		s += "" + n31 + "," + n32 + "," + n33 + "," + n34 + "\n";
		s += "" + n41 + "," + n42 + "," + n43 + "," + n44 + "\n";
		
		return s;
	}
}