« AndroidのOpenGLで透視投影 | トップページ | AndroidのOpenGLでテクスチャにはまる »

AndroidのOpenGL ESで高レベルオブジェクト

少し前にPaperVision3Dを使って3D系の物を作っていたので、 OpenGL流の頂点がなんたらかんたら、という扱いが非常にめんどくさく感じる。

そこで、そこらへんをカプセル化して使えるオブジェクトを作ってみた。 イメージとしては、PaperVision3Dで言うところのPlaneが近い。

class TexturePlane{
    private ByteBuffer  mIndexBuffer;
    private IntBuffer   mVertexBuffer;
    private IntBuffer mTextureBuffer;
    private int texid;
    private int x, y, z;
    private int rotateX, rotateY, rotateZ;

    int one = 0x10000;
    int vertices[] = {
           -one, -one, 0,
            one, -one, 0,
            one,  one, 0,
           -one,  one, 0,
        };
       
    byte indices[] = {
            0, 1, 2,    2, 3, 0
    };
int textures[] = {
one, one,
0, one,
0, 0,
one, 0
};
   
    public TexturePlane(int texid){
    mVertexBuffer = createIntBuffer(vertices);
    mIndexBuffer = createByteBuffer(indices);
    mTextureBuffer = createIntBuffer(textures);
    this.texid = texid;
    }
   
    public void setX(int x){
    this.x = x;
    for(int i = 0; i < vertices.length; i+=3){
        mVertexBuffer.put(i, vertices[i] + x);
    }
    }
   
    public void setY(int y){
    this.y = y;
    for(int i = 1; i < vertices.length; i+=3){
        mVertexBuffer.put(i, vertices[i] + y);
    }
    }
   
    public void setZ(int z){
    this.z = z;
    for(int i = 2; i < vertices.length; i+=3){
        mVertexBuffer.put(i, vertices[i] + z);
    }
    }
   
    public void setRotateX(int rotateX){
    this.rotateX = rotateX;
    for(int i = 1; i < vertices.length; i+=3){
    double y = (double)(vertices[i]) / 0x10000;
    double z = (double)(vertices[i+1]) / 0x10000;
    int flagY = y > 0 ? 1 : -1;
    double r = Math.sqrt(y * y + z * z);
        mVertexBuffer.put(i,
        flagY * (int)(r * Math.cos(rotateX * Math.PI / 0x10000) * 0x10000) + this.y);
        mVertexBuffer.put(i+1,
        - flagY * (int)(r * Math.sin(rotateX * Math.PI / 0x10000) * 0x10000) + this.z);
    }
    }
   
    public void setRotateY(int rotateY){
    this.rotateY = rotateY;
    for(int i = 0; i < vertices.length; i+=3){
    double x = (double)(vertices[i]) / 0x10000;
    double z = (double)(vertices[i+2]) / 0x10000;
    int flagX = x > 0 ? 1 : -1;
    double r = Math.sqrt(x * x + z * z);
        mVertexBuffer.put(i,
        flagX * (int)(r * Math.cos(rotateY * Math.PI / 0x10000) * 0x10000) + this.x);
        mVertexBuffer.put(i+2,
        - flagX * (int)(r * Math.sin(rotateY * Math.PI / 0x10000) * 0x10000) + this.z);
    }
    }
   
    public void setRotateZ(int rotateZ){
    this.rotateZ = rotateZ;
    for(int i = 0; i < vertices.length; i+=3){
    double x = (double)(vertices[i]) / 0x10000;
    double y = (double)(vertices[i+1]) / 0x10000;
    int flagX = x > 0 ? 1 : -1;
    double r = Math.sqrt(x * x + y * y);
        mVertexBuffer.put(i,
        flagX * (int)(r * Math.cos(rotateZ * Math.PI / 0x10000) * 0x10000) + this.x);
        mVertexBuffer.put(i+1,
        - flagX * (int)(r * Math.sin(rotateZ * Math.PI / 0x10000) * 0x10000) + this.y);
    }
    }
   
    public int getX(){return x;}
    public int getY(){return y;}
    public int getZ(){return z;}
    public int getRotateX(){return rotateX;}
    public int getRotateY(){return rotateY;}
    public int getRotateZ(){return rotateZ;}
    public int getTextureID(){return texid;}
   
    public void render(GL10 gl){
        gl.glColor4f(1f, 1f, 1f, 1f);

gl.glBindTexture(gl.GL_TEXTURE_2D, texid);

        gl.glTexCoordPointer(2, gl.GL_FIXED, 0, mTextureBuffer);
        gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);
        gl.glDrawElements(gl.GL_TRIANGLES, 6, gl.GL_UNSIGNED_BYTE, mIndexBuffer);
    }
   
    public static IntBuffer createIntBuffer(int[] data){
    ByteBuffer buffer = ByteBuffer.allocateDirect(data.length * 4);
    buffer.order(ByteOrder.nativeOrder());
    IntBuffer ret = buffer.asIntBuffer();
    ret.put(data);
    ret.position(0);
   
    return ret;
    }

    public static FloatBuffer createFloatBuffer(float[] data){
    ByteBuffer buffer = ByteBuffer.allocateDirect(data.length * 4);
    buffer.order(ByteOrder.nativeOrder());
    FloatBuffer ret = buffer.asFloatBuffer();
    ret.put(data);
    ret.position(0);
   
    return ret;
    }
   
    public static ByteBuffer createByteBuffer(byte[] data){
    ByteBuffer buffer = ByteBuffer.allocateDirect(data.length);
    buffer.order(ByteOrder.nativeOrder());
    buffer.put(data);
    buffer.position(0);
    return buffer;
    }
}

使い方は、テクスチャを自前で生成して、そのテクスチャ番号を コンストラクタに与える。あとは適当にパラメータを設定して renderメソッドでレンダリング。

まだ拡大縮小をサポートしていなかったり、テクスチャを作るまでが 自前だったりするので、そこらへんを拡張予定。

|

« AndroidのOpenGLで透視投影 | トップページ | AndroidのOpenGLでテクスチャにはまる »

コメント

hello,if I want to make the plane's length can be changed by the user ,could you tell me what should i do or can you show me the codes ? thanks

投稿: | 2008年2月21日 (木) 12時33分

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/486213/9026188

この記事へのトラックバック一覧です: AndroidのOpenGL ESで高レベルオブジェクト:

« AndroidのOpenGLで透視投影 | トップページ | AndroidのOpenGLでテクスチャにはまる »