Subversion Repositories AndroidProjects

Rev

Rev 168 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.gebauz.Bauzoid.graphics.model;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import android.opengl.GLES20;

import com.gebauz.Bauzoid.math.Vector2;
import com.gebauz.Bauzoid.math.Vector3;
import com.gebauz.Bauzoid.math.Vector4;

/** Simple Geometry class that manages vertex buffers and index buffers. */
public class SimpleGeometry
{
    static final int SIZEOF_FLOAT = Float.SIZE / 8;
    static final int SIZEOF_SHORT = Short.SIZE / 8;
       
        /** Helper class to fill an array with vertex information. */
        public static class AttributeArray
        {
                private float[] mAttributeArray;
                private int mCurrentIndex = 0;
               
                public AttributeArray(int size)
                {
                        mAttributeArray = new float[size];
                        mCurrentIndex = 0;
                }
               
                public void fill(float x)
                {
                        mAttributeArray[mCurrentIndex] = x; mCurrentIndex++;
                }
               
                public void fill(float x, float y)
                {
                        mAttributeArray[mCurrentIndex] = x; mCurrentIndex++;
                        mAttributeArray[mCurrentIndex] = y; mCurrentIndex++;
                }
               
                public void fill(float x, float y, float z)
                {
                        mAttributeArray[mCurrentIndex] = x; mCurrentIndex++;
                        mAttributeArray[mCurrentIndex] = y; mCurrentIndex++;           
                        mAttributeArray[mCurrentIndex] = z; mCurrentIndex++;
                }
               
                public void fill(float x, float y, float z, float w)
                {
                        mAttributeArray[mCurrentIndex] = x; mCurrentIndex++;
                        mAttributeArray[mCurrentIndex] = y; mCurrentIndex++;           
                        mAttributeArray[mCurrentIndex] = z; mCurrentIndex++;
                        mAttributeArray[mCurrentIndex] = w; mCurrentIndex++;                   
                }
               
                public float[] getAttributeArray()
                {
                        return mAttributeArray;
                }
               
                public int getUsedCount()
                {
                        return mCurrentIndex;
                }
        }
       
        public class AttributeBuffer
        {
                public ByteBuffer byteBuffer;
                public FloatBuffer floatBuffer;
                public int length = 0;
               
                private int mID = 0;
               
                public AttributeBuffer()
                {
                }
               
                public AttributeBuffer(float data[])
                {
                        setData(data);
                }
               
                public void setData(float data[])
                {
                        byteBuffer = ByteBuffer.allocateDirect(data.length * 4);
                        byteBuffer.order(ByteOrder.nativeOrder());
                        floatBuffer = byteBuffer.asFloatBuffer();
                        floatBuffer.put(data);
                        floatBuffer.position(0);
                        length = data.length;
                }
               
                public void createBuffer()
                {
                        GLES20.glGenBuffers(1, BUFFERID, 0);
                        mID = BUFFERID[0];
                       
                        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mID);
                        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, floatBuffer.capacity() * SIZEOF_FLOAT, floatBuffer, GLES20.GL_STATIC_DRAW);
                        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
                }
               
                public void destroyBuffer()
                {
                        if (mID != 0)
                        {
                                BUFFERID[0] = mID;
                                GLES20.glDeleteBuffers(1, BUFFERID, 0);
                                mID = 0;
                        }
                }
               
                public void bindBuffer(int attribHandle, int numComponents)
                {
                        // TODO: state tracking for bindbuffer                 
                       
                        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mID);
                        GLES20.glVertexAttribPointer(attribHandle, numComponents, GLES20.GL_FLOAT, false, 0, 0);
                        GLES20.glEnableVertexAttribArray(attribHandle);
                }
               
                public void unbindBuffer()
                {
                        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
                }
        }
       
        public class IndexBuffer
        {
                public ByteBuffer byteBuffer;
                public ShortBuffer shortBuffer;
                public int length = 0;
               
                private int mID = 0;

                public IndexBuffer()
                {
                }
               
                public IndexBuffer(short data[])
                {
                        setData(data);
                }
               
                public void setData(short data[])
                {
                        byteBuffer = ByteBuffer.allocateDirect(data.length * 2);
                        byteBuffer.order(ByteOrder.nativeOrder());
                        shortBuffer = byteBuffer.asShortBuffer();
                        shortBuffer.put(data);
                        shortBuffer.position(0);
                        length = data.length;
                }
               
                public void createBuffer()
                {
                        GLES20.glGenBuffers(1, BUFFERID, 0);
                        mID = BUFFERID[0];
                       
                        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mID);
                        GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, shortBuffer.capacity() * SIZEOF_SHORT, shortBuffer, GLES20.GL_STATIC_DRAW);
                        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
                }
               
                public void destroyBuffer()
                {
                        if (mID != 0)
                        {
                                BUFFERID[0] = mID;
                                GLES20.glDeleteBuffers(1, BUFFERID, 0);
                                mID = 0;
                        }
                }
               
                public void bindBuffer()
                {
                        if (mID == 0)
                                return;
                       
                        // TODO: state tracking for bindbuffer
                       
                        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mID);
                }
               
                public void unbindBuffer()
                {
                        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
                }
        }
       
        private AttributeBuffer mVertexBuffer = null;
        private AttributeBuffer mColorBuffer = null;
        private AttributeBuffer mNormalBuffer = null;
        private AttributeBuffer mTexCoordBuffer = null;
        private IndexBuffer mIndexBuffer = null;
       
        public static final int COORD_ELEMENTS_COUNT = 3;
        public static final int COLOR_ELEMENTS_COUNT = 4;
        public static final int TEX_COORD_ELEMENTS_COUNT = 2;
        public static final int NORMAL_ELEMENTS_COUNT = 3;
       
        private int mPrimitiveType = GLES20.GL_TRIANGLES;
       
        public static final int COORD_ATTRIB_INDEX = 0;
        public static final int COLOR_ATTRIB_INDEX = 1;
        public static final int TEX_COORD_ATTRIB_INDEX = 2;
        public static final int NORMAL_ATTRIB_INDEX = 3;
       
        public static int BUFFERID[] = new int[1];
       
        public SimpleGeometry()
        {
               
        }
       
        /** Create the vertex buffer objects after modifying the attribute buffers. */
        public void createBuffers()
        {
                if (mVertexBuffer != null)
                        mVertexBuffer.createBuffer();
               
                if (mColorBuffer != null)
                        mColorBuffer.createBuffer();
               
                if (mNormalBuffer != null)
                        mNormalBuffer.createBuffer();
               
                if (mTexCoordBuffer != null)
                        mTexCoordBuffer.createBuffer();
               
                if (mIndexBuffer != null)
                        mIndexBuffer.createBuffer();
        }
       
        /** Destroy all buffers. */
        public void destroyBuffers()
        {
                if (mVertexBuffer != null)
                        mVertexBuffer.destroyBuffer();
               
                if (mColorBuffer != null)
                        mColorBuffer.destroyBuffer();
               
                if (mNormalBuffer != null)
                        mNormalBuffer.destroyBuffer();
               
                if (mTexCoordBuffer != null)
                        mTexCoordBuffer.destroyBuffer();
               
                if (mIndexBuffer != null)
                        mIndexBuffer.destroyBuffer();
        }
       
        /** Activate the vertex buffer for rendering */
        public void activate()
        {              
                if (mVertexBuffer != null)
                        mVertexBuffer.bindBuffer(COORD_ATTRIB_INDEX, COORD_ELEMENTS_COUNT);
               
                if (mColorBuffer != null)
                        mColorBuffer.bindBuffer(COLOR_ATTRIB_INDEX, COLOR_ELEMENTS_COUNT);

                if (mNormalBuffer != null)
                        mNormalBuffer.bindBuffer(NORMAL_ATTRIB_INDEX, NORMAL_ELEMENTS_COUNT);

                if (mTexCoordBuffer != null)
                        mTexCoordBuffer.bindBuffer(TEX_COORD_ATTRIB_INDEX, TEX_COORD_ELEMENTS_COUNT);

                if (mIndexBuffer != null)
                        mIndexBuffer.bindBuffer();
        }
       
        /**
         * Deactivate the vertex buffer for rendering
         */

        public void deactivate()
        {
                if (mVertexBuffer != null)
                        mVertexBuffer.unbindBuffer();
               
                if (mColorBuffer != null)
                        mColorBuffer.unbindBuffer();

                if (mNormalBuffer != null)
                        mNormalBuffer.unbindBuffer();

                if (mTexCoordBuffer != null)
                        mTexCoordBuffer.unbindBuffer();

                if (mIndexBuffer != null)
                        mIndexBuffer.unbindBuffer();
        }
       
        public void setPrimitiveType(int primitiveType)
        {
                mPrimitiveType = primitiveType;
        }
       
        /**
         * Render the vertex buffer
         */

        public void render()
        {              
                activate();
               
                if (mIndexBuffer != null)
                {
                        GLES20.glDrawElements(mPrimitiveType, mIndexBuffer.length, GLES20.GL_UNSIGNED_SHORT, 0);
                }
                else
                {
                        GLES20.glDrawArrays(mPrimitiveType, 0, mVertexBuffer.length);
                }
               
                deactivate();
               
/*              GL10 gl = GLUtil.getGL();
               
                activate();
               
                if (mIndexBuffer != null)
                {
                        // indexed drawing
                        gl.glDrawElements(mPrimitiveType, mIndexBuffer.length, GL10.GL_UNSIGNED_SHORT, mIndexBuffer.shortBuffer);
                }
                else if (mVertexBuffer != null)
                {                      
                        // non-indexed drawing
                        gl.glDrawArrays(mPrimitiveType, 0, mVertexBuffer.length);
                }
               
                deactivate();*/

        }
       
        /**
         * Render the vertex buffer with a specified amount of primitives
         */

        public void render(int numPrimitives)
        {
/*              GL10 gl = GLUtil.getGL();
               
                activate();
               
                if (mIndexBuffer != null)
                {
                        // indexed drawing
                        gl.glDrawElements(mPrimitiveType, numPrimitives, GL10.GL_UNSIGNED_SHORT, mIndexBuffer.shortBuffer);
                }
                else if (mVertexBuffer != null)
                {                      
                        // non-indexed drawing
                        gl.glDrawArrays(mPrimitiveType, 0, numPrimitives);
                }
               
                deactivate();*/

        }
       
        public void setVertices(float vertices[])
        {
                if (vertices == null)
                {
                        mVertexBuffer = null;
                        return;
                }
               
                mVertexBuffer = new AttributeBuffer(vertices);         
        }
       
        public void setColors(float colors[])
        {
                if (colors == null)
                {
                        mColorBuffer = null;
                        return;
                }
               
                mColorBuffer = new AttributeBuffer(colors);    
        }
       
        public void setNormals(float normals[])
        {
                if (normals == null)
                {
                        mNormalBuffer = null;
                        return;
                }
               
                mNormalBuffer = new AttributeBuffer(normals);  
        }
       
        public void setTexCoords(float texCoords[])
        {
                if (texCoords == null)
                {
                        mTexCoordBuffer = null;
                        return;
                }
               
                mTexCoordBuffer = new AttributeBuffer(texCoords);      
        }
       
        public void setIndices(short indices[])
        {
                if (indices == null)
                {
                        mIndexBuffer = null;
                        return;
                }
               
                mIndexBuffer = new IndexBuffer(indices);       
        }
       
        public void setVertex(int index, Vector3 vertex)
        {
                mVertexBuffer.floatBuffer.put(index * COORD_ELEMENTS_COUNT + 0, vertex.x);
                mVertexBuffer.floatBuffer.put(index * COORD_ELEMENTS_COUNT + 1, vertex.y);
                mVertexBuffer.floatBuffer.put(index * COORD_ELEMENTS_COUNT + 2, vertex.z);
        }
       
        public Vector3 getVertex(int index)
        {
                return new Vector3(
                                mVertexBuffer.floatBuffer.get(index * COORD_ELEMENTS_COUNT + 0),
                                mVertexBuffer.floatBuffer.get(index * COORD_ELEMENTS_COUNT + 1),
                                mVertexBuffer.floatBuffer.get(index * COORD_ELEMENTS_COUNT + 2));
        }
       
        public int getVertexCount()
        {
                return mVertexBuffer.floatBuffer.limit() / COORD_ELEMENTS_COUNT;
        }
       
        public void setColor(int index, Vector4 color)
        {
                mColorBuffer.floatBuffer.put(index * COLOR_ELEMENTS_COUNT + 0, color.x);
                mColorBuffer.floatBuffer.put(index * COLOR_ELEMENTS_COUNT + 1, color.y);
                mColorBuffer.floatBuffer.put(index * COLOR_ELEMENTS_COUNT + 2, color.z);
                mColorBuffer.floatBuffer.put(index * COLOR_ELEMENTS_COUNT + 3, color.w);
        }
       
        public int getColorCount()
        {
                return mColorBuffer.floatBuffer.limit() / COLOR_ELEMENTS_COUNT;
        }
       
        public Vector4 getColor(int index)
        {
                return new Vector4(
                                mColorBuffer.floatBuffer.get(index * COLOR_ELEMENTS_COUNT + 0),
                                mColorBuffer.floatBuffer.get(index * COLOR_ELEMENTS_COUNT + 1),
                                mColorBuffer.floatBuffer.get(index * COLOR_ELEMENTS_COUNT + 2),
                                mColorBuffer.floatBuffer.get(index * COLOR_ELEMENTS_COUNT + 3));
        }
       
        public void setNormal(int index, Vector3 normal)
        {
                mNormalBuffer.floatBuffer.put(index * NORMAL_ELEMENTS_COUNT + 0, normal.x);
                mNormalBuffer.floatBuffer.put(index * NORMAL_ELEMENTS_COUNT + 1, normal.y);
                mNormalBuffer.floatBuffer.put(index * NORMAL_ELEMENTS_COUNT + 2, normal.z);
        }

        public Vector3 getNormal(int index)
        {
                return new Vector3(
                                mNormalBuffer.floatBuffer.get(index * NORMAL_ELEMENTS_COUNT + 0),
                                mNormalBuffer.floatBuffer.get(index * NORMAL_ELEMENTS_COUNT + 1),
                                mNormalBuffer.floatBuffer.get(index * NORMAL_ELEMENTS_COUNT + 2));
        }
       
        public int getNormalCount()
        {
                return mNormalBuffer.floatBuffer.limit() / NORMAL_ELEMENTS_COUNT;
        }
       
        public void setTexCoord(int index, Vector2 texCoord)
        {
                mTexCoordBuffer.floatBuffer.put(index * TEX_COORD_ELEMENTS_COUNT + 0, texCoord.x);
                mTexCoordBuffer.floatBuffer.put(index * TEX_COORD_ELEMENTS_COUNT + 1, texCoord.y);
        }
       
        public Vector2 getTexCoord(int index)
        {
                return new Vector2(
                                mTexCoordBuffer.floatBuffer.get(index * TEX_COORD_ELEMENTS_COUNT + 0),
                                mTexCoordBuffer.floatBuffer.get(index * TEX_COORD_ELEMENTS_COUNT + 1));
        }      
       
        public int getTexCoordCount()
        {
                return mTexCoordBuffer.floatBuffer.limit() / TEX_COORD_ELEMENTS_COUNT;
        }
}