webXRDefaultExperience.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import { WebXRExperienceHelper } from "./webXRExperienceHelper";
  2. import { Scene } from "../scene";
  3. import { WebXRInput, IWebXRInputOptions } from "./webXRInput";
  4. import { WebXRControllerPointerSelection, IWebXRControllerPointerSelectionOptions } from "./features/WebXRControllerPointerSelection";
  5. import { WebXRRenderTarget } from "./webXRTypes";
  6. import { WebXREnterExitUI, WebXREnterExitUIOptions } from "./webXREnterExitUI";
  7. import { AbstractMesh } from "../Meshes/abstractMesh";
  8. import { WebXRManagedOutputCanvasOptions } from "./webXRManagedOutputCanvas";
  9. import { WebXRMotionControllerTeleportation, IWebXRTeleportationOptions } from "./features/WebXRControllerTeleportation";
  10. import { Logger } from "../Misc/logger";
  11. /**
  12. * Options for the default xr helper
  13. */
  14. export class WebXRDefaultExperienceOptions {
  15. /**
  16. * Enable or disable default UI to enter XR
  17. */
  18. public disableDefaultUI?: boolean;
  19. /**
  20. * Should teleportation not initialize. defaults to false.
  21. */
  22. public disableTeleportation?: boolean;
  23. /**
  24. * Floor meshes that will be used for teleport
  25. */
  26. public floorMeshes?: Array<AbstractMesh>;
  27. /**
  28. * If set to true, the first frame will not be used to reset position
  29. * The first frame is mainly used when copying transformation from the old camera
  30. * Mainly used in AR
  31. */
  32. public ignoreNativeCameraTransformation?: boolean;
  33. /**
  34. * Disable the controller mesh-loading. Can be used if you want to load your own meshes
  35. */
  36. public inputOptions?: IWebXRInputOptions;
  37. /**
  38. * optional configuration for the output canvas
  39. */
  40. public outputCanvasOptions?: WebXRManagedOutputCanvasOptions;
  41. /**
  42. * optional UI options. This can be used among other to change session mode and reference space type
  43. */
  44. public uiOptions?: WebXREnterExitUIOptions;
  45. /**
  46. * When loading teleportation and pointer select, use stable versions instead of latest.
  47. */
  48. public useStablePlugins?: boolean;
  49. /**
  50. * An optional rendering group id that will be set globally for teleportation, pointer selection and default controller meshes
  51. */
  52. public renderingGroupId?: number;
  53. /**
  54. * A list of optional features to init the session with
  55. * If set to true, all features we support will be added
  56. */
  57. optionalFeatures?: boolean | string[];
  58. }
  59. /**
  60. * Default experience which provides a similar setup to the previous webVRExperience
  61. */
  62. export class WebXRDefaultExperience {
  63. /**
  64. * Base experience
  65. */
  66. public baseExperience: WebXRExperienceHelper;
  67. /**
  68. * Enables ui for entering/exiting xr
  69. */
  70. public enterExitUI: WebXREnterExitUI;
  71. /**
  72. * Input experience extension
  73. */
  74. public input: WebXRInput;
  75. /**
  76. * Enables laser pointer and selection
  77. */
  78. public pointerSelection: WebXRControllerPointerSelection;
  79. /**
  80. * Default target xr should render to
  81. */
  82. public renderTarget: WebXRRenderTarget;
  83. /**
  84. * Enables teleportation
  85. */
  86. public teleportation: WebXRMotionControllerTeleportation;
  87. private constructor() {}
  88. /**
  89. * Creates the default xr experience
  90. * @param scene scene
  91. * @param options options for basic configuration
  92. * @returns resulting WebXRDefaultExperience
  93. */
  94. public static CreateAsync(scene: Scene, options: WebXRDefaultExperienceOptions = {}) {
  95. var result = new WebXRDefaultExperience();
  96. // Create base experience
  97. return WebXRExperienceHelper.CreateAsync(scene)
  98. .then((xrHelper) => {
  99. result.baseExperience = xrHelper;
  100. if (options.ignoreNativeCameraTransformation) {
  101. result.baseExperience.camera.compensateOnFirstFrame = false;
  102. }
  103. // Add controller support
  104. result.input = new WebXRInput(xrHelper.sessionManager, xrHelper.camera, {
  105. controllerOptions: {
  106. renderingGroupId: options.renderingGroupId,
  107. },
  108. ...(options.inputOptions || {}),
  109. });
  110. result.pointerSelection = <WebXRControllerPointerSelection>result.baseExperience.featuresManager.enableFeature(WebXRControllerPointerSelection.Name, options.useStablePlugins ? "stable" : "latest", <IWebXRControllerPointerSelectionOptions>{
  111. xrInput: result.input,
  112. renderingGroupId: options.renderingGroupId,
  113. });
  114. // Add default teleportation, including rotation
  115. if (!options.disableTeleportation) {
  116. result.teleportation = <WebXRMotionControllerTeleportation>result.baseExperience.featuresManager.enableFeature(WebXRMotionControllerTeleportation.Name, options.useStablePlugins ? "stable" : "latest", <IWebXRTeleportationOptions>{
  117. floorMeshes: options.floorMeshes,
  118. xrInput: result.input,
  119. renderingGroupId: options.renderingGroupId,
  120. });
  121. result.teleportation.setSelectionFeature(result.pointerSelection);
  122. }
  123. // Create the WebXR output target
  124. result.renderTarget = result.baseExperience.sessionManager.getWebXRRenderTarget(options.outputCanvasOptions);
  125. if (!options.disableDefaultUI) {
  126. const uiOptions: WebXREnterExitUIOptions = {
  127. renderTarget: result.renderTarget,
  128. ...(options.uiOptions || {}),
  129. };
  130. if (options.optionalFeatures) {
  131. if (typeof options.optionalFeatures === "boolean") {
  132. uiOptions.optionalFeatures = ["hit-test", "anchors", "plane-detection", "hand-tracking"];
  133. } else {
  134. uiOptions.optionalFeatures = options.optionalFeatures;
  135. }
  136. }
  137. // Create ui for entering/exiting xr
  138. return WebXREnterExitUI.CreateAsync(scene, result.baseExperience, uiOptions).then((ui) => {
  139. result.enterExitUI = ui;
  140. });
  141. } else {
  142. return;
  143. }
  144. })
  145. .then(() => {
  146. return result;
  147. })
  148. .catch((error) => {
  149. Logger.Error("Error initializing XR");
  150. Logger.Error(error);
  151. return result;
  152. });
  153. }
  154. /**
  155. * Disposes of the experience helper
  156. */
  157. public dispose() {
  158. if (this.baseExperience) {
  159. this.baseExperience.dispose();
  160. }
  161. if (this.input) {
  162. this.input.dispose();
  163. }
  164. if (this.enterExitUI) {
  165. this.enterExitUI.dispose();
  166. }
  167. if (this.renderTarget) {
  168. this.renderTarget.dispose();
  169. }
  170. }
  171. }