Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Adding Controls to the OpenGL Spinning Cube

Author: Marco Dinacci -- Published? true -- FormatLanguage: W

Problem:

You want to interact with an OpenGL polygon using the keyboard of your device.

Solution:

We're going to create a custom GLSurfaceView and override the onKeyUp method to listens to KeyEvent created from the D-pad.

Discussion:

This recipe extends on the "Create a spinning cube OpenGL" to show how to control the cube using a D-pad. We're going to increment the speed rotation along the X and Y axes using the directional keys of the D-pad.

The biggest change is that we now have our custom class that extends the SurfaceView. We do this so we can override the onKeyUp method and be notified when the user uses the D-pad.

The onCreate of our Activity looks like this:

public class SpinningCubeActivity2 extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // go fullscreen
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                        WindowManager.LayoutParams.FLAG_FULLSCREEN);
        
        // create our custom view
        GLSurfaceView view = new OpenGLSurfaceView(this);
        view.setRenderer((Renderer)view);
        setContentView(view);
    }
}

Our new GLSurfaceView also implements the Renderer interface. The onSurfaceCreated and onSurfaceChanged method are exactly the same as in the previous recipe, most of the changes occur in the onDrawFrame as we introduce four new parameters: mXrot and mYrot to control the rotation of the cube along the X and Y axis and mXspeed and mYSpeed to store the speed of the rotation along the X and Y axis.

Each time the user click on a D-pad button we alter the speed of the cube by modifying these parameters.

Here's the full code of our new class:

class OpenGLSurfaceView extends GLSurfaceView implements Renderer {

    private Cube mCube;
    private float mXrot;
    private float mYrot;
    private float mXspeed;
    private float mYspeed;
        
    public OpenGLSurfaceView(Context context) {
        super(context);
        
        // give focus to the GLSurfaceView    
        requestFocus();
        setFocusableInTouchMode(true);
                
        mCube = new Cube();
    }

    @Override
    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.glRotatef(mXrot, 1.0f, 0.0f, 0.0f);  
        gl.glRotatef(mYrot, 0.0f, 1.0f, 0.0f);
        
        mCube.draw(gl);
                
        gl.glLoadIdentity();                                    
                
        mXrot += mXspeed;
        mYrot += mYspeed;
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT)
            mYspeed -= 0.1f;
        else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)
            mYspeed += 0.1f;
        else if(keyCode == KeyEvent.KEYCODE_DPAD_UP)
            mXspeed -= 0.1f;
        else if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN)
            mXspeed += 0.1f;
             
        return true;
     }

     // unchanged
     @Override
     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); 
                
         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);        
     }

     
     // unchanged
     @Override
     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.glViewport(0, 0, width, height);

         gl.glMatrixMode(GL10.GL_MODELVIEW);
         gl.glLoadIdentity();
     }
}

The Cube is inherited from the previous recipe. Don't forget to call the requestFocus() and setFocusableInTouchMode(true) in the constructor of the view or else the key events will not be received.

See Also:

Create a spinning cube with OpenGL ES recipe: http://androidcookbook.com/Recipe.seam?recipeId=1418

Download:

The source code for this project can be downloaded from http://db.tt/jPQEDnzt.
No records found.