this.align = function() { tempVector3 .set(0, 0, -1) .applyQuaternion( tempQuaternion.copy(this.orientationQuaternion).inverse(), 'ZXY' ); tempEuler.setFromQuaternion( tempQuaternion.setFromRotationMatrix( tempMatrix4.lookAt(tempVector3, v0, up) ) ); tempEuler.set(0, tempEuler.y, 0); this.alignQuaternion.setFromEuler(tempEuler); };
return function(delta) { if (this.freeze) return; // should not need this //var orientation = getOrientation(); //if (orientation !== this.screenOrientation) { //this.screenOrientation = orientation; //this.autoAlign = true; //} this.alpha = deviceOrientation.gamma ? THREE.Math.degToRad(deviceOrientation.alpha) : 0; // Z this.beta = deviceOrientation.beta ? THREE.Math.degToRad(deviceOrientation.beta) : 0; // X' this.gamma = deviceOrientation.gamma ? THREE.Math.degToRad(deviceOrientation.gamma) : 0; // Y'' this.orient = screenOrientation ? THREE.Math.degToRad(screenOrientation) : 0; // O // The angles alpha, beta and gamma // form a set of intrinsic Tait-Bryan angles of type Z-X'-Y'' // 'ZXY' for the device, but 'YXZ' for us euler.set(this.beta, this.alpha, - this.gamma, 'YXZ'); quaternion.setFromEuler(euler); quaternionLerp.slerp(quaternion, 0.5); // interpolate // orient the device if (this.autoAlign) this.orientationQuaternion.copy(quaternion); // interpolation breaks the auto alignment else this.orientationQuaternion.copy(quaternionLerp); // camera looks out the back of the device, not the top this.orientationQuaternion.multiply(q1); // adjust for screen orientation this.orientationQuaternion.multiply(q0.setFromAxisAngle(zee, - this.orient)); this.object.quaternion.copy(this.alignQuaternion); this.object.quaternion.multiply(this.orientationQuaternion); if (this.autoForward) { tempVector3 .set(0, 0, -1) .applyQuaternion(this.object.quaternion, 'ZXY') .setLength(this.movementSpeed / 50); // TODO: why 50 :S this.object.position.add(tempVector3); } if (this.autoAlign && this.alpha !== 0) { this.autoAlign = false; this.align(); } };
THREE.DeviceOrientationControls = function(object) { this.object = object; this.object.rotation.reorder('YXZ'); this.freeze = true; this.movementSpeed = 1.0; this.rollSpeed = 0.005; this.autoAlign = true; this.autoForward = false; this.alpha = 0; this.beta = 0; this.gamma = 0; this.orient = 0; this.alignQuaternion = new THREE.Quaternion(); this.orientationQuaternion = new THREE.Quaternion(); var quaternion = new THREE.Quaternion(); var quaternionLerp = new THREE.Quaternion(); var tempVector3 = new THREE.Vector3(); var tempMatrix4 = new THREE.Matrix4(); var tempEuler = new THREE.Euler(0, 0, 0, 'YXZ'); var tempQuaternion = new THREE.Quaternion(); var zee = new THREE.Vector3(0, 0, 1); var up = new THREE.Vector3(0, 1, 0); var v0 = new THREE.Vector3(0, 0, 0); var euler = new THREE.Euler(); var q0 = new THREE.Quaternion(); // - PI/2 around the x-axis var q1 = new THREE.Quaternion(- Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)); this.update = (function(delta) { return function(delta) { if (this.freeze) return; // should not need this //var orientation = getOrientation(); //if (orientation !== this.screenOrientation) { //this.screenOrientation = orientation; //this.autoAlign = true; //} this.alpha = deviceOrientation.gamma ? THREE.Math.degToRad(deviceOrientation.alpha) : 0; // Z this.beta = deviceOrientation.beta ? THREE.Math.degToRad(deviceOrientation.beta) : 0; // X' this.gamma = deviceOrientation.gamma ? THREE.Math.degToRad(deviceOrientation.gamma) : 0; // Y'' this.orient = screenOrientation ? THREE.Math.degToRad(screenOrientation) : 0; // O // The angles alpha, beta and gamma // form a set of intrinsic Tait-Bryan angles of type Z-X'-Y'' // 'ZXY' for the device, but 'YXZ' for us euler.set(this.beta, this.alpha, - this.gamma, 'YXZ'); quaternion.setFromEuler(euler); quaternionLerp.slerp(quaternion, 0.5); // interpolate // orient the device if (this.autoAlign) this.orientationQuaternion.copy(quaternion); // interpolation breaks the auto alignment else this.orientationQuaternion.copy(quaternionLerp); // camera looks out the back of the device, not the top this.orientationQuaternion.multiply(q1); // adjust for screen orientation this.orientationQuaternion.multiply(q0.setFromAxisAngle(zee, - this.orient)); this.object.quaternion.copy(this.alignQuaternion); this.object.quaternion.multiply(this.orientationQuaternion); if (this.autoForward) { tempVector3 .set(0, 0, -1) .applyQuaternion(this.object.quaternion, 'ZXY') .setLength(this.movementSpeed / 50); // TODO: why 50 :S this.object.position.add(tempVector3); } if (this.autoAlign && this.alpha !== 0) { this.autoAlign = false; this.align(); } }; })(); // //debug // window.addEventListener('click', (function(){ // this.align(); // }).bind(this)); this.align = function() { tempVector3 .set(0, 0, -1) .applyQuaternion( tempQuaternion.copy(this.orientationQuaternion).inverse(), 'ZXY' ); tempEuler.setFromQuaternion( tempQuaternion.setFromRotationMatrix( tempMatrix4.lookAt(tempVector3, v0, up) ) ); tempEuler.set(0, tempEuler.y, 0); this.alignQuaternion.setFromEuler(tempEuler); }; this.connect = function() { this.freeze = false; }; this.disconnect = function() { this.freze = true; }; };