i am trying to build a one-different-color-per-face cube in Android API 3 OpenGL (so OpenGL ES 1.0). ( I am a beginner in OpenGL programming ). I managed to make it rotate in a constant period, but the big problem is that i can’t manage to have all faces drawn.
Indeed, the missing face will not be the same whether
- i rotate around x or y axis
- i use or don’t use the GL10#glEnable(GL10.GL_DEPTH_TEST) command in the method onSurfaceCreated
So, what is the simplest way to correct that ? (I have thought of using glClearDepth() and glCullFace(), without any success).
Here is the code of my class inherited from GLSurfaceView.Renderer :
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.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
public class MyGLRenderer implements Renderer {
public MyGLRenderer(){
buildCubeBuffers();
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glRotatef(0.6f, 1.0f, 0.0f, 0.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glVertexPointer(COORDS_PER_VERTEX, GL10.GL_FLOAT, 0, cubeBuffer);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//--- FRONT
gl.glColor4f(1.0f, 0.0f, 0.0f, 0.0f); //RED
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, VERTICES_NUMBER);
//--- RIGHT
gl.glColor4f(0.0f, 1.0f, 0.0f, 0.0f); // GREEN
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, VERTICES_NUMBER);
//--- BACK
gl.glColor4f(0.0f, 0.0f, 1.0f, 0.0f); // BLUE
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, VERTICES_NUMBER);
//--- LEFT
gl.glColor4f(1.0f, 1.0f, 0.0f, 0.0f); // YELLOW
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, VERTICES_NUMBER);
//--- TOP
gl.glColor4f(1.0f, 0.5f, 0.0f, 0.0f); // ORANGE
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, VERTICES_NUMBER);
//--- BOTTOM
gl.glColor4f(1.0f, 0.0f, 1.0f, 0.0f); // PURPLE
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, VERTICES_NUMBER);
//--
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if (height == 0) height = 1;
if (width < height)
gl.glViewport(0, 0, width, width);
else
gl.glViewport(0, 0, height, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
//////////////////////////////////////
/*
* If i comment next line :
* => Rotation on y axis
* yellow face is visible, red face is invisible
* Otherwise : yellow invisible and red visible !!!
* => Rotation on x axis
* purple face is visible, red face is invisible
* Otherwise : purple invisible and red visible !!!
* Why ???
*/
//////////////////////////////////////
gl.glEnable(GL10.GL_DEPTH_TEST);
}
private void buildCubeBuffers(){
final float cubeVertices[] = {
// front
-CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 0 : Left-Top-Front
+CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 1 : Right-Top-Front
-CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 3 : Left-Bottom-Front
+CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 2 : Right-Bottom-Front
// right
+CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 1 : Right-Top-Front
+CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 5 : Right-Top-Back
+CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 2 : Right-Bottom-Front
+CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 6 : Right-Bottom-Back
// back
+CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 5 : Right-Top-Back
-CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 4 : Left-Top-Back
+CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 6 : Right-Bottom-Back
-CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 7 : Left-Bottom-Back
// left
-CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 4 : Left-Top-Back
-CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 0 : Left-Top-Front
-CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 7 : Left-Bottom-Back
-CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 3 : Left-Bottom-Front
// top
-CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 4 : Left-Top-Back
+CUBE_UNITY_COORD, +CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 5 : Right-Top-Back
-CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 0 : Left-Top-Front
+CUBE_UNITY_COORD, +CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 1 : Right-Top-Front
// bottom
-CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 3 : Left-Bottom-Front
+CUBE_UNITY_COORD, -CUBE_UNITY_COORD, +CUBE_UNITY_COORD, // point 2 : Right-Bottom-Front
-CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 7 : Left-Bottom-Back
+CUBE_UNITY_COORD, -CUBE_UNITY_COORD, -CUBE_UNITY_COORD, // point 6 : Right-Bottom-Back
};
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(cubeVertices.length * FLOAT_CAPACITY_BYTES);
byteBuffer.order(ByteOrder.nativeOrder());
cubeBuffer = byteBuffer.asFloatBuffer();
cubeBuffer.put(cubeVertices);
cubeBuffer.rewind();
}
private final static float CUBE_UNITY_COORD = 0.5f;
private static FloatBuffer cubeBuffer;
private final static int FLOAT_CAPACITY_BYTES = 4;
private final static int COORDS_PER_VERTEX = 3;
private final static int VERTICES_NUMBER = 4;
}
I think you have the purpose of the matrix stacks slightly confused.
Projection should map from a fixed position in world space to eye space.
Modelview should be the combination of everything that moves the world around relative to the screen. So, you’ll typically have some sort of transform that moves the whole of the world equally depending on your in-world camera, then for each object in the world you’ll append an additional transform to modelview to place it relative to the world.
The effect of depth testing depends on what the projection matrix ends up doing, so this confusion could well be causing the problems you describe.
I’d suggest that rather than:
You probably want something like:
See the documentation on gluPerspective here. That says that you want a perspective projection, then switches to modelview and sets up a camera position.
You also wouldn’t normally just accumulate rotations on modelview indefinitely as your code does, because the numerical errors will accumulate quite quickly. But I’ll wager that’s just a quick bit of test code?