Index: /issm/trunk-jpl/src/m/plot/plot_mesh.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_mesh.js	(revision 19918)
+++ /issm/trunk-jpl/src/m/plot/plot_mesh.js	(revision 19919)
@@ -50,4 +50,7 @@
 	node["overlay"] = false;
 	node["drawOrder"] = 0;
+	node["maskEnabled"] = options.exist('mask');
+	node["maskHeight"] = options.getfieldvalue('maskheight',150.0)*options.getfieldvalue('heightscale',1);
+	node["maskColor"] = options.getfieldvalue('maskcolor',[0.0,0.0,1.0,1.0]);
 				
 	//some defaults:
Index: /issm/trunk-jpl/src/m/plot/plot_overlay.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_overlay.js	(revision 19918)
+++ /issm/trunk-jpl/src/m/plot/plot_overlay.js	(revision 19919)
@@ -55,4 +55,7 @@
 	node["overlay"] = false;
 	node["drawOrder"] = 1;
+	node["maskEnabled"] = options.getfieldvalue('outermask','off') == 'on';
+	node["maskHeight"] = options.getfieldvalue('outermaskheight',150.0)*options.getfieldvalue('heightscale',1);
+	node["maskColor"] = options.getfieldvalue('outermaskcolor',[0.0,0.0,1.0,1.0]);
 				
 	//some defaults:
Index: /issm/trunk-jpl/src/m/plot/plot_unit.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/plot_unit.js	(revision 19918)
+++ /issm/trunk-jpl/src/m/plot/plot_unit.js	(revision 19919)
@@ -61,4 +61,7 @@
 	node["overlay"] = options.getfieldvalue('overlay','off') == 'on';
 	node["drawOrder"] = 0;
+	node["maskEnabled"] = options.getfieldvalue('innermask','off') == 'on';
+	node["maskHeight"] = options.getfieldvalue('innermaskheight',150.0)*options.getfieldvalue('heightscale',1);
+	node["maskColor"] = options.getfieldvalue('innermaskcolor',[0.0,0.0,1.0,1.0]);
 	
 	switch(datatype){
Index: /issm/trunk-jpl/src/m/plot/webgl.js
===================================================================
--- /issm/trunk-jpl/src/m/plot/webgl.js	(revision 19918)
+++ /issm/trunk-jpl/src/m/plot/webgl.js	(revision 19919)
@@ -51,6 +51,6 @@
 	var mc = new Hammer.Manager(canvas);
 
-    mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
-    mc.add(new Hammer.Pinch({ threshold: 0})).recognizeWith(mc.get('pan'));
+    mc.add(new Hammer.Pan({threshold:0, pointers:0}));
+    mc.add(new Hammer.Pinch({threshold:0})).recognizeWith(mc.get('pan'));
 
     mc.on("panstart panmove", function (ev) {onPan(ev,canvas);});
@@ -124,4 +124,7 @@
 		overlay:false,
 		drawOrder:0,
+		maskEnabled:false,
+		maskHeight:150.0,
+		maskColor:vec4.fromValues(0.0, 0.0, 1.0, 1.0),
 	};
 } //}}}
@@ -194,8 +197,10 @@
 		'',
 		'varying vec2 vTextureCoord;',
+		'varying float vZCoord;',
 		'',
 		'void main(void) {',
 		'	gl_Position = uMVPMatrix * vec4(aVertexPosition.xyz, 1.0);',
 		'	vTextureCoord = aTextureCoord;',
+		'	vZCoord = aVertexPosition.z;',
 		'}'].join('\n');
 	shaders["unlit_textured"]["fsh"]["string"] =
@@ -203,10 +208,19 @@
 		'',
 		'varying vec2 vTextureCoord;',
+		'varying float vZCoord;',
 		'',
 		'uniform sampler2D uColorSampler;',
 		'uniform float uAlpha;',
+		'uniform bool uMaskEnabled;',
+		'uniform float uMaskHeight;',
+		'uniform vec4 uMaskColor;',
 		'',
 		'void main(void) {',
-		'	gl_FragColor = vec4(texture2D(uColorSampler, vec2(vTextureCoord.s, vTextureCoord.t)).rgb, uAlpha);',
+		'	if (uMaskEnabled && (vZCoord < uMaskHeight)) {',
+		'		gl_FragColor = uMaskColor;',
+		'	}',
+		'	else {',
+		'		gl_FragColor = vec4(texture2D(uColorSampler, vec2(vTextureCoord.s, vTextureCoord.t)).rgb, uAlpha);',
+		'	}',
 		'}'].join('\n');
 	shaderNames.forEach(function(shaderName){
@@ -290,19 +304,24 @@
 		canvas.lastDeltaY = 0;
 	}
-	// if single finger/pan without modifier key, rotate around center
-	//canvas.translation[0] += (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * canvas.zoomFactor * 2;
-	//canvas.translation[1] -= (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * canvas.zoomFactor * 2;
-	// else if double finger/pan with modifier key, move camera center
-	canvas.rotation[0] += degrees((canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * canvas.zoomFactor * 2);
-	canvas.rotation[1] += degrees((canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * canvas.zoomFactor * 2);
-	
-	if (canvas.rotation[0] > 360) {canvas.rotation[0] -= 360};
-	if (canvas.rotation[0] < 0) {canvas.rotation[0] += 360};
-	if (canvas.rotation[1] > 180) {canvas.rotation[1] -= 360};
-	if (canvas.rotation[1] < -180) {canvas.rotation[1] += 360};
-	
-	canvas.rotation[0] = clamp(canvas.rotation[0], canvas.rotationAzimuthBounds[0], canvas.rotationAzimuthBounds[1]);
-	canvas.rotation[1] = clamp(canvas.rotation[1], canvas.rotationElevationBounds[0], canvas.rotationElevationBounds[1])
-	
+	if (ev.srcEvent.shiftKey || ev.pointers.length == 2) {
+		var deltaX = (canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * canvas.zoomFactor * 2;
+		var deltaY = (canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * canvas.zoomFactor * 2;
+		
+		canvas.translation[0] += Math.cos(radians(canvas.rotation[0])) * deltaX - Math.sin(radians(canvas.rotation[0])) * deltaY;
+		//console.log(Math.cos(radians(canvas.rotation[0])) * deltaX, Math.sin(radians(canvas.rotation[0])) * deltaY);
+		canvas.translation[1] += Math.sin(radians(canvas.rotation[0])) * deltaX + Math.cos(radians(canvas.rotation[0])) * deltaY;
+	}
+	else {
+		canvas.rotation[0] += degrees((canvas.lastDeltaX - ev.deltaX) / canvas.clientWidth * canvas.zoomFactor * 2);
+		canvas.rotation[1] += degrees((canvas.lastDeltaY - ev.deltaY) / canvas.clientHeight * canvas.zoomFactor * 2);
+		
+		if (canvas.rotation[0] > 360) {canvas.rotation[0] -= 360};
+		if (canvas.rotation[0] < 0) {canvas.rotation[0] += 360};
+		if (canvas.rotation[1] > 180) {canvas.rotation[1] -= 360};
+		if (canvas.rotation[1] < -180) {canvas.rotation[1] += 360};
+		
+		canvas.rotation[0] = clamp(canvas.rotation[0], canvas.rotationAzimuthBounds[0], canvas.rotationAzimuthBounds[1]);
+		canvas.rotation[1] = clamp(canvas.rotation[1], canvas.rotationElevationBounds[0], canvas.rotationElevationBounds[1])
+	}
 	canvas.lastDeltaX = ev.deltaX;
 	canvas.lastDeltaY = ev.deltaY;
@@ -329,7 +348,8 @@
 //{{{ Drawing Functions
 function updateCameraMatrix(canvas) { //{{{
-       	//Update view matrix and multiply with projection matrix to get the view-projection (camera) matrix.
+    //Update view matrix and multiply with projection matrix to get the view-projection (camera) matrix.
 	var vMatrix = mat4.create();
 	var pMatrix = mat4.create();
+	var translateMatrix = mat4.create();
 	var rotationMatrix = mat4.create();
 	var azimuthRotationMatrix = mat4.create();
@@ -337,4 +357,8 @@
 
 	mat4.perspective(pMatrix, 90 * Math.PI / 180, canvas.clientWidth / canvas.clientHeight, 0.001, 10000.0);
+	
+	//Apply worldspace translation
+	mat4.translate(translateMatrix, translateMatrix, [canvas.translation[0], 0.0, canvas.translation[1]]);
+	mat4.multiply(vMatrix, translateMatrix, vMatrix);
 	
 	//Calculate rotation around camera focal point about worldspace origin
@@ -346,7 +370,7 @@
 	mat4.multiply(vMatrix, rotationMatrix, vMatrix);
 	
-	//Apply screenspace relative translation
-	var translateMatrix = mat4.create();
-	mat4.translate(translateMatrix, translateMatrix, [canvas.translation[0], canvas.translation[1], canvas.zoomFactor]);
+	//Apply screenspace translation
+	mat4.identity(translateMatrix);
+	mat4.translate(translateMatrix, translateMatrix, [0.0, 0.0, canvas.zoomFactor]);
 	mat4.multiply(vMatrix, translateMatrix, vMatrix);
 
@@ -371,4 +395,7 @@
 	gl.uniformMatrix4fv(node["shader"]["uMVPMatrix"], false, mvpMatrix);
 	gl.uniform1f(node["shader"]["uAlpha"], node["alpha"]);
+	gl.uniform1i(node["shader"]["uMaskEnabled"], node["maskEnabled"]);
+	gl.uniform1f(node["shader"]["uMaskHeight"], node["maskHeight"]);
+	gl.uniform4fv(node["shader"]["uMaskColor"], node["maskColor"]);
 	if (node["texture"]) {
 		gl.activeTexture(gl.TEXTURE0);
