Android Maps, WebGL




CS175

Chris Pollett

Dec 1, 2014

Outline

Introduction

Introduction

More Maps

Simple Map Example Code

Below is the simple map activity from the Google map documentation site.

import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.*;
import android.app.Activity;
import android.os.Bundle;

public class MapPane extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.map_activity);

        // Get a handle to the Map Fragment
        GoogleMap map = ((MapFragment) getFragmentManager()
                .findFragmentById(R.id.map)).getMap(); //set up map

        LatLng sydney = new LatLng(-33.867, 151.206); // specify a location

        map.setMyLocationEnabled(true);
       //move camera to location using a given zoom level.
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 13)); 
        // create a marker.
        map.addMarker(new MarkerOptions()
                .title("Sydney")
                .snippet("The most populous city in Australia.")
                .position(sydney));
    }
}

Quiz

Which of the following is true?

  1. An AVAudioPlayer can be used to play back audio on an iPhone
  2. Google Maps is the earliest online mapping software.
  3. Google Maps does not have a Javascript API.

WebGL

Using WebGL

A Complicated Way to Draw a Red Screen

The code below illustrates setting up a WebGL context. To see what it looks like look at the WebGL getContext Demo Page.

<!DOCTYPE html>
<html>
    <head>
        <title>Basic HTML 5 document with a WebGL Canvas</title>
        <meta charset="utf-8" />
        <script type="text/javascript">
        var gl; // A global variable for the WebGL context
        function initWebGL(canvas) 
        {
            gl = null;
            try {
                // Try to grab the standard context.
                // If it fails, fallback to experimental.
                gl = canvas.getContext("webgl") ||
                    canvas.getContext("experimental-webgl");
            } catch(e) {
                alert("getContext didn't work");
            }

            // If we don't have a GL context, give up now
            if (!gl) {
                alert("Unable to initialize WebGL.");
                gl = null;
            } 
            return gl;
        }
        function start() 
        {
           var canvas = document.getElementById("glcanvas");
           gl = initWebGL(canvas);      // Initialize the GL context
           // Only continue if WebGL is available and working
           if (gl) {
             gl.clearColor(1.0, 0.0, 0.0, 1.0);  
                // Set clear color to red
             gl.enable(gl.DEPTH_TEST);  // Enable depth testing
             gl.depthFunc(gl.LEQUAL);  // Near things obscure far things
             gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); 
                // Clear the color as well as the depth buffer.
           }
       }
       </script>
   </head>
   <body onload="start()">
   <canvas id="glcanvas" style="width:640px; height:480px" >
   To see this demo your browser needs to support the canvas element.
   $5 donations accepted
   </canvas>
   </body>
</html>

Remarks on Code

Making A More Complicated Example with Shaders

New Start Function

function start() 
{
    canvas = document.getElementById("glcanvas");
    initWebGL(canvas);// Initialize the GL context
    // Only continue if WebGL is available and working
    if (gl) {
        gl.clearColor(1.0, 0.0, 0.0, 1.0);
        // Set clear color to red
        gl.clearDepth(1.0);
        gl.enable(gl.DEPTH_TEST);  // Enable depth testing
        gl.depthFunc(gl.LEQUAL);  // Near things obscure far things

        // Initialize the shaders; this is where all the lighting for the
        // vertices and so forth is established.
        initShaders();
        // Here's where we call the routine that builds all the objects
        // we'll be drawing.
        initBuffers();
        // Set up to draw the scene periodically.
        setInterval(drawScene, 15);
    }
}

initShaders

initBuffers

initBuffer sets up the vertex buffere for our square.

function initBuffers() 
{
    // Create a buffer for the square's vertices.
    squareVerticesBuffer = gl.createBuffer();
    // Select the squareVerticesBuffer as the one to apply vertex
    // operations to from here out.
    gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
    // Now create an array of vertices for the square. Note that the Z
    // coordinate is always 0 here.
    var vertices = [
    1.0,  1.0,  0.0,
    -1.0, 1.0,  0.0,
    1.0,  -1.0, 0.0,
    -1.0, -1.0, 0.0
    ];
    // Now pass the list of vertices into WebGL to build the shape. We
    // do this by creating a Float32Array from the JavaScript array,
    // then use it to fill the current vertex buffer.
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
}

drawScene

Here is the code to actually draw the vertex buffer we had using the shader we have set up. The function makePerspective all comes from glUtils.js and make use of sylvester.js.

Notice we set up an attribute pointer immediate after the bindBuffer call to say how the vertices will be mapped into aVertexPosition (3 coordinates, each vertex is a float, vertices should be fixed point rather than normalized, no stride and no first pointer).

function drawScene()
{
    // Clear the canvas before we start drawing on it.
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    // Establish the perspective with which we want to view the
    // scene. Our field of view is 45 degrees, with a width/height
    // ratio of 640:480, and we only want to see objects between 0.1 units
    // and 100 units away from the camera.
    perspectiveMatrix = makePerspective(45, 640.0/480.0, 0.1, 100.0);
    // Set the drawing position to the "identity" point, which is
    // the center of the scene.
    loadIdentity();
    // Now move the drawing position a bit to where we want to start
    // drawing the square.
    mvTranslate([-0.0, 0.0, -6.0]);
    // Draw the square by binding the array buffer to the square's vertices
    // array, setting attributes, and pushing it to GL.
    gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesBuffer);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
    setMatrixUniforms();
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}

setMatrixUniforms passes our projection and model view matrices to shader land:

function loadIdentity() 
{
    mvMatrix = Matrix.I(4); //Matrix is sylvester
}
function multMatrix(m) 
{
    mvMatrix = mvMatrix.x(m);
}
function mvTranslate(v)
{
    multMatrix(Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4());
}
function setMatrixUniforms()
{
    var pUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
    gl.uniformMatrix4fv(pUniform, false, 
        new Float32Array(perspectiveMatrix.flatten()));
    var mvUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
    gl.uniformMatrix4fv(mvUniform, false, new Float32Array(mvMatrix.flatten()));
}