Subversion Repositories AndroidProjects

Rev

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Tao.OpenGl;
#pragma warning disable 0618

using BauzoidNET.math;
using BauzoidNET.graphics;
using BauzoidNET.graphics.model;
using BauzoidNET.graphics.renderstates;
using BauzoidNET.graphics.texture;

namespace BauzoidNET.graphics.sprite
{
    public class TileBatch : GraphicsObject
    {
        // Constants========================================================================================
       
            public const int POSITION_COORD_PER_ELEMENT = 3;
            public const int NORMAL_COORD_PER_ELEMENT = 3;
            public const int COLOR_COORD_PER_ELEMENT = 4;
            public const int TEXCOORD_COORD_PER_ELEMENT = 2;
       
            public static readonly Vector4 WHITE_COLOR = new Vector4(1, 1, 1, 1);
        public static readonly Vector4 BLACK_COLOR = new Vector4(0, 0, 0, 0);
       
            public const int COORDS_PER_ELEMENT = POSITION_COORD_PER_ELEMENT + COLOR_COORD_PER_ELEMENT + TEXCOORD_COORD_PER_ELEMENT;

            // Embedded Types===================================================================================

            // Fields===========================================================================================
       
            /** Number of vertices. */
            private int mSize = 0;
            private float[] mVertices = null;
            private int mNumQuads = 0;
       
    //  private SimpleGeometry mMesh = null;
            private Texture mCurrentTexture = null;
            private bool mIsDrawing = false;
       
            private VertexStream mVertexStream= null;
            private IndexStream mIndexStream = null;


            // Methods==========================================================================================

            public TileBatch(Graphics graphics)
            : this(graphics, 250)
            {
            }
       
            public TileBatch(Graphics graphics, int size)
            : base(graphics)
            {
                    mSize = size;
               
                    mVertexStream = new VertexStream(
                                    getGraphics(),
                                    VertexStream.StreamType.INTERLEAVED,
                                    "Vertices",
                                    new VertexAttribute[]
                                            {
                                                    new VertexAttribute(VertexAttribute.POSITION, POSITION_COORD_PER_ELEMENT, 0),
                                                    new VertexAttribute(VertexAttribute.COLOR, COLOR_COORD_PER_ELEMENT, POSITION_COORD_PER_ELEMENT*sizeof(float)),
                                                    new VertexAttribute(VertexAttribute.TEXCOORD0, TEXCOORD_COORD_PER_ELEMENT, (POSITION_COORD_PER_ELEMENT+COLOR_COORD_PER_ELEMENT)*sizeof(float))
                                            },
                                    false);
               
                    mIndexStream = new IndexStream(getGraphics());
               
                    mVertices = new float[size * 4 * (COORDS_PER_ELEMENT)];
                    //mCurrentVertex = 0;
                    mNumQuads = 0;
               
                    // create indices as those will stay the same
                    int len = size * 6;
                    short[] indices = new short[len];
                    short j = 0;
                    for (int i = 0; i < len; i += 6, j += 4)
                    {
                            indices[i + 0] = (short)(j + 0);
                            indices[i + 1] = (short)(j + 1);
                            indices[i + 2] = (short)(j + 2);
                            indices[i + 3] = (short)(j + 0);
                            indices[i + 4] = (short)(j + 2);
                            indices[i + 5] = (short)(j + 3);
                    }
                    mIndexStream.setData(indices);
                    mIndexStream.upload();
            }
       
            public void dispose()
            {
                    if (mVertexStream != null)
                    {
                            mVertexStream.dispose();
                            mVertexStream = null;
                    }
               
                    if (mIndexStream != null)
                    {
                            mIndexStream.dispose();
                            mIndexStream = null;
                    }
            }
       
            /** Initialize internal variables for a new batch. */
            public void begin()
            {
                    if (mIsDrawing)
                            return;
               
                    mIsDrawing = true;
                    //mCurrentVertex = 0;
                    mNumQuads = 0;
            }
       
            /** Stops collecting and renders what's left on the screen. */
            public void end()
            {
                    if (!mIsDrawing)
                            return;
               
                    if (mNumQuads == 0)
                            return;
               
                    flush();
            }
       
            /** Flush everything collected so far to screen and clear everything for new collection. */
            public void flush()
            {
                    if (mCurrentTexture == null)
                            return;
               
                    SpriteShader shader = getGraphics().getSpriteShader();
                    RenderStates rs = getRenderStates();

                    // bind VBO and upload geometry
               
                    mVertexStream.setData(mVertices, COORDS_PER_ELEMENT, COORDS_PER_ELEMENT * sizeof(float));
                    mVertexStream.reupload();          
               
                    // bind texture and render
                    rs.pushModelMatrix();
                    {
                            rs.model.identity();
                       
                            // draw sprite
                            shader.activate(mCurrentTexture, 1.0f, WHITE_COLOR, BLACK_COLOR);
                            {
                                    rs.blending.setEnabled(true);
                                    rs.culling.setEnabled(false);
                                    rs.activate();
                                    {
                                            mVertexStream.activate();
                                            mIndexStream.activate();
                                            //Gdx.gl20.glDrawElements(GL20.GL_TRIANGLES, mNumQuads*6, GL20.GL_UNSIGNED_SHORT, 0);
                        Gl.glDrawElements(Gl.GL_TRIANGLES, mNumQuads * 6, Gl.GL_UNSIGNED_SHORT, 0);
                                            mVertexStream.deactivate();
                                            mIndexStream.deactivate();
                                    }
                                    rs.deactivate();
                            }
                            shader.deactivate();
                    }
                    rs.popModelMatrix();
               
                    //mCurrentVertex = 0;
                    mNumQuads = 0;
            }
       
            /** Takes a sprite and uses its own properties to add it to the VBO. */
            public void drawSprite(SpriteInstance sprite)
            {
                    drawSprite(sprite, sprite.transform);
            }

            /** Takes a sprite and sprite properties and adds it to the VBO. */
            public void drawSprite(SpriteInstance sprite, SpriteTransform param)
            {
                    if (!isDrawing())
                            return;
               
                    if (sprite.getSprite().getTexture() != mCurrentTexture)
                            flush();
               
                    if ((mNumQuads+1) > mSize)
                            flush();
               
                    mCurrentTexture = sprite.getSprite().getTexture();
               
                    // transform quad vertices based on sprite's properties
                    SpriteRegion r = sprite.getSpriteRegion(); //sprite.getSprite().getRegion(sprite.getRegionIndex());
               
                    // bottom left and top right corner points relative to origin
                    float worldOriginX = param.x + param.pivotX;
                    float worldOriginY = param.y + param.pivotY;
                    float fx = -param.pivotX;
                    float fy = -param.pivotY;
                    float fx2 = param.w - param.pivotX;
                    float fy2 = param.h - param.pivotY;

                    // construct corner points, start from top left and go counter clockwise
                    float p1x = fx;
                    float p1y = fy;
                    float p2x = fx;
                    float p2y = fy2;
                    float p3x = fx2;
                    float p3y = fy2;
                    float p4x = fx2;
                    float p4y = fy;

                    float x1;
                    float y1;
                    float x2;
                    float y2;
                    float x3;
                    float y3;
                    float x4;
                    float y4;

                    // rotate
                    if (param.angle != 0)
                    {
                            float cos = MathUtil.cos(param.angle);
                       
                            // Angle is CCW
                            float sin = -MathUtil.sin(param.angle);

                            x1 = cos * p1x - sin * p1y;
                            y1 = sin * p1x + cos * p1y;

                            x2 = cos * p2x - sin * p2y;
                            y2 = sin * p2x + cos * p2y;

                            x3 = cos * p3x - sin * p3y;
                            y3 = sin * p3x + cos * p3y;

                            x4 = x1 + (x3 - x2);
                            y4 = y3 - (y2 - y1);
                    }
                    else
                    {
                            x1 = p1x;
                            y1 = p1y;

                            x2 = p2x;
                            y2 = p2y;

                            x3 = p3x;
                            y3 = p3y;

                            x4 = p4x;
                            y4 = p4y;
                    }

                    x1 += worldOriginX - param.pivotX;
                    y1 += worldOriginY - param.pivotY;
                    x2 += worldOriginX - param.pivotX;
                    y2 += worldOriginY - param.pivotY;
                    x3 += worldOriginX - param.pivotX;
                    y3 += worldOriginY - param.pivotY;
                    x4 += worldOriginX - param.pivotX;
                    y4 += worldOriginY - param.pivotY;
               
                    float u = r.left;
                    float v = r.top;
                    float u2 = r.right;
                    float v2 = r.bottom;

                    if (param.mirrorX)
                    {
                            float tmp = u;
                            u = u2;
                            u2 = tmp;
                    }

                    if (param.mirrorY)
                    {
                            float tmp = v;
                            v = v2;
                            v2 = tmp;
                    }
               
                    // add vertices to buffer
                    int n = mNumQuads * 4 * (COORDS_PER_ELEMENT);
               
                    mVertices[n++] = x1;
                    mVertices[n++] = y1;
                    mVertices[n++] = 0;
                    mVertices[n++] = sprite.color.x;
                    mVertices[n++] = sprite.color.y;
                    mVertices[n++] = sprite.color.z;
                    mVertices[n++] = sprite.color.w;
                    mVertices[n++] = u;
                    mVertices[n++] = v;
                    //mVertices[n++] = texCoords[0];
                    //mVertices[n++] = texCoords[1];
               
                    mVertices[n++] = x2;
                    mVertices[n++] = y2;
                    mVertices[n++] = 0;
                    mVertices[n++] = sprite.color.x;
                    mVertices[n++] = sprite.color.y;
                    mVertices[n++] = sprite.color.z;
                    mVertices[n++] = sprite.color.w;
                    mVertices[n++] = u;
                    mVertices[n++] = v2;
                    //mVertices[n++] = texCoords[2];
                    //mVertices[n++] = texCoords[3];
               
                    mVertices[n++] = x3;
                    mVertices[n++] = y3;
                    mVertices[n++] = 0;
                    mVertices[n++] = sprite.color.x;
                    mVertices[n++] = sprite.color.y;
                    mVertices[n++] = sprite.color.z;
                    mVertices[n++] = sprite.color.w;
                    mVertices[n++] = u2;
                    mVertices[n++] = v2;
                    //mVertices[n++] = texCoords[4];
                    //mVertices[n++] = texCoords[5];
               
                    mVertices[n++] = x4;
                    mVertices[n++] = y4;
                    mVertices[n++] = 0;
                    mVertices[n++] = sprite.color.x;
                    mVertices[n++] = sprite.color.y;
                    mVertices[n++] = sprite.color.z;
                    mVertices[n++] = sprite.color.w;
                    mVertices[n++] = u2;
                    mVertices[n++] = v;
                    //mVertices[n++] = texCoords[6];
                    //mVertices[n++] = texCoords[7];
               
                    //mCurrentVertex += 4;
                    mNumQuads++;
            }
       
            // Getters/Setters==================================================================================
       
       
            private bool isDrawing() { return mIsDrawing; }
       
    }
}