Bläddra i källkod

Merge pull request #3693 from TrevorDev/webVRAsyncMethods

Web vr async methods
Raanan Weber 7 år sedan
förälder
incheckning
8e0c76fb6b

+ 1 - 0
dist/preview release/what's new.md

@@ -66,6 +66,7 @@
 - Added promise-based async functions to the SceneLoader, Scene.whenReadyAsync, and material.forceCompilationAsync. ([bghgary](https://github.com/bghgary)]
 - Added checks to VertexData.merge to ensure data is valid before merging. ([bghgary](https://github.com/bghgary)]
 - Ability to set a mesh to customize the webVR gaze tracker ([trevordev](https://github.com/trevordev))
+- Added promise-based async functions for initWebVRAsync and useStandingMatrixAsync ([trevordev](https://github.com/trevordev))
 - Add stroke (outline) options on GUI text control ([SvenFrankson](https://github.com/SvenFrankson))
 - Add floating point texture support for RenderTargetCubeTexture ([PeapBoy](https://github.com/NicolasBuecher))
 

+ 3 - 4
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -207,15 +207,14 @@ module BABYLON {
         }
 
         /**
-         * The mesh used to display where the user is selecting.
+         * The mesh used to display where the user is selecting, 
+         * when set bakeCurrentTransformIntoVertices will be called on the mesh.
+         * See http://doc.babylonjs.com/resources/baking_transformations 
          */
         public get gazeTrackerMesh(): Mesh {
             return this._gazeTracker;
         }
 
-        /**
-         * Sets the mesh to be used to display where the user is selecting.
-         */
         public set gazeTrackerMesh(value: Mesh) {
             if (value) {
                 this._gazeTracker = value;

+ 30 - 22
src/Cameras/VR/babylon.webVRCamera.ts

@@ -114,7 +114,7 @@ module BABYLON {
         rayLength?: number;
 
         /**
-         * To change the default offset from the ground to account for user's height. (default: 1.7)
+         * To change the default offset from the ground to account for user's height in meters. (default: 1.7)
          */
         defaultHeight?: number;
 
@@ -282,11 +282,11 @@ module BABYLON {
         }
 
         /**
-         * Gets the device distance from the ground.
-         * @returns the distance from the vrDevice to ground in device space. If standing matrix is not supported for the vrDevice 0 is returned.
+         * Gets the device distance from the ground in meters.
+         * @returns the distance in meters from the vrDevice to ground in device space. If standing matrix is not supported for the vrDevice 0 is returned.
          */
         public deviceDistanceToRoomGround(): number {
-            if (this._standingMatrix && this._defaultHeight === undefined) {
+            if (this._standingMatrix) {
                 // Add standing matrix offset to get real offset from ground in room
                 this._standingMatrix.getTranslationToRef(this._workingVector);
                 return this._deviceRoomPosition.y + this._workingVector.y
@@ -301,26 +301,34 @@ module BABYLON {
          */
         public useStandingMatrix(callback = (bool: boolean) => { }) {
             // Use standing matrix if available
-            if (!navigator || !navigator.getVRDisplays) {
-                callback(false);
-            } else {
-                navigator.getVRDisplays().then((displays: any) => {
-                    if (!displays || !displays[0] || !displays[0].stageParameters || !displays[0].stageParameters.sittingToStandingTransform) {
-                        callback(false);
-                    } else {
-                        this._standingMatrix = new Matrix();
-                        Matrix.FromFloat32ArrayToRefScaled(displays[0].stageParameters.sittingToStandingTransform, 0, 1, this._standingMatrix);
-                        if (!this.getScene().useRightHandedSystem) {
-                            [2, 6, 8, 9, 14].forEach((num) => {
-                                if (this._standingMatrix) {
-                                    this._standingMatrix.m[num] *= -1;
-                                }
-                            });
-                        }
-                        callback(true);
+            this.getEngine().initWebVRAsync().then((result)=>{
+                if (!result.vrDisplay || !result.vrDisplay.stageParameters || !result.vrDisplay.stageParameters.sittingToStandingTransform) {
+                    callback(false);
+                } else {
+                    this._standingMatrix = new Matrix();
+                    Matrix.FromFloat32ArrayToRefScaled(result.vrDisplay.stageParameters.sittingToStandingTransform, 0, 1, this._standingMatrix);
+                    if (!this.getScene().useRightHandedSystem) {
+                        [2, 6, 8, 9, 14].forEach((num) => {
+                            if (this._standingMatrix) {
+                                this._standingMatrix.m[num] *= -1;
+                            }
+                        });
                     }
+                    callback(true);
+                }
+            });
+        }
+
+        /**
+         * Enables the standing matrix when supported. This can be used to position the user's view the correct height from the ground.
+         * @returns A promise with a boolean set to if the standing matrix is supported.
+         */
+        public useStandingMatrixAsync():Promise<boolean> {
+            return new Promise((res, rej)=>{
+                this.useStandingMatrix((supported)=>{
+                    res(supported);
                 });
-            }
+            });
         }
 
         /**

+ 43 - 25
src/Engine/babylon.engine.ts

@@ -270,7 +270,7 @@
     }
 
     export interface IDisplayChangedEventArgs {
-        vrDisplay: any;
+        vrDisplay: Nullable<any>;
         vrSupported: boolean;
     }
 
@@ -619,6 +619,7 @@
         private _oldSize: Size;
         private _oldHardwareScaleFactor: number;
         private _vrExclusivePointerMode = false;
+        private _webVRInitPromise: Promise<IDisplayChangedEventArgs>;
 
         public get isInVRExclusivePointerMode(): boolean {
             return this._vrExclusivePointerMode;
@@ -1809,13 +1810,29 @@
             return this._vrDisplay;
         }
 
-        public initWebVR(): Observable<{ vrDisplay: any, vrSupported: any }> {
+        /**
+         * Initializes a webVR display and starts listening to display change events.
+         * The onVRDisplayChangedObservable will be notified upon these changes.
+         * @returns The onVRDisplayChangedObservable.
+         */
+        public initWebVR(): Observable<IDisplayChangedEventArgs> {
+            this.initWebVRAsync();
+            return this.onVRDisplayChangedObservable;
+        }
+
+        /**
+         * Initializes a webVR display and starts listening to display change events.
+         * The onVRDisplayChangedObservable will be notified upon these changes.
+         * @returns A promise containing a VRDisplay and if vr is supported.
+         */
+        public initWebVRAsync(): Promise<IDisplayChangedEventArgs> {
             var notifyObservers = () => {
                 var eventArgs = {
                     vrDisplay: this._vrDisplay,
                     vrSupported: this._vrSupported
                 };
                 this.onVRDisplayChangedObservable.notifyObservers(eventArgs);
+                this._webVRInitPromise = new Promise((res)=>{res(eventArgs)});
             }
 
             if (!this._onVrDisplayConnect) {
@@ -1836,10 +1853,9 @@
                 window.addEventListener('vrdisplaydisconnect', this._onVrDisplayDisconnect);
                 window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
             }
-
-            this._getVRDisplays(notifyObservers);
-
-            return this.onVRDisplayChangedObservable;
+            this._webVRInitPromise = this._webVRInitPromise || this._getVRDisplaysAsync();
+            this._webVRInitPromise.then(notifyObservers);
+            return this._webVRInitPromise;
         }
 
         public enableVR() {
@@ -1879,26 +1895,28 @@
             }
         }
 
-        private _getVRDisplays(callback: () => void) {
-            var getWebVRDevices = (devices: Array<any>) => {
-                this._vrSupported = true;
-                // note that devices may actually be an empty array. This is fine;
-                // we expect this._vrDisplay to be undefined in this case.
-                return this._vrDisplay = devices[0];
-            }
-
-            if (navigator.getVRDisplays) {
-                navigator.getVRDisplays().then(getWebVRDevices).then(callback).catch((error: () => void) => {
-                    // TODO: System CANNOT support WebVR, despite API presence.
+        private _getVRDisplaysAsync():Promise<IDisplayChangedEventArgs> {
+            return new Promise((res, rej)=>{    
+                if (navigator.getVRDisplays) {
+                    navigator.getVRDisplays().then((devices: Array<any>)=>{
+                        this._vrSupported = true;
+                        // note that devices may actually be an empty array. This is fine;
+                        // we expect this._vrDisplay to be undefined in this case.
+                        this._vrDisplay = devices[0];
+                        res({
+                            vrDisplay: this._vrDisplay,
+                            vrSupported: this._vrSupported
+                        });
+                    });
+                } else {
+                    this._vrDisplay = undefined;
                     this._vrSupported = false;
-                    callback();
-                });
-            } else {
-                // TODO: Browser does not support WebVR
-                this._vrDisplay = undefined;
-                this._vrSupported = false;
-                callback();
-            }
+                    res({
+                        vrDisplay: this._vrDisplay,
+                        vrSupported: this._vrSupported
+                    });
+                }
+            });
         }
 
         public bindFramebuffer(texture: InternalTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number, forceFullscreenViewport?: boolean): void {