1. A concise explanation of the problem you're experiencing.
Hey Guys,
I´m trying to control the position of the camera with the HTML5 device orientation (similar to
https://groups.google.com/forum/#!topic/cesium-dev/cr2P2wfOwl4). The idea is that a user can move around his smartphone and
see for example terrain as if the camera would point out of the back of the device. I´ve searched around the web for quite a bit and found some useful sites (
https://dev.opera.com/articles/w3c-device-orientation-usage/,
http://www.users.on.net/~wallala/Cesium/Apps/Soarer/) but unfortunately I can not get it to work properly.
With the below code I can move the camera around by moving the device but the movements are not correct. Since I am stuck and not sure where exactly my problem is I thought I post this question and see if you guys can help me.
////////
var viewer = new Cesium.Viewer('cesiumContainer');
var scene = viewer.scene;
var camera = viewer.camera;
var terrainProvider = Cesium.createWorldTerrain();
function flyToLocation() {
// Create callback for browser's geolocation
function fly(position) {
viewer.camera.flyTo({
destination : Cesium.Cartesian3.fromDegrees(position.coords.longitude, position.coords.latitude, 10.0)
});
}
// Ask browser for location, and fly there.
navigator.geolocation.getCurrentPosition(fly);
};
var currentScreenOrientation = window.orientation || 0; // active default
if (window.DeviceOrientationEvent) {
window.addEventListener('deviceorientation', onDeviceOrientationChanged, false);
}
/**
* Rotation Matrix functions
* Convert Yaw/alpha/Z, Pitch/beta/X, Roll/gamma/Y to and from rotation matrix, apply transformations
*
* @author Rich Tibbett <
https://dev.opera.com/articles/w3c-device-orientation-usage/>, Nghia Ho <
http://nghiaho.com/?page_id=846>, Derek Wee
* @copyright
* @version 0.1
* @license
*/
var degtorad = Math.PI / 180; // Degree-to-Radian conversion
var worldOrientation = 90;
var screenOrientation = 90;
//R.1: Converting deviceorientation angles to a Rotation Matrix representation
function getBaseRotationMatrix( alpha, beta, gamma ) {
var _x = beta ? beta * degtorad : 0; // beta value
var _y = gamma ? gamma * degtorad : 0; // gamma value
var _z = alpha ? alpha * degtorad : 0; // alpha value
var cX = Math.cos( _x );
var cY = Math.cos( _y );
var cZ = Math.cos( _z );
var sX = Math.sin( _x );
var sY = Math.sin( _y );
var sZ = Math.sin( _z );
//
// ZXY-ordered rotation matrix construction.
//
var m11 = cZ * cY - sZ * sX * sY;
var m12 = - cX * sZ;
var m13 = cY * sZ * sX + cZ * sY;
var m21 = cY * sZ + cZ * sX * sY;
var m22 = cZ * cX;
var m23 = sZ * sY - cZ * cY * sX;
var m31 = - cX * sY;
var m32 = sX;
var m33 = cX * cY;
return [
m11, m12, m13,
m21, m22, m23,
m31, m32, m33
];
};
//R.2: Fixing our rotation matrix frame relative to the current screen orientation
function getScreenTransformationMatrix( screenOrientation ) {
var orientationAngle = screenOrientation ? screenOrientation * degtorad : 0;
var cA = Math.cos( orientationAngle );
var sA = Math.sin( orientationAngle );
// Construct our screen transformation matrix
var r_s = [
cA, -sA, 0,
sA, cA, 0,
0, 0, 1
];
return r_s;
}
//R.3: Fix our rotation matrix frame relative to our application’s world orientation (rotation around x-axis)
function getWorldTransformationMatrix() {
var x = 90 * degtorad;
var cA = Math.cos( x );
var sA = Math.sin( x );
// Construct our world transformation matrix
var r_w = [
1, 0, 0,
0, cA, -sA,
0, sA, cA
];
return r_w;
}
//R.4: Computing our final rotation matrix representation
function matrixMultiply( a, b ) {
var final = [];
final[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6];
final[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7];
final[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8];
final[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6];
final[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7];
final[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8];
final[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6];
final[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7];
final[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8];
return final;
}
//Returns a 3 x 3 rotation matrix as an array
function computeMatrix(alpha, beta, gamma, currentScreenOrientation) {
var rotationMatrix = getBaseRotationMatrix(
alpha,
beta,
gamma
); // R
var screenTransform = getScreenTransformationMatrix( currentScreenOrientation ); // r_s
var screenAdjustedMatrix = matrixMultiply( rotationMatrix, screenTransform ); // R_s
var worldTransform = getWorldTransformationMatrix(); // r_w
var finalMatrix = matrixMultiply( screenAdjustedMatrix, worldTransform ); // R_w
return finalMatrix; // [ m11, m12, m13, m21, m22, m23, m31, m32, m33 ]
}
//Decomposes a 3 x 3 rotation matrix into an array containing Yaw/alpha/Z Pitch/beta/X Roll/gamma/Y
function getYawPitchRoll(rotationMatrix) {
var rm11 = rotationMatrix[0]; var rm12 = rotationMatrix[1]; var rm13 = rotationMatrix[2];
var rm21 = rotationMatrix[3]; var rm22 = rotationMatrix[4]; var rm23 = rotationMatrix[5];
var rm31 = rotationMatrix[6]; var rm32 = rotationMatrix[7]; var rm33 = rotationMatrix[8];
var yaw = Math.atan2(rm21, rm11);
var pitch = Math.atan2(rm32, rm33);
var roll = Math.atan2(rm31, Math.sqrt(Math.pow(rm32,2) + Math.pow(rm33,2)));
return [yaw, pitch, roll]; //[yaw, pitch, roll]
}
function onDeviceOrientationChanged(eventData) {
var beta = eventData.beta;
var gamma = eventData.gamma;
var alpha = eventData.alpha;
var matrix = computeMatrix(alpha, beta, gamma, screenOrientation)
var matrix = getYawPitchRoll(matrix);
console.log(matrix);
var right = Cesium.Matrix3.getRow(matrix, 0, new Cesium.Cartesian3);
var up = Cesium.Matrix3.getRow(matrix, 1, new Cesium.Cartesian3);
var direction = Cesium.Matrix3.getRow(matrix, 2, new Cesium.Cartesian3);
viewer.camera.setView({
orientation: {
heading : matrix[0],
pitch : matrix[1],
roll : matrix[2]
}
});
};
/////
Some notes: As you can see the code to get the rotation matrix is not by me. To test I use the Google Chrome Developer Tools Sensors to simulate the movement of the device. The Cesium version is 1.44.
Thanks for your help!