webXRDefaultExperience.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { WebXRExperienceHelper } from "./webXRExperienceHelper.js";
  2. import { WebXRInput } from "./webXRInput.js";
  3. import { WebXRControllerPointerSelection } from "./features/WebXRControllerPointerSelection.js";
  4. import { WebXRNearInteraction } from "./features/WebXRNearInteraction.js";
  5. import { WebXREnterExitUI } from "./webXREnterExitUI.js";
  6. import { WebXRHandTracking } from "./features/WebXRHandTracking.js";
  7. import { WebXRMotionControllerTeleportation } from "./features/WebXRControllerTeleportation.js";
  8. import { Logger } from "../Misc/logger.js";
  9. /**
  10. * Options for the default xr helper
  11. */
  12. export class WebXRDefaultExperienceOptions {
  13. }
  14. /**
  15. * Default experience for webxr
  16. */
  17. export class WebXRDefaultExperience {
  18. constructor() { }
  19. /**
  20. * Creates the default xr experience
  21. * @param scene scene
  22. * @param options options for basic configuration
  23. * @returns resulting WebXRDefaultExperience
  24. */
  25. static CreateAsync(scene, options = {}) {
  26. const result = new WebXRDefaultExperience();
  27. scene.onDisposeObservable.addOnce(() => {
  28. result.dispose();
  29. });
  30. // init the UI right after construction
  31. if (!options.disableDefaultUI) {
  32. const uiOptions = {
  33. renderTarget: result.renderTarget,
  34. ...(options.uiOptions || {}),
  35. };
  36. if (options.optionalFeatures) {
  37. if (typeof options.optionalFeatures === "boolean") {
  38. uiOptions.optionalFeatures = ["hit-test", "anchors", "plane-detection", "hand-tracking"];
  39. }
  40. else {
  41. uiOptions.optionalFeatures = options.optionalFeatures;
  42. }
  43. }
  44. result.enterExitUI = new WebXREnterExitUI(scene, uiOptions);
  45. }
  46. // Create base experience
  47. return WebXRExperienceHelper.CreateAsync(scene)
  48. .then((xrHelper) => {
  49. result.baseExperience = xrHelper;
  50. if (options.ignoreNativeCameraTransformation) {
  51. result.baseExperience.camera.compensateOnFirstFrame = false;
  52. }
  53. // Add controller support
  54. result.input = new WebXRInput(xrHelper.sessionManager, xrHelper.camera, {
  55. controllerOptions: {
  56. renderingGroupId: options.renderingGroupId,
  57. },
  58. ...(options.inputOptions || {}),
  59. });
  60. if (!options.disablePointerSelection) {
  61. // Add default pointer selection
  62. const pointerSelectionOptions = {
  63. ...options.pointerSelectionOptions,
  64. xrInput: result.input,
  65. renderingGroupId: options.renderingGroupId,
  66. };
  67. result.pointerSelection = (result.baseExperience.featuresManager.enableFeature(WebXRControllerPointerSelection.Name, options.useStablePlugins ? "stable" : "latest", pointerSelectionOptions));
  68. if (!options.disableTeleportation) {
  69. // Add default teleportation, including rotation
  70. result.teleportation = result.baseExperience.featuresManager.enableFeature(WebXRMotionControllerTeleportation.Name, options.useStablePlugins ? "stable" : "latest", {
  71. floorMeshes: options.floorMeshes,
  72. xrInput: result.input,
  73. renderingGroupId: options.renderingGroupId,
  74. ...options.teleportationOptions,
  75. });
  76. result.teleportation.setSelectionFeature(result.pointerSelection);
  77. }
  78. }
  79. if (!options.disableNearInteraction) {
  80. // Add default pointer selection
  81. result.nearInteraction = result.baseExperience.featuresManager.enableFeature(WebXRNearInteraction.Name, options.useStablePlugins ? "stable" : "latest", {
  82. xrInput: result.input,
  83. farInteractionFeature: result.pointerSelection,
  84. renderingGroupId: options.renderingGroupId,
  85. useUtilityLayer: true,
  86. enableNearInteractionOnAllControllers: true,
  87. ...options.nearInteractionOptions,
  88. });
  89. }
  90. if (!options.disableHandTracking) {
  91. // Add default hand tracking
  92. result.baseExperience.featuresManager.enableFeature(WebXRHandTracking.Name, options.useStablePlugins ? "stable" : "latest", {
  93. xrInput: result.input,
  94. ...options.handSupportOptions,
  95. }, undefined, false);
  96. }
  97. // Create the WebXR output target
  98. result.renderTarget = result.baseExperience.sessionManager.getWebXRRenderTarget(options.outputCanvasOptions);
  99. if (!options.disableDefaultUI) {
  100. // Create ui for entering/exiting xr
  101. return result.enterExitUI.setHelperAsync(result.baseExperience, result.renderTarget);
  102. }
  103. else {
  104. return;
  105. }
  106. })
  107. .then(() => {
  108. return result;
  109. })
  110. .catch((error) => {
  111. Logger.Error("Error initializing XR");
  112. Logger.Error(error);
  113. return result;
  114. });
  115. }
  116. /**
  117. * Disposes of the experience helper
  118. */
  119. dispose() {
  120. if (this.baseExperience) {
  121. this.baseExperience.dispose();
  122. }
  123. if (this.input) {
  124. this.input.dispose();
  125. }
  126. if (this.enterExitUI) {
  127. this.enterExitUI.dispose();
  128. }
  129. if (this.renderTarget) {
  130. this.renderTarget.dispose();
  131. }
  132. }
  133. }
  134. //# sourceMappingURL=webXRDefaultExperience.js.map