Index: /issm/trunk-jpl/src/android/ISSM/project.properties
===================================================================
--- /issm/trunk-jpl/src/android/ISSM/project.properties	(revision 14079)
+++ /issm/trunk-jpl/src/android/ISSM/project.properties	(revision 14080)
@@ -12,3 +12,3 @@
 
 # Project target.
-target=android-15
+target=Google Inc.:Google APIs:16
Index: /issm/trunk-jpl/src/android/ISSM_Visual/AndroidManifest.xml
===================================================================
--- /issm/trunk-jpl/src/android/ISSM_Visual/AndroidManifest.xml	(revision 14079)
+++ /issm/trunk-jpl/src/android/ISSM_Visual/AndroidManifest.xml	(revision 14080)
@@ -1,4 +1,4 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.example.issm_visual"
+    package="gov.nasa.jpl.issm.visual"
     android:versionCode="1"
     android:versionName="1.0" >
Index: /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/ISSMVisual.java
===================================================================
--- /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/ISSMVisual.java	(revision 14080)
+++ /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/ISSMVisual.java	(revision 14080)
@@ -0,0 +1,95 @@
+package gov.nasa.jpl.issm.visual;
+
+
+import android.app.Activity;
+import android.content.DialogInterface.OnClickListener;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+public class ISSMVisual extends Activity implements OnSeekBarChangeListener
+{
+	private SeekBar bar;
+    private TextView /*txtStatus,*/ txtValue;
+    private GLSurfaceView mGLView;
+	private FrameLayout frame;
+	
+    @Override
+    public void onCreate(Bundle savedInstanceState) 
+    {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_issmvisual);
+        
+        bar = (SeekBar)findViewById(R.id.seekBar); // make seekbar object
+        bar.setOnSeekBarChangeListener(this); // set seekbar listener
+        txtValue = (TextView)findViewById(R.id.value);
+        Button reset = (Button)findViewById(R.id.button1);
+        reset.setOnClickListener(new View.OnClickListener()
+        {
+            public void onClick(View v) 
+            {
+            	frame.removeView(mGLView);
+            	mGLView = new MyGLSurfaceView(ISSMVisual.this);
+            	frame.addView(mGLView);
+            }
+        });
+        //txtStatus = (TextView)findViewById(R.id.status);
+        
+        mGLView = new MyGLSurfaceView(this);
+        frame = (FrameLayout)findViewById(R.id.frame);
+        frame.addView(mGLView);
+    }
+	public void onProgressChanged(SeekBar seekBar, int val,
+    		boolean fromUser) 
+    {
+    	// change progress text label with current Seekbar value
+    	txtValue.setText("alpha value = " + val);
+    	//txtStatus.setText("Status: changing");
+    }
+	
+    public void onStartTrackingTouch(SeekBar seekBar) {/*txtStatus.setText("Status: Starting to track touch");*/}
+    
+    public void onStopTrackingTouch(SeekBar seekBar) 
+    {
+    	seekBar.setSecondaryProgress(seekBar.getProgress()); // set the shade of the previous value.
+    	
+    	//txtStatus.setText("Status: Ended tracking touch");
+    	frame.removeView(mGLView);
+    	mGLView = new MyGLSurfaceView(this);
+        frame.addView(mGLView);
+    }
+    
+    @Override
+    protected void onPause() 
+    {
+        super.onPause();
+        // The following call pauses the rendering thread.
+        // If your OpenGL application is memory intensive,
+        // you should consider de-allocating objects that
+        // consume significant memory here.
+        mGLView.onPause();
+    }
+    
+    @Override
+    protected void onResume() 
+    {
+        super.onResume();
+        // The following call resumes a paused rendering thread.
+        // If you de-allocated graphic objects for onPause()
+        // this is a good place to re-allocate them.
+        mGLView.onResume();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) 
+    {
+        getMenuInflater().inflate(R.menu.activity_issmvisual, menu);
+        return true;
+    }
+}
Index: /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/MyGLRenderer.java
===================================================================
--- /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/MyGLRenderer.java	(revision 14080)
+++ /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/MyGLRenderer.java	(revision 14080)
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package gov.nasa.jpl.issm.visual;
+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.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.Matrix;
+
+public class MyGLRenderer implements GLSurfaceView.Renderer 
+{
+	public volatile float mAngle;
+	
+	/**
+	 * Store the model matrix. This matrix is used to move models from object space (where each model can be thought
+	 * of being located at the center of the universe) to world space.
+	 */
+	private float[][] mModelMatrix;
+	
+	/**
+	 * Store the view matrix. This can be thought of as our camera. This matrix transforms world space to eye space;
+	 * it positions things relative to our eye.
+	 */
+	private float[][] mViewMatrix;
+
+	/** Store the projection matrix. This is used to project the scene onto a 2D viewport. */
+	private float[][] mProjectionMatrix;
+
+	/** Allocate storage for the final combined matrix. This will be passed into the shader program. */
+	private float[][] mMVPMatrix;
+
+	/** This will be used to pass in the transformation matrix. */
+	private int mMatrixHandle;
+	
+    private FloatBuffer[] triangleVert;
+    
+    private float[][] triangleData2DArr;
+    
+    private int mPositionHandle;
+    
+    private int mColorHandle;
+    
+	/** How many bytes per float. */
+    private final int mBytesPerFloat = 4;
+
+    /** How many elements per vertex. */
+    private final int mStrideBytes = 7 * mBytesPerFloat;
+
+    /** Offset of the position data. */
+    private final int mPositionOffset = 0;
+
+    /** Size of the position data in elements. */
+    private final int mPositionDataSize = 3;
+
+    /** Offset of the color data. */
+    private final int mColorOffset = 3;
+
+    /** Size of the color data in elements. */
+    private final int mColorDataSize = 4;	
+
+    public MyGLRenderer(float[][] vertices)
+    {	
+    	triangleData2DArr = new float[vertices.length][21];
+    	triangleVert = new FloatBuffer[vertices.length];
+    	
+    	for (int i = 0; i < vertices.length; i++)
+    	{
+    		for (int j = 0; j < 21; j++)
+    			triangleData2DArr[i][j] = vertices[i][j]; 
+    	}
+	    		
+	    // initialize vertex byte buffer for shape coordinates
+    	for (int i = 0; i < vertices.length; i++)
+    	{
+    		triangleVert[i] = ByteBuffer.allocateDirect(triangleData2DArr[i].length * mBytesPerFloat)
+    													.order(ByteOrder.nativeOrder()).asFloatBuffer();
+    		triangleVert[i].put(triangleData2DArr[i]).position(0);
+    	}
+    }
+    
+    public void onSurfaceCreated(GL10 unused, EGLConfig config) 
+    {
+        // Set the background frame color
+        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        
+		// Position the eye behind the origin.
+		final float eyeX = 0.0f;
+		final float eyeY = 0.0f;
+		final float eyeZ = 1.5f;
+
+		// We are looking toward the distance
+		final float lookX = 0.0f;
+		final float lookY = 0.0f;
+		final float lookZ = -5.0f;
+
+		// Set our up vector. This is where our head would be pointing were we holding the camera.
+		final float upX = 0.0f;
+		final float upY = 1.0f;
+		final float upZ = 0.0f;
+
+		// Set the view matrix. This matrix can be said to represent the camera position.
+		// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
+		// view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
+		mViewMatrix = new float[triangleVert.length][16];
+		
+		for (int i = 0; i < triangleVert.length; i++)
+			Matrix.setLookAtM(mViewMatrix[i], 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
+        
+		final String vertexShader =
+				"uniform mat4 u_MVPMatrix;      \n"		// A constant representing the combined model/view/projection matrix.
+			  + "attribute vec4 a_Position;     \n"		// Per-vertex position information we will pass in.
+			  + "attribute vec4 a_Color;        \n"		// Per-vertex color information we will pass in.			  
+			  + "varying vec4 v_Color;          \n"		// This will be passed into the fragment shader.
+			  + "void main()                    \n"		// The entry point for our vertex shader.
+			  + "{                              \n"
+			  + "   v_Color = a_Color;          \n"		// Pass the color through to the fragment shader. 
+			  											// It will be interpolated across the triangle.
+			  + "   gl_Position = u_MVPMatrix   \n" 	// gl_Position is a special variable used to store the final position.
+			  + "               * a_Position;   \n"     // Multiply the vertex by the matrix to get the final point in 			                                            			 
+			  + "}                              \n";    // normalized screen coordinates.
+
+			final String fragmentShader =
+				"precision mediump float;       \n"		// Set the default precision to medium. We don't need as high of a											// precision in the fragment shader.				
+			  + "varying vec4 v_Color;          \n"		// This is the color from the vertex shader interpolated across the 
+			  											// triangle per fragment.			  
+			  + "void main()                    \n"		// The entry point for our fragment shader.
+			  + "{                              \n"
+			  + "   gl_FragColor = v_Color;     \n"		// Pass the color directly through the pipeline.		  
+			  + "}                              \n";												
+
+    	   
+        int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
+		// Pass in the shader source.
+		GLES20.glShaderSource(vertexShaderHandle, vertexShader);
+
+		// Compile the shader.
+		GLES20.glCompileShader(vertexShaderHandle);
+
+		// Get the compilation status.
+		final int[] compileStatus1 = new int[1];
+		GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus1, 0);
+
+		// If the compilation failed, delete the shader.
+		if (compileStatus1[0] == 0) 
+		{				
+			GLES20.glDeleteShader(vertexShaderHandle);
+			vertexShaderHandle = 0;
+		}
+		
+         
+    	int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
+		// Pass in the shader source.
+		GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
+
+		// Compile the shader.
+		GLES20.glCompileShader(fragmentShaderHandle);
+
+		// Get the compilation status.
+		final int[] compileStatus2 = new int[1];
+		GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus2, 0);
+
+		// If the compilation failed, delete the shader.
+		if (compileStatus2[0] == 0) 
+		{				
+			GLES20.glDeleteShader(fragmentShaderHandle);
+			fragmentShaderHandle = 0;
+		}
+
+        
+        int mProgram = GLES20.glCreateProgram();
+		// Bind the vertex shader to the program.
+		GLES20.glAttachShader(mProgram, vertexShaderHandle);			
+
+		// Bind the fragment shader to the program.
+		GLES20.glAttachShader(mProgram, fragmentShaderHandle);
+
+		// Bind attributes
+		GLES20.glBindAttribLocation(mProgram, 0, "a_Position");
+		GLES20.glBindAttribLocation(mProgram, 1, "a_Color");
+
+		// Link the two shaders together into a program.
+		GLES20.glLinkProgram(mProgram);
+
+		// Get the link status.
+		final int[] linkStatus = new int[1];
+		GLES20.glGetProgramiv(mProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
+
+		// If the link failed, delete the program.
+		if (linkStatus[0] == 0) 
+		{				
+			GLES20.glDeleteProgram(mProgram);
+			mProgram = 0;
+		}
+		
+		for (int i = 0; i < triangleVert.length; i++)
+		{
+			mMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix");        
+	        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
+	        mColorHandle = GLES20.glGetAttribLocation(mProgram, "a_Color");
+		}
+        
+        // Add program to OpenGL environment
+        GLES20.glUseProgram(mProgram);
+    }
+    
+    public void onSurfaceChanged(GL10 unused, int width, int height) 
+    {
+        // Adjust the viewport based on geometry changes,
+        // such as screen rotation
+        GLES20.glViewport(0, 0, width, height);
+        
+		// Create a new perspective projection matrix. The height will stay the same
+		// while the width will vary as per aspect ratio.
+		final float ratio = (float) width / height;
+		
+		mProjectionMatrix = new float[triangleVert.length][16];
+		for (int i = 0; i < triangleVert.length; i++)
+			Matrix.frustumM(mProjectionMatrix[i], 0, -ratio*1.4f, ratio*1.4f, -1.4f, 1.4f, 1.4f, 14f);
+    }
+    
+    public void onDrawFrame(GL10 glUnused) 
+    {
+    	// Draw background color
+    	GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+    	
+    	mModelMatrix = new float[triangleVert.length][16];
+        // Draw the triangle facing straight on.
+    	for (int i = 0; i < triangleVert.length; i++)
+    		Matrix.setIdentityM(mModelMatrix[i], 0);
+    		
+    	mMVPMatrix = new float[triangleVert.length][16];
+    	draw(triangleVert); 
+
+    }
+
+    private void draw(final FloatBuffer[] aTriangleBuffer)
+    {
+    	for (int i = 0; i < aTriangleBuffer.length; i++)
+    	{
+	        // Pass in the position information
+	        aTriangleBuffer[i].position(mPositionOffset);
+	        GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
+	                				     mStrideBytes, aTriangleBuffer[i]);
+	        
+	        GLES20.glEnableVertexAttribArray(mPositionHandle);
+	     
+	        
+	        // Pass in the color information
+	        aTriangleBuffer[i].position(mColorOffset);
+	        GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false,
+	                					 mStrideBytes, aTriangleBuffer[i]);
+	        
+	        GLES20.glEnableVertexAttribArray(mColorHandle);
+	        
+	        Matrix.setRotateM(mModelMatrix[i], 0, mAngle, 0, 0, -1.0f);
+
+			// This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
+	        // (which currently contains model * view).
+	        Matrix.multiplyMM(mMVPMatrix[i], 0, mViewMatrix[i], 0, mModelMatrix[i], 0);
+	        
+	        // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
+	        // (which now contains model * view * projection).
+	        Matrix.multiplyMM(mMVPMatrix[i], 0, mProjectionMatrix[i], 0, mMVPMatrix[i], 0);
+	        
+	        GLES20.glUniformMatrix4fv(mMatrixHandle, 1, false, mMVPMatrix[i], 0);
+	        
+	        // Draw the triangle
+	        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
+	        
+	        // Disable vertex array
+	        GLES20.glDisableVertexAttribArray(mPositionHandle);
+    	}
+    }
+
+}
Index: /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/MyGLSurfaceView.java
===================================================================
--- /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/MyGLSurfaceView.java	(revision 14080)
+++ /issm/trunk-jpl/src/android/ISSM_Visual/src/gov/nasa/jpl/issm/visual/MyGLSurfaceView.java	(revision 14080)
@@ -0,0 +1,82 @@
+package gov.nasa.jpl.issm.visual;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.view.MotionEvent;
+
+
+class MyGLSurfaceView extends GLSurfaceView 
+{
+	private MyGLRenderer mRend;
+    public MyGLSurfaceView(Context context) 
+    {
+        super(context);
+
+        // Create an OpenGL ES 2.0 context.
+        setEGLContextClientVersion(2);
+        
+        final int NMAX_TRIANGLES = 2000;
+        final int MAX_VERTICES = 21;
+        
+        float f[][] = new float[NMAX_TRIANGLES][MAX_VERTICES];
+        int n, random;
+		for (int i = 0; i < f.length; i++)
+		{
+			for (int j = 0; j < MAX_VERTICES; j++)
+			{
+				if (j == 6 || j == 13 || j == 20) continue;
+				n = 1;
+		        random = (int)(Math.floor((Math.random()*10)+1));
+		        if (random <= 5) n = -1;
+		        
+				f[i][j] = (float)(Math.random()*n);
+			}
+		}
+
+        mRend = new MyGLRenderer(f);
+        
+        // Set the Renderer for drawing on the GLSurfaceView
+        setRenderer(mRend);
+
+        // Render the view only when there is a change in the drawing data
+        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+    }
+    
+    private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
+    private float mPreviousX;
+    
+    private float mPreviousY;
+    @Override
+    public boolean onTouchEvent(MotionEvent e) {
+        // MotionEvent reports input details from the touch screen
+        // and other input controls. In this case, you are only
+        // interested in events where the touch position changed.
+
+        float x = e.getX();
+        float y = e.getY();
+
+        switch (e.getAction()) {
+            case MotionEvent.ACTION_MOVE:
+
+                float dx = x - mPreviousX;
+                float dy = y - mPreviousY;
+
+                // reverse direction of rotation above the mid-line
+                if (y > getHeight() / 2) {
+                  dx = dx * -1 ;
+                }
+
+                // reverse direction of rotation to left of the mid-line
+                if (x < getWidth() / 2) {
+                  dy = dy * -1 ;
+                }
+
+                mRend.mAngle += (dx + dy) * TOUCH_SCALE_FACTOR;  // = 180.0f / 320
+                requestRender();
+        }
+
+        mPreviousX = x;
+        mPreviousY = y;
+        return true;
+    }
+}
