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; } }