Преглед изворни кода

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;
+            }
         }
 
         /**