Moving camera with keboard.

What is the best way to move the camera with the keyboard in the 3D view without overriding the default behaviour?
I would like to maintain the underlying mouse controls and simply add additional controls for panning, rotating and zooming around the “camera pivot” with keboard keys.

I tried to customize the camera example in the sandcastle editor but it seems that if I start messing with the camera positions it breaks the default camera controls, especially when using the lookAt function.

I am wondering if there are functions in the Camera or ScreenSpaceCameraController classes which can be used to simulate mouse actions.

The following Sandcastle code simulates rotation and zoom with QWEASD keys but it breaks camera rotation with the mouse (pan still works), if the last line of code is removed (viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY):wink: panning with mouse will not work.

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

infoBox : false,

selectionIndicator : false,

shadows : true

});

var scene = viewer.scene;

var canvas = viewer.canvas;

canvas.setAttribute(‘tabindex’, ‘0’); // needed to put focus on the canvas

canvas.onclick = function() { canvas.focus();

};

var ellipsoid = viewer.scene.globe.ellipsoid;

var globe = viewer.scene.globe;

var heading = 0;

var pitch = -0.60;

var range = 2000;

var targetHeading = 0;

var targetPitch = -0.60;

var headingSpeed = 0;

var pitchSpeed = 0;

var rangeSpeed = 0;

var camera = viewer.camera;

//The point around what camera rotates

var center = Cesium.Cartesian3.fromDegrees(-98.0, 40.0);

var flags = {

looking : false,

moveForward : false,

moveBackward : false,

moveUp : false,

moveDown : false,

moveLeft : false,

moveRight : false,

z : false,

cesiumCameraMoving : false

};

camera.moveStart.addEventListener(function()

{

flags.cesiumCameraMoving = true;

});

camera.moveEnd.addEventListener(function()

{

flags.cesiumCameraMoving = false;

});

function getFlagForKeyCode(keyCode) {

switch (keyCode) {

case ‘W’.charCodeAt(0):

return ‘moveForward’;

case ‘S’.charCodeAt(0):

return ‘moveBackward’;

case ‘Q’.charCodeAt(0):

return ‘moveUp’;

case ‘E’.charCodeAt(0):

return ‘moveDown’;

case ‘D’.charCodeAt(0):

return ‘moveRight’;

case ‘A’.charCodeAt(0):

return ‘moveLeft’;

case ‘Z’.charCodeAt(0):

return ‘moveLeft’;

default:

return undefined;

}

}

document.addEventListener(‘keydown’, function(e) {

var flagName = getFlagForKeyCode(e.keyCode);

if (typeof flagName !== ‘undefined’) {

flags[flagName] = true;

}

}, false);

document.addEventListener(‘keyup’, function(e) {

var flagName = getFlagForKeyCode(e.keyCode);

if (typeof flagName !== ‘undefined’) {

flags[flagName] = false;

}

}, false);

var lastHeight = 0;

viewer.scene.preRender.addEventListener(function(scene, time)

{

if (!center)

center = camera.position;

var width = canvas.clientWidth;

var windowPosition = new Cesium.Cartesian2(viewer.container.clientWidth / 2, viewer.container.clientHeight / 2);

var pickRay = viewer.scene.camera.getPickRay(windowPosition);

var pickPosition = viewer.scene.globe.pick(pickRay, viewer.scene);

if (pickPosition) center = pickPosition;

var centerCarto = ellipsoid.cartesianToCartographic(center);

var newHeight = globe.getHeight(centerCarto);

if (newHeight)

{

centerCarto.height = newHeight;

}

else

{

centerCarto.height = lastHeight

}

lastHeight = centerCarto.height;

var center = ellipsoid.cartographicToCartesian(centerCarto);

var cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;

if (flags.moveForward) {

rangeSpeed -= 0.001;

}

if (flags.moveBackward) {

rangeSpeed += 0.001;

}

if (flags.moveUp) {

pitchSpeed += 0.001;

}

if (flags.moveDown) {

pitchSpeed -= 0.001;

}

if (flags.moveLeft) {

headingSpeed += 0.001;

}

if (flags.moveRight) {

headingSpeed -= 0.001;

}

headingSpeed *= 0.90;

pitchSpeed *= 0.90;

rangeSpeed *= 0.96;

targetHeading += headingSpeed;

targetPitch += pitchSpeed;

heading = heading * 0.90 + targetHeading * 0.1;

pitch = pitch * 0.90 + targetPitch * 0.1;

range = range + rangeSpeed * range;

viewer.camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, range));

viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);

});