I am making a 3D project with threejs which allows control of the camera with mouse for computer devices, and also allows control with touch events and deviceorientation event for smartphones. As an example, this site works the same way as what I want to do.
As I am using OrbitControls to move camera on the PC version, I bound the touchstart/move/end events to mousedown/move/up and it works perfectly.
The problem is when I try to add the device orientation event's values. Here is what I tried to add in OrbitControls.js :
THREE.OrbitControls = function (object, domElement) {
const scope = this;
let lastBeta = 0;
let lastGamma = 0;
this.deviceOrientation = {};
function onDeviceOrientationChangeEvent(event) {
scope.deviceOrientation = event;
// Z
var alpha = scope.deviceOrientation.alpha
? THREE.Math.degToRad(scope.deviceOrientation.alpha)
: 0;
// X'
var beta = scope.deviceOrientation.beta
? THREE.Math.degToRad(scope.deviceOrientation.beta)
: 0;
// Y''
var gamma = scope.deviceOrientation.gamma
? THREE.Math.degToRad(scope.deviceOrientation.gamma)
: 0;
// O
var orient = scope.screenOrientation
? THREE.Math.degToRad(scope.screenOrientation)
: 0;
rotateLeft(lastGamma - gamma);
rotateUp(lastBeta - beta);
lastBeta = beta; //is working
lastGamma = gamma; //doesn't work properly
}
window.addEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
};
As beta's values are within a [-180,180] degree range the vertical rotation encounters no problem, whereas gamma's range is [-90,90] and values are also changing suddenly when orientating device' screen up and down (even if, I think, it should return horizontal rotation). And even when converting gamma's range to make it takes values from -180 to 180, the sudden shifts make everything goes wrong.
I guess that I have to use quaternions as in deviceOrientationControls.js, but I really don't know how it works and every attempt I've made so far was a fail. Can someone help me please?
PS: Here is a link to the description on the deviceorientation event to have a better comprehension of what really are alpha beta and gamma.
EDIT
I added a snippet bellow to show the beta and gamma variations.
let deltaBeta = 0;
let deltaGamma = 0;
if (window.DeviceOrientationEvent) {
window.addEventListener('deviceorientation', function (e) {
const beta = (e.beta != null) ? Math.round(e.beta) : 0;
const gamma = (e.gamma != null) ? Math.round(e.gamma) : 0;
deltaBeta = Math.abs(beta - deltaBeta);
deltaGamma = Math.abs(gamma - deltaGamma);
$("#beta").html("Beta: " + beta);
$("#gamma").html("Gamma: " + gamma);
if (Math.abs(deltaBeta) > Math.abs(Number($("#deltaBeta").html()))) {
$("#deltaBeta").html(deltaBeta);
if (Number($("#deltaBeta").html()) >= 30) {
$("#deltaBeta").removeAttr("class", "blue").addClass("red");
}
}
if (Math.abs(deltaGamma) > Math.abs(Number($("#deltaGamma").html()))) {
$("#deltaGamma").html(deltaGamma);
if (Number($("#deltaGamma").html()) >= 30) {
$("#deltaGamma").removeAttr("class", "blue").addClass("red");
}
}
}, true);
} else {
$("#gamma").html("deviceorientation not supported");
}
.red {
color: red;
font-weight: bold;
}
.blue {
color: blue;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div>
<span id="beta"></span>
<span> [-180; 180]</span>
</div>
<div>
<span>DeltaMax</span>
<span id="deltaBeta" class="blue">0</span>
</div>
<div>
<span id="gamma"></span>
<span> [-90; 90]</span>
</div>
<div>
<span>DeltaMax</span>
<span id="deltaGamma" class="blue">0</span>
</div>
</body>
rotateUp(lastBeta-beta);
) . While beta is taking value from -180 to 180 ONLY according to the device up/down angle, the gamma (right/left angle) takes awkward values depending on beta and alpha. That's the reason why I can't use it to make my camera rotating normally. I'll try to add a JSFiddle latter to make it clearer. – Tidewater