Related
Because of performance I moved to OpenGL ES 2D from canvas.drawBitmap
This is sprite sheet 4x1:
Now to make it work I had followed class:
public Vulcan(ScreenObjectsView objectsView, int vulkanSpriteID, Context context) {
this.b = BitmapFactory.decodeResource(context.getResources(), vulkanSpriteID);
// 1x4
height = b.getHeight();
width = b.getWidth()/4;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
x = display.getWidth()/2-width/2; // deprecated
y = display.getHeight()-height; // deprecated
}
public void update() {
frameFreq++;
if(frameFreq > 0){
currentFrame = ++currentFrame % 4;
frameFreq = 0;
}
}
#Override
public void draw(Canvas canvas) {
update();
int srcX = currentFrame * width;
Rect src = new Rect(srcX, 0, srcX+width, height);
Rect dst = new Rect(x, y, x+width, y+height);
canvas.drawBitmap(b, src, dst, null);
}
Each period of time I take Rect and shift from left to right (in loop):
currentFrame = ++currentFrame % 4;
So far so good.
How can I animate above mentioned sprite sheet in in OpenGL ES?
Today, I know how to draw and move objects in OpenGL ES (thanks to good demo)
but don't know to play with sprites.
Any ideas, links, snippets of code?
[Edit]
Ther is no mater to use sprite sheet or 4 images like:
, and so on.
Strange that still didn't get any answer or direction.
Thank you,
[Edit 2]
According to what Aert says I implemented the following code and it works.
But it seems messy
Too much code for OpenGL ES. For each texture (I have 4), I need create FloatBuffer:
Maybe someone have shorter way, or I did something wrong.
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class DevQuestSpriteBase {
private static final String LOG_TAG = "Fess";//DevQuestSpriteBase.class.getSimpleName();
protected int mFrame = 0;
protected int mSwitcher = 0;
private int textureCount = 1; // frame animation
protected int[] textures = new int[textureCount]; // frame animation
// texture and verts
protected FloatBuffer vertexBuffer,
textureBuffer1,
textureBuffer2,
textureBuffer3,
textureBuffer4;
ByteBuffer bb1;
protected float vertices[] = {
0f,0f,0.0f,
1f,0f,0.0f,
0f,1f,0.0f,
1f,1f,0.0f
};
/** 1 frame */
protected float texture1[] = {
0.0f, 1.0f,
0.0f, 0.0f,
0.25f, 1.0f,
0.25f, 0.0f
};
/** 2 frame */
protected float texture2[] = {
0.25f, 1.0f,
0.25f, 0.0f,
0.5f, 1.0f,
0.5f, 0.0f
};
/** 3 frame */
protected float texture3[] = {
0.5f, 1.0f,
0.5f, 0.0f,
0.75f, 1.0f,
0.75f, 0.0f
};
/** 4 frame */
protected float texture4[] = {
0.75f, 1.0f,
0.75f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
public DevQuestSpriteBase(){
// vertices buffer
bb1 = ByteBuffer.allocateDirect(vertices.length * 4);
bb1.order(ByteOrder.nativeOrder());
vertexBuffer = bb1.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// texture buffer
bb1 = ByteBuffer.allocateDirect(texture1.length * 4);
bb1.order(ByteOrder.nativeOrder());
textureBuffer1 = bb1.asFloatBuffer();
textureBuffer1.put(texture1);
textureBuffer1.position(0);
//#########################################################
// texture buffer
bb1 = ByteBuffer.allocateDirect(texture2.length * 4);
bb1.order(ByteOrder.nativeOrder());
textureBuffer2 = bb1.asFloatBuffer();
textureBuffer2.put(texture2);
textureBuffer2.position(0);
//#########################################################
// texture buffer
bb1 = ByteBuffer.allocateDirect(texture3.length * 4);
bb1.order(ByteOrder.nativeOrder());
textureBuffer3 = bb1.asFloatBuffer();
textureBuffer3.put(texture3);
textureBuffer3.position(0);
//#########################################################
// texture buffer
bb1 = ByteBuffer.allocateDirect(texture4.length * 4);
bb1.order(ByteOrder.nativeOrder());
textureBuffer4 = bb1.asFloatBuffer();
textureBuffer4.put(texture4);
textureBuffer4.position(0);
}
private void update() {
if(mSwitcher == 5){
mFrame = ++mFrame % 4;
mSwitcher = 0;
// Log.e(LOG_TAG, "DevQuestSpriteBase :: " + mFrame);
}
else{
mSwitcher++;
}
}
public void draw(GL10 gl){
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
if(mFrame == 0){
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer1);
}
else if(mFrame == 1){
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer2);
}
else if(mFrame == 2){
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer3);
}
else if(mFrame == 3){
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer4);
}
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
//Log.e(LOG_TAG, "DevQuestSpriteBase :: draw");
update();
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer1);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
public int[] getTextures() {
return textures;
}
}
Without going into a lot of detail, you need to do the following (assuming you are already drawing a sprite using 4 vertices):
Define the texture coordinates corresponding to the vertices of the sprite for each animation frame, e.g.
texCoordsFrame1 = [0.0f, 0.0f, 0.25f, 0.0f, 0.0f, 1.0f, 0.25f, 1.0f];
Upload the spritesheet texture, e.g.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
Draw using the texture coordinates corresponding to the frame you want to show when required, e.g.
...
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexCoordPointer(2, GL_FLOAT, 0, texCoordsFrame1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Alternatively, you can upload the separate frames as individual textures, but that is undesirable from a performance point of view.
There are a few gotcha's
When using GLES1, you can only use power-of-two textures. In that case you'll have to scale the texture or increase its size to be power-of-two and adjust the texture coordinates.
The bitmap vs GL y-coordinate direction difference is a bit confusing, and you might end up with a vertically flipped sprite.
I found different Stackoverflow-Questons, but I don't see what I'm doing wrong in my code, because the 2D "_floorhelper" texture doesn't show up on the screen. I would like to used it as a HUD element:
Trying to use Ortho for drawing 2D
https://stackoverflow.com/questions/9406753/android-opengl-gluortho2d-keep-original-shape-of-an-object
Android - Draw 3D then 2D with openGL ES
this is my setup:
public void gameSetup(GameActivity activity, GL10 gl) {
_floorhelper = new Mesh( gl, 4, false, true, false );
_floorhelper.texCoord(1, 1);
_floorhelper.vertex(-1, 0, 1 );
_floorhelper.texCoord(1, 0);
_floorhelper.vertex(1, 0, 1 );
_floorhelper.texCoord(0, 0);
_floorhelper.vertex(1, 0, -1 );
_floorhelper.texCoord(0, 1);
_floorhelper.vertex(-1, 0, -1);
try {
InputStream is = getResources().openRawResource(getResources().getIdentifier("levels", "raw", getPackageName()));
levelBitmap = BitmapFactory.decodeStream(is);
levelTexture = new Texture(gl, levelBitmap, TextureFilter.Linear, TextureFilter.Linear, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge);
}
catch(Exception ex){
System.out.print(ex.getMessage());
}
setTractFloor(gl);
float[] lightColor = { 1, 1, 1, 1 };
float[] ambientLightColor = { 0.0f, 0.0f, 0.0f, 1 };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientLightColor, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightColor, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lightColor, 0);
}
public void gameLoop(GameActivity activity, GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glViewport(0, 0, activity.getViewportWidth(), activity.getViewportHeight());
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable( GL10.GL_CULL_FACE );
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
float aspectRatio = (float) activity.getViewportWidth() / activity.getViewportHeight();
GLU.gluPerspective(gl, 67, aspectRatio, 1, 100);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, _scaleFactor, 5.0f, _scaleFactor, 0.0f, 0.0f, 0.0f, 0, 1, 0);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
float[] direction = { 1.5f, 0.5f, 0, 0 };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, direction, 0);
gl.glEnable(GL10.GL_COLOR_MATERIAL);
// rotation
gl.glRotatef(135, 0, 1, 0);
gl.glEnable(GL10.GL_LINE_SMOOTH);
gl.glBlendFunc(GL10.GL_SRC_ALPHA_SATURATE, GL10.GL_ONE);
gl.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST); // no visible diff
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glColor4f(1, 1, 1, 1);
// translation
gl.glTranslatef(-_oldTouchY, 0, _oldTouchX);
// render
currentTractFloor.render();
// Draw 2D ontop of 3D - floorhelper
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0.0f, (float) activity.getViewportWidth(), 0.0f, (float)activity.getViewportHeight());
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glDisable(GL10.GL_COLOR_MATERIAL);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
levelTexture.bind();
_floorhelper.render(PrimitiveType.TriangleFan);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPopMatrix();
}
After the Answer of Stefan Hanke I found the solution.
I've defined the vertices in the mesh wrong. So I always saw just the side of the mesh....
Thanks to Stefan Hanke.
//* Solution Code
public void gameSetup(GameActivity activity, GL10 gl) {
_floorhelper = new Mesh(gl, 4, false, true, false);
_floorhelper.texCoord(0, 1);
_floorhelper.vertex(50, 50, 0);
_floorhelper.texCoord(1, 1);
_floorhelper.vertex(1000, 50, 0);
_floorhelper.texCoord(1, 0);
_floorhelper.vertex(1000, 1000, 0);
_floorhelper.texCoord(0, 0);
_floorhelper.vertex(50, 1000, 0);
try {
InputStream is = getResources().openRawResource(getResources().getIdentifier("levels", "raw", getPackageName()));
levelBitmap = BitmapFactory.decodeStream(is);
levelTexture = new Texture(gl, levelBitmap, TextureFilter.Linear, TextureFilter.Linear, TextureWrap.ClampToEdge, TextureWrap.ClampToEdge);
}
catch(Exception ex){
System.out.print(ex.getMessage());
}
setTractFloor(gl);
float[] lightColor = { 1, 1, 1, 1 };
float[] ambientLightColor = { 0.0f, 0.0f, 0.0f, 1 };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientLightColor, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightColor, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lightColor, 0);
}
public void gameLoop(GameActivity activity, GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glViewport(0, 0, activity.getViewportWidth(), activity.getViewportHeight());
gl.glClearColor(0.18f, 0.68f, 1.0f, 1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_CULL_FACE );
setPerspective(activity, gl);
GLU.gluLookAt(gl, getScaleFactor(), 5.0f, getScaleFactor(), 0.0f, 0.0f, 0.0f, 0, 1, 0);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
float[] direction = { 1.5f, 0.5f, 0, 0 };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, direction, 0);
gl.glEnable(GL10.GL_COLOR_MATERIAL);
// rotation
gl.glRotatef(135, 0, 1, 0);
gl.glEnable(GL10.GL_LINE_SMOOTH);
gl.glBlendFunc(GL10.GL_SRC_ALPHA_SATURATE, GL10.GL_ONE);
gl.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST); // no visible diff
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glColor4f(1, 1, 1, 1);
// translation
gl.glTranslatef(-_oldTouchY, 0, _oldTouchX);
// render
currentTractFloor.render();
// levels
setOrtho2D(activity, gl);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
levelTexture.bind();
_floorhelper.render(PrimitiveType.TriangleFan);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPopMatrix();
}
private void setPerspective(GameActivity activity, GL10 gl) {
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
float aspectRatio = (float) activity.getViewportWidth() / activity.getViewportHeight();
GLU.gluPerspective(gl, 67, aspectRatio, 1, 100);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
private void setOrtho2D(GameActivity activity, GL10 gl) {
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
// set ortho view
gl.glOrthof(0.0f,(float) activity.getViewportWidth(), 0.0f, (float)activity.getViewportHeight(), -1.0f, 1.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
}
Looks like the matrix setup is incorrect. The meshes vertices all have y=0. With no ModelView matrix whatsoever, you will look at the front edge of the whole mesh. If you remove the second matrix setup from the code -- as you did in your comment to Vincents post -- , the ModelView will be a concoction of the previous gl* calls.
It could be that you didn't define the normals of the vertices of your Mesh.
I've got a few planes on my OpenGlSurfaceView. Now I want to detect whether a plane is touched. I found a few topics on stackoverflow and in other forums, but I don't know how to deal with them. Maybe anyone could help me.
My planes are all of that structure:
public SimplePlane() {
float textureCoordinates[] = {
0.0f, 1.0f, //
1.0f, 1.0f, //
0.0f, 0.0f, //
1.0f, 0.0f, //
};
short[] indices = new short[] {
0, 1,
2, 1,
3, 2 };
float[] vertices = new float[] {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f };
setIndices(indices);
setVertices(vertices);
setTextureCoordinates(textureCoordinates);
}
I've got an own class for all my Meshes, so SimplePlane extends Mesh. Here you can see the draw method in the Mesh class:
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
if (colorBuffer != null) {
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
}
if (mShouldLoadTexture) {
loadGLTexture(gl);
mShouldLoadTexture = false;
}
if (mTextureId != -1 && mTextureBuffer != null) {
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
}
gl.glRotatef(rx, 1, 0, 0);
gl.glRotatef(ry, 0, 1, 0);
gl.glRotatef(rz, 0, 0, 1);
gl.glTranslatef(x, y, z);
gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices,
GL10.GL_UNSIGNED_SHORT, indicesBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
if (mTextureId != -1 && mTextureBuffer != null) {
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
gl.glDisable(GL10.GL_CULL_FACE);
}
And that the onDrawFrame Method of my Renderer:
public void onDrawFrame(GL10 gl) {
gl.glClearColor(_red, _green, _blue, 0.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
GLU.gluLookAt(gl, 0,0,0, 0,0,0, 0,0,0);
gl.glLoadIdentity();
gl.glRotatef(_ry, 0f, 1f, 0f);
root.draw(gl); // a group of meshes
}
But now I don't know how I can start to detect a touch of my plane. I read much about color picking or ray picking, but I don't know where I should start in my code to implement it.
First get the point where the user touched on screen using myGLSurfaceView.setOnTouchListener(new MyOnTouchListener()) (where myOnTouchListener implements OnTouchListener).
Then you need to get the MatrixGrabber, MatrixStack, MatrixTracking classes from the API demo's (C:\android-sdk\samples\android-7\ApiDemos\src\com\example\android\apis\graphics\spritetext).
Next, to use the MatrixGrabber, first attach it as a wrapper to your GLSurfaceView:
public class GraphicsEngine extends Activity {
protected GLSurfaceView mGLView;
protected GraphicsRenderer graphicsRenderer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.graphics);
graphicsRenderer = new GraphicsRenderer(this);
mGLView = (GLSurfaceView) findViewById(R.id.graphics_glsurfaceview1);
// ------
// THIS BIT HERE
mGLView.setGLWrapper(new GLSurfaceView.GLWrapper() {
public GL wrap(GL gl) {
return new MatrixTrackingGL(gl);
}});
// ------
mGLView.setEGLConfigChooser(true);
mGLView.setRenderer(graphicsRenderer);
}
Then you can get the matrices needed for GLU.gluUnProject(). This last method gives you a 3D point on the near-plane (i.e. z = near-plane) where the user touched. You can create a ray using it and the camera 'eye' point, and then detect which objects in your 3D world the ray intersected to get which objects the user picked*:
MatrixGrabber matrixGrabber = new MatrixGrabber();
matrixGrabber.getCurrentModelView(gl);
matrixGrabber.getCurrentProjection(gl);
float[] vector = new float[4];
// x and y come from the x/y you get from the OnTouchListener.
// OpenGL works from the bottom left corner, so flip the y
GLU.gluUnProject(x, mGLView.getHeight()-y, 0.9f, matrixGrabber.mModelView, 0, matrixGrabber.mProjection, 0, new int[]{mGLView.getTop(),mGLView.getLeft(),mGLView.getWidth(),mGLView.getHeight()}, 0, vector, 0);
Vector3f pickPosition = new Vector3f();
if(vector[3]!=0){
pickPosition.x = vector[0] / vector[3];
pickPosition.y = vector[1] / vector[3];
pickPosition.z = vector[2] / vector[3];
}
*This last code snippet I'm not 100% certain works, but the real solution will look something like it
Edit: updated the last code snippet
i am working on a program which draws polygons according to user inputs.
I have problems with drawing triangles using GL_TRIANGLE. I used the same code below to draw square and it worked well. Hovewer, if i want to draw only one triangle it does not work.
Can anyone help me?
public class Triangle extends Shape{
private FloatBuffer vertexBuffer;
private FloatBuffer _colorBuffer;
private ShortBuffer indexBuffer;
private float vertices[] = {
-0.5f, -0.5f, 0.5f, // 0
0.5f, -0.5f, 0.5f, // 1
0f, -0.5f, -0.5f, // 2
};
private short[] indices = { 0, 2, 1 };
float[] colors = {1f, 1f, 0f, 1f };
public Triangle() {
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
cbb.order(ByteOrder.nativeOrder());
_colorBuffer = cbb.asFloatBuffer();
_colorBuffer.put(colors);
_colorBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,GL10.GL_UNSIGNED_SHORT, indexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
}
edit:
i call my Triangle class from here, maybe i have made mistake here
public class OpenGLRenderer implements Renderer {
String name;
ArrayList myArr ;
private float angle, x,y,z;
public OpenGLRenderer(String nm ) {
name =nm;
myArr = new ArrayList<Shape>();
x=0;
y=0;
z=-3;
}
#Override
public void onDrawFrame(GL10 gl) {
//clear the screen and depth buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(x, y, z);
for (Shape t : myArr)
{
if (t instanceof Rectangle)
{
// gl.glTranslatef(0, 0, -4);
((Rectangle )t).draw(gl);
}
if (t instanceof Square)
{ //gl.glTranslatef(0, 1, 0);
((Square )t).draw(gl);}
if (t instanceof Pyramid){
((Pyramid)t).draw(gl);
if (t instanceof Triangle){
((Triangle)t).draw(gl);
}
if (t instanceof Line){
((Line)t).draw(gl);
}
}
}//for
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity(); //reset the projection matrix
GLU.gluPerspective(gl, 45.0f, (float)width/(float)height,
0.1f, 100.0f); //calculate the aspect ratio of window
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//set the bg as black
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glShadeModel(GL10.GL_SMOOTH);
//depth buffer setup
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}
public void addshape(Shape s)
{y=y+0.1f;
myArr.add(s);
}
}
It looks to me like you don't have enough colors in your colors array. This might result in an invisible triangle depending on the initial garbage values in your _colorBuffer.
(Edit) try:
float[] colors = {
1f, 1f, 0f, 1f,
1f, 1f, 0f, 1f,
1f, 1f, 0f, 1f
};
First, Martin is correct about the colors array. It needs to have a color (4 values in your case) for every vertex (so 12 values at all).
Next, at the moment your triangle lies inside the x-z-plane and as you don't make any changes to the modelview matrix (except translating along the z-axis), you should just see a line, if any, (think of a sheet of paper viewed from the side).
But your real problem is your draw loop. I guess you're not only new to OpenGL, but also to Java and object oriented programming in general. This whole design is complete rubbish. That's what virtual functions are for in object oriented code. Just let each shape implement its correct draw method. So the only thing you need to do is
for (Shape t : myArr)
t.draw(gl);
Given that Shape has an abstract draw method, that the other subclasses implement. But this is more of a design flaw. The actual error is, that the braces of the ifs are broken. At the moment the triangle is only drawn, if t is an instance of Pyramid and of Triangle, so draw is never called for triangles (and also for lines).
here my triangle code from a project which works. Looks like your indices and colour arrays are different
package com.martynhaigh.Vortex;
import android.view.animation.Transformation;
import javax.microedition.khronos.opengles.GL10;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class Triangle {
private ShortBuffer _indexBuffer;
private FloatBuffer _vertexBuffer;
private FloatBuffer _colorBuffer;
static float _xAngle, _yAngle;
private int _nrOfVertices;
Triangle() {
float[] coords = {
-0.5f, -0.5f, 0f, // (x1, y1, z1)
0.5f, -0.5f, 0f, // (x2, y2, z2)
0f, 0.5f, 0f // (x3, y3, z3)
}; // 9
_nrOfVertices = coords.length / 3;
float[] colors = {
1f, 0f, 0f, 1f, // point 1
0f, 1f, 0f, 1f, // point 2
0f, 0f, 1f, 1f // point 3
}; // 12
short[] indices = {0, 1, 2}; // 3
// float has 4 bytes, coordinate * 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4); //36
vbb.order(ByteOrder.nativeOrder());
_vertexBuffer = vbb.asFloatBuffer();
// short has 2 bytes, indices * 2 bytes
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); // 6
ibb.order(ByteOrder.nativeOrder());
_indexBuffer = ibb.asShortBuffer();
// float has 4 bytes, colors (RGBA) * 4 bytes
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4); // 48
cbb.order(ByteOrder.nativeOrder());
_colorBuffer = cbb.asFloatBuffer();
_vertexBuffer.put(coords);
_indexBuffer.put(indices);
_colorBuffer.put(colors);
_vertexBuffer.position(0);
_indexBuffer.position(0);
_colorBuffer.position(0);
}
public void onDraw(GL10 gl) {
// set rotation
gl.glRotatef(_xAngle, 1f, 0f, 0f);
gl.glRotatef(_yAngle, 0f, 1f, 0f);
// set the color of our element
//gl.glColor4f(0.5f, 0f, 0f, 0.5f);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
// define the vertices we want to draw
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);
// finally draw the vertices
gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
}
public void setXAngle(float angle) {
_xAngle = angle;
}
public float getXAngle() {
return _xAngle;
}
public void setYAngle(float angle) {
_yAngle = angle;
}
public float getYAngle() {
return _yAngle;
}
}
Working through some OpenGL-ES tutorials, using the Android emulator. I've gotten up to texture mapping and am having some trouble mapping to a cube. Is it possible to map a texture to all faces of a cube that has 8 vertices and 12 triangles for the 6 faces as described below?
// Use half as we are going for a 0,0,0 centre.
width /= 2;
height /= 2;
depth /= 2;
float vertices[] = { -width, -height, depth, // 0
width, -height, depth, // 1
width, height, depth, // 2
-width, height, depth, // 3
-width, -height, -depth, // 4
width, -height, -depth, // 5
width, height, -depth, // 6
-width, height, -depth, // 7
};
short indices[] = {
// Front
0,1,2,
0,2,3,
// Back
5,4,7,
5,7,6,
// Left
4,0,3,
4,3,7,
// Right
1,5,6,
1,6,2,
// Top
3,2,6,
3,6,7,
// Bottom
4,5,1,
4,1,0,
};
float texCoords[] = {
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
I have gotten the front and back faces working correctly, however, none of the other faces are showing the texture.
Drawing code
public void draw(GL10 gl) {
// Counter-clockwise winding.
gl.glFrontFace(GL10.GL_CCW);
// Enable face culling.
gl.glEnable(GL10.GL_CULL_FACE);
// What faces to remove with the face culling.
gl.glCullFace(GL10.GL_BACK);
// Enabled the vertices buffer for writing and to be used during
// rendering.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// Specifies the location and data format of an array of vertex
// coordinates to use when rendering.
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
if (normalsBuffer != null) {
// Enabled the normal buffer for writing and to be used during rendering.
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
// Specifies the location and data format of an array of normals to use when rendering.
gl.glNormalPointer(GL10.GL_FLOAT, 0, normalsBuffer);
}
// Set flat color
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
// Smooth color
if ( colorBuffer != null ) {
// Enable the color array buffer to be used during rendering.
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
// Point out the where the color buffer is.
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
}
// Use textures?
if ( textureBuffer != null) {
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
}
// Translation and rotation before drawing
gl.glTranslatef(x, y, z);
gl.glRotatef(rx, 1, 0, 0);
gl.glRotatef(ry, 0, 1, 0);
gl.glRotatef(rz, 0, 0, 1);
gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices, GL10.GL_UNSIGNED_SHORT, indicesBuffer);
// Disable the vertices buffer.
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Disable face culling.
gl.glDisable(GL10.GL_CULL_FACE);
}
You have to use 24 vertexes. In OpenGL, a vertex is more than just position, it is the collection of all vertex attributes. Every vertex array is accessed with the same index.
The infamous cube example is something almost everyone feels is inefficient when starting to use OpenGL, but in real-world, more complex models, the degree of duplication is quite low.
I have "only" modified the GLES20TriangleRenderer.java file into the SDK example BasicGLSurfaceView, compile it and test it on two Android devices, an Android Phone and a Nexus 7 and this work good on the two devices :)
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
Modified by YLP (06 January 2014) for to handle a rotated texture mapped cube
*/
package com.example.android.basicglsurfaceview;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.os.SystemClock;
import android.util.Log;
class GLES20TriangleRenderer implements GLSurfaceView.Renderer {
public GLES20TriangleRenderer(Context context) {
mContext = context;
// mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
// mTriangleVertices.put(mTriangleVerticesData).position(0);
mTriangleVertices = ByteBuffer.allocateDirect(cubeVerticesStrip.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangleVertices.put(cubeVerticesStrip).position(0);
mTriangleTexcoords = ByteBuffer.allocateDirect(cubeTexCoordsStrip.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
mTriangleTexcoords.put(cubeTexCoordsStrip).position(0);
}
public void onDrawFrame(GL10 glUnused) {
// Ignore the passed-in GL10 interface, and use the GLES20
// class's static methods instead.
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable( GLES20.GL_DEPTH_TEST );
GLES20.glDepthFunc( GLES20.GL_LEQUAL );
GLES20.glDepthMask( true );
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
// mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
// GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
// TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
// checkGlError("glVertexAttribPointer maPosition");
// mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
// GLES20.glEnableVertexAttribArray(maPositionHandle);
// checkGlError("glEnableVertexAttribArray maPositionHandle");
// GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
// TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
// checkGlError("glVertexAttribPointer maTextureHandle");
// GLES20.glEnableVertexAttribArray(maTextureHandle);
// checkGlError("glEnableVertexAttribArray maTextureHandle");
// From http://www.endodigital.com/opengl-es-2-0-on-the-iphone/part-fourteen-creating-the-cube
// (but slighty modified)
mTriangleVertices.position(0);
// GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 0, mTriangleVertices);
GLES20.glEnableVertexAttribArray(maPositionHandle);
mTriangleTexcoords.position(0);
// GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 0, mTriangleTexcoords);
GLES20.glEnableVertexAttribArray(maTextureHandle);
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
float scale = 0.7f;
Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f);
// YLP : add others movements cycles
Matrix.rotateM(mMMatrix, 0, angle, 1.0f, 0.0f, 0.0f );
// Matrix.rotateM(mMMatrix, 0, angle, 0.0f, 1.0f, 0.0f );
// float scale = (float)( Math.abs( Math.sin( ((float)time) * (6.28f/4000.0f) ) ));
Matrix.scaleM(mMMatrix, 0, scale, scale, scale);
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Somes tests with only somes triangles
// GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); // worked initialy but only one triangle
// GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); // worked initialy but only two triangles
// GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); // GL_QUADS does not exist in GL 2.0 :(
// GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 8); // GL_QUADS does not exist in GL 2.0 :(
// Draw the cube
// TODO : make only one glDraWArrays() call instead one per face
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 4, 4);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 8, 4);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 12, 4);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 16, 4);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 20, 4);
checkGlError("glDrawArrays");
}
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
// Ignore the passed-in GL10 interface, and use the GLES20
// class's static methods instead.
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
// Ignore the passed-in GL10 interface, and use the GLES20
// class's static methods instead.
mProgram = createProgram(mVertexShader, mFragmentShader);
if (mProgram == 0) {
return;
}
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
checkGlError("glGetAttribLocation aPosition");
if (maPositionHandle == -1) {
throw new RuntimeException("Could not get attrib location for aPosition");
}
maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
checkGlError("glGetAttribLocation aTextureCoord");
if (maTextureHandle == -1) {
throw new RuntimeException("Could not get attrib location for aTextureCoord");
}
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
checkGlError("glGetUniformLocation uMVPMatrix");
if (muMVPMatrixHandle == -1) {
throw new RuntimeException("Could not get attrib location for uMVPMatrix");
}
/*
* Create our texture. This has to be done each time the
* surface is created.
*/
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
mTextureID = textures[0];
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_REPEAT);
InputStream is = mContext.getResources()
.openRawResource(R.raw.robot);
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch(IOException e) {
// Ignore.
}
}
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
}
private int loadShader(int shaderType, String source) {
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Log.e(TAG, "Could not compile shader " + shaderType + ":");
Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
private int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0) {
return 0;
}
int program = GLES20.glCreateProgram();
if (program != 0) {
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
GLES20.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GLES20.GL_TRUE) {
Log.e(TAG, "Could not link program: ");
Log.e(TAG, GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
private void checkGlError(String op) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, op + ": glError " + error);
throw new RuntimeException(op + ": glError " + error);
}
}
private static final int FLOAT_SIZE_BYTES = 4;
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
private static final int TRIANGLE_TEXCOORDS_DATA_STRIDE_BYTES = 2 * FLOAT_SIZE_BYTES;
private final float[] mTriangleVerticesData =
{
// X, Y, Z, U, V
// initial triangle from the source
// -1.0f, -0.5f, 0, -0.5f, 0.0f,
// 1.0f, -0.5f, 0, 1.5f, -0.0f,
// 0.0f, 1.11803399f, 0, 0.5f, 1.61803399f,
// YLP : transform this to two triangles for to have a quad
// -1, -1, 0, 0, 0,
// 1, -1, 0, 1, 0,
// -1, 1, 0, 0, 1,
// 1, 1, 0, 1, 1,
// -1, 1, 0, 0, 1,
// 1, -1, 0, 1, 0
// YLP : use two quads with GL_TRIANGLE_STRIP
// Don't work because this make one accordeon effect :(
-1, -1, -1, 0, 0,
1, -1, -1, 1, 0,
-1, 1, -1, 0, 1,
1, 1, -1, 1, 1,
-1, -1, 1, 0, 0,
1, -1, 1, 1, 0,
-1, 1, 1, 0, 1,
1, 1, 1, 1, 1,
};
// From http://www.endodigital.com/opengl-es-2-0-on-the-iphone/part-fourteen-creating-the-cube/
// (only moodify "static const GLfloat" to "private final float" on it)
private final float cubeVerticesStrip[] = {
// Front face
-1,-1,1, 1,-1,1, -1,1,1, 1,1,1,
// Right face
1,-1,1, 1,-1,-1, 1,1,1, 1,1,-1,
// Back face
1,-1,-1, -1,-1,-1, 1,1,-1, -1,1,-1,
// Left face
-1,-1,-1, -1,-1,1, -1,1,-1, -1,1,1,
// Bottom face
-1,-1,-1, 1,-1,-1, -1,-1,1, 1,-1,1,
// Top face
-1,1,1, 1,1,1, -1,1,-1, 1,1,-1
};
private final float cubeTexCoordsStrip[] = {
// Front face
0,0, 1,0, 0,1, 1,1,
// Right face
0,0, 1,0, 0,1, 1,1,
// Back face
0,0, 1,0, 0,1, 1,1,
// Left face
0,0, 1,0, 0,1, 1,1,
// Bottom face
0,0, 1,0, 0,1, 1,1,
// Top face
0,0, 1,0, 0,1, 1,1
};
private FloatBuffer mTriangleVertices;
private FloatBuffer mTriangleTexcoords;
private final String mVertexShader =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec2 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = aTextureCoord;\n" +
"}\n";
private final String mFragmentShader =
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform sampler2D sTexture;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}\n";
private float[] mMVPMatrix = new float[16];
private float[] mProjMatrix = new float[16];
private float[] mMMatrix = new float[16];
private float[] mVMatrix = new float[16];
private float[] mMMatrix2 = new float[16];
private int mProgram;
private int mTextureID;
private int muMVPMatrixHandle;
private int maPositionHandle;
private int maTextureHandle;
private Context mContext;
private static String TAG = "GLES20TriangleRenderer";
}
=> I managed to implement this in just a few hours and this work :)
==> so if Android is not the best platform, this seem however a really good and viable plateform for that I begin to play a little more with some multimédia developments on Android's devices :)