DeviceOrientationControls.js 5.9 KB

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