DeviceOrientationControls.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /**
  2. * @author richt / http://richt.me
  3. *
  4. * W3C Device Orientation control (http://www.w3.org/TR/orientation-event/)
  5. */
  6. THREE.DeviceOrientationControls = function ( object ) {
  7. this.object = object;
  8. this.degtorad = Math.PI / 180;
  9. this.freeze = true;
  10. this.deviceOrientation = {};
  11. this.screenOrientation = 0;
  12. this._rotationVector = new THREE.Vector3();
  13. this._rotationMatrix = new THREE.Matrix4();
  14. this.onDeviceOrientationChangeEvent = function( rawEvtData ) {
  15. this.deviceOrientation = rawEvtData;
  16. };
  17. this.onScreenOrientationChangeEvent = function() {
  18. this.screenOrientation = window.orientation || 0;
  19. };
  20. this.setRotationVectorFromDeviceOrientation = function( alpha, beta, gamma) {
  21. this._rotationVector.set(
  22. (beta || 0) * this.degtorad, // x
  23. (gamma || 0) * this.degtorad, // y
  24. (alpha || 0) * this.degtorad // z
  25. );
  26. return this._rotationVector;
  27. };
  28. this.setRotationMatrixFromRotationVector = function( rotationVector ) {
  29. var x = rotationVector.x || 0; // beta
  30. var y = rotationVector.y || 0; // gamma
  31. var z = rotationVector.z || 0; // alpha
  32. var cX = Math.cos(x);
  33. var cY = Math.cos(y);
  34. var cZ = Math.cos(z);
  35. var sX = Math.sin(x);
  36. var sY = Math.sin(y);
  37. var sZ = Math.sin(z);
  38. //
  39. // ZXY rotation matrix construction.
  40. //
  41. // (see: http://bit.ly/1fjIr6Y)
  42. //
  43. var m11 = cZ * cY - sZ * sX * sY;
  44. var m12 = - cX * sZ;
  45. var m13 = cY * sZ * sX + cZ * sY;
  46. var m21 = cY * sZ + cZ * sX * sY;
  47. var m22 = cZ * cX;
  48. var m23 = sZ * sY - cZ * cY * sX;
  49. var m31 = - cX * sY;
  50. var m32 = sX;
  51. var m33 = cX * cY;
  52. this._rotationMatrix.set(
  53. m11, m12, m13, 0,
  54. m21, m22, m23, 0,
  55. m31, m32, m33, 0,
  56. 0, 0, 0, 1
  57. );
  58. return this._rotationMatrix;
  59. };
  60. this.remapRotationMatrixByScreenOrientation = function( screenOrientation, rotationMatrix ) {
  61. var transformedRotationMatrix = new THREE.Matrix4();
  62. transformedRotationMatrix.copy( rotationMatrix );
  63. switch( screenOrientation ) {
  64. case 90:
  65. case -270:
  66. //
  67. // 90 degrees counter-clockwise screen transformation matrix:
  68. //
  69. // / 0 -1 0 0 \
  70. // | 1 0 0 0 |
  71. // | 0 0 1 0 |
  72. // \ 0 0 0 1 /
  73. //
  74. // (see: http://bit.ly/1itCOq2)
  75. //
  76. transformedRotationMatrix.elements[0] = -rotationMatrix.elements[4];
  77. transformedRotationMatrix.elements[4] = rotationMatrix.elements[0];
  78. transformedRotationMatrix.elements[8] = rotationMatrix.elements[8];
  79. transformedRotationMatrix.elements[1] = -rotationMatrix.elements[5];
  80. transformedRotationMatrix.elements[5] = rotationMatrix.elements[1];
  81. transformedRotationMatrix.elements[9] = rotationMatrix.elements[9];
  82. transformedRotationMatrix.elements[2] = -rotationMatrix.elements[6];
  83. transformedRotationMatrix.elements[6] = rotationMatrix.elements[2];
  84. transformedRotationMatrix.elements[10] = rotationMatrix.elements[10];
  85. break;
  86. case 180:
  87. case -180:
  88. //
  89. // 180 degrees counter-clockwise screen transformation matrix:
  90. //
  91. // / -1 0 0 0 \
  92. // | 0 -1 0 0 |
  93. // | 0 0 1 0 |
  94. // \ 0 0 0 1 /
  95. //
  96. // (see: http://bit.ly/1dIrx0I)
  97. //
  98. transformedRotationMatrix.elements[0] = -rotationMatrix.elements[0];
  99. transformedRotationMatrix.elements[4] = -rotationMatrix.elements[4];
  100. transformedRotationMatrix.elements[8] = rotationMatrix.elements[8];
  101. transformedRotationMatrix.elements[1] = -rotationMatrix.elements[1];
  102. transformedRotationMatrix.elements[5] = -rotationMatrix.elements[5];
  103. transformedRotationMatrix.elements[9] = rotationMatrix.elements[9];
  104. transformedRotationMatrix.elements[2] = -rotationMatrix.elements[2];
  105. transformedRotationMatrix.elements[6] = -rotationMatrix.elements[6];
  106. transformedRotationMatrix.elements[10] = rotationMatrix.elements[10];
  107. break;
  108. case 270:
  109. case -90:
  110. //
  111. // 270 degrees counter-clockwise screen transformation matrix:
  112. //
  113. // / 0 1 0 0 \
  114. // | -1 0 0 0 |
  115. // | 0 0 1 0 |
  116. // \ 0 0 0 1 /
  117. //
  118. // (see: http://bit.ly/1h73sQ0)
  119. //
  120. transformedRotationMatrix.elements[0] = rotationMatrix.elements[4];
  121. transformedRotationMatrix.elements[4] = -rotationMatrix.elements[0];
  122. transformedRotationMatrix.elements[8] = rotationMatrix.elements[8];
  123. transformedRotationMatrix.elements[1] = rotationMatrix.elements[5];
  124. transformedRotationMatrix.elements[5] = -rotationMatrix.elements[1];
  125. transformedRotationMatrix.elements[9] = rotationMatrix.elements[9];
  126. transformedRotationMatrix.elements[2] = rotationMatrix.elements[6];
  127. transformedRotationMatrix.elements[6] = -rotationMatrix.elements[2];
  128. transformedRotationMatrix.elements[10] = rotationMatrix.elements[10];
  129. break;
  130. default:
  131. //
  132. // 0 degrees screen transformation matrix:
  133. //
  134. // / 1 0 0 0 \
  135. // | 0 1 0 0 |
  136. // | 0 0 1 0 |
  137. // \ 0 0 0 1 /
  138. //
  139. // This transformation is the same as the identity matrix so we need do nothing
  140. break;
  141. }
  142. this._rotationMatrix.copy( transformedRotationMatrix );
  143. return this._rotationMatrix;
  144. };
  145. this.update = function( delta ) {
  146. if ( this.freeze ) {
  147. return;
  148. }
  149. this.setRotationVectorFromDeviceOrientation(
  150. this.deviceOrientation.alpha,
  151. this.deviceOrientation.beta,
  152. this.deviceOrientation.gamma
  153. );
  154. this.setRotationMatrixFromRotationVector( this._rotationVector );
  155. this.remapRotationMatrixByScreenOrientation( this.screenOrientation, this._rotationMatrix );
  156. this.object.quaternion.setFromRotationMatrix( this._rotationMatrix );
  157. this.object.updateProjectionMatrix();
  158. };
  159. function bind( scope, fn ) {
  160. return function () {
  161. fn.apply( scope, arguments );
  162. };
  163. };
  164. this.connect = function() {
  165. this.onScreenOrientationChangeEvent(); // run once on load
  166. window.addEventListener( 'orientationchange', bind( this, this.onScreenOrientationChangeEvent ), false );
  167. window.addEventListener( 'deviceorientation', bind( this, this.onDeviceOrientationChangeEvent ), false );
  168. this.freeze = false;
  169. };
  170. this.disconnect = function() {
  171. this.freeze = true;
  172. window.removeEventListener( 'orientationchange', bind( this, this.onScreenOrientationChangeEvent ), false );
  173. window.removeEventListener( 'deviceorientation', bind( this, this.onDeviceOrientationChangeEvent ), false );
  174. };
  175. };