PDA

View Full Version : Not purely opengl but making a sprite class



blubee
09-02-2012, 10:24 PM
This question might be a little silly but I don't know the answer so I'm asking for help.

I have made it to the point where I can load textures *even atlas textures* and pull out a sub region, and also draw that region on call. I'll show code below.

My question how is how do I create a sprite class. I want it to eventually be able to support sprite batching but I am coming up a little empty right now. Here is my sprite class.


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


import android.opengl.GLES20;


public class Sprite {
final public float[] vertices = new float[20];
final public short[] indices = new short[6];
public FloatBuffer vertBuffer;
public FloatBuffer texBuffer;
public ShortBuffer indxBuffer;
Texture texture;
public float width;
public float height;
public float sMin, sMax, tMin, tMax;

public Sprite(SpriteSheetRegion region){
this.texture = region.texture;
this.width = region.width;
this.height = region.height;
this.sMax = region.sMax;
this.sMin = region.sMin;
this.tMax = region.tMax;
this.tMin = region.tMin;

vertices[0] = -width*0.5f;
vertices[1] = -height*0.5f;
vertices[2] = 0.0f;
vertices[3] = sMin;
vertices[4] = tMax;
vertices[5] = width*0.5f;
vertices[6] = -height*0.5f;
vertices[7] = 0.0f;
vertices[8] = sMax;
vertices[9] = tMax;
vertices[10] = -width*0.5f;
vertices[11] = height*0.5f;
vertices[12] = 0.0f;
vertices[13] = sMin;
vertices[14] = tMin;
vertices[15] = width*0.5f;
vertices[16] = height*0.5f;
vertices[17] = 0.0f;
vertices[18] = sMax;
vertices[19] = tMin;

System.out.println((width*0.5f)+" "+(height*0.5f));

indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 1;
indices[5] = 3;

vertBuffer = ByteBuffer.allocateDirect(vertices.length*4).order (ByteOrder.nativeOrder()).asFloatBuffer();
vertBuffer.put(vertices).position(0);
indxBuffer = ByteBuffer.allocateDirect(indices.length*2).order( ByteOrder.nativeOrder()).asShortBuffer();
indxBuffer.put(indices).position(0);
}

public Sprite(SpriteSheetRegion region, float width, float height){
this.texture = region.texture;
this.width = width;
this.height = height;
this.sMax = region.sMax;
this.sMin = region.sMin;
this.tMax = region.tMax;
this.tMin = region.tMin;

vertices[0] = -width*0.5f;
vertices[1] = -height*0.5f;
vertices[2] = 0.0f;
vertices[3] = sMin;
vertices[4] = tMax;
vertices[5] = width*0.5f;
vertices[6] = -height*0.5f;
vertices[7] = 0.0f;
vertices[8] = sMax;
vertices[9] = tMax;
vertices[10] = -width*0.5f;
vertices[11] = height*0.5f;
vertices[12] = 0.0f;
vertices[13] = sMin;
vertices[14] = tMin;
vertices[15] = width*0.5f;
vertices[16] = height*0.5f;
vertices[17] = 0.0f;
vertices[18] = sMax;
vertices[19] = tMin;

indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 1;
indices[5] = 3;

vertBuffer = ByteBuffer.allocateDirect(vertices.length*4).order (ByteOrder.nativeOrder()).asFloatBuffer();
vertBuffer.put(vertices).position(0);
indxBuffer = ByteBuffer.allocateDirect(indices.length*2).order( ByteOrder.nativeOrder()).asShortBuffer();
indxBuffer.put(indices).position(0);
}


public void draw(int program){
GLES20.glUseProgram(program);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.id);

vertBuffer.position(0);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLoc ation(program, "aPos"), 3, GLES20.GL_FLOAT, false, 20, vertBuffer);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttri bLocation(program, "aPos"));


vertBuffer.position(3);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLoc ation(program, "aTexPos"), 2, GLES20.GL_FLOAT, false, 20, vertBuffer);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttri bLocation(program, "aTexPos"));

GLES20.glUniform1i(GLES20.glGetUniformLocation(pro gram, "texture"), 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, indxBuffer);
}

@Override
public String toString(){
return texture.toString();
}
}

I basically took all the code I had in my rendering function and put it in the sprite class, from binding the textures and all. For instance, I have no idea how to rotate this sprite. Well Actually I could put a model matrix inside the sprite class but I get the feeling that's going down the wrong road. I can move the sprite horizontally by adding some uniform value to the x vertices or horizontally by adding some uniform value to the y vertices but again I feel that's going down the wrong path but honestly I don't know. Here is my rendering code now.



public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(sProgram);


Matrix.setIdentityM(modelMatrix, 0);
Matrix.translateM(modelMatrix, 0, 0.0f, 0.0f, -1.0f);


Matrix.multiplyMM(cam.combMatrix, 0, cam.viewMatrix, 0, modelMatrix, 0);
Matrix.multiplyMM(cam.combMatrix, 0, cam.projMatrix, 0, cam.combMatrix, 0);
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocat ion(sProgram, "MVPMat"), 1, false, cam.combMatrix, 0);

sp.draw(sProgram);
}


I really hope someone with a little more experience can help me out with this.
quick edit!
added videos:
1. http://www.youtube.com/watch?v=TECYZN2udSA&feature=plcp
translated, rotated, and scaled based on the camera view matrix

2.http://www.youtube.com/watch?v=0aYOIWyDiCk&feature=plcp
similar but larger image loaded.

the difference in videos show that i can get texture atlas sub regions w/o changing my code, just pass in the name of the texture sub region and do sprite.draw(glprogram);