freeCameraDeviceOrientationInput.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { Nullable } from "types";
  2. import { ICameraInput, CameraInputTypes } from "Cameras/cameraInputsManager";
  3. import { FreeCamera } from "Cameras/freeCamera";
  4. import { Quaternion } from "Maths/math";
  5. import { Tools } from "Misc/tools";
  6. /**
  7. * Takes information about the orientation of the device as reported by the deviceorientation event to orient the camera.
  8. * Screen rotation is taken into account.
  9. * @see http://doc.babylonjs.com/how_to/customizing_camera_inputs
  10. */
  11. export class FreeCameraDeviceOrientationInput implements ICameraInput<FreeCamera> {
  12. private _camera: FreeCamera;
  13. private _screenOrientationAngle: number = 0;
  14. private _constantTranform: Quaternion;
  15. private _screenQuaternion: Quaternion = new Quaternion();
  16. private _alpha: number = 0;
  17. private _beta: number = 0;
  18. private _gamma: number = 0;
  19. /**
  20. * Instantiates a new input
  21. * @see http://doc.babylonjs.com/how_to/customizing_camera_inputs
  22. */
  23. constructor() {
  24. this._constantTranform = new Quaternion(- Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
  25. this._orientationChanged();
  26. }
  27. /**
  28. * Define the camera controlled by the input.
  29. */
  30. public get camera(): FreeCamera {
  31. return this._camera;
  32. }
  33. public set camera(camera: FreeCamera) {
  34. this._camera = camera;
  35. if (this._camera != null && !this._camera.rotationQuaternion) {
  36. this._camera.rotationQuaternion = new Quaternion();
  37. }
  38. }
  39. /**
  40. * Attach the input controls to a specific dom element to get the input from.
  41. * @param element Defines the element the controls should be listened from
  42. * @param noPreventDefault Defines whether event caught by the controls should call preventdefault() (https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault)
  43. */
  44. public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
  45. window.addEventListener("orientationchange", this._orientationChanged);
  46. window.addEventListener("deviceorientation", this._deviceOrientation);
  47. //In certain cases, the attach control is called AFTER orientation was changed,
  48. //So this is needed.
  49. this._orientationChanged();
  50. }
  51. private _orientationChanged = () => {
  52. this._screenOrientationAngle = (<any>window.orientation !== undefined ? +<any>window.orientation : ((<any>window.screen).orientation && ((<any>window.screen).orientation)['angle'] ? ((<any>window.screen).orientation).angle : 0));
  53. this._screenOrientationAngle = -Tools.ToRadians(this._screenOrientationAngle / 2);
  54. this._screenQuaternion.copyFromFloats(0, Math.sin(this._screenOrientationAngle), 0, Math.cos(this._screenOrientationAngle));
  55. }
  56. private _deviceOrientation = (evt: DeviceOrientationEvent) => {
  57. this._alpha = evt.alpha !== null ? evt.alpha : 0;
  58. this._beta = evt.beta !== null ? evt.beta : 0;
  59. this._gamma = evt.gamma !== null ? evt.gamma : 0;
  60. }
  61. /**
  62. * Detach the current controls from the specified dom element.
  63. * @param element Defines the element to stop listening the inputs from
  64. */
  65. public detachControl(element: Nullable<HTMLElement>): void {
  66. window.removeEventListener("orientationchange", this._orientationChanged);
  67. window.removeEventListener("deviceorientation", this._deviceOrientation);
  68. }
  69. /**
  70. * Update the current camera state depending on the inputs that have been used this frame.
  71. * This is a dynamically created lambda to avoid the performance penalty of looping for inputs in the render loop.
  72. */
  73. public checkInputs(): void {
  74. //if no device orientation provided, don't update the rotation.
  75. //Only testing against alpha under the assumption thatnorientation will never be so exact when set.
  76. if (!this._alpha) { return; }
  77. Quaternion.RotationYawPitchRollToRef(Tools.ToRadians(this._alpha), Tools.ToRadians(this._beta), -Tools.ToRadians(this._gamma), this.camera.rotationQuaternion);
  78. this._camera.rotationQuaternion.multiplyInPlace(this._screenQuaternion);
  79. this._camera.rotationQuaternion.multiplyInPlace(this._constantTranform);
  80. //Mirror on XY Plane
  81. this._camera.rotationQuaternion.z *= -1;
  82. this._camera.rotationQuaternion.w *= -1;
  83. }
  84. /**
  85. * Gets the class name of the current intput.
  86. * @returns the class name
  87. */
  88. public getClassName(): string {
  89. return "FreeCameraDeviceOrientationInput";
  90. }
  91. /**
  92. * Get the friendly name associated with the input class.
  93. * @returns the input friendly name
  94. */
  95. public getSimpleName(): string {
  96. return "deviceOrientation";
  97. }
  98. }
  99. (<any>CameraInputTypes)["FreeCameraDeviceOrientationInput"] = FreeCameraDeviceOrientationInput;