Three.js: rotate camera with touch orientation and device

I am making a 3D project with three functions, which allows me to control the camera with a mouse for computer devices, and also allows me to control touch events and device events for smartphones. For example, this site works the way I want.

Since I use OrbitControls to move the camera to the PC version, I have attached touchstart / move / end events to mousedown / move / up, and it works great.
The problem is that I am trying to add device orientation event values. Here is what I tried to add to OrbitControls.js:

THREE.OrbitControls = function ( object, domElement ) {
 /* 
 other variables
 */
 var scope = this;
 var lastBeta=0;
 var lastGamma=0;
 this.deviceOrientation = {};

      function onDeviceOrientationChangeEvent( event ){
         scope.deviceOrientation = event;
         var alpha  = scope.deviceOrientation.alpha ? THREE.Math.degToRad( scope.deviceOrientation.alpha ) : 0; // Z
         var beta   = scope.deviceOrientation.beta  ? THREE.Math.degToRad( scope.deviceOrientation.beta  ) : 0; // X'
         var gamma  = scope.deviceOrientation.gamma ? THREE.Math.degToRad( scope.deviceOrientation.gamma ) : 0; // Y''
         var orient = scope.screenOrientation       ? THREE.Math.degToRad( scope.screenOrientation       ) : 0; // O

         rotateLeft(lastGamma-gamma);
         rotateUp(lastBeta-beta);
         lastBeta=beta; //is working
         lastGamma=gamma; //doesn't work properly
     }

window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
};

[-180,180], , [-90,90], ( , , ). -, , -180 180, .

, , deviceOrientationControls.js, , , , , . - ?

PS: deviceorientation, , - .


, - .

var deltaBeta = 0;
var deltaGamma = 0;

if (window.DeviceOrientationEvent) {

  window.addEventListener('deviceorientation', function(e) {
    var beta = (e.beta != null) ? Math.round(e.beta) : 0;
    var 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>
Hide result
+4
1

, , , - / + OrbitControls.

(x1, y1, z1) (x2, y2, z3), - , .

this.update = function () {
        var alpha = scope.deviceOrientation.alpha ? THREE.Math.degToRad(scope.deviceOrientation.alpha) : 0; // Z
        var beta = scope.deviceOrientation.beta ? THREE.Math.degToRad(scope.deviceOrientation.beta) : 0; // X'
        var gamma = scope.deviceOrientation.gamma ? THREE.Math.degToRad(scope.deviceOrientation.gamma) : 0; // Y''
        var orient = scope.screenOrientation ? THREE.Math.degToRad(scope.screenOrientation) : 0; // O

        var currentQ = new THREE.Quaternion().copy(scope.object.quaternion);

        setObjectQuaternion(currentQ, alpha, beta, gamma, orient);
        var currentAngle = Quat2Angle(currentQ.x, currentQ.y, currentQ.z, currentQ.w);
        var radDeg = 180 / Math.PI;
        // currentAngle.z = Left-right
        // currentAngle.y = Up-down
        this.rotateLeft((lastGamma - currentAngle.z) / 2);
        lastGamma = currentAngle.z;
        this.rotateUp(lastBeta - currentAngle.y);
        lastBeta = currentAngle.y;
}

function onDeviceOrientationChangeEvent( event ) {
    scope.deviceOrientation = event;
}

window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );

</" >

function onScreenOrientationChangeEvent( event ) {
    scope.screenOrientation = window.orientation || 0;
}

window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );

var setObjectQuaternion = function () {

    var zee = new THREE.Vector3( 0, 0, 1 );

    var euler = new THREE.Euler();

    var q0 = new THREE.Quaternion();

    var q1 = new THREE.Quaternion(  - Math.sqrt( 0.5 ), 0, 0,  Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis

    //beta=beta-180;
    return function ( quaternion, alpha, beta, gamma, orient ) {

        euler.set( beta, alpha, - gamma, 'YXZ' );                       // 'ZXY' for the device, but 'YXZ' for us

        quaternion.setFromEuler( euler );                               // orient the device

        quaternion.multiply( q1 );                                      // camera looks out the back of the device, not the top

        quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) );    // adjust for screen orientation

    }

}();

</" >

function Quat2Angle( x, y, z, w ) {

    var pitch, roll, yaw;

    var test = x * y + z * w;
    if (test > 0.499) { // singularity at north pole
        yaw = 2 * Math.atan2(x, w);
        pitch = Math.PI / 2;
        roll = 0;

        var euler = new THREE.Vector3( pitch, roll, yaw);
        return euler;
    }
    if (test < -0.499) { // singularity at south pole
        yaw = -2 * Math.atan2(x, w);
        pitch = -Math.PI / 2;
        roll = 0;
        var euler = new THREE.Vector3( pitch, roll, yaw);
        return euler;
    }
    var sqx = x * x;
    var sqy = y * y;
    var sqz = z * z;
    yaw = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz);
    pitch = Math.asin(2 * test);
    roll = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz);

    var euler = new THREE.Vector3( pitch, roll, yaw);
    return euler;
}
+6

Source: https://habr.com/ru/post/1627898/


All Articles