Quellcode durchsuchen

Merge pull request #7550 from BabylonJS/master

Nightly
David Catuhe vor 5 Jahren
Ursprung
Commit
f0188f5f51
32 geänderte Dateien mit 885 neuen und 780 gelöschten Zeilen
  1. 27 30
      dist/preview release/babylon.d.ts
  2. 1 1
      dist/preview release/babylon.js
  3. 346 351
      dist/preview release/babylon.max.js
  4. 1 1
      dist/preview release/babylon.max.js.map
  5. 69 75
      dist/preview release/babylon.module.d.ts
  6. 27 30
      dist/preview release/documentation.d.ts
  7. 69 75
      dist/preview release/viewer/babylon.module.d.ts
  8. 23 23
      dist/preview release/viewer/babylon.viewer.js
  9. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  10. 3 2
      dist/preview release/what's new.md
  11. 106 0
      gui/src/2D/controls/scrollViewers/scrollViewer.ts
  12. 33 4
      nodeEditor/src/diagram/graphFrame.ts
  13. 3 0
      nodeEditor/src/diagram/properties/framePropertyComponent.tsx
  14. 1 1
      nodeEditor/src/globalState.ts
  15. 1 1
      nodeEditor/src/graphEditor.tsx
  16. 4 3
      nodeEditor/src/nodeLocationInfo.ts
  17. 4 4
      src/XR/features/WebXRControllerPhysics.ts
  18. 10 10
      src/XR/features/WebXRControllerPointerSelection.ts
  19. 8 8
      src/XR/features/WebXRControllerTeleportation.ts
  20. 1 1
      src/XR/index.ts
  21. 1 1
      src/XR/motionController/index.ts
  22. 0 0
      src/XR/motionController/webXRAbstractMotionController.ts
  23. 7 7
      src/XR/motionController/webXRControllerComponent.ts
  24. 1 1
      src/XR/motionController/webXRGenericMotionController.ts
  25. 2 2
      src/XR/motionController/webXRHTCViveMotionController.ts
  26. 3 3
      src/XR/motionController/webXRMicrosoftMixedRealityController.ts
  27. 1 1
      src/XR/motionController/webXRMotionControllerManager.ts
  28. 2 2
      src/XR/motionController/webXROculusTouchMotionController.ts
  29. 1 1
      src/XR/motionController/webXRProfiledMotionController.ts
  30. 113 127
      src/XR/webXRCamera.ts
  31. 7 7
      src/XR/webXRInput.ts
  32. 9 7
      src/XR/webXRController.ts

+ 27 - 30
dist/preview release/babylon.d.ts

@@ -42654,48 +42654,44 @@ declare module BABYLON {
 declare module BABYLON {
     /**
      * WebXR Camera which holds the views for the xrSession
-     * @see https://doc.babylonjs.com/how_to/webxr
+     * @see https://doc.babylonjs.com/how_to/webxr_camera
      */
     export class WebXRCamera extends FreeCamera {
         private _xrSessionManager;
-        /**
-         * Should position compensation execute on first frame.
-         * This is used when copying the position from a native (non XR) camera
-         */
-        compensateOnFirstFrame: boolean;
         private _firstFrame;
-        private _referencedPosition;
         private _referenceQuaternion;
+        private _referencedPosition;
         private _xrInvPositionCache;
         private _xrInvQuaternionCache;
-        private _realWorldHeight;
-        /**
-         * Prevent the camera from calculating the real-world height
-         * If you are not using the user's height disable this for better performance
-         */
-        disableRealWorldHeightCalculation: boolean;
         /**
-         * Return the user's height, unrelated to the current ground.
+         * Should position compensation execute on first frame.
+         * This is used when copying the position from a native (non XR) camera
          */
-        get realWorldHeight(): number;
+        compensateOnFirstFrame: boolean;
         /**
          * Creates a new webXRCamera, this should only be set at the camera after it has been updated by the xrSessionManager
          * @param name the name of the camera
          * @param scene the scene to add the camera to
+         * @param _xrSessionManager a constructed xr session manager
          */
         constructor(name: string, scene: Scene, _xrSessionManager: WebXRSessionManager);
-        private _updateNumberOfRigCameras;
+        /**
+         * Return the user's height, unrelated to the current ground.
+         * This will be the y position of this camera, when ground level is 0.
+         */
+        get realWorldHeight(): number;
+        /** @hidden */
+        _updateForDualEyeDebugging(): void;
         /**
          * Sets this camera's transformation based on a non-vr camera
          * @param otherCamera the non-vr camera to copy the transformation from
          * @param resetToBaseReferenceSpace should XR reset to the base reference space
          */
         setTransformationFromNonVRCamera(otherCamera?: Camera, resetToBaseReferenceSpace?: boolean): void;
-        /** @hidden */
-        _updateForDualEyeDebugging(): void;
+        private _updateFromXRSession;
+        private _updateNumberOfRigCameras;
         private _updateReferenceSpace;
         private _updateReferenceSpaceOffset;
-        private _updateFromXRSession;
     }
 }
 declare module BABYLON {
@@ -43026,12 +43022,12 @@ declare module BABYLON {
          * Observers registered here will be triggered when the state of a button changes
          * State change is either pressed / touched / value
          */
-        onButtonStateChanged: Observable<WebXRControllerComponent>;
+        onButtonStateChangedObservable: Observable<WebXRControllerComponent>;
         /**
          * If axes are available for this component (like a touchpad or thumbstick) the observers will be notified when
          * the axes data changes
          */
-        onAxisValueChanged: Observable<{
+        onAxisValueChangedObservable: Observable<{
             x: number;
             y: number;
         }>;
@@ -44056,7 +44052,7 @@ declare module BABYLON {
     /**
      * Represents an XR controller
      */
-    export class WebXRController {
+    export class WebXRInputSource {
         private _scene;
         /** The underlying input source for the controller  */
         inputSource: XRInputSource;
@@ -44090,7 +44086,7 @@ declare module BABYLON {
          * The object provided as event data is this controller, after associated assets were disposed.
          * uniqueId is still available.
          */
-        onDisposeObservable: Observable<WebXRController>;
+        onDisposeObservable: Observable<WebXRInputSource>;
         private _tmpQuaternion;
         private _tmpVector;
         private _uniqueId;
@@ -44115,10 +44111,11 @@ declare module BABYLON {
          */
         updateFromXRFrame(xrFrame: XRFrame, referenceSpace: XRReferenceSpace): void;
         /**
-         * Gets a world space ray coming from the controller
+         * Gets a world space ray coming from the pointer or grip
          * @param result the resulting ray
+         * @param gripIfAvailable use the grip mesh instead of the pointer, if available
          */
-        getWorldPointerRayToRef(result: Ray): void;
+        getWorldPointerRayToRef(result: Ray, gripIfAvailable?: boolean): void;
         /**
          * Disposes of the object
          */
@@ -44171,18 +44168,18 @@ declare module BABYLON {
         /**
          * XR controllers being tracked
          */
-        controllers: Array<WebXRController>;
+        controllers: Array<WebXRInputSource>;
         private _frameObserver;
         private _sessionEndedObserver;
         private _sessionInitObserver;
         /**
          * Event when a controller has been connected/added
          */
-        onControllerAddedObservable: Observable<WebXRController>;
+        onControllerAddedObservable: Observable<WebXRInputSource>;
         /**
          * Event when a controller has been removed/disconnected
          */
-        onControllerRemovedObservable: Observable<WebXRController>;
+        onControllerRemovedObservable: Observable<WebXRInputSource>;
         /**
          * Initializes the WebXRInput
          * @param xrSessionManager the xr session manager for this session
@@ -44374,7 +44371,7 @@ declare module BABYLON {
          * @param id the pointer id to search for
          * @returns the controller that correlates to this id or null if not found
          */
-        getXRControllerByPointerId(id: number): Nullable<WebXRController>;
+        getXRControllerByPointerId(id: number): Nullable<WebXRInputSource>;
         protected _onXRFrame(_xrFrame: XRFrame): void;
         private _attachController;
         private _attachScreenRayMode;
@@ -68770,7 +68767,7 @@ declare module BABYLON {
          * Manually add a controller (if no xrInput was provided or physics engine was not enabled)
          * @param xrController the controller to add
          */
-        addController(xrController: WebXRController): void;
+        addController(xrController: WebXRInputSource): void;
         private _debugMode;
         /**
          * @hidden

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
dist/preview release/babylon.js


Datei-Diff unterdrückt, da er zu groß ist
+ 346 - 351
dist/preview release/babylon.max.js


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
dist/preview release/babylon.max.js.map


+ 69 - 75
dist/preview release/babylon.module.d.ts

@@ -44144,48 +44144,44 @@ declare module "babylonjs/XR/webXRCamera" {
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
     /**
      * WebXR Camera which holds the views for the xrSession
-     * @see https://doc.babylonjs.com/how_to/webxr
+     * @see https://doc.babylonjs.com/how_to/webxr_camera
      */
     export class WebXRCamera extends FreeCamera {
         private _xrSessionManager;
-        /**
-         * Should position compensation execute on first frame.
-         * This is used when copying the position from a native (non XR) camera
-         */
-        compensateOnFirstFrame: boolean;
         private _firstFrame;
-        private _referencedPosition;
         private _referenceQuaternion;
+        private _referencedPosition;
         private _xrInvPositionCache;
         private _xrInvQuaternionCache;
-        private _realWorldHeight;
-        /**
-         * Prevent the camera from calculating the real-world height
-         * If you are not using the user's height disable this for better performance
-         */
-        disableRealWorldHeightCalculation: boolean;
         /**
-         * Return the user's height, unrelated to the current ground.
+         * Should position compensation execute on first frame.
+         * This is used when copying the position from a native (non XR) camera
          */
-        get realWorldHeight(): number;
+        compensateOnFirstFrame: boolean;
         /**
          * Creates a new webXRCamera, this should only be set at the camera after it has been updated by the xrSessionManager
          * @param name the name of the camera
          * @param scene the scene to add the camera to
+         * @param _xrSessionManager a constructed xr session manager
          */
         constructor(name: string, scene: Scene, _xrSessionManager: WebXRSessionManager);
-        private _updateNumberOfRigCameras;
+        /**
+         * Return the user's height, unrelated to the current ground.
+         * This will be the y position of this camera, when ground level is 0.
+         */
+        get realWorldHeight(): number;
+        /** @hidden */
+        _updateForDualEyeDebugging(): void;
         /**
          * Sets this camera's transformation based on a non-vr camera
          * @param otherCamera the non-vr camera to copy the transformation from
          * @param resetToBaseReferenceSpace should XR reset to the base reference space
          */
         setTransformationFromNonVRCamera(otherCamera?: Camera, resetToBaseReferenceSpace?: boolean): void;
-        /** @hidden */
-        _updateForDualEyeDebugging(): void;
+        private _updateFromXRSession;
+        private _updateNumberOfRigCameras;
         private _updateReferenceSpace;
         private _updateReferenceSpaceOffset;
-        private _updateFromXRSession;
     }
 }
 declare module "babylonjs/XR/webXRFeaturesManager" {
@@ -44439,7 +44435,7 @@ declare module "babylonjs/XR/webXRExperienceHelper" {
     }
 }
 declare module "babylonjs/XR/motionController/webXRControllerComponent" {
-    import { IMinimalMotionControllerObject, MotionControllerComponentType } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { IMinimalMotionControllerObject, MotionControllerComponentType } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { Observable } from "babylonjs/Misc/observable";
     import { IDisposable } from "babylonjs/scene";
     /**
@@ -44527,12 +44523,12 @@ declare module "babylonjs/XR/motionController/webXRControllerComponent" {
          * Observers registered here will be triggered when the state of a button changes
          * State change is either pressed / touched / value
          */
-        onButtonStateChanged: Observable<WebXRControllerComponent>;
+        onButtonStateChangedObservable: Observable<WebXRControllerComponent>;
         /**
          * If axes are available for this component (like a touchpad or thumbstick) the observers will be notified when
          * the axes data changes
          */
-        onAxisValueChanged: Observable<{
+        onAxisValueChangedObservable: Observable<{
             x: number;
             y: number;
         }>;
@@ -45026,7 +45022,7 @@ declare module "babylonjs/Loading/sceneLoader" {
         static ImportAnimationsAsync(rootUrl: string, sceneFilename?: string | File, scene?: Nullable<Scene>, overwriteAnimations?: boolean, animationGroupLoadingMode?: SceneLoaderAnimationGroupLoadingMode, targetConverter?: Nullable<(target: any) => any>, onSuccess?: Nullable<(scene: Scene) => void>, onProgress?: Nullable<(event: SceneLoaderProgressEvent) => void>, onError?: Nullable<(scene: Scene, message: string, exception?: any) => void>): Promise<Scene>;
     }
 }
-declare module "babylonjs/XR/motionController/webXRAbstractController" {
+declare module "babylonjs/XR/motionController/webXRAbstractMotionController" {
     import { IDisposable, Scene } from "babylonjs/scene";
     import { WebXRControllerComponent } from "babylonjs/XR/motionController/webXRControllerComponent";
     import { Observable } from "babylonjs/Misc/observable";
@@ -45383,7 +45379,7 @@ declare module "babylonjs/XR/motionController/webXRAbstractController" {
     }
 }
 declare module "babylonjs/XR/motionController/webXRGenericMotionController" {
-    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Scene } from "babylonjs/scene";
     /**
@@ -45448,7 +45444,7 @@ declare module "babylonjs/Meshes/Builders/sphereBuilder" {
 }
 declare module "babylonjs/XR/motionController/webXRProfiledMotionController" {
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { WebXRAbstractMotionController, IMotionControllerProfile } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController, IMotionControllerProfile } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { Scene } from "babylonjs/scene";
     /**
      * A profiled motion controller has its profile loaded from an online repository.
@@ -45475,7 +45471,7 @@ declare module "babylonjs/XR/motionController/webXRProfiledMotionController" {
     }
 }
 declare module "babylonjs/XR/motionController/webXRMotionControllerManager" {
-    import { WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { Scene } from "babylonjs/scene";
     /**
      * A construction function type to create a new controller based on an xrInput object
@@ -45562,12 +45558,12 @@ declare module "babylonjs/XR/motionController/webXRMotionControllerManager" {
         static DefaultFallbacks(): void;
     }
 }
-declare module "babylonjs/XR/webXRController" {
+declare module "babylonjs/XR/webXRInputSource" {
     import { Observable } from "babylonjs/Misc/observable";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Ray } from "babylonjs/Culling/ray";
     import { Scene } from "babylonjs/scene";
-    import { WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     /**
      * Configuration options for the WebXR controller creation
      */
@@ -45590,7 +45586,7 @@ declare module "babylonjs/XR/webXRController" {
     /**
      * Represents an XR controller
      */
-    export class WebXRController {
+    export class WebXRInputSource {
         private _scene;
         /** The underlying input source for the controller  */
         inputSource: XRInputSource;
@@ -45624,7 +45620,7 @@ declare module "babylonjs/XR/webXRController" {
          * The object provided as event data is this controller, after associated assets were disposed.
          * uniqueId is still available.
          */
-        onDisposeObservable: Observable<WebXRController>;
+        onDisposeObservable: Observable<WebXRInputSource>;
         private _tmpQuaternion;
         private _tmpVector;
         private _uniqueId;
@@ -45649,10 +45645,11 @@ declare module "babylonjs/XR/webXRController" {
          */
         updateFromXRFrame(xrFrame: XRFrame, referenceSpace: XRReferenceSpace): void;
         /**
-         * Gets a world space ray coming from the controller
+         * Gets a world space ray coming from the pointer or grip
          * @param result the resulting ray
+         * @param gripIfAvailable use the grip mesh instead of the pointer, if available
          */
-        getWorldPointerRayToRef(result: Ray): void;
+        getWorldPointerRayToRef(result: Ray, gripIfAvailable?: boolean): void;
         /**
          * Disposes of the object
          */
@@ -45662,7 +45659,7 @@ declare module "babylonjs/XR/webXRController" {
 declare module "babylonjs/XR/webXRInput" {
     import { Observable } from "babylonjs/Misc/observable";
     import { IDisposable } from "babylonjs/scene";
-    import { WebXRController } from "babylonjs/XR/webXRController";
+    import { WebXRInputSource } from "babylonjs/XR/webXRInputSource";
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
     import { WebXRCamera } from "babylonjs/XR/webXRCamera";
     /**
@@ -45710,18 +45707,18 @@ declare module "babylonjs/XR/webXRInput" {
         /**
          * XR controllers being tracked
          */
-        controllers: Array<WebXRController>;
+        controllers: Array<WebXRInputSource>;
         private _frameObserver;
         private _sessionEndedObserver;
         private _sessionInitObserver;
         /**
          * Event when a controller has been connected/added
          */
-        onControllerAddedObservable: Observable<WebXRController>;
+        onControllerAddedObservable: Observable<WebXRInputSource>;
         /**
          * Event when a controller has been removed/disconnected
          */
-        onControllerRemovedObservable: Observable<WebXRController>;
+        onControllerRemovedObservable: Observable<WebXRInputSource>;
         /**
          * Initializes the WebXRInput
          * @param xrSessionManager the xr session manager for this session
@@ -45805,7 +45802,7 @@ declare module "babylonjs/XR/features/WebXRAbstractFeature" {
 declare module "babylonjs/XR/features/WebXRControllerPointerSelection" {
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
     import { WebXRInput } from "babylonjs/XR/webXRInput";
-    import { WebXRController } from "babylonjs/XR/webXRController";
+    import { WebXRInputSource } from "babylonjs/XR/webXRInputSource";
     import { Nullable } from "babylonjs/types";
     import { Color3 } from "babylonjs/Maths/math.color";
     import { WebXRAbstractFeature } from "babylonjs/XR/features/WebXRAbstractFeature";
@@ -45922,7 +45919,7 @@ declare module "babylonjs/XR/features/WebXRControllerPointerSelection" {
          * @param id the pointer id to search for
          * @returns the controller that correlates to this id or null if not found
          */
-        getXRControllerByPointerId(id: number): Nullable<WebXRController>;
+        getXRControllerByPointerId(id: number): Nullable<WebXRInputSource>;
         protected _onXRFrame(_xrFrame: XRFrame): void;
         private _attachController;
         private _attachScreenRayMode;
@@ -72393,7 +72390,7 @@ declare module "babylonjs/XR/features/WebXRBackgroundRemover" {
 }
 declare module "babylonjs/XR/features/WebXRControllerPhysics" {
     import { WebXRAbstractFeature } from "babylonjs/XR/features/WebXRAbstractFeature";
-    import { WebXRController } from "babylonjs/XR/webXRController";
+    import { WebXRInputSource } from "babylonjs/XR/webXRInputSource";
     import { WebXRInput } from "babylonjs/XR/webXRInput";
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
     /**
@@ -72494,7 +72491,7 @@ declare module "babylonjs/XR/features/WebXRControllerPhysics" {
          * Manually add a controller (if no xrInput was provided or physics engine was not enabled)
          * @param xrController the controller to add
          */
-        addController(xrController: WebXRController): void;
+        addController(xrController: WebXRInputSource): void;
         private _debugMode;
         /**
          * @hidden
@@ -72516,7 +72513,7 @@ declare module "babylonjs/XR/features/index" {
     export * from "babylonjs/XR/features/WebXRControllerPhysics";
 }
 declare module "babylonjs/XR/motionController/webXRMicrosoftMixedRealityController" {
-    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Scene } from "babylonjs/scene";
     /**
@@ -72600,7 +72597,7 @@ declare module "babylonjs/XR/motionController/webXRMicrosoftMixedRealityControll
     }
 }
 declare module "babylonjs/XR/motionController/webXROculusTouchMotionController" {
-    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Scene } from "babylonjs/scene";
     /**
@@ -72644,7 +72641,7 @@ declare module "babylonjs/XR/motionController/webXROculusTouchMotionController"
     }
 }
 declare module "babylonjs/XR/motionController/webXRHTCViveMotionController" {
-    import { IMinimalMotionControllerObject, MotionControllerHandness, WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { IMinimalMotionControllerObject, MotionControllerHandness, WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { Scene } from "babylonjs/scene";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     /**
@@ -72679,7 +72676,7 @@ declare module "babylonjs/XR/motionController/webXRHTCViveMotionController" {
     }
 }
 declare module "babylonjs/XR/motionController/index" {
-    export * from "babylonjs/XR/motionController/webXRAbstractController";
+    export * from "babylonjs/XR/motionController/webXRAbstractMotionController";
     export * from "babylonjs/XR/motionController/webXRControllerComponent";
     export * from "babylonjs/XR/motionController/webXRGenericMotionController";
     export * from "babylonjs/XR/motionController/webXRMicrosoftMixedRealityController";
@@ -72693,7 +72690,7 @@ declare module "babylonjs/XR/index" {
     export * from "babylonjs/XR/webXREnterExitUI";
     export * from "babylonjs/XR/webXRExperienceHelper";
     export * from "babylonjs/XR/webXRInput";
-    export * from "babylonjs/XR/webXRController";
+    export * from "babylonjs/XR/webXRInputSource";
     export * from "babylonjs/XR/webXRManagedOutputCanvas";
     export * from "babylonjs/XR/webXRTypes";
     export * from "babylonjs/XR/webXRSessionManager";
@@ -115510,48 +115507,44 @@ declare module BABYLON {
 declare module BABYLON {
     /**
      * WebXR Camera which holds the views for the xrSession
-     * @see https://doc.babylonjs.com/how_to/webxr
+     * @see https://doc.babylonjs.com/how_to/webxr_camera
      */
     export class WebXRCamera extends FreeCamera {
         private _xrSessionManager;
-        /**
-         * Should position compensation execute on first frame.
-         * This is used when copying the position from a native (non XR) camera
-         */
-        compensateOnFirstFrame: boolean;
         private _firstFrame;
-        private _referencedPosition;
         private _referenceQuaternion;
+        private _referencedPosition;
         private _xrInvPositionCache;
         private _xrInvQuaternionCache;
-        private _realWorldHeight;
-        /**
-         * Prevent the camera from calculating the real-world height
-         * If you are not using the user's height disable this for better performance
-         */
-        disableRealWorldHeightCalculation: boolean;
         /**
-         * Return the user's height, unrelated to the current ground.
+         * Should position compensation execute on first frame.
+         * This is used when copying the position from a native (non XR) camera
          */
-        get realWorldHeight(): number;
+        compensateOnFirstFrame: boolean;
         /**
          * Creates a new webXRCamera, this should only be set at the camera after it has been updated by the xrSessionManager
          * @param name the name of the camera
          * @param scene the scene to add the camera to
+         * @param _xrSessionManager a constructed xr session manager
          */
         constructor(name: string, scene: Scene, _xrSessionManager: WebXRSessionManager);
-        private _updateNumberOfRigCameras;
+        /**
+         * Return the user's height, unrelated to the current ground.
+         * This will be the y position of this camera, when ground level is 0.
+         */
+        get realWorldHeight(): number;
+        /** @hidden */
+        _updateForDualEyeDebugging(): void;
         /**
          * Sets this camera's transformation based on a non-vr camera
          * @param otherCamera the non-vr camera to copy the transformation from
          * @param resetToBaseReferenceSpace should XR reset to the base reference space
          */
         setTransformationFromNonVRCamera(otherCamera?: Camera, resetToBaseReferenceSpace?: boolean): void;
-        /** @hidden */
-        _updateForDualEyeDebugging(): void;
+        private _updateFromXRSession;
+        private _updateNumberOfRigCameras;
         private _updateReferenceSpace;
         private _updateReferenceSpaceOffset;
-        private _updateFromXRSession;
     }
 }
 declare module BABYLON {
@@ -115882,12 +115875,12 @@ declare module BABYLON {
          * Observers registered here will be triggered when the state of a button changes
          * State change is either pressed / touched / value
          */
-        onButtonStateChanged: Observable<WebXRControllerComponent>;
+        onButtonStateChangedObservable: Observable<WebXRControllerComponent>;
         /**
          * If axes are available for this component (like a touchpad or thumbstick) the observers will be notified when
          * the axes data changes
          */
-        onAxisValueChanged: Observable<{
+        onAxisValueChangedObservable: Observable<{
             x: number;
             y: number;
         }>;
@@ -116912,7 +116905,7 @@ declare module BABYLON {
     /**
      * Represents an XR controller
      */
-    export class WebXRController {
+    export class WebXRInputSource {
         private _scene;
         /** The underlying input source for the controller  */
         inputSource: XRInputSource;
@@ -116946,7 +116939,7 @@ declare module BABYLON {
          * The object provided as event data is this controller, after associated assets were disposed.
          * uniqueId is still available.
          */
-        onDisposeObservable: Observable<WebXRController>;
+        onDisposeObservable: Observable<WebXRInputSource>;
         private _tmpQuaternion;
         private _tmpVector;
         private _uniqueId;
@@ -116971,10 +116964,11 @@ declare module BABYLON {
          */
         updateFromXRFrame(xrFrame: XRFrame, referenceSpace: XRReferenceSpace): void;
         /**
-         * Gets a world space ray coming from the controller
+         * Gets a world space ray coming from the pointer or grip
          * @param result the resulting ray
+         * @param gripIfAvailable use the grip mesh instead of the pointer, if available
          */
-        getWorldPointerRayToRef(result: Ray): void;
+        getWorldPointerRayToRef(result: Ray, gripIfAvailable?: boolean): void;
         /**
          * Disposes of the object
          */
@@ -117027,18 +117021,18 @@ declare module BABYLON {
         /**
          * XR controllers being tracked
          */
-        controllers: Array<WebXRController>;
+        controllers: Array<WebXRInputSource>;
         private _frameObserver;
         private _sessionEndedObserver;
         private _sessionInitObserver;
         /**
          * Event when a controller has been connected/added
          */
-        onControllerAddedObservable: Observable<WebXRController>;
+        onControllerAddedObservable: Observable<WebXRInputSource>;
         /**
          * Event when a controller has been removed/disconnected
          */
-        onControllerRemovedObservable: Observable<WebXRController>;
+        onControllerRemovedObservable: Observable<WebXRInputSource>;
         /**
          * Initializes the WebXRInput
          * @param xrSessionManager the xr session manager for this session
@@ -117230,7 +117224,7 @@ declare module BABYLON {
          * @param id the pointer id to search for
          * @returns the controller that correlates to this id or null if not found
          */
-        getXRControllerByPointerId(id: number): Nullable<WebXRController>;
+        getXRControllerByPointerId(id: number): Nullable<WebXRInputSource>;
         protected _onXRFrame(_xrFrame: XRFrame): void;
         private _attachController;
         private _attachScreenRayMode;
@@ -141626,7 +141620,7 @@ declare module BABYLON {
          * Manually add a controller (if no xrInput was provided or physics engine was not enabled)
          * @param xrController the controller to add
          */
-        addController(xrController: WebXRController): void;
+        addController(xrController: WebXRInputSource): void;
         private _debugMode;
         /**
          * @hidden

+ 27 - 30
dist/preview release/documentation.d.ts

@@ -42654,48 +42654,44 @@ declare module BABYLON {
 declare module BABYLON {
     /**
      * WebXR Camera which holds the views for the xrSession
-     * @see https://doc.babylonjs.com/how_to/webxr
+     * @see https://doc.babylonjs.com/how_to/webxr_camera
      */
     export class WebXRCamera extends FreeCamera {
         private _xrSessionManager;
-        /**
-         * Should position compensation execute on first frame.
-         * This is used when copying the position from a native (non XR) camera
-         */
-        compensateOnFirstFrame: boolean;
         private _firstFrame;
-        private _referencedPosition;
         private _referenceQuaternion;
+        private _referencedPosition;
         private _xrInvPositionCache;
         private _xrInvQuaternionCache;
-        private _realWorldHeight;
-        /**
-         * Prevent the camera from calculating the real-world height
-         * If you are not using the user's height disable this for better performance
-         */
-        disableRealWorldHeightCalculation: boolean;
         /**
-         * Return the user's height, unrelated to the current ground.
+         * Should position compensation execute on first frame.
+         * This is used when copying the position from a native (non XR) camera
          */
-        get realWorldHeight(): number;
+        compensateOnFirstFrame: boolean;
         /**
          * Creates a new webXRCamera, this should only be set at the camera after it has been updated by the xrSessionManager
          * @param name the name of the camera
          * @param scene the scene to add the camera to
+         * @param _xrSessionManager a constructed xr session manager
          */
         constructor(name: string, scene: Scene, _xrSessionManager: WebXRSessionManager);
-        private _updateNumberOfRigCameras;
+        /**
+         * Return the user's height, unrelated to the current ground.
+         * This will be the y position of this camera, when ground level is 0.
+         */
+        get realWorldHeight(): number;
+        /** @hidden */
+        _updateForDualEyeDebugging(): void;
         /**
          * Sets this camera's transformation based on a non-vr camera
          * @param otherCamera the non-vr camera to copy the transformation from
          * @param resetToBaseReferenceSpace should XR reset to the base reference space
          */
         setTransformationFromNonVRCamera(otherCamera?: Camera, resetToBaseReferenceSpace?: boolean): void;
-        /** @hidden */
-        _updateForDualEyeDebugging(): void;
+        private _updateFromXRSession;
+        private _updateNumberOfRigCameras;
         private _updateReferenceSpace;
         private _updateReferenceSpaceOffset;
-        private _updateFromXRSession;
     }
 }
 declare module BABYLON {
@@ -43026,12 +43022,12 @@ declare module BABYLON {
          * Observers registered here will be triggered when the state of a button changes
          * State change is either pressed / touched / value
          */
-        onButtonStateChanged: Observable<WebXRControllerComponent>;
+        onButtonStateChangedObservable: Observable<WebXRControllerComponent>;
         /**
          * If axes are available for this component (like a touchpad or thumbstick) the observers will be notified when
          * the axes data changes
          */
-        onAxisValueChanged: Observable<{
+        onAxisValueChangedObservable: Observable<{
             x: number;
             y: number;
         }>;
@@ -44056,7 +44052,7 @@ declare module BABYLON {
     /**
      * Represents an XR controller
      */
-    export class WebXRController {
+    export class WebXRInputSource {
         private _scene;
         /** The underlying input source for the controller  */
         inputSource: XRInputSource;
@@ -44090,7 +44086,7 @@ declare module BABYLON {
          * The object provided as event data is this controller, after associated assets were disposed.
          * uniqueId is still available.
          */
-        onDisposeObservable: Observable<WebXRController>;
+        onDisposeObservable: Observable<WebXRInputSource>;
         private _tmpQuaternion;
         private _tmpVector;
         private _uniqueId;
@@ -44115,10 +44111,11 @@ declare module BABYLON {
          */
         updateFromXRFrame(xrFrame: XRFrame, referenceSpace: XRReferenceSpace): void;
         /**
-         * Gets a world space ray coming from the controller
+         * Gets a world space ray coming from the pointer or grip
          * @param result the resulting ray
+         * @param gripIfAvailable use the grip mesh instead of the pointer, if available
          */
-        getWorldPointerRayToRef(result: Ray): void;
+        getWorldPointerRayToRef(result: Ray, gripIfAvailable?: boolean): void;
         /**
          * Disposes of the object
          */
@@ -44171,18 +44168,18 @@ declare module BABYLON {
         /**
          * XR controllers being tracked
          */
-        controllers: Array<WebXRController>;
+        controllers: Array<WebXRInputSource>;
         private _frameObserver;
         private _sessionEndedObserver;
         private _sessionInitObserver;
         /**
          * Event when a controller has been connected/added
          */
-        onControllerAddedObservable: Observable<WebXRController>;
+        onControllerAddedObservable: Observable<WebXRInputSource>;
         /**
          * Event when a controller has been removed/disconnected
          */
-        onControllerRemovedObservable: Observable<WebXRController>;
+        onControllerRemovedObservable: Observable<WebXRInputSource>;
         /**
          * Initializes the WebXRInput
          * @param xrSessionManager the xr session manager for this session
@@ -44374,7 +44371,7 @@ declare module BABYLON {
          * @param id the pointer id to search for
          * @returns the controller that correlates to this id or null if not found
          */
-        getXRControllerByPointerId(id: number): Nullable<WebXRController>;
+        getXRControllerByPointerId(id: number): Nullable<WebXRInputSource>;
         protected _onXRFrame(_xrFrame: XRFrame): void;
         private _attachController;
         private _attachScreenRayMode;
@@ -68770,7 +68767,7 @@ declare module BABYLON {
          * Manually add a controller (if no xrInput was provided or physics engine was not enabled)
          * @param xrController the controller to add
          */
-        addController(xrController: WebXRController): void;
+        addController(xrController: WebXRInputSource): void;
         private _debugMode;
         /**
          * @hidden

+ 69 - 75
dist/preview release/viewer/babylon.module.d.ts

@@ -44144,48 +44144,44 @@ declare module "babylonjs/XR/webXRCamera" {
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
     /**
      * WebXR Camera which holds the views for the xrSession
-     * @see https://doc.babylonjs.com/how_to/webxr
+     * @see https://doc.babylonjs.com/how_to/webxr_camera
      */
     export class WebXRCamera extends FreeCamera {
         private _xrSessionManager;
-        /**
-         * Should position compensation execute on first frame.
-         * This is used when copying the position from a native (non XR) camera
-         */
-        compensateOnFirstFrame: boolean;
         private _firstFrame;
-        private _referencedPosition;
         private _referenceQuaternion;
+        private _referencedPosition;
         private _xrInvPositionCache;
         private _xrInvQuaternionCache;
-        private _realWorldHeight;
-        /**
-         * Prevent the camera from calculating the real-world height
-         * If you are not using the user's height disable this for better performance
-         */
-        disableRealWorldHeightCalculation: boolean;
         /**
-         * Return the user's height, unrelated to the current ground.
+         * Should position compensation execute on first frame.
+         * This is used when copying the position from a native (non XR) camera
          */
-        get realWorldHeight(): number;
+        compensateOnFirstFrame: boolean;
         /**
          * Creates a new webXRCamera, this should only be set at the camera after it has been updated by the xrSessionManager
          * @param name the name of the camera
          * @param scene the scene to add the camera to
+         * @param _xrSessionManager a constructed xr session manager
          */
         constructor(name: string, scene: Scene, _xrSessionManager: WebXRSessionManager);
-        private _updateNumberOfRigCameras;
+        /**
+         * Return the user's height, unrelated to the current ground.
+         * This will be the y position of this camera, when ground level is 0.
+         */
+        get realWorldHeight(): number;
+        /** @hidden */
+        _updateForDualEyeDebugging(): void;
         /**
          * Sets this camera's transformation based on a non-vr camera
          * @param otherCamera the non-vr camera to copy the transformation from
          * @param resetToBaseReferenceSpace should XR reset to the base reference space
          */
         setTransformationFromNonVRCamera(otherCamera?: Camera, resetToBaseReferenceSpace?: boolean): void;
-        /** @hidden */
-        _updateForDualEyeDebugging(): void;
+        private _updateFromXRSession;
+        private _updateNumberOfRigCameras;
         private _updateReferenceSpace;
         private _updateReferenceSpaceOffset;
-        private _updateFromXRSession;
     }
 }
 declare module "babylonjs/XR/webXRFeaturesManager" {
@@ -44439,7 +44435,7 @@ declare module "babylonjs/XR/webXRExperienceHelper" {
     }
 }
 declare module "babylonjs/XR/motionController/webXRControllerComponent" {
-    import { IMinimalMotionControllerObject, MotionControllerComponentType } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { IMinimalMotionControllerObject, MotionControllerComponentType } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { Observable } from "babylonjs/Misc/observable";
     import { IDisposable } from "babylonjs/scene";
     /**
@@ -44527,12 +44523,12 @@ declare module "babylonjs/XR/motionController/webXRControllerComponent" {
          * Observers registered here will be triggered when the state of a button changes
          * State change is either pressed / touched / value
          */
-        onButtonStateChanged: Observable<WebXRControllerComponent>;
+        onButtonStateChangedObservable: Observable<WebXRControllerComponent>;
         /**
          * If axes are available for this component (like a touchpad or thumbstick) the observers will be notified when
          * the axes data changes
          */
-        onAxisValueChanged: Observable<{
+        onAxisValueChangedObservable: Observable<{
             x: number;
             y: number;
         }>;
@@ -45026,7 +45022,7 @@ declare module "babylonjs/Loading/sceneLoader" {
         static ImportAnimationsAsync(rootUrl: string, sceneFilename?: string | File, scene?: Nullable<Scene>, overwriteAnimations?: boolean, animationGroupLoadingMode?: SceneLoaderAnimationGroupLoadingMode, targetConverter?: Nullable<(target: any) => any>, onSuccess?: Nullable<(scene: Scene) => void>, onProgress?: Nullable<(event: SceneLoaderProgressEvent) => void>, onError?: Nullable<(scene: Scene, message: string, exception?: any) => void>): Promise<Scene>;
     }
 }
-declare module "babylonjs/XR/motionController/webXRAbstractController" {
+declare module "babylonjs/XR/motionController/webXRAbstractMotionController" {
     import { IDisposable, Scene } from "babylonjs/scene";
     import { WebXRControllerComponent } from "babylonjs/XR/motionController/webXRControllerComponent";
     import { Observable } from "babylonjs/Misc/observable";
@@ -45383,7 +45379,7 @@ declare module "babylonjs/XR/motionController/webXRAbstractController" {
     }
 }
 declare module "babylonjs/XR/motionController/webXRGenericMotionController" {
-    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Scene } from "babylonjs/scene";
     /**
@@ -45448,7 +45444,7 @@ declare module "babylonjs/Meshes/Builders/sphereBuilder" {
 }
 declare module "babylonjs/XR/motionController/webXRProfiledMotionController" {
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { WebXRAbstractMotionController, IMotionControllerProfile } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController, IMotionControllerProfile } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { Scene } from "babylonjs/scene";
     /**
      * A profiled motion controller has its profile loaded from an online repository.
@@ -45475,7 +45471,7 @@ declare module "babylonjs/XR/motionController/webXRProfiledMotionController" {
     }
 }
 declare module "babylonjs/XR/motionController/webXRMotionControllerManager" {
-    import { WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { Scene } from "babylonjs/scene";
     /**
      * A construction function type to create a new controller based on an xrInput object
@@ -45562,12 +45558,12 @@ declare module "babylonjs/XR/motionController/webXRMotionControllerManager" {
         static DefaultFallbacks(): void;
     }
 }
-declare module "babylonjs/XR/webXRController" {
+declare module "babylonjs/XR/webXRInputSource" {
     import { Observable } from "babylonjs/Misc/observable";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Ray } from "babylonjs/Culling/ray";
     import { Scene } from "babylonjs/scene";
-    import { WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     /**
      * Configuration options for the WebXR controller creation
      */
@@ -45590,7 +45586,7 @@ declare module "babylonjs/XR/webXRController" {
     /**
      * Represents an XR controller
      */
-    export class WebXRController {
+    export class WebXRInputSource {
         private _scene;
         /** The underlying input source for the controller  */
         inputSource: XRInputSource;
@@ -45624,7 +45620,7 @@ declare module "babylonjs/XR/webXRController" {
          * The object provided as event data is this controller, after associated assets were disposed.
          * uniqueId is still available.
          */
-        onDisposeObservable: Observable<WebXRController>;
+        onDisposeObservable: Observable<WebXRInputSource>;
         private _tmpQuaternion;
         private _tmpVector;
         private _uniqueId;
@@ -45649,10 +45645,11 @@ declare module "babylonjs/XR/webXRController" {
          */
         updateFromXRFrame(xrFrame: XRFrame, referenceSpace: XRReferenceSpace): void;
         /**
-         * Gets a world space ray coming from the controller
+         * Gets a world space ray coming from the pointer or grip
          * @param result the resulting ray
+         * @param gripIfAvailable use the grip mesh instead of the pointer, if available
          */
-        getWorldPointerRayToRef(result: Ray): void;
+        getWorldPointerRayToRef(result: Ray, gripIfAvailable?: boolean): void;
         /**
          * Disposes of the object
          */
@@ -45662,7 +45659,7 @@ declare module "babylonjs/XR/webXRController" {
 declare module "babylonjs/XR/webXRInput" {
     import { Observable } from "babylonjs/Misc/observable";
     import { IDisposable } from "babylonjs/scene";
-    import { WebXRController } from "babylonjs/XR/webXRController";
+    import { WebXRInputSource } from "babylonjs/XR/webXRInputSource";
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
     import { WebXRCamera } from "babylonjs/XR/webXRCamera";
     /**
@@ -45710,18 +45707,18 @@ declare module "babylonjs/XR/webXRInput" {
         /**
          * XR controllers being tracked
          */
-        controllers: Array<WebXRController>;
+        controllers: Array<WebXRInputSource>;
         private _frameObserver;
         private _sessionEndedObserver;
         private _sessionInitObserver;
         /**
          * Event when a controller has been connected/added
          */
-        onControllerAddedObservable: Observable<WebXRController>;
+        onControllerAddedObservable: Observable<WebXRInputSource>;
         /**
          * Event when a controller has been removed/disconnected
          */
-        onControllerRemovedObservable: Observable<WebXRController>;
+        onControllerRemovedObservable: Observable<WebXRInputSource>;
         /**
          * Initializes the WebXRInput
          * @param xrSessionManager the xr session manager for this session
@@ -45805,7 +45802,7 @@ declare module "babylonjs/XR/features/WebXRAbstractFeature" {
 declare module "babylonjs/XR/features/WebXRControllerPointerSelection" {
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
     import { WebXRInput } from "babylonjs/XR/webXRInput";
-    import { WebXRController } from "babylonjs/XR/webXRController";
+    import { WebXRInputSource } from "babylonjs/XR/webXRInputSource";
     import { Nullable } from "babylonjs/types";
     import { Color3 } from "babylonjs/Maths/math.color";
     import { WebXRAbstractFeature } from "babylonjs/XR/features/WebXRAbstractFeature";
@@ -45922,7 +45919,7 @@ declare module "babylonjs/XR/features/WebXRControllerPointerSelection" {
          * @param id the pointer id to search for
          * @returns the controller that correlates to this id or null if not found
          */
-        getXRControllerByPointerId(id: number): Nullable<WebXRController>;
+        getXRControllerByPointerId(id: number): Nullable<WebXRInputSource>;
         protected _onXRFrame(_xrFrame: XRFrame): void;
         private _attachController;
         private _attachScreenRayMode;
@@ -72393,7 +72390,7 @@ declare module "babylonjs/XR/features/WebXRBackgroundRemover" {
 }
 declare module "babylonjs/XR/features/WebXRControllerPhysics" {
     import { WebXRAbstractFeature } from "babylonjs/XR/features/WebXRAbstractFeature";
-    import { WebXRController } from "babylonjs/XR/webXRController";
+    import { WebXRInputSource } from "babylonjs/XR/webXRInputSource";
     import { WebXRInput } from "babylonjs/XR/webXRInput";
     import { WebXRSessionManager } from "babylonjs/XR/webXRSessionManager";
     /**
@@ -72494,7 +72491,7 @@ declare module "babylonjs/XR/features/WebXRControllerPhysics" {
          * Manually add a controller (if no xrInput was provided or physics engine was not enabled)
          * @param xrController the controller to add
          */
-        addController(xrController: WebXRController): void;
+        addController(xrController: WebXRInputSource): void;
         private _debugMode;
         /**
          * @hidden
@@ -72516,7 +72513,7 @@ declare module "babylonjs/XR/features/index" {
     export * from "babylonjs/XR/features/WebXRControllerPhysics";
 }
 declare module "babylonjs/XR/motionController/webXRMicrosoftMixedRealityController" {
-    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Scene } from "babylonjs/scene";
     /**
@@ -72600,7 +72597,7 @@ declare module "babylonjs/XR/motionController/webXRMicrosoftMixedRealityControll
     }
 }
 declare module "babylonjs/XR/motionController/webXROculusTouchMotionController" {
-    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { WebXRAbstractMotionController, IMinimalMotionControllerObject, MotionControllerHandness } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Scene } from "babylonjs/scene";
     /**
@@ -72644,7 +72641,7 @@ declare module "babylonjs/XR/motionController/webXROculusTouchMotionController"
     }
 }
 declare module "babylonjs/XR/motionController/webXRHTCViveMotionController" {
-    import { IMinimalMotionControllerObject, MotionControllerHandness, WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractController";
+    import { IMinimalMotionControllerObject, MotionControllerHandness, WebXRAbstractMotionController } from "babylonjs/XR/motionController/webXRAbstractMotionController";
     import { Scene } from "babylonjs/scene";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     /**
@@ -72679,7 +72676,7 @@ declare module "babylonjs/XR/motionController/webXRHTCViveMotionController" {
     }
 }
 declare module "babylonjs/XR/motionController/index" {
-    export * from "babylonjs/XR/motionController/webXRAbstractController";
+    export * from "babylonjs/XR/motionController/webXRAbstractMotionController";
     export * from "babylonjs/XR/motionController/webXRControllerComponent";
     export * from "babylonjs/XR/motionController/webXRGenericMotionController";
     export * from "babylonjs/XR/motionController/webXRMicrosoftMixedRealityController";
@@ -72693,7 +72690,7 @@ declare module "babylonjs/XR/index" {
     export * from "babylonjs/XR/webXREnterExitUI";
     export * from "babylonjs/XR/webXRExperienceHelper";
     export * from "babylonjs/XR/webXRInput";
-    export * from "babylonjs/XR/webXRController";
+    export * from "babylonjs/XR/webXRInputSource";
     export * from "babylonjs/XR/webXRManagedOutputCanvas";
     export * from "babylonjs/XR/webXRTypes";
     export * from "babylonjs/XR/webXRSessionManager";
@@ -115510,48 +115507,44 @@ declare module BABYLON {
 declare module BABYLON {
     /**
      * WebXR Camera which holds the views for the xrSession
-     * @see https://doc.babylonjs.com/how_to/webxr
+     * @see https://doc.babylonjs.com/how_to/webxr_camera
      */
     export class WebXRCamera extends FreeCamera {
         private _xrSessionManager;
-        /**
-         * Should position compensation execute on first frame.
-         * This is used when copying the position from a native (non XR) camera
-         */
-        compensateOnFirstFrame: boolean;
         private _firstFrame;
-        private _referencedPosition;
         private _referenceQuaternion;
+        private _referencedPosition;
         private _xrInvPositionCache;
         private _xrInvQuaternionCache;
-        private _realWorldHeight;
-        /**
-         * Prevent the camera from calculating the real-world height
-         * If you are not using the user's height disable this for better performance
-         */
-        disableRealWorldHeightCalculation: boolean;
         /**
-         * Return the user's height, unrelated to the current ground.
+         * Should position compensation execute on first frame.
+         * This is used when copying the position from a native (non XR) camera
          */
-        get realWorldHeight(): number;
+        compensateOnFirstFrame: boolean;
         /**
          * Creates a new webXRCamera, this should only be set at the camera after it has been updated by the xrSessionManager
          * @param name the name of the camera
          * @param scene the scene to add the camera to
+         * @param _xrSessionManager a constructed xr session manager
          */
         constructor(name: string, scene: Scene, _xrSessionManager: WebXRSessionManager);
-        private _updateNumberOfRigCameras;
+        /**
+         * Return the user's height, unrelated to the current ground.
+         * This will be the y position of this camera, when ground level is 0.
+         */
+        get realWorldHeight(): number;
+        /** @hidden */
+        _updateForDualEyeDebugging(): void;
         /**
          * Sets this camera's transformation based on a non-vr camera
          * @param otherCamera the non-vr camera to copy the transformation from
          * @param resetToBaseReferenceSpace should XR reset to the base reference space
          */
         setTransformationFromNonVRCamera(otherCamera?: Camera, resetToBaseReferenceSpace?: boolean): void;
-        /** @hidden */
-        _updateForDualEyeDebugging(): void;
+        private _updateFromXRSession;
+        private _updateNumberOfRigCameras;
         private _updateReferenceSpace;
         private _updateReferenceSpaceOffset;
-        private _updateFromXRSession;
     }
 }
 declare module BABYLON {
@@ -115882,12 +115875,12 @@ declare module BABYLON {
          * Observers registered here will be triggered when the state of a button changes
          * State change is either pressed / touched / value
          */
-        onButtonStateChanged: Observable<WebXRControllerComponent>;
+        onButtonStateChangedObservable: Observable<WebXRControllerComponent>;
         /**
          * If axes are available for this component (like a touchpad or thumbstick) the observers will be notified when
          * the axes data changes
          */
-        onAxisValueChanged: Observable<{
+        onAxisValueChangedObservable: Observable<{
             x: number;
             y: number;
         }>;
@@ -116912,7 +116905,7 @@ declare module BABYLON {
     /**
      * Represents an XR controller
      */
-    export class WebXRController {
+    export class WebXRInputSource {
         private _scene;
         /** The underlying input source for the controller  */
         inputSource: XRInputSource;
@@ -116946,7 +116939,7 @@ declare module BABYLON {
          * The object provided as event data is this controller, after associated assets were disposed.
          * uniqueId is still available.
          */
-        onDisposeObservable: Observable<WebXRController>;
+        onDisposeObservable: Observable<WebXRInputSource>;
         private _tmpQuaternion;
         private _tmpVector;
         private _uniqueId;
@@ -116971,10 +116964,11 @@ declare module BABYLON {
          */
         updateFromXRFrame(xrFrame: XRFrame, referenceSpace: XRReferenceSpace): void;
         /**
-         * Gets a world space ray coming from the controller
+         * Gets a world space ray coming from the pointer or grip
          * @param result the resulting ray
+         * @param gripIfAvailable use the grip mesh instead of the pointer, if available
          */
-        getWorldPointerRayToRef(result: Ray): void;
+        getWorldPointerRayToRef(result: Ray, gripIfAvailable?: boolean): void;
         /**
          * Disposes of the object
          */
@@ -117027,18 +117021,18 @@ declare module BABYLON {
         /**
          * XR controllers being tracked
          */
-        controllers: Array<WebXRController>;
+        controllers: Array<WebXRInputSource>;
         private _frameObserver;
         private _sessionEndedObserver;
         private _sessionInitObserver;
         /**
          * Event when a controller has been connected/added
          */
-        onControllerAddedObservable: Observable<WebXRController>;
+        onControllerAddedObservable: Observable<WebXRInputSource>;
         /**
          * Event when a controller has been removed/disconnected
          */
-        onControllerRemovedObservable: Observable<WebXRController>;
+        onControllerRemovedObservable: Observable<WebXRInputSource>;
         /**
          * Initializes the WebXRInput
          * @param xrSessionManager the xr session manager for this session
@@ -117230,7 +117224,7 @@ declare module BABYLON {
          * @param id the pointer id to search for
          * @returns the controller that correlates to this id or null if not found
          */
-        getXRControllerByPointerId(id: number): Nullable<WebXRController>;
+        getXRControllerByPointerId(id: number): Nullable<WebXRInputSource>;
         protected _onXRFrame(_xrFrame: XRFrame): void;
         private _attachController;
         private _attachScreenRayMode;
@@ -141626,7 +141620,7 @@ declare module BABYLON {
          * Manually add a controller (if no xrInput was provided or physics engine was not enabled)
          * @param xrController the controller to add
          */
-        addController(xrController: WebXRController): void;
+        addController(xrController: WebXRInputSource): void;
         private _debugMode;
         /**
          * @hidden

Datei-Diff unterdrückt, da er zu groß ist
+ 23 - 23
dist/preview release/viewer/babylon.viewer.js


Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 3 - 2
dist/preview release/what's new.md

@@ -60,7 +60,6 @@
 - Make sure all properties of CascadedShadowMap class are serialized/parsed ([Popov72](https://github.com/Popov72))
 - Added `textures/opacity.png` file to the Playground ([Popov72](https://github.com/Popov72))
 - Refactored the shadow generators code ([Popov72](https://github.com/Popov72))
-- Added preview area pop up for NME ([Kyle Belfort](https://github.com/belfortk))
 - Supports clip planes with shadows ([sebavan](http://www.github.com/sebavan))
 - Added Workbench color scheme for VSCode ([drigax](https://github.com/drigax) & [Patrick Ryan](https://github.com/PatrickRyanMS))
 
@@ -107,6 +106,8 @@
 - Added diff navigator in the playground ([sailro](http://www.github.com/sailro))
 - Added custom filter to remove internals from the completion in the playground ([sailro](http://www.github.com/sailro))
 - Added support for tagging deprecated members (both in editor and for completion) in the playground ([sailro](http://www.github.com/sailro))
+- Added preview area pop up for NME ([Kyle Belfort](https://github.com/belfortk))
+- Added comments to frames in NME ([Kyle Belfort](https://github.com/belfortk))
 
 ### Meshes
 
@@ -205,7 +206,7 @@
 - Selection has gaze mode (which can be forced) and touch-screen support ([#7395](https://github.com/BabylonJS/Babylon.js/issues/7395)) ([RaananW](https://github.com/RaananW/))
 - Laser pointers can be excluded from lighting influence so that they are always visible in both WebXR and WebVR ([#7323](https://github.com/BabylonJS/Babylon.js/issues/7323)) ([RaananW](https://github.com/RaananW/))
 - Full support for the online motion controller repository ([#7323](https://github.com/BabylonJS/Babylon.js/issues/7323)) ([RaananW](https://github.com/RaananW/))
-- New feature - XR Controller physics impostor ([RaananW](https://github.com/RaananW/))
+- New feature - XR Controller physics impostor for motion controllers ([RaananW](https://github.com/RaananW/))
 - Teleportation between different ground levels in WebXR is enabled ([RaananW](https://github.com/RaananW/))
 
 ### Ray

+ 106 - 0
gui/src/2D/controls/scrollViewers/scrollViewer.ts

@@ -27,7 +27,11 @@ export class ScrollViewer extends Rectangle {
     private _barColor: string;
     private _barBackground: string;
     private _barImage: Image;
+    private _horizontalBarImage: Image;
+    private _verticalBarImage: Image;
     private _barBackgroundImage: Image;
+    private _horizontalBarBackgroundImage: Image;
+    private _verticalBarBackgroundImage: Image;
     private _barSize: number = 20;
     private _window: _ScrollViewerWindow;
     private _pointerIsOver: Boolean = false;
@@ -39,6 +43,8 @@ export class ScrollViewer extends Rectangle {
     private _thumbLength: number = 0.5;
     private _thumbHeight: number = 1;
     private _barImageHeight: number = 1;
+    private _horizontalBarImageHeight: number = 1;
+    private _verticalBarImageHeight: number = 1;
 
     /**
      * Gets the horizontal scrollbar
@@ -326,6 +332,36 @@ export class ScrollViewer extends Rectangle {
         vb.thumbImage = value;
     }
 
+    /** Gets or sets the horizontal bar image */
+    public get horizontalThumbImage(): Image {
+        return this._horizontalBarImage;
+    }
+
+    public set horizontalThumbImage(value: Image) {
+        if (this._horizontalBarImage === value) {
+            return;
+        }
+
+        this._horizontalBarImage = value;
+        let hb = <ImageScrollBar>this._horizontalBar;
+        hb.thumbImage = value;
+    }
+
+    /** Gets or sets the vertical bar image */
+    public get verticalThumbImage(): Image {
+        return this._verticalBarImage;
+    }
+
+    public set verticalThumbImage(value: Image) {
+        if (this._verticalBarImage === value) {
+            return;
+        }
+
+        this._verticalBarImage = value;
+        let vb = <ImageScrollBar>this._verticalBar;
+        vb.thumbImage = value;
+    }
+
     /** Gets or sets the size of the bar */
     public get barSize(): number {
         return this._barSize;
@@ -416,6 +452,48 @@ export class ScrollViewer extends Rectangle {
         this._markAsDirty();
     }
 
+    /** Gets or sets the height of the horizontal bar image */
+    public get horizontalBarImageHeight(): number {
+        return this._horizontalBarImageHeight;
+    }
+
+    public set horizontalBarImageHeight(value: number) {
+        if (this._horizontalBarImageHeight === value) {
+            return;
+        }
+        if (value <= 0) {
+            value = 0.1;
+        }
+        if (value > 1) {
+            value = 1;
+        }
+        this._horizontalBarImageHeight = value;
+        var hb = <ImageScrollBar>this._horizontalBar;
+        hb.barImageHeight = value;
+        this._markAsDirty();
+    }
+
+    /** Gets or sets the height of the vertical bar image */
+    public get verticalBarImageHeight(): number {
+        return this._verticalBarImageHeight;
+    }
+
+    public set verticalBarImageHeight(value: number) {
+        if (this._verticalBarImageHeight === value) {
+            return;
+        }
+        if (value <= 0) {
+            value = 0.1;
+        }
+        if (value > 1) {
+            value = 1;
+        }
+        this._verticalBarImageHeight = value;
+        var vb = <ImageScrollBar>this._verticalBar;
+        vb.barImageHeight = value;
+        this._markAsDirty();
+    }
+
     /** Gets or sets the bar background */
     public get barBackground(): string {
         return this._barBackground;
@@ -450,6 +528,34 @@ export class ScrollViewer extends Rectangle {
         vb.backgroundImage = value;
     }
 
+    /** Gets or sets the horizontal bar background image */
+    public get horizontalBarImage(): Image {
+        return this._horizontalBarBackgroundImage;
+    }
+
+    public set horizontalBarImage(value: Image) {
+        if (this._horizontalBarBackgroundImage === value) {
+        }
+
+        this._horizontalBarBackgroundImage = value;
+        let hb = <ImageScrollBar>this._horizontalBar;
+        hb.backgroundImage = value;
+    }
+
+    /** Gets or sets the vertical bar background image */
+    public get verticalBarImage(): Image {
+        return this._verticalBarBackgroundImage;
+    }
+
+    public set verticalBarImage(value: Image) {
+        if (this._verticalBarBackgroundImage === value) {
+        }
+
+        this._verticalBarBackgroundImage = value;
+        let vb = <ImageScrollBar>this._verticalBar;
+        vb.backgroundImage = value;
+    }
+
     private _setWindowPosition(): void {
         let ratio = this.host.idealRatio;
         let windowContentsWidth = this._window._currentMeasure.width;

+ 33 - 4
nodeEditor/src/diagram/graphFrame.ts

@@ -25,7 +25,8 @@ export class GraphFrame {
     private _headerElement: HTMLDivElement;    
     private _headerTextElement: HTMLDivElement;        
     private _headerCollapseElement: HTMLDivElement;    
-    private _headerCloseElement: HTMLDivElement;    
+    private _headerCloseElement: HTMLDivElement;
+    private _commentsElement: HTMLDivElement;    
     private _portContainer: HTMLDivElement;    
     private _outputPortContainer: HTMLDivElement;    
     private _inputPortContainer: HTMLDivElement;    
@@ -38,6 +39,7 @@ export class GraphFrame {
     private _ports: NodePort[] = [];
     private _controlledPorts: NodePort[] = [];
     private _id: number;
+    private _comments: string;
 
     public onExpandStateChanged = new Observable<GraphFrame>();
 
@@ -241,6 +243,24 @@ export class GraphFrame {
         this.element.style.height = `${gridAlignedBottom - this._gridAlignedY}px`;
     }
 
+    public get comments(): string {
+        return this._comments;
+    }
+
+    public set comments(comments: string) {
+        if (comments.length > 0) {
+            this.element.style.gridTemplateRows = "40px 40px calc(100% - 80px)";
+            this._borderElement.style.gridRow = "1 / span 3";
+            this._portContainer.style.gridRow = "3";
+            this._commentsElement.style.display = "grid";
+            this._commentsElement.style.gridRow = "2";
+            this._commentsElement.style.gridColumn = "1";
+            this._commentsElement.style.paddingLeft = "10px";
+        }
+        this._comments = comments;
+        this._commentsElement.innerText = comments;
+    }
+
     public constructor(candidate: Nullable<HTMLDivElement>, canvas: GraphCanvasComponent, doNotCaptureNodes = false) {
         this._id = GraphFrame._FrameCounter++;
 
@@ -331,8 +351,15 @@ export class GraphFrame {
             } else {
                 this.element.classList.remove("selected");
             }
-        });  
-                
+        }); 
+
+        this._commentsElement = document.createElement('div');
+        this._commentsElement.className = 'frame-comments';
+        this._commentsElement.style.color = 'white';
+        this._commentsElement.style.fontSize = '16px';
+        
+        this.element.appendChild(this._commentsElement);
+
         // Get nodes
         if (!doNotCaptureNodes) {
             this.refresh();
@@ -471,7 +498,8 @@ export class GraphFrame {
             color: this._color.asArray(),
             name: this.name,
             isCollapsed: this.isCollapsed,
-            blocks: this.nodes.map(n => n.block.uniqueId)
+            blocks: this.nodes.map(n => n.block.uniqueId),
+            comments: this._comments
         }
     }
 
@@ -491,6 +519,7 @@ export class GraphFrame {
         newFrame.height = serializationData.height;
         newFrame.name = serializationData.name;
         newFrame.color = Color3.FromArray(serializationData.color);
+        newFrame.comments = serializationData.comments;
 
         if (serializationData.blocks && map) {
             for (var blockId of serializationData.blocks) {

+ 3 - 0
nodeEditor/src/diagram/properties/framePropertyComponent.tsx

@@ -46,6 +46,9 @@ export class FramePropertyTabComponent extends React.Component<IFramePropertyTab
                 <LineContainerComponent title="GENERAL">
                     <TextInputLineComponent globalState={this.props.globalState} label="Name" propertyName="name" target={this.props.frame} />
                     <Color3LineComponent globalState={this.props.globalState} label="Color" target={this.props.frame} propertyName="color"></Color3LineComponent>
+                    <TextInputLineComponent globalState={this.props.globalState} label="Comments" propertyName="comments" target={this.props.frame}
+                    />
+
                     {
                         !this.props.frame.isCollapsed &&
                         <ButtonLineComponent label="Collapse" onClick={() => {

+ 1 - 1
nodeEditor/src/globalState.ts

@@ -35,7 +35,7 @@ export class GlobalState {
     onAnimationCommandActivated = new Observable<void>();
     onCandidateLinkMoved = new Observable<Nullable<Vector2>>();   
     onSelectionBoxMoved = new Observable<ClientRect | DOMRect>();       
-    onFrameCreated = new Observable<GraphFrame>();   
+    onFrameCreated = new Observable<GraphFrame>();
     onCandidatePortSelected = new Observable<Nullable<NodePort>>();
     onGetNodeFromBlock: (block: NodeMaterialBlock) => GraphNode;
     onGridSizeChanged = new Observable<void>();

+ 1 - 1
nodeEditor/src/graphEditor.tsx

@@ -116,7 +116,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps, State> {
         let nodeType: NodeMaterialBlockConnectionPointTypes = BlockTools.GetConnectionNodeTypeFromString(type);
 
         let newInputBlock = new InputBlock(type, undefined, nodeType);
-        return this.createNodeFromObject(newInputBlock)
+        return this.createNodeFromObject(newInputBlock);
     }
 
     componentDidMount() {

+ 4 - 3
nodeEditor/src/nodeLocationInfo.ts

@@ -10,9 +10,10 @@ export interface IFrameData {
     width: number;
     height: number;
     color: number[];
-    name: string,
-    isCollapsed: boolean,
-    blocks: number[]
+    name: string;
+    isCollapsed: boolean;
+    blocks: number[];
+    comments: string;
 }
 
 export interface IEditorData {

+ 4 - 4
src/XR/features/WebXRControllerPhysics.ts

@@ -1,6 +1,6 @@
 import { WebXRAbstractFeature } from "./WebXRAbstractFeature";
 import { Vector3, Quaternion } from "../../Maths/math.vector";
-import { WebXRController } from "../webXRController";
+import { WebXRInputSource } from "../webXRInputSource";
 import { PhysicsImpostor } from "../../Physics/physicsImpostor";
 import { WebXRInput } from "../webXRInput";
 import { WebXRSessionManager } from "../webXRSessionManager";
@@ -67,7 +67,7 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
 
     private _controllers: {
         [id: string]: {
-            xrController: WebXRController;
+            xrController: WebXRInputSource;
             impostorMesh?: AbstractMesh,
             impostor: PhysicsImpostor
             oldPos?: Vector3;
@@ -154,7 +154,7 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
      * Manually add a controller (if no xrInput was provided or physics engine was not enabled)
      * @param xrController the controller to add
      */
-    public addController(xrController: WebXRController) {
+    public addController(xrController: WebXRInputSource) {
         this._attachController(xrController);
     }
 
@@ -174,7 +174,7 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
         });
     }
 
-    private _attachController = (xrController: WebXRController
+    private _attachController = (xrController: WebXRInputSource
     ) => {
         if (this._controllers[xrController.uniqueId]) {
             // already attached

+ 10 - 10
src/XR/features/WebXRControllerPointerSelection.ts

@@ -3,7 +3,7 @@ import { WebXRSessionManager } from '../webXRSessionManager';
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { Observer } from '../../Misc/observable';
 import { WebXRInput } from '../webXRInput';
-import { WebXRController } from '../webXRController';
+import { WebXRInputSource } from '../webXRInputSource';
 import { Scene } from '../../scene';
 import { WebXRControllerComponent } from '../motionController/webXRControllerComponent';
 import { Nullable } from '../../types';
@@ -115,7 +115,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
 
     private _controllers: {
         [controllerUniqueId: string]: {
-            xrController: WebXRController;
+            xrController: WebXRInputSource;
             selectionComponent?: WebXRControllerComponent;
             onButtonChangedObserver?: Nullable<Observer<WebXRControllerComponent>>;
             onFrameObserver?: Nullable<Observer<XRFrame>>;
@@ -183,7 +183,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
      * @param id the pointer id to search for
      * @returns the controller that correlates to this id or null if not found
      */
-    public getXRControllerByPointerId(id: number): Nullable<WebXRController> {
+    public getXRControllerByPointerId(id: number): Nullable<WebXRInputSource> {
         const keys = Object.keys(this._controllers);
 
         for (let i = 0; i < keys.length; ++i) {
@@ -231,7 +231,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
         });
     }
 
-    private _attachController = (xrController: WebXRController) => {
+    private _attachController = (xrController: WebXRInputSource) => {
         if (this._controllers[xrController.uniqueId]) {
             // already attached
             return;
@@ -257,7 +257,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
         }
     }
 
-    private _attachScreenRayMode(xrController: WebXRController) {
+    private _attachScreenRayMode(xrController: WebXRInputSource) {
         const controllerData = this._controllers[xrController.uniqueId];
         let downTriggered = false;
         controllerData.onFrameObserver = this._xrSessionManager.onXRFrameObservable.add(() => {
@@ -279,7 +279,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
         });
     }
 
-    private _attachGazeMode(xrController: WebXRController) {
+    private _attachGazeMode(xrController: WebXRInputSource) {
         const controllerData = this._controllers[xrController.uniqueId];
         // attached when touched, detaches when raised
         const timeToSelect = this._options.timeToSelect || 3000;
@@ -356,7 +356,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
 
     }
 
-    private _attachTrackedPointerRayMode(xrController: WebXRController) {
+    private _attachTrackedPointerRayMode(xrController: WebXRInputSource) {
         xrController.onMotionControllerInitObservable.add((motionController) => {
             if (this._options.forceGazeMode) {
                 return this._attachGazeMode(xrController);
@@ -388,7 +388,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
                 }
             });
 
-            controllerData.onButtonChangedObserver = controllerData.selectionComponent.onButtonStateChanged.add((component) => {
+            controllerData.onButtonChangedObserver = controllerData.selectionComponent.onButtonStateChangedObservable.add((component) => {
                 if (component.changes.pressed) {
                     const pressed = component.changes.pressed.current;
                     if (controllerData.pick) {
@@ -409,7 +409,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
         if (!controllerData) { return; }
         if (controllerData.selectionComponent) {
             if (controllerData.onButtonChangedObserver) {
-                controllerData.selectionComponent.onButtonStateChanged.remove(controllerData.onButtonChangedObserver);
+                controllerData.selectionComponent.onButtonStateChangedObservable.remove(controllerData.onButtonChangedObserver);
             }
         }
         if (controllerData.onFrameObserver) {
@@ -421,7 +421,7 @@ export class WebXRControllerPointerSelection extends WebXRAbstractFeature {
         delete this._controllers[xrControllerUniqueId];
     }
 
-    private _generateNewMeshPair(xrController: WebXRController) {
+    private _generateNewMeshPair(xrController: WebXRInputSource) {
         const laserPointer = CylinderBuilder.CreateCylinder("laserPointer", {
             height: 1,
             diameterTop: 0.0002,

+ 8 - 8
src/XR/features/WebXRControllerTeleportation.ts

@@ -3,7 +3,7 @@ import { Observer } from '../../Misc/observable';
 import { WebXRSessionManager } from '../webXRSessionManager';
 import { Nullable } from '../../types';
 import { WebXRInput } from '../webXRInput';
-import { WebXRController } from '../webXRController';
+import { WebXRInputSource } from '../webXRInputSource';
 import { WebXRControllerComponent, IWebXRMotionControllerAxesValue } from '../motionController/webXRControllerComponent';
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { Vector3, Quaternion } from '../../Maths/math.vector';
@@ -169,7 +169,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
 
     private _controllers: {
         [controllerUniqueId: string]: {
-            xrController: WebXRController;
+            xrController: WebXRInputSource;
             teleportationComponent?: WebXRControllerComponent;
             teleportationState: {
                 forward: boolean;
@@ -315,7 +315,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
 
     private _currentTeleportationControllerId: string;
 
-    private _attachController = (xrController: WebXRController) => {
+    private _attachController = (xrController: WebXRInputSource) => {
         if (this._controllers[xrController.uniqueId]) {
             // already attached
             return;
@@ -341,7 +341,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
                     if (!mainComponent) {
                         return;
                     }
-                    controllerData.onButtonChangedObserver = mainComponent.onButtonStateChanged.add(() => {
+                    controllerData.onButtonChangedObserver = mainComponent.onButtonStateChangedObservable.add(() => {
                         // did "pressed" changed?
                         if (mainComponent.changes.pressed) {
                             if (mainComponent.changes.pressed.current) {
@@ -374,13 +374,13 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
                         }
                     });
                 } else {
-                    controllerData.onButtonChangedObserver = movementController.onButtonStateChanged.add(() => {
+                    controllerData.onButtonChangedObserver = movementController.onButtonStateChangedObservable.add(() => {
                         if (this._currentTeleportationControllerId === controllerData.xrController.uniqueId && controllerData.teleportationState.forward && !movementController.touched) {
                             this._teleportForward(xrController.uniqueId);
                         }
                     });
                     // use thumbstick (or touchpad if thumbstick not available)
-                    controllerData.onAxisChangedObserver = movementController.onAxisValueChanged.add((axesData) => {
+                    controllerData.onAxisChangedObserver = movementController.onAxisValueChangedObservable.add((axesData) => {
                         if (axesData.y <= 0.7 && controllerData.teleportationState.backwards) {
                             //if (this._currentTeleportationControllerId === controllerData.xrController.uniqueId) {
                             controllerData.teleportationState.backwards = false;
@@ -462,10 +462,10 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
         if (!controllerData) { return; }
         if (controllerData.teleportationComponent) {
             if (controllerData.onAxisChangedObserver) {
-                controllerData.teleportationComponent.onAxisValueChanged.remove(controllerData.onAxisChangedObserver);
+                controllerData.teleportationComponent.onAxisValueChangedObservable.remove(controllerData.onAxisChangedObserver);
             }
             if (controllerData.onButtonChangedObserver) {
-                controllerData.teleportationComponent.onButtonStateChanged.remove(controllerData.onButtonChangedObserver);
+                controllerData.teleportationComponent.onButtonStateChangedObservable.remove(controllerData.onButtonChangedObserver);
             }
         }
         // remove from the map

+ 1 - 1
src/XR/index.ts

@@ -2,7 +2,7 @@ export * from "./webXRCamera";
 export * from "./webXREnterExitUI";
 export * from "./webXRExperienceHelper";
 export * from "./webXRInput";
-export * from "./webXRController";
+export * from "./webXRInputSource";
 export * from "./webXRManagedOutputCanvas";
 export * from "./webXRTypes";
 export * from "./webXRSessionManager";

+ 1 - 1
src/XR/motionController/index.ts

@@ -1,4 +1,4 @@
-export * from "./webXRAbstractController";
+export * from "./webXRAbstractMotionController";
 export * from "./webXRControllerComponent";
 export * from "./webXRGenericMotionController";
 export * from "./webXRMicrosoftMixedRealityController";

src/XR/motionController/webXRAbstractController.ts → src/XR/motionController/webXRAbstractMotionController.ts


+ 7 - 7
src/XR/motionController/webXRControllerComponent.ts

@@ -1,4 +1,4 @@
-import { IMinimalMotionControllerObject, MotionControllerComponentType } from "./webXRAbstractController";
+import { IMinimalMotionControllerObject, MotionControllerComponentType } from "./webXRAbstractMotionController";
 import { Observable } from '../../Misc/observable';
 import { IDisposable } from '../../scene';
 
@@ -80,12 +80,12 @@ export class WebXRControllerComponent implements IDisposable {
      * Observers registered here will be triggered when the state of a button changes
      * State change is either pressed / touched / value
      */
-    public onButtonStateChanged: Observable<WebXRControllerComponent> = new Observable();
+    public onButtonStateChangedObservable: Observable<WebXRControllerComponent> = new Observable();
     /**
      * If axes are available for this component (like a touchpad or thumbstick) the observers will be notified when
      * the axes data changes
      */
-    public onAxisValueChanged: Observable<{ x: number, y: number }> = new Observable();
+    public onAxisValueChangedObservable: Observable<{ x: number, y: number }> = new Observable();
 
     private _currentValue: number = 0;
     private _touched: boolean = false;
@@ -257,11 +257,11 @@ export class WebXRControllerComponent implements IDisposable {
 
         if (buttonUpdated) {
             this._hasChanges = true;
-            this.onButtonStateChanged.notifyObservers(this);
+            this.onButtonStateChangedObservable.notifyObservers(this);
         }
         if (axesUpdate) {
             this._hasChanges = true;
-            this.onAxisValueChanged.notifyObservers(this._axes);
+            this.onAxisValueChangedObservable.notifyObservers(this._axes);
         }
     }
 
@@ -269,7 +269,7 @@ export class WebXRControllerComponent implements IDisposable {
      * Dispose this component
      */
     public dispose(): void {
-        this.onAxisValueChanged.clear();
-        this.onButtonStateChanged.clear();
+        this.onAxisValueChangedObservable.clear();
+        this.onButtonStateChangedObservable.clear();
     }
 }

+ 1 - 1
src/XR/motionController/webXRGenericMotionController.ts

@@ -3,7 +3,7 @@ import {
     IMinimalMotionControllerObject,
     MotionControllerHandness,
     IMotionControllerLayoutMap
-} from "./webXRAbstractController";
+} from "./webXRAbstractMotionController";
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { Scene } from '../../scene';
 import { Mesh } from '../../Meshes/mesh';

+ 2 - 2
src/XR/motionController/webXRHTCViveMotionController.ts

@@ -3,7 +3,7 @@ import {
     IMinimalMotionControllerObject,
     MotionControllerHandness,
     WebXRAbstractMotionController
-} from "./webXRAbstractController";
+} from "./webXRAbstractMotionController";
 import { Scene } from '../../scene';
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { Mesh } from '../../Meshes/mesh';
@@ -43,7 +43,7 @@ export class WebXRHTCViveMotionController extends WebXRAbstractMotionController
         this.getComponentIds().forEach((id) => {
             const comp = id && this.getComponent(id);
             if (comp) {
-                comp.onButtonStateChanged.add((component) => {
+                comp.onButtonStateChangedObservable.add((component) => {
 
                     if (!this.rootMesh || this.disableAnimation) { return; }
 

+ 3 - 3
src/XR/motionController/webXRMicrosoftMixedRealityController.ts

@@ -3,7 +3,7 @@ import {
     IMinimalMotionControllerObject,
     MotionControllerHandness,
     IMotionControllerLayoutMap
-} from "./webXRAbstractController";
+} from "./webXRAbstractMotionController";
 import { WebXRMotionControllerManager } from './webXRMotionControllerManager';
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { Scene } from '../../scene';
@@ -118,7 +118,7 @@ export class WebXRMicrosoftMixedRealityController extends WebXRAbstractMotionCon
                 if (buttonMap.valueMesh && buttonMap.pressedMesh && buttonMap.unpressedMesh) {
                     const comp = this.getComponent(id);
                     if (comp) {
-                        comp.onButtonStateChanged.add((component) => {
+                        comp.onButtonStateChangedObservable.add((component) => {
                             this._lerpTransform(buttonMap, component.value);
                         }, undefined, true);
                     }
@@ -153,7 +153,7 @@ export class WebXRMicrosoftMixedRealityController extends WebXRAbstractMotionCon
 
                 if (axisMap.valueMesh && axisMap.minMesh && axisMap.maxMesh) {
                     if (comp) {
-                        comp.onAxisValueChanged.add((axisValues) => {
+                        comp.onAxisValueChangedObservable.add((axisValues) => {
                             const value = axis === "x-axis" ? axisValues.x : axisValues.y;
                             this._lerpTransform(axisMap, value, true);
                         }, undefined, true);

+ 1 - 1
src/XR/motionController/webXRMotionControllerManager.ts

@@ -1,6 +1,6 @@
 import {
     WebXRAbstractMotionController, IMotionControllerProfile,
-} from './webXRAbstractController';
+} from './webXRAbstractMotionController';
 import { WebXRGenericTriggerMotionController } from './webXRGenericMotionController';
 import { Scene } from '../../scene';
 import { Tools } from '../../Misc/tools';

+ 2 - 2
src/XR/motionController/webXROculusTouchMotionController.ts

@@ -3,7 +3,7 @@ import {
     IMinimalMotionControllerObject,
     MotionControllerHandness,
     IMotionControllerLayoutMap
-} from "./webXRAbstractController";
+} from "./webXRAbstractMotionController";
 import { WebXRMotionControllerManager } from './webXRMotionControllerManager';
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { Scene } from '../../scene';
@@ -53,7 +53,7 @@ export class WebXROculusTouchMotionController extends WebXRAbstractMotionControl
         this.getComponentIds().forEach((id) => {
             const comp = id && this.getComponent(id);
             if (comp) {
-                comp.onButtonStateChanged.add((component) => {
+                comp.onButtonStateChangedObservable.add((component) => {
 
                     if (!this.rootMesh || this.disableAnimation) { return; }
 

+ 1 - 1
src/XR/motionController/webXRProfiledMotionController.ts

@@ -1,5 +1,5 @@
 import { AbstractMesh } from '../../Meshes/abstractMesh';
-import { WebXRAbstractMotionController, IMotionControllerProfile, IMotionControllerMeshMap } from './webXRAbstractController';
+import { WebXRAbstractMotionController, IMotionControllerProfile, IMotionControllerMeshMap } from './webXRAbstractMotionController';
 import { Scene } from '../../scene';
 import { SceneLoader } from '../../Loading/sceneLoader';
 import { Mesh } from '../../Meshes/mesh';

+ 113 - 127
src/XR/webXRCamera.ts

@@ -8,41 +8,26 @@ import { Viewport } from '../Maths/math.viewport';
 
 /**
  * WebXR Camera which holds the views for the xrSession
- * @see https://doc.babylonjs.com/how_to/webxr
+ * @see https://doc.babylonjs.com/how_to/webxr_camera
  */
 export class WebXRCamera extends FreeCamera {
-
-    /**
-     * Should position compensation execute on first frame.
-     * This is used when copying the position from a native (non XR) camera
-     */
-    public compensateOnFirstFrame: boolean = true;
-
     private _firstFrame = false;
-    private _referencedPosition: Vector3 = new Vector3();
     private _referenceQuaternion: Quaternion = Quaternion.Identity();
+    private _referencedPosition: Vector3 = new Vector3();
     private _xrInvPositionCache: Vector3 = new Vector3();
     private _xrInvQuaternionCache = Quaternion.Identity();
 
-    private _realWorldHeight: number = 0;
-
     /**
-     * Prevent the camera from calculating the real-world height
-     * If you are not using the user's height disable this for better performance
-     */
-    public disableRealWorldHeightCalculation: boolean = false;
-
-    /**
-     * Return the user's height, unrelated to the current ground.
+     * Should position compensation execute on first frame.
+     * This is used when copying the position from a native (non XR) camera
      */
-    public get realWorldHeight(): number {
-        return this._realWorldHeight;
-    }
+    public compensateOnFirstFrame: boolean = true;
 
     /**
      * Creates a new webXRCamera, this should only be set at the camera after it has been updated by the xrSessionManager
      * @param name the name of the camera
      * @param scene the scene to add the camera to
+     * @param _xrSessionManager a constructed xr session manager
      */
     constructor(name: string, scene: Scene, private _xrSessionManager: WebXRSessionManager) {
         super(name, Vector3.Zero(), scene);
@@ -73,24 +58,31 @@ export class WebXRCamera extends FreeCamera {
         }, undefined, true);
     }
 
-    private _updateNumberOfRigCameras(viewCount = 1) {
-        while (this.rigCameras.length < viewCount) {
-            var newCamera = new TargetCamera("XR-RigCamera: " + this.rigCameras.length, Vector3.Zero(), this.getScene());
-            newCamera.minZ = 0.1;
-            newCamera.rotationQuaternion = new Quaternion();
-            newCamera.updateUpVectorFromRotation = true;
-            newCamera.isRigCamera = true;
-            newCamera.rigParent = this;
-            this.rigCameras.push(newCamera);
-        }
-        while (this.rigCameras.length > viewCount) {
-            var removedCamera = this.rigCameras.pop();
-            if (removedCamera) {
-                removedCamera.dispose();
-            }
+    /**
+     * Return the user's height, unrelated to the current ground.
+     * This will be the y position of this camera, when ground level is 0.
+     */
+    public get realWorldHeight(): number {
+        const basePose = this._xrSessionManager.currentFrame && this._xrSessionManager.currentFrame.getViewerPose(this._xrSessionManager.baseReferenceSpace);
+        if (basePose && basePose.transform) {
+            return basePose.transform.position.y;
+        } else {
+            return 0;
         }
     }
 
+    /** @hidden */
+    public _updateForDualEyeDebugging(/*pupilDistance = 0.01*/) {
+        // Create initial camera rigs
+        this._updateNumberOfRigCameras(2);
+        this.rigCameras[0].viewport = new Viewport(0, 0, 0.5, 1.0);
+        // this.rigCameras[0].position.x = -pupilDistance / 2;
+        this.rigCameras[0].outputRenderTarget = null;
+        this.rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
+        // this.rigCameras[1].position.x = pupilDistance / 2;
+        this.rigCameras[1].outputRenderTarget = null;
+    }
+
     /**
      * Sets this camera's transformation based on a non-vr camera
      * @param otherCamera the non-vr camera to copy the transformation from
@@ -111,97 +103,7 @@ export class WebXRCamera extends FreeCamera {
         }
     }
 
-    /** @hidden */
-    public _updateForDualEyeDebugging(/*pupilDistance = 0.01*/) {
-        // Create initial camera rigs
-        this._updateNumberOfRigCameras(2);
-        this.rigCameras[0].viewport = new Viewport(0, 0, 0.5, 1.0);
-        // this.rigCameras[0].position.x = -pupilDistance / 2;
-        this.rigCameras[0].outputRenderTarget = null;
-        this.rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
-        // this.rigCameras[1].position.x = pupilDistance / 2;
-        this.rigCameras[1].outputRenderTarget = null;
-    }
-
-    private _updateReferenceSpace() {
-        // were position & rotation updated OUTSIDE of the xr update loop
-        if (!this.position.equals(this._referencedPosition) || !this.rotationQuaternion.equals(this._referenceQuaternion)) {
-            this.position.subtractToRef(this._referencedPosition, this._referencedPosition);
-            this._referenceQuaternion.conjugateInPlace();
-            this._referenceQuaternion.multiplyToRef(this.rotationQuaternion, this._referenceQuaternion);
-            this._updateReferenceSpaceOffset(this._referencedPosition, this._referenceQuaternion.normalize());
-        }
-    }
-
-    private _updateReferenceSpaceOffset(positionOffset: Vector3, rotationOffset?: Quaternion, ignoreHeight: boolean = false) {
-        if (!this._xrSessionManager.referenceSpace || !this._xrSessionManager.currentFrame) {
-            return;
-        }
-        // Compute the origin offset based on player position/orientation.
-        this._xrInvPositionCache.copyFrom(positionOffset);
-        if (rotationOffset) {
-            this._xrInvQuaternionCache.copyFrom(rotationOffset);
-        } else {
-            this._xrInvQuaternionCache.copyFromFloats(0, 0, 0, 1);
-        }
-
-        // right handed system
-        if (!this._scene.useRightHandedSystem) {
-            this._xrInvPositionCache.z *= -1;
-            this._xrInvQuaternionCache.z *= -1;
-            this._xrInvQuaternionCache.w *= -1;
-        }
-
-        this._xrInvPositionCache.negateInPlace();
-        this._xrInvQuaternionCache.conjugateInPlace();
-        // transform point according to rotation with pivot
-        this._xrInvPositionCache.rotateByQuaternionToRef(this._xrInvQuaternionCache, this._xrInvPositionCache);
-        if (ignoreHeight) {
-            this._xrInvPositionCache.y = 0;
-        }
-        const transform = new XRRigidTransform(
-            { ...this._xrInvPositionCache },
-            { ...this._xrInvQuaternionCache });
-        // Update offset reference to use a new originOffset with the teleported
-        // player position and orientation.
-        // This new offset needs to be applied to the base ref space.
-        const referenceSpace = this._xrSessionManager.referenceSpace.getOffsetReferenceSpace(transform);
-
-        const pose = this._xrSessionManager.currentFrame && this._xrSessionManager.currentFrame.getViewerPose(referenceSpace);
-
-        if (pose) {
-            const pos = new Vector3();
-            pos.copyFrom(<any>(pose.transform.position));
-            if (!this._scene.useRightHandedSystem) {
-                pos.z *= -1;
-            }
-            this.position.subtractToRef(pos, pos);
-            if (!this._scene.useRightHandedSystem) {
-                pos.z *= -1;
-            }
-            pos.negateInPlace();
-
-            const transform2 = new XRRigidTransform(
-                { ...pos });
-            // Update offset reference to use a new originOffset with the teleported
-            // player position and orientation.
-            // This new offset needs to be applied to the base ref space.
-            this._xrSessionManager.referenceSpace = referenceSpace.getOffsetReferenceSpace(transform2);
-        }
-    }
-
     private _updateFromXRSession() {
-
-        // user height
-        if (!this.disableRealWorldHeightCalculation) {
-            const basePose = this._xrSessionManager.currentFrame && this._xrSessionManager.currentFrame.getViewerPose(this._xrSessionManager.baseReferenceSpace);
-            if (basePose && basePose.transform) {
-                this._realWorldHeight = basePose.transform.position.y;
-            }
-        } else {
-            this._realWorldHeight = 0;
-        }
-
         const pose = this._xrSessionManager.currentFrame && this._xrSessionManager.currentFrame.getViewerPose(this._xrSessionManager.referenceSpace);
 
         if (!pose) {
@@ -227,7 +129,6 @@ export class WebXRCamera extends FreeCamera {
                 // avoid using the head rotation on the first frame.
                 this._referenceQuaternion.copyFromFloats(0, 0, 0, 1);
                 // update the reference space so that the position will be correct
-
             }
             else {
                 this.rotationQuaternion.copyFrom(this._referenceQuaternion);
@@ -286,4 +187,89 @@ export class WebXRCamera extends FreeCamera {
             currentRig.outputRenderTarget = this._xrSessionManager.getRenderTargetTextureForEye(view.eye);
         });
     }
+
+    private _updateNumberOfRigCameras(viewCount = 1) {
+        while (this.rigCameras.length < viewCount) {
+            var newCamera = new TargetCamera("XR-RigCamera: " + this.rigCameras.length, Vector3.Zero(), this.getScene());
+            newCamera.minZ = 0.1;
+            newCamera.rotationQuaternion = new Quaternion();
+            newCamera.updateUpVectorFromRotation = true;
+            newCamera.isRigCamera = true;
+            newCamera.rigParent = this;
+            this.rigCameras.push(newCamera);
+        }
+        while (this.rigCameras.length > viewCount) {
+            var removedCamera = this.rigCameras.pop();
+            if (removedCamera) {
+                removedCamera.dispose();
+            }
+        }
+    }
+
+    private _updateReferenceSpace() {
+        // were position & rotation updated OUTSIDE of the xr update loop
+        if (!this.position.equals(this._referencedPosition) || !this.rotationQuaternion.equals(this._referenceQuaternion)) {
+            this.position.subtractToRef(this._referencedPosition, this._referencedPosition);
+            this._referenceQuaternion.conjugateInPlace();
+            this._referenceQuaternion.multiplyToRef(this.rotationQuaternion, this._referenceQuaternion);
+            this._updateReferenceSpaceOffset(this._referencedPosition, this._referenceQuaternion.normalize());
+        }
+    }
+
+    private _updateReferenceSpaceOffset(positionOffset: Vector3, rotationOffset?: Quaternion, ignoreHeight: boolean = false) {
+        if (!this._xrSessionManager.referenceSpace || !this._xrSessionManager.currentFrame) {
+            return;
+        }
+        // Compute the origin offset based on player position/orientation.
+        this._xrInvPositionCache.copyFrom(positionOffset);
+        if (rotationOffset) {
+            this._xrInvQuaternionCache.copyFrom(rotationOffset);
+        } else {
+            this._xrInvQuaternionCache.copyFromFloats(0, 0, 0, 1);
+        }
+
+        // right handed system
+        if (!this._scene.useRightHandedSystem) {
+            this._xrInvPositionCache.z *= -1;
+            this._xrInvQuaternionCache.z *= -1;
+            this._xrInvQuaternionCache.w *= -1;
+        }
+
+        this._xrInvPositionCache.negateInPlace();
+        this._xrInvQuaternionCache.conjugateInPlace();
+        // transform point according to rotation with pivot
+        this._xrInvPositionCache.rotateByQuaternionToRef(this._xrInvQuaternionCache, this._xrInvPositionCache);
+        if (ignoreHeight) {
+            this._xrInvPositionCache.y = 0;
+        }
+        const transform = new XRRigidTransform(
+            { ...this._xrInvPositionCache },
+            { ...this._xrInvQuaternionCache });
+        // Update offset reference to use a new originOffset with the teleported
+        // player position and orientation.
+        // This new offset needs to be applied to the base ref space.
+        const referenceSpace = this._xrSessionManager.referenceSpace.getOffsetReferenceSpace(transform);
+
+        const pose = this._xrSessionManager.currentFrame && this._xrSessionManager.currentFrame.getViewerPose(referenceSpace);
+
+        if (pose) {
+            const pos = new Vector3();
+            pos.copyFrom(<any>(pose.transform.position));
+            if (!this._scene.useRightHandedSystem) {
+                pos.z *= -1;
+            }
+            this.position.subtractToRef(pos, pos);
+            if (!this._scene.useRightHandedSystem) {
+                pos.z *= -1;
+            }
+            pos.negateInPlace();
+
+            const transform2 = new XRRigidTransform(
+                { ...pos });
+            // Update offset reference to use a new originOffset with the teleported
+            // player position and orientation.
+            // This new offset needs to be applied to the base ref space.
+            this._xrSessionManager.referenceSpace = referenceSpace.getOffsetReferenceSpace(transform2);
+        }
+    }
 }

+ 7 - 7
src/XR/webXRInput.ts

@@ -1,7 +1,7 @@
 import { Nullable } from "../types";
 import { Observer, Observable } from "../Misc/observable";
 import { IDisposable } from "../scene";
-import { WebXRController } from './webXRController';
+import { WebXRInputSource } from './webXRInputSource';
 import { WebXRSessionManager } from './webXRSessionManager';
 import { WebXRCamera } from './webXRCamera';
 import { WebXRMotionControllerManager } from './motionController/webXRMotionControllerManager';
@@ -46,18 +46,18 @@ export class WebXRInput implements IDisposable {
     /**
      * XR controllers being tracked
      */
-    public controllers: Array<WebXRController> = [];
+    public controllers: Array<WebXRInputSource> = [];
     private _frameObserver: Nullable<Observer<any>>;
     private _sessionEndedObserver: Nullable<Observer<any>>;
     private _sessionInitObserver: Nullable<Observer<any>>;
     /**
      * Event when a controller has been connected/added
      */
-    public onControllerAddedObservable = new Observable<WebXRController>();
+    public onControllerAddedObservable = new Observable<WebXRInputSource>();
     /**
      * Event when a controller has been removed/disconnected
      */
-    public onControllerRemovedObservable = new Observable<WebXRController>();
+    public onControllerRemovedObservable = new Observable<WebXRInputSource>();
 
     /**
      * Initializes the WebXRInput
@@ -114,7 +114,7 @@ export class WebXRInput implements IDisposable {
         let sources = this.controllers.map((c) => { return c.inputSource; });
         for (let input of addInputs) {
             if (sources.indexOf(input) === -1) {
-                let controller = new WebXRController(this.xrSessionManager.scene, input, {
+                let controller = new WebXRInputSource(this.xrSessionManager.scene, input, {
                     forceControllerProfile: this.options.forceInputProfile,
                     doNotLoadControllerMesh: this.options.doNotLoadControllerMeshes,
                     disableMotionControllerAnimation: this.options.disableControllerAnimation
@@ -125,8 +125,8 @@ export class WebXRInput implements IDisposable {
         }
 
         // Remove and dispose of controllers to be disposed
-        let keepControllers: Array<WebXRController> = [];
-        let removedControllers: Array<WebXRController> = [];
+        let keepControllers: Array<WebXRInputSource> = [];
+        let removedControllers: Array<WebXRInputSource> = [];
         this.controllers.forEach((c) => {
             if (removeInputs.indexOf(c.inputSource) === -1) {
                 keepControllers.push(c);

+ 9 - 7
src/XR/webXRController.ts

@@ -3,7 +3,7 @@ import { AbstractMesh } from "../Meshes/abstractMesh";
 import { Quaternion, Vector3 } from '../Maths/math.vector';
 import { Ray } from '../Culling/ray';
 import { Scene } from '../scene';
-import { WebXRAbstractMotionController } from './motionController/webXRAbstractController';
+import { WebXRAbstractMotionController } from './motionController/webXRAbstractMotionController';
 import { WebXRMotionControllerManager } from './motionController/webXRMotionControllerManager';
 
 let idCount = 0;
@@ -33,7 +33,7 @@ export interface IWebXRControllerOptions {
 /**
  * Represents an XR controller
  */
-export class WebXRController {
+export class WebXRInputSource {
     /**
      * 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
      */
@@ -66,7 +66,7 @@ export class WebXRController {
      * The object provided as event data is this controller, after associated assets were disposed.
      * uniqueId is still available.
      */
-    public onDisposeObservable = new Observable<WebXRController>();
+    public onDisposeObservable = new Observable<WebXRInputSource>();
 
     private _tmpQuaternion = new Quaternion();
     private _tmpVector = new Vector3();
@@ -159,15 +159,17 @@ export class WebXRController {
     }
 
     /**
-     * Gets a world space ray coming from the controller
+     * Gets a world space ray coming from the pointer or grip
      * @param result the resulting ray
+     * @param gripIfAvailable use the grip mesh instead of the pointer, if available
      */
-    public getWorldPointerRayToRef(result: Ray) {
-        let worldMatrix = this.pointer.computeWorldMatrix();
+    public getWorldPointerRayToRef(result: Ray, gripIfAvailable: boolean = false) {
+        const object = gripIfAvailable && this.grip ? this.grip : this.pointer;
+        let worldMatrix = object.computeWorldMatrix();
         worldMatrix.decompose(undefined, this._tmpQuaternion, undefined);
         this._tmpVector.set(0, 0, 1);
         this._tmpVector.rotateByQuaternionToRef(this._tmpQuaternion, this._tmpVector);
-        result.origin.copyFrom(this.pointer.absolutePosition);
+        result.origin.copyFrom(object.absolutePosition);
         result.direction.copyFrom(this._tmpVector);
         result.length = 1000;
     }