@Override
  public void onDrawFrame(GL10 glUnused) {
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

    // Set our per-vertex lighting program.
    GLES20.glUseProgram(mPerVertexProgramHandle);

    // Set program handles for cube drawing.
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mPerVertexProgramHandle, "u_MVPMatrix");
    mMVMatrixHandle = GLES20.glGetUniformLocation(mPerVertexProgramHandle, "u_MVMatrix");
    mLightPosHandle = GLES20.glGetUniformLocation(mPerVertexProgramHandle, "u_LightPos");
    mPositionHandle = GLES20.glGetAttribLocation(mPerVertexProgramHandle, "a_Position");
    mColorHandle = GLES20.glGetAttribLocation(mPerVertexProgramHandle, "a_Color");
    mNormalHandle = GLES20.glGetAttribLocation(mPerVertexProgramHandle, "a_Normal");
    mTextureCoordinateHandle =
        GLES20.glGetAttribLocation(mPerVertexProgramHandle, "a_TexCoordinate");

    // Set the active texture unit to texture unit 0.
    GLES20.glEnable(GLES20.GL_TEXTURE_2D);
    // Bind the texture to this unit.
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureArray.get(0));
    drawPlane(this.mGroundVertices, this.mGroundColors, this.mGroundNormals, mGroundTextures);
    // bind the next texture
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureArray.get(1));
    drawPlane(this.mOceanVertices, this.mOceanColors, this.mOceanNormals, mOceanTextures);
    // bind the next texture
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureArray.get(3));
    drawCube();

    // Get changes in finger positions and add to total for moving and rotating
    totalDiffX += diffX;
    totalDiffY += diffY;
    angleX += dx;
    angleY += dy;
    // to prevent the user from looking more than straight up and less and straight down.
    if (Math.abs(angleY) > 1.5f) {
      angleY -= dy;
    }

    // move the model matrix by finger distance changes for pinch zoom movement.
    Matrix.translateM(mModelMatrix, 0, this.diffX, this.diffY, 0);

    // rotate camera based on finger movements
    this.mCamera.look.x = (float) Math.cos(angleX);
    this.mCamera.look.y = (float) Math.sin(angleX);
    this.mCamera.look.z = (float) Math.tan(angleY);
    updateLookAt();

    // reset variables so that movement stops after finger movement stops
    this.dx = 0;
    this.dy = 0;
    this.diffX = 0;
    this.diffY = 0;

    // update the lookAt coordinates
    updateLookAt();
    // redraw each object in the array.
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureArray.get(2));
    synchronized (this.objects) {
      for (Prim p : this.objects) {
        p.draw(
            this.mPositionHandle,
            this.mColorHandle,
            this.mNormalHandle,
            this.mTextureCoordinateHandle);
      }
    }
    GLES20.glDisable(GLES20.GL_TEXTURE_2D);
  }