babylon.webXRInput.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. module BABYLON {
  2. /**
  3. * Represents an XR input
  4. */
  5. export class WebXRController {
  6. /**
  7. * Represents the part of the controller that is held. This may not exist if the controller is the head mounted display itself, if thats the case only the pointer from the head will be availible
  8. */
  9. public grip?: BABYLON.AbstractMesh;
  10. /**
  11. * Pointer which can be used to select objects or attach a visible laser to
  12. */
  13. public pointer: BABYLON.AbstractMesh;
  14. /**
  15. * Creates the controller
  16. * @see https://doc.babylonjs.com/how_to/webxr
  17. * @param scene the scene which the controller should be associated to
  18. */
  19. constructor(scene: BABYLON.Scene) {
  20. this.pointer = new BABYLON.AbstractMesh("controllerPointer", scene);
  21. }
  22. /**
  23. * Disposes of the object
  24. */
  25. dispose() {
  26. if (this.grip) {
  27. this.grip.dispose();
  28. }
  29. this.pointer.dispose();
  30. }
  31. }
  32. /**
  33. * XR input used to track XR inputs such as controllers/rays
  34. */
  35. export class WebXRInput implements IDisposable {
  36. /**
  37. * XR controllers being tracked
  38. */
  39. public controllers: Array<WebXRController> = [];
  40. private _tmpMatrix = new BABYLON.Matrix();
  41. private _frameObserver: Nullable<Observer<any>>;
  42. /**
  43. * Initializes the WebXRInput
  44. * @param helper experience helper which the input should be created for
  45. */
  46. public constructor(private helper: WebXRExperienceHelper) {
  47. this._frameObserver = helper._sessionManager.onXRFrameObservable.add(() => {
  48. if (!helper._sessionManager._currentXRFrame || !helper._sessionManager._currentXRFrame.getDevicePose) {
  49. return false;
  50. }
  51. var xrFrame = helper._sessionManager._currentXRFrame;
  52. var inputSources = helper._sessionManager._xrSession.getInputSources();
  53. inputSources.forEach((input, i) => {
  54. let inputPose = xrFrame.getInputPose(input, helper._sessionManager._frameOfReference);
  55. if (inputPose) {
  56. if (this.controllers.length <= i) {
  57. this.controllers.push(new WebXRController(helper.container.getScene()));
  58. }
  59. var controller = this.controllers[i];
  60. // Manage the grip if it exists
  61. if (inputPose.gripMatrix) {
  62. if (!controller.grip) {
  63. controller.grip = new BABYLON.AbstractMesh("controllerGrip", helper.container.getScene());
  64. }
  65. BABYLON.Matrix.FromFloat32ArrayToRefScaled(inputPose.gripMatrix, 0, 1, this._tmpMatrix);
  66. if (!controller.grip.getScene().useRightHandedSystem) {
  67. this._tmpMatrix.toggleModelMatrixHandInPlace();
  68. }
  69. if (!controller.grip.rotationQuaternion) {
  70. controller.grip.rotationQuaternion = new BABYLON.Quaternion();
  71. }
  72. this._tmpMatrix.decompose(controller.grip.scaling, controller.grip.rotationQuaternion, controller.grip.position);
  73. }
  74. // Manager pointer of controller
  75. BABYLON.Matrix.FromFloat32ArrayToRefScaled(inputPose.targetRay.transformMatrix, 0, 1, this._tmpMatrix);
  76. if (!controller.pointer.getScene().useRightHandedSystem) {
  77. this._tmpMatrix.toggleModelMatrixHandInPlace();
  78. }
  79. if (!controller.pointer.rotationQuaternion) {
  80. controller.pointer.rotationQuaternion = new BABYLON.Quaternion();
  81. }
  82. this._tmpMatrix.decompose(controller.pointer.scaling, controller.pointer.rotationQuaternion, controller.pointer.position);
  83. }
  84. });
  85. });
  86. }
  87. /**
  88. * Disposes of the object
  89. */
  90. public dispose() {
  91. this.controllers.forEach((c) => {
  92. c.dispose();
  93. });
  94. this.helper._sessionManager.onXRFrameObservable.remove(this._frameObserver);
  95. }
  96. }
  97. }