I have an application that receives information from a database, and is used to visualize 2D bitmaps onto a GLSurfaceView. The information received will determine the x-position of the bitmap, and which bitmap image to use (there are 4 different bitmaps in my res folder to choose from).
Below are the three classes that are being used. The Activity sets the Shapes objects that need to be drawn by passing an ArrayList to the GLLayer class. This ArrayList is passed to the instance of ShapeStorage class via another setList method. This class is responsible for drawing when they are received.
The problem that I'm having is the following. Suppose I receive one object (let's say that it's a square at it's located at x=1). Some time goes by, and I receive another shape (this time, it's a triangle, and it's located at x=-1). However, when this new shape appears on the screen, the old bitmap's appearance changes to a triangle, and the new one becomes a square. In other words, the objects themselves are at the correct position that they are supposed to be at, but the bitmap being associated with them has changed. Does anyone know what the possible cause of this can be? I'm still a newbie to OpenGL-ES, and while this code looks very convoluted, it just involves setting a bunch of various properties for the View. Please help me, StackOverflow! You're my only hope.
public class GLLayer extends GLSurfaceView implements Renderer {
int onDrawFrameCounter=1;
int[] cameraTexture;
byte[] glCameraFrame=new byte[256*256]; //size of a texture must be a power of 2
private Context context;
FloatBuffer cubeBuff;
FloatBuffer texBuff;
ShapeStorage shapes;
ArrayList<Shapes> shapereceptionbuffer;
public GLLayer(Context c) {
super(c);
this.context=c;
//Initiate our stars class with the number of stars
shapes = new ShapeStorage();
shapereceptionbuffer=new ArrayList<Shapes>();
this.setEGLConfigChooser(5, 6, 5, 8, 16, 0);
this.setRenderer(this); //set the following class as a GLSurfaceView renderer
this.getHolder().setFormat(PixelFormat.TRANSPARENT); //makes the GLSurfaceView translucent
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
try {
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping
gl.glEnable(GL10.GL_BLEND); //Enable blending
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Black Background
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glDisable(GL10.GL_DEPTH_TEST); //Disable depth test
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); //Set The Blending Function For Translucency
shapes.setTextures(gl,context);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Created",e.getMessage());
}
}//end of surfacecreated
public void setList(ArrayList<Shapes> receivedList){
synchronized(this.shapereceptionbuffer){
shapereceptionbuffer=receivedList;
}
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
try {
if(height == 0) { //Prevent A Divide By Zero By
height = 1; //Making Height Equal One
}
gl.glViewport(0, 0, width, height);//specifies transformation from normalized device coordinates to window coordinates
float ratio = (float) width / height;
gl.glMatrixMode(GL11.GL_PROJECTION); //Select The Projection Matrix
gl.glLoadIdentity();//Reset The Projection Matrix
GLU.gluPerspective(gl, 45.0f, ratio, 0.1f, 100.0f);
gl.glMatrixMode(GL11.GL_MODELVIEW);//Select The Modelview Matrix
gl.glLoadIdentity();//Reset The Modelview Matrix
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Changed",e.getMessage());
}
//GLU.gluLookAt(gl, 0, 0, 4.2f, 0, 0, 0, 0, 1, 0);//eye-point location, center of the scene and an UP vector
}//end of surfacechanged
public void onDrawFrame(GL10 gl) {
try {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //Clear Screen And Depth Buffer
Log.d("Buffer Size", String.valueOf(shapereceptionbuffer.size()));
synchronized(this.shapereceptionbuffer){
shapes.setShapes(shapereceptionbuffer);
shapes.draw(gl, this.context);
}
} catch (Exception e) {
Log.d("Draw",e.getMessage());
}
}//end of ondrawframe
}
This class is responsible for drawing each of the shapes that are received from the external database.
/**
* This class contains, loads, initiates textures and draws our Shapes
*/
public class ShapeStorage {
private ArrayList<Shapes> shapestoragebuffer;
private Random rand = new Random(); // Initiate Random for random values of
// stars
/** Our texture pointer */
private int[] textures = new int[4];
/**
* Constructor for our holder
*/
public ShapeStorage() {
shapestoragebuffer = new ArrayList<Shapes>();
}
public void setShapes(ArrayList<Shapes> receivedlist) {
shapestoragebuffer = receivedList;
}
public void setupTextures(GL10 gl, Context context) {
// Get the texture from the Android resource directory
InputStream is = null;
gl.glGenTextures(4, textures, 0);
for (int i = 2; i < 6; i++) {
switch (i) {
case 2:
is = context.getResources().openRawResource(R.drawable.square);
break;
case 3:
is = context.getResources().openRawResource(R.drawable.circle);
break;
case 4:
is = context.getResources().openRawResource(R.drawable.hexagon);
break;
case 5:
is = context.getResources()
.openRawResource(R.drawable.triangle);
break;
}
Bitmap bitmap = null;
try {
// BitmapFactory is an Android graphics utility for images
bitmap = BitmapFactory.decodeStream(is);
} finally {
// Always clear and close
try {
is.close();
is = null;
} catch (IOException e) {
}
}
// Generate the texture pointer
// Create Linear Filtered Texture and bind it to texture
GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0);
gl.glBindTexture(GL11.GL_TEXTURE_2D, textures[i - 2]);
gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
GL11.GL_LINEAR);
gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
GL11.GL_LINEAR);
// Clean up
bitmap.recycle();
}
}
/**
* The drawing function.
*
* @param gl
* - The GL Context
* @param twinkle
* - Twinkle on or off
*/
public void draw(GL10 gl, Context context) {
// Bind the icon texture for all Shapes
for (int loop = 0; loop < shapestoragebuffer.size(); loop++) {
// Recover the current star into an object
Shapes shape = shapestoragebuffer.get(loop);
gl.glLoadIdentity(); // Reset The Current Modelview Matrix
// gl.glRotatef(180.0f, -1.0f, 0.0f, 0.0f);
float x = shape.get_Offset_from_center();
gl.glTranslatef(x, 0.0f, -40.0f);
// Draw
switch (victim.getType()) {
// green
case 2:
shape.draw(gl, textures[0]);
break;
// red
case 3:
shape.draw(gl, textures[1]);
break;
// yellow
case 4:
shape.draw(gl, textures[2]);
break;
case 5:
shape.draw(gl, textures[3]);
break;
}
}
}
}
Here is the class that defines each of the objects that are being drawn to the GLSurfaceView; each of the shapes that are being drawn.
public class Shapes {
private int _Offset_from_center;
private int type;
Context c;
/** The buffer holding the vertices */
private FloatBuffer vertexBuffer;
/** The buffer holding the texture coordinates */
private FloatBuffer textureBuffer;
/** The initial vertex definition */
private float vertices[] = {
-1.0f, -1.0f, 0.0f, //Bottom Left
1.0f, -1.0f, 0.0f, //Bottom Right
-1.0f, 1.0f, 0.0f, //Top Left
1.0f, 1.0f, 0.0f //Top Right
};
/** The initial texture coordinates (u, v) */
private float texture[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
public Shapes() {
//
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
//
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
}
public int get_Offset_from_center() {
return _Offset_from_center;
}
public void set_Offset_from_center(int _Offset_from_center) {
this._Offset_from_center = _Offset_from_center;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
/**
* The object own drawing function.
* Called from the renderer to redraw this instance
* with possible changes in values.
*
* @param gl - The GL Context
*/
public void draw(GL10 gl,int texture) {
gl.glBindTexture(GL11.GL_TEXTURE_2D, texture);
//Enable the vertex, texture and normal state
gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
//Point to our buffers
gl.glVertexPointer(3, GL11.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, textureBuffer);
//Draw the vertices as triangle strip
gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL11.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
}
}