Rev 1728 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
package com.gebauz.bauzoid2.graphics.sprite;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.gebauz.bauzoid2.game.Consts;
import com.gebauz.bauzoid2.game.Engine;
import com.gebauz.bauzoid2.graphics.geometry.IndexStream;
import com.gebauz.bauzoid2.graphics.geometry.VertexAttribute;
import com.gebauz.bauzoid2.graphics.geometry.VertexStream;
import com.gebauz.bauzoid2.math.MathUtil;
import com.gebauz.bauzoid2.math.Vector4;
/** Batcher that collects Texture draw calls and batches them into a single VBO.
* A possibly faster alternative to Sprite and AtlasSprite which have rather
* small geometry objects.
*
* It is designed to be easy to convert code that used AtlasSprite and Sprite
* to use TileBatch instead.
*
* Also contains convenience functions to import Sprite and AtlasSprite info.
*
* @author chiu
*
*/
public class TileBatch
{
// Constants========================================================================================
public static final int POSITION_COORD_PER_ELEMENT = 3;
public static final int NORMAL_COORD_PER_ELEMENT = 3;
public static final int COLOR_COORD_PER_ELEMENT = 4;
public static final int TEXCOORD_COORD_PER_ELEMENT = 2;
public static final Vector4 WHITE_COLOR = new Vector4(1, 1, 1, 1);
public static final Vector4 BLACK_COLOR = new Vector4(0, 0, 0, 0);
public static final 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 boolean mIsDrawing = false;
private VertexStream mVertexStream= null;
private IndexStream mIndexStream = null;
// Methods==========================================================================================
public TileBatch()
{
this(250);
}
public TileBatch( int size)
{
mSize = size;
mVertexStream = new VertexStream(
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*Consts.SIZEOF_FLOAT),
new VertexAttribute(VertexAttribute.TEXCOORD0, TEXCOORD_COORD_PER_ELEMENT, (POSITION_COORD_PER_ELEMENT+COLOR_COORD_PER_ELEMENT)*Consts.SIZEOF_FLOAT)
},
false);
mIndexStream = new IndexStream();
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 = Engine.graphics.getSpriteShader();
// bind VBO and upload geometry
mVertexStream.setData(mVertices, COORDS_PER_ELEMENT, COORDS_PER_ELEMENT * Consts.SIZEOF_FLOAT);
mVertexStream.reupload();
// bind texture and render
Engine.graphics.renderStates.pushModelMatrix();
{
Engine.graphics.renderStates.model.identity();
// draw sprite
shader.activate(mCurrentTexture, 1.0f, WHITE_COLOR, BLACK_COLOR);
{
Engine.graphics.renderStates.blending.setEnabled(true);
Engine.graphics.renderStates.culling.setEnabled(false);
Engine.graphics.renderStates.activate();
{
mVertexStream.activate();
mIndexStream.activate();
Gdx.gl20.glDrawElements(GL20.GL_TRIANGLES, mNumQuads*6, GL20.GL_UNSIGNED_SHORT, 0);
mVertexStream.deactivate();
mIndexStream.deactivate();
}
Engine.graphics.renderStates.deactivate();
}
shader.deactivate();
}
Engine.graphics.renderStates.popModelMatrix();
//mCurrentVertex = 0;
mNumQuads = 0;
}
/** Takes a sprite and uses its own properties to add it to the VBO. */
/*public void drawSprite(Sprite sprite)
{
drawSprite(sprite, sprite.transform);
}*/
/** Takes a sprite and sprite properties and adds it to the VBO. */
public void drawSprite(SpriteSheetRegion r, SpriteTransform transform)
{
if (!isDrawing())
return;
if (r.getOwner().getTexture() != mCurrentTexture)
flush();
if ((mNumQuads+1) > mSize)
flush();
mCurrentTexture = r.getOwner().getTexture();
// transform quad vertices based on sprite's properties
//SpriteSheetRegion r = sprite.getSpriteRegion(); //sprite.getSprite().getRegion(sprite.getRegionIndex());
// bottom left and top right corner points relative to origin
final float worldOriginX = transform.x + transform.pivotX;
final float worldOriginY = transform.y + transform.pivotY;
float fx = -transform.pivotX;
float fy = -transform.pivotY;
float fx2 = transform.w - transform.pivotX;
float fy2 = transform.h - transform.pivotY;
// construct corner points, start from top left and go counter clockwise
final float p1x = fx;
final float p1y = fy;
final float p2x = fx;
final float p2y = fy2;
final float p3x = fx2;
final float p3y = fy2;
final float p4x = fx2;
final float p4y = fy;
float x1;
float y1;
float x2;
float y2;
float x3;
float y3;
float x4;
float y4;
// rotate
if (transform.angle != 0)
{
final float cos = MathUtil.cos(transform.angle);
// Angle is CCW
final float sin = -MathUtil.sin(transform.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 - transform.pivotX;
y1 += worldOriginY - transform.pivotY;
x2 += worldOriginX - transform.pivotX;
y2 += worldOriginY - transform.pivotY;
x3 += worldOriginX - transform.pivotX;
y3 += worldOriginY - transform.pivotY;
x4 += worldOriginX - transform.pivotX;
y4 += worldOriginY - transform.pivotY;
float u = r.left;
float v = r.top;
float u2 = r.right;
float v2 = r.bottom;
if (transform.mirrorX)
{
float tmp = u;
u = u2;
u2 = tmp;
}
if (transform.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++] = transform.color.x;
mVertices[n++] = transform.color.y;
mVertices[n++] = transform.color.z;
mVertices[n++] = transform.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++] = transform.color.x;
mVertices[n++] = transform.color.y;
mVertices[n++] = transform.color.z;
mVertices[n++] = transform.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++] = transform.color.x;
mVertices[n++] = transform.color.y;
mVertices[n++] = transform.color.z;
mVertices[n++] = transform.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++] = transform.color.x;
mVertices[n++] = transform.color.y;
mVertices[n++] = transform.color.z;
mVertices[n++] = transform.color.w;
mVertices[n++] = u2;
mVertices[n++] = v;
//mVertices[n++] = texCoords[6];
//mVertices[n++] = texCoords[7];
//mCurrentVertex += 4;
mNumQuads++;
}
// Getters/Setters==================================================================================
private boolean isDrawing() { return mIsDrawing; }
}