瀏覽代碼

Implemented VR observables in Viewer and SceneManager to address issue here VRExperienceHelper (and its observables) is overwritten. Code still needs to be commented and cleaned.

Atulya Ravishankar 7 年之前
父節點
當前提交
04cb5ed694

+ 10 - 0
Viewer/src/managers/observablesManager.ts

@@ -54,6 +54,10 @@ export class ObservablesManager {
      */
     public onFrameRenderedObservable: Observable<any>;
 
+
+    public onEnteringVRObservable: Observable<any>;
+    public onExitingVRObservable: Observable<any>;
+
     constructor() {
         this.onSceneInitObservable = new Observable();
         this.onEngineInitObservable = new Observable();
@@ -66,6 +70,9 @@ export class ObservablesManager {
         this.onViewerInitStartedObservable = new Observable();
         this.onLoaderInitObservable = new Observable();
         this.onFrameRenderedObservable = new Observable();
+
+        this.onEnteringVRObservable = new Observable();
+        this.onExitingVRObservable = new Observable();
     }
 
     dispose() {
@@ -79,6 +86,9 @@ export class ObservablesManager {
         this.onViewerInitDoneObservable.clear();
         this.onLoaderInitObservable.clear();
         this.onFrameRenderedObservable.clear();
+
+        this.onEnteringVRObservable.clear();
+        this.onExitingVRObservable.clear();
     }
 
 }

+ 16 - 1
Viewer/src/managers/sceneManager.ts

@@ -59,6 +59,9 @@ export class SceneManager {
      */
     onVRConfiguredObservable: Observable<IPostConfigurationCallback<VRExperienceHelper, IVRConfiguration>>;
 
+    onEnteringVRObservable: Observable<any>;
+    onExitingVRObservable: Observable<any>;
+
     /**
      * The Babylon Scene of this viewer
      */
@@ -134,6 +137,9 @@ export class SceneManager {
         this.onEnvironmentConfiguredObservable = new Observable();
         this.onVRConfiguredObservable = new Observable();
 
+        this.onEnteringVRObservable = new Observable();
+        this.onExitingVRObservable = new Observable();
+
         //this._viewer.onEngineInitObservable.add(() => {
         this._handleHardwareLimitations();
         //});
@@ -798,6 +804,12 @@ export class SceneManager {
                 });
             });
         }
+        this._vrHelper.onEnteringVRObservable.add(() => {
+            this.onEnteringVRObservable.notifyObservers(this);
+        });
+        this._vrHelper.onExitingVRObservable.add(() => {
+            this.onExitingVRObservable.notifyObservers(this);
+        });
         this.onVRConfiguredObservable.notifyObservers({
             sceneManager: this,
             object: this._vrHelper,
@@ -933,7 +945,7 @@ export class SceneManager {
         this.camera.beta = (this._globalConfiguration.camera && this._globalConfiguration.camera.beta) || this.camera.beta;
         this.camera.radius = (this._globalConfiguration.camera && this._globalConfiguration.camera.radius) || this.camera.radius;
 
-        const sceneDiagonalLenght = sizeVec.length();
+        const sceneDiagonalLenght = sizeVec.length(); 
         if (isFinite(sceneDiagonalLenght))
             this.camera.upperRadiusLimit = sceneDiagonalLenght * 4;
 
@@ -1420,6 +1432,9 @@ export class SceneManager {
         this.onSceneOptimizerConfiguredObservable.clear();
         this.onVRConfiguredObservable.clear();
 
+        this.onEnteringVRObservable.clear();
+        this.onExitingVRObservable.clear();
+
         if (this.sceneOptimizer) {
             this.sceneOptimizer.stop();
             this.sceneOptimizer.dispose();

+ 99 - 22
Viewer/src/viewer/viewer.ts

@@ -1,4 +1,4 @@
-import { Database, Effect, Engine, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Observable, RenderingManager, Scene, SceneLoaderProgressEvent, TargetCamera, Tools, Vector3 } from 'babylonjs';
+import { Database, Effect, Engine, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Observable, RenderingManager, Scene, SceneLoaderProgressEvent, TargetCamera, Tools, Vector3, Observer } from 'babylonjs';
 import { IModelConfiguration, IObserversConfiguration, ViewerConfiguration } from '../configuration/';
 import { processConfigurationCompatibility } from '../configuration/configurationCompatibility';
 import { ConfigurationContainer } from '../configuration/configurationContainer';
@@ -121,6 +121,13 @@ export abstract class AbstractViewer {
         return this.observablesManager.onFrameRenderedObservable;
     }
 
+    public get onEnteringVRObservable(): Observable<AbstractViewer> {
+        return this.observablesManager.onEnteringVRObservable;
+    }
+    public get onExitingVRObservable(): Observable<AbstractViewer> {
+        return this.observablesManager.onExitingVRObservable;
+    }
+
     public observablesManager: ObservablesManager;
 
     /**
@@ -146,6 +153,7 @@ export abstract class AbstractViewer {
      * This functions are also registered at the native scene. The reference can be used to unregister them.
      */
     protected _registeredOnBeforeRenderFunctions: Array<() => void>;
+
     /**
      * The configuration loader of this viewer
      */
@@ -264,17 +272,63 @@ export abstract class AbstractViewer {
 
     protected _vrInit: boolean = false;
 
+    // private upscaleModelAndEnvironment() {
+    //     // scale the model
+    //     if (this.sceneManager.models.length) {
+    //         let boundingVectors = this.sceneManager.models[0].rootMesh.getHierarchyBoundingVectors();
+    //         let sizeVec = boundingVectors.max.subtract(boundingVectors.min);
+    //         let maxDimension = Math.max(sizeVec.x, sizeVec.y, sizeVec.z);
+    //         this._vrScale = (1 / maxDimension);
+    //         if (this.configuration.vr && this.configuration.vr.objectScaleFactor) {
+    //             this._vrScale *= this.configuration.vr.objectScaleFactor;
+    //         }
+
+    //         this.sceneManager.models[0].rootMesh.scaling.scaleInPlace(this._vrScale);
+
+    //         // reposition the object to "float" in front of the user
+    //         this.sceneManager.models[0].rootMesh.position.y += this._vrModelRepositioning;
+    //         this.sceneManager.models[0].rootMesh.rotationQuaternion = null;
+    //     }
+
+    //     // scale the environment to match the model
+    //     if (this.sceneManager.environmentHelper) {
+    //         this.sceneManager.environmentHelper.ground && this.sceneManager.environmentHelper.ground.scaling.scaleInPlace(this._vrScale);
+    //         this.sceneManager.environmentHelper.skybox && this.sceneManager.environmentHelper.skybox.scaling.scaleInPlace(this._vrScale);
+    //     }
+    // }
+
+    // private downscaleModelAndEnvironment() {
+    //     // undo the scaling of the model
+    //     if (this.sceneManager.models.length) {
+    //         this.sceneManager.models[0].rootMesh.scaling.scaleInPlace(1 / this._vrScale);
+    //         this.sceneManager.models[0].rootMesh.position.y -= this._vrModelRepositioning;
+    //     }
+
+    //     // undo the scaling of the environment
+    //     if (this.sceneManager.environmentHelper) {
+    //         this.sceneManager.environmentHelper.ground && this.sceneManager.environmentHelper.ground.scaling.scaleInPlace(1 / this._vrScale);
+    //         this.sceneManager.environmentHelper.skybox && this.sceneManager.environmentHelper.skybox.scaling.scaleInPlace(1 / this._vrScale);
+    //     }
+    // }
+
     public toggleVR() {
         if (!this._vrInit) {
             this._initVR();
         }
 
         if (this.sceneManager.vrHelper && !this.sceneManager.vrHelper.isInVRMode) {
+
+            //this.sceneManager.onEnteringVRObservable.remove(o)
+            // this.sceneManager.onEnteringVRObservable.add(() => {
+            //     this.onEnteringVRObservable.notifyObservers(this);
+            // });
+
             // make sure the floor is set
             if (this.sceneManager.environmentHelper && this.sceneManager.environmentHelper.ground) {
                 this.sceneManager.vrHelper.addFloorMesh(this.sceneManager.environmentHelper.ground);
             }
 
+            this._vrToggled = true;
             this.sceneManager.vrHelper.enterVR();
 
             // position the vr camera to be in front of the object or wherever the user has configured it to be
@@ -296,6 +350,8 @@ export abstract class AbstractViewer {
                     }
                 }
 
+                console.log("upscaling");
+
                 // scale the model
                 if (this.sceneManager.models.length) {
                     let boundingVectors = this.sceneManager.models[0].rootMesh.getHierarchyBoundingVectors();
@@ -337,29 +393,41 @@ export abstract class AbstractViewer {
     protected _initVR() {
 
         if (this.sceneManager.vrHelper) {
-            this.sceneManager.vrHelper.onExitingVR.add(() => {
-                // undo the scaling of the model
-                if (this.sceneManager.models.length) {
-                    this.sceneManager.models[0].rootMesh.scaling.scaleInPlace(1 / this._vrScale);
-                    this.sceneManager.models[0].rootMesh.position.y -= this._vrModelRepositioning;
-                }
+            this.sceneManager.onExitingVRObservable.add(() => {
+                if (this._vrToggled) {
+
+                    //this.sceneManager.onExitingVRObservable.remove(o)
+                    // var o = this.sceneManager.onExitingVRObservable.add(() => {
+                    //     this.onExitingVRObservable.notifyObservers(this);
+                    // });
+
+                    console.log("downscaling");
+
+                    this._vrToggled = false;
+                    
+                    // undo the scaling of the model
+                    if (this.sceneManager.models.length) {
+                        this.sceneManager.models[0].rootMesh.scaling.scaleInPlace(1 / this._vrScale);
+                        this.sceneManager.models[0].rootMesh.position.y -= this._vrModelRepositioning;
+                    }
 
-                // undo the scaling of the environment
-                if (this.sceneManager.environmentHelper) {
-                    this.sceneManager.environmentHelper.ground && this.sceneManager.environmentHelper.ground.scaling.scaleInPlace(1 / this._vrScale);
-                    this.sceneManager.environmentHelper.skybox && this.sceneManager.environmentHelper.skybox.scaling.scaleInPlace(1 / this._vrScale);
-                }
+                    // undo the scaling of the environment
+                    if (this.sceneManager.environmentHelper) {
+                        this.sceneManager.environmentHelper.ground && this.sceneManager.environmentHelper.ground.scaling.scaleInPlace(1 / this._vrScale);
+                        this.sceneManager.environmentHelper.skybox && this.sceneManager.environmentHelper.skybox.scaling.scaleInPlace(1 / this._vrScale);
+                    }
 
-                // post processing
-                if (this.sceneManager.defaultRenderingPipelineEnabled && this.sceneManager.defaultRenderingPipeline) {
-                    this.sceneManager.defaultRenderingPipeline.imageProcessingEnabled = true;
-                    this.sceneManager.defaultRenderingPipeline.prepare();
-                }
+                    // post processing
+                    if (this.sceneManager.defaultRenderingPipelineEnabled && this.sceneManager.defaultRenderingPipeline) {
+                        this.sceneManager.defaultRenderingPipeline.imageProcessingEnabled = true;
+                        this.sceneManager.defaultRenderingPipeline.prepare();
+                    }
 
-                // clear set height and eidth
-                this.canvas.removeAttribute("height");
-                this.canvas.removeAttribute("width");
-                this.engine.resize();
+                    // clear set height and eidth
+                    this.canvas.removeAttribute("height");
+                    this.canvas.removeAttribute("width");
+                    this.engine.resize();
+                }
             })
         }
 
@@ -531,7 +599,7 @@ export abstract class AbstractViewer {
     }
 
     /**
-     * Dispoe the entire viewer including the scene and the engine
+     * Dispose the entire viewer including the scene and the engine
      */
     public dispose() {
         if (this._isDisposed) {
@@ -653,6 +721,15 @@ export abstract class AbstractViewer {
 
         // create a new template manager for this viewer
         this.sceneManager = new SceneManager(this.engine, this._configurationContainer, this.observablesManager);
+        
+        // //this.sceneManager.onEnteringVRObservable.remove(o)
+        var o = this.sceneManager.onEnteringVRObservable.add(() => {
+            this.onEnteringVRObservable.notifyObservers(this);
+        });
+        
+        this.sceneManager.onExitingVRObservable.add(() => {
+            this.onExitingVRObservable.notifyObservers(this);
+        });
 
         return Promise.resolve(this.engine);
     }

+ 55 - 40
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -71,6 +71,8 @@ module BABYLON {
         /** @hidden */
         public _activePointer = false;
 
+        
+
         constructor(public scene: Scene, gazeTrackerToClone: Nullable<Mesh> = null) {
             this._id = VRExperienceHelperGazer._idCounter++;
 
@@ -257,6 +259,8 @@ module BABYLON {
         // Are we presenting to the headset right now?
         private _webVRpresenting = false;
 
+        private hasEnteredVR: boolean;
+
         // Are we presenting in the fullscreen fallback?
         private _fullscreenVRpresenting = false;
 
@@ -566,6 +570,8 @@ module BABYLON {
                 this._defaultHeight *= webVROptions.positionScale;
             }
 
+            this.hasEnteredVR = false;
+
             // Set position
             if (this._scene.activeCamera) {
                 this._position = this._scene.activeCamera.position.clone();
@@ -772,12 +778,15 @@ module BABYLON {
         private onVrDisplayPresentChange() {
             var vrDisplay = this._scene.getEngine().getVRDevice();
             if (vrDisplay) {
+                // var wasPresenting = this._webVRpresenting;
+                // if (wasPresenting && this.isInVRMode) {
+                //     this.exitVR();
+                // }
+                // // A VR display is connected
+                // this._webVRpresenting = vrDisplay.isPresenting;
                 var wasPresenting = this._webVRpresenting;
-
-                // A VR display is connected
                 this._webVRpresenting = vrDisplay.isPresenting;
-
-                if (wasPresenting && !this._webVRpresenting && this.isInVRMode)
+                if (wasPresenting && !this._webVRpresenting)
                     this.exitVR();
             } else {
                 Tools.Warn('Detected VRDisplayPresentChange on an unknown VRDisplay. Did you can enterVR on the vrExperienceHelper?');
@@ -869,54 +878,60 @@ module BABYLON {
             if (this._interactionsEnabled) {
                 this._scene.registerBeforeRender(this.beforeRender);
             }
+
+            this.hasEnteredVR = true;
         }
 
         /**
          * Attempt to exit VR, or fullscreen.
          */
         public exitVR() {
-            if (this.onExitingVRObservable) {
-                try {
-                    this.onExitingVRObservable.notifyObservers(this);
+            if (this.hasEnteredVR) { ////////////////////////////////////////////////////////////////////////// risky!
+                if (this.onExitingVRObservable) {
+                    try {
+                        this.onExitingVRObservable.notifyObservers(this);
+                    }
+                    catch (err) {
+                        Tools.Warn("Error in your custom logic onExitingVR: " + err);
+                    }
                 }
-                catch (err) {
-                    Tools.Warn("Error in your custom logic onExitingVR: " + err);
+                if (this._webVRpresenting) {
+                    this._scene.getEngine().disableVR();
                 }
-            }
-            if (this._webVRpresenting) {
-                this._scene.getEngine().disableVR();
-            }
-            if (this._scene.activeCamera) {
-                this._position = this._scene.activeCamera.position.clone();
-
-            }
-
-            if (this._deviceOrientationCamera) {
-                this._deviceOrientationCamera.position = this._position;
-                this._scene.activeCamera = this._deviceOrientationCamera;
-                if (this._canvas) {
-                    this._scene.activeCamera.attachControl(this._canvas);
+                if (this._scene.activeCamera) {
+                    this._position = this._scene.activeCamera.position.clone();
+    
                 }
-            } else if (this._existingCamera) {
-                this._existingCamera.position = this._position;
-                this._scene.activeCamera = this._existingCamera;
-            }
-
-            this.updateButtonVisibility();
-
-            if (this._interactionsEnabled) {
-                this._scene.unregisterBeforeRender(this.beforeRender);
-                this._cameraGazer._gazeTracker.isVisible = false;
-                if (this.leftController) {
-                    this.leftController._gazeTracker.isVisible = false;
+    
+                if (this._deviceOrientationCamera) {
+                    this._deviceOrientationCamera.position = this._position;
+                    this._scene.activeCamera = this._deviceOrientationCamera;
+                    if (this._canvas) {
+                        this._scene.activeCamera.attachControl(this._canvas);
+                    }
+                } else if (this._existingCamera) {
+                    this._existingCamera.position = this._position;
+                    this._scene.activeCamera = this._existingCamera;
                 }
-                if (this.rightController) {
-                    this.rightController._gazeTracker.isVisible = false;
+    
+                this.updateButtonVisibility();
+    
+                if (this._interactionsEnabled) {
+                    this._scene.unregisterBeforeRender(this.beforeRender);
+                    this._cameraGazer._gazeTracker.isVisible = false;
+                    if (this.leftController) {
+                        this.leftController._gazeTracker.isVisible = false;
+                    }
+                    if (this.rightController) {
+                        this.rightController._gazeTracker.isVisible = false;
+                    }
                 }
-            }
+    
+                // resize to update width and height when exiting vr exits fullscreen
+                this._scene.getEngine().resize();
 
-            // resize to update width and height when exiting vr exits fullscreen
-            this._scene.getEngine().resize();
+                this.hasEnteredVR = false;
+            }
         }
 
         /**