How to lock the cesium camera and make it behave like AR

I trying to make my own version of AR as cesium does not support natively. I want to lock the cesium camera make the AR camera move behind the Cesium globe like real AR. What I got till now is like VR in AR:https://youtu.be/MCy8KgLVwYU. I want like this: https://twitter.com/Liam2404/status/1100082605477822464?s=20.

	var destination = new Cesium.Cartesian3();
	var currentScreenOrientation = window.orientation || 1; // active default
	// THIS ALLOWS YOU TO USE THE PHONE TO CONTROL THE CESIUM CAMERA VIEW
	if (window.DeviceOrientationEvent) {
	window.addEventListener('deviceorientation', onDeviceOrientationChanged, false);
	}
	window.addEventListener('orientationchange', function() {
	currentScreenOrientation = window.orientation;
	}, false);
	var degtorad = Math.PI / 180; // Degree-to-Radian conversion
	//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 ]
	}
	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, currentScreenOrientation);
	var YawPitchRoll = getYawPitchRoll(matrix);
	console.log(YawPitchRoll);
	widget.camera.setView({
	orientation : {
	heading : -YawPitchRoll[0],
	pitch : YawPitchRoll[1],
	roll: -YawPitchRoll[2]
	}
	});
	}

I was looking at the getYawPitchRoll function. Not sure about the rest, but I know you can’t determine pitch solely based on the object’s up vector.

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]
	}
//var myMat=[1,0,0, 0,1,0, 0,0,1]; //dir north, right east, up up (yields 0 0 0 )
//var myMat=[0,-1,0, 1,0,0, 0,0,1]; //dir east, right south, up up (yields 90 0 0 )
//var myMat=[1,0,0, 0,0,1, 0,-1,0]; //dir up, right east, up south (yields 0 -90 0) (usually +pitch is up)
var myMat=[0,1,0, 0,0,1, -1,0,0]; //dir up, right north, up east (yields 0 0 -90) (pitched up yet 0 pitch)

var bla = getYawPitchRoll(myMat);
outputString = bla[0]*180/Math.PI+" "+bla[1]*180/Math.PI+" "+bla[2]*180/Math.PI+" ";

However you can determine it soley by the z component of the forward vector.

I’ve been using atan2(direction.x,direction.y) to determine heading. I wonder if atan2 (dir.x rig.x) will work in all cases.

I’ve never seen a roll calc like that, I wonder if it yields the same values as atan2 (-right.z up.z) for all cases as well.

1 Like

I just tried on some other orientations:

This rot mat is 45deg hea 45deg pitch 0deg roll
yields 35.264 -35.264 -30.000 (hpr)
0: 0.7071067811865476
1: -0.7071067811865475
2: -0
3: 0.5
4: 0.5000000000000001
5: 0.7071067811865475
6: -0.4999999999999999
7: -0.5
8: 0.7071067811865476

This rot mat is 45deg hea 45deg pitch 45deg roll
yields 30.361 -59.639 8.421 (hpr)
0: 0.8535533905932737
1: -0.14644660940672627
2: -0.5
3: 0.5
4: 0.5000000000000001
5: 0.7071067811865475
6: 0.14644660940672627
7: -0.8535533905932737
8: 0.5000000000000001

Cesium does have functions for this
heading
github.com/CesiumGS/cesium/blob/bfdd1050bb21706fe694c480602bc9f1581e769c/Source/Scene/Camera.js#L736
pitch
github.com/CesiumGS/cesium/blob/bfdd1050bb21706fe694c480602bc9f1581e769c/Source/Scene/Camera.js#L749
roll
github.com/CesiumGS/cesium/blob/bfdd1050bb21706fe694c480602bc9f1581e769c/Source/Scene/Camera.js#L753

AR Cesium looks cool, look forward to seeing it progress. Would be real cool with astronomy, putting your smartphone up to the night sky and seeing virtual planets where you’d see the actual planets!