Hi!
I'm learning Java and OpenGL ES for Android by reading tutorials and applying what I already know. And I have now hit a brick wall when it comes to rotating an object.
Rotating a cube by touching the screen is no problem. But if I rotate the cube 180 degrees up or down, then when I now try to rotate the cube left or right it is inverted. I know why this is happening but I cannot find a solution.
The code is below if some want to test it:
File "Rotating.java":
package com.test.opengl;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class Rotating extends Activity {
private GLControlView glControlView;
@Override
public void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
this.requestWindowFeature( Window.FEATURE_NO_TITLE );
getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN );
glControlView = new GLControlView( this );
setContentView( glControlView );
}
}
File "GLControlView.java":
package com.test.opengl;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
import android.view.MotionEvent;
public class GLControlView extends GLSurfaceView implements Renderer {
private Context context;
private float xPrevious, yPrevious;
private float xRotation = 0.0f, yRotation = 0.0f;
private SimpleCubeObject cubeObject;
public GLControlView( Context context ) {
super( context );
this.context = context;
this.setRenderer( this );
this.requestFocus();
this.setFocusableInTouchMode( true );
cubeObject = new SimpleCubeObject();
}
public void onSurfaceCreated( GL10 gl, EGLConfig config ) {
gl.glClearColor( 0.0f, 0.0f, 0.0f, 0.5f );
gl.glShadeModel( GL10.GL_SMOOTH );
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 onDrawFrame( GL10 gl ) {
gl.glClear( GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT );
gl.glLoadIdentity();
gl.glTranslatef( 0.0f, 0.0f, -10.0f );
gl.glPushMatrix();
gl.glRotatef( xRotation, 1.0f, 0.0f, 0.0f );
gl.glRotatef( yRotation, 0.0f, 1.0f, 0.0f );
gl.glPushMatrix();
cubeObject.draw( gl );
gl.glPopMatrix();
gl.glPopMatrix();
}
public void onSurfaceChanged( GL10 gl, int width, int height ) {
gl.glViewport( 0, 0, width, height );
gl.glMatrixMode( GL10.GL_PROJECTION );
gl.glLoadIdentity();
GLU.gluPerspective( gl, 45.0f, ( ( float )width / ( float )height ), 0.1f, 100.0f );
gl.glMatrixMode( GL10.GL_MODELVIEW );
gl.glLoadIdentity();
}
@Override
public boolean onTouchEvent( MotionEvent event ) {
float xEvent = event.getX();
float yEvent = event.getY();
switch( event.getAction() ) {
case MotionEvent.ACTION_DOWN: {
xPrevious = xEvent;
yPrevious = yEvent;
return true;
}
case MotionEvent.ACTION_MOVE: {
float xDelta = xEvent - xPrevious;
float yDelta = yEvent - yPrevious;
xRotation += ( yDelta * 0.5f );
yRotation += ( xDelta * 0.5f );
xPrevious = xEvent;
yPrevious = yEvent;
return true;
}
default: return super.onTouchEvent( event );
}
}
}
File "SimpleCubeObject.java":
package com.test.opengl;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
public class SimpleCubeObject {
private int[] textures = new int[ 1 ];
private float[] colors = {
0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
private short[] indices = {
0, 1, 2, 0, 2, 3,
1, 5, 6, 1, 6, 2,
2, 6, 7, 2, 7, 3,
3, 7, 4, 3, 4, 0,
0, 4, 5, 0, 5, 1,
7, 6, 5, 7, 5, 4
};
private float[] vertices = {
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f
};
private FloatBuffer colorBuffer;
private ShortBuffer indexBuffer;
private FloatBuffer vertexBuffer;
public SimpleCubeObject() {
ByteBuffer cbb = ByteBuffer.allocateDirect( colors.length * 4 );
cbb.order( ByteOrder.nativeOrder() );
colorBuffer = cbb.asFloatBuffer();
colorBuffer.put( colors );
colorBuffer.position( 0 );
ByteBuffer ibb = ByteBuffer.allocateDirect( indices.length * 2 );
ibb.order( ByteOrder.nativeOrder() );
indexBuffer = ibb.asShortBuffer();
indexBuffer.put( indices );
indexBuffer.position( 0 );
ByteBuffer vbb = ByteBuffer.allocateDirect( vertices.length * 4 );
vbb.order( ByteOrder.nativeOrder() );
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put( vertices );
vertexBuffer.position( 0 );
}
public void draw( GL10 gl ) {
gl.glFrontFace( GL10.GL_CCW );
gl.glEnable( GL10.GL_CULL_FACE );
gl.glCullFace( GL10.GL_BACK );
gl.glBindTexture( GL10.GL_TEXTURE_2D, textures[ 0 ] );
gl.glEnableClientState( GL10.GL_COLOR_ARRAY );
gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY );
gl.glColorPointer( 4, GL10.GL_FLOAT, 0, colorBuffer );
gl.glVertexPointer( 3, GL10.GL_FLOAT, 0, vertexBuffer );
gl.glDrawElements( GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer );
gl.glDisableClientState( GL10.GL_VERTEX_ARRAY );
gl.glDisableClientState( GL10.GL_COLOR_ARRAY );
gl.glDisable( GL10.GL_CULL_FACE );
}
}
I sure hope someone can help me with this. I believe, as always, that the solution is simple and easy - it is just me who can't see it right now.