Sfoglia il codice sorgente

small architectural changes

Raanan Weber 7 anni fa
parent
commit
649e675c65
2 ha cambiato i file con 53 aggiunte e 60 eliminazioni
  1. 7 41
      Viewer/src/viewer/defaultViewer.ts
  2. 46 19
      Viewer/src/viewer/viewer.ts

+ 7 - 41
Viewer/src/viewer/defaultViewer.ts

@@ -1,6 +1,6 @@
 import { Template } from './../templateManager';
 import { AbstractViewer } from './viewer';
-import { Observable, Engine, Scene, StandardMaterial, ShadowOnlyMaterial, ArcRotateCamera, ImageProcessingConfiguration, Color3, Vector3, SceneLoader, Mesh, HemisphericLight } from 'babylonjs';
+import { Observable, Engine, Scene, AbstractMesh, StandardMaterial, ShadowOnlyMaterial, ArcRotateCamera, ImageProcessingConfiguration, Color3, Vector3, SceneLoader, Mesh, HemisphericLight } from 'babylonjs';
 
 // A small hack for the inspector. to be removed!
 import * as BABYLON from 'babylonjs';
@@ -8,13 +8,6 @@ window['BABYLON'] = BABYLON;
 
 export class DefaultViewer extends AbstractViewer {
 
-    protected initScene() {
-        return super.initScene().then(() => {
-            this.scene.createDefaultCameraOrLight(true, true, true);
-            return this.scene;
-        });
-    }
-
     protected onTemplatesLoaded() {
 
         this.showLoadingScreen();
@@ -39,41 +32,16 @@ export class DefaultViewer extends AbstractViewer {
         this.containerElement.style.display = 'flex';
     }
 
-    protected initCameras(): Promise<Scene> {
-        return Promise.resolve(this.scene);
-    }
-
-    protected initLights(): Promise<Scene> {
-        var light = new HemisphericLight("light1", new Vector3(0, 1, 0), this.scene);
-        return Promise.resolve(this.scene);
-    }
-
     public loadModel(model: any = this.configuration.model): Promise<Scene> {
         this.showLoadingScreen();
+        return super.loadModel(model, true);
+    }
 
-        //TODO should the scene be cleared?
-
-        let modelUrl = (typeof model === 'string') ? model : model.url;
-        let parts = modelUrl.split('/');
-        let filename = parts.pop();
-        let base = parts.join('/') + '/';
-
-        return new Promise((resolve, reject) => {
-            SceneLoader.ImportMesh(undefined, base, filename, this.scene, (meshes) => {
-                console.log("model loaded");
-
-                this.onModelLoaded(meshes).then(() => {
-                    resolve(this.scene);
-                });
+    public onModelLoaded(meshes: Array<AbstractMesh>) {
 
-            }, undefined, (e, m, exception) => {
-                console.log(m, exception);
-                reject(m);
-            });
-        })
-    }
+        this.hideLoadingScreen();
 
-    public onModelLoaded(meshes) {
+        // recreate the camera
         this.scene.createDefaultCameraOrLight(true, true, true);
 
         // TODO do it better, no casting!
@@ -84,7 +52,7 @@ export class DefaultViewer extends AbstractViewer {
 
         // Get the bounding vectors of the mesh hierarchy (meshes[0] = root node in gltf)
         meshes[0].rotation.y += Math.PI;
-        var bounding = meshes[0].getHierarchyBoundingVectors();
+        let bounding = meshes[0].getHierarchyBoundingVectors();
         camera.framingBehavior.zoomOnBoundingInfo(bounding.min, bounding.max);
 
         // Remove default light and create a new one to have a dynamic shadow                            
@@ -112,8 +80,6 @@ export class DefaultViewer extends AbstractViewer {
             shadowGenerator.getShadowMap().renderList.push(meshes[index]);
         }
 
-        this.hideLoadingScreen();
-
         return Promise.resolve(this.scene);
     }
 

+ 46 - 19
Viewer/src/viewer/viewer.ts

@@ -25,9 +25,12 @@ export abstract class AbstractViewer {
 
         this.prepareContainerElement();
 
+        // extend the configuration
         configurationLoader.loadConfiguration(initialConfiguration).then((configuration) => {
             this.configuration = configuration;
+            // initialize the templates
             this.templateManager.initTemplate(this.configuration.template);
+            // when done, execute onTemplatesLoaded()
             this.templateManager.onAllLoaded.add(() => {
                 this.onTemplatesLoaded();
             })
@@ -39,25 +42,22 @@ export abstract class AbstractViewer {
         return this.baseId;
     }
 
-    protected prepareContainerElement() {
-        // nothing to see here, go home!
-    }
+    protected abstract prepareContainerElement();
 
+    /**
+     * This function will execute when the HTML templates finished initializing.
+     * It should initialize the engine and continue execution.
+     * 
+     * @protected
+     * @returns {Promise<AbstractViewer>} The viewer object will be returned after the object was loaded.
+     * @memberof AbstractViewer
+     */
     protected onTemplatesLoaded(): Promise<AbstractViewer> {
         return this.initEngine().then(() => {
-            return this.initScene();
-        }).then(() => {
-            return this.initCameras();
-        }).then(() => {
-            return this.initLights();
-        }).then(() => {
-            return this.initEnvironment();
-        }).then(() => {
             return this.loadModel();
         }).then(() => {
             return this;
         });
-
     }
 
     /**
@@ -77,6 +77,10 @@ export abstract class AbstractViewer {
             this.engine.resize();
         });
 
+        this.engine.runRenderLoop(() => {
+            this.scene && this.scene.render();
+        });
+
         var scale = Math.max(0.5, 1 / (window.devicePixelRatio || 2));
         this.engine.setHardwareScalingLevel(scale);
 
@@ -84,18 +88,41 @@ export abstract class AbstractViewer {
     }
 
     protected initScene(): Promise<Scene> {
+
+        // if the scen exists, dispose it.
+        if (this.scene) {
+            this.scene.dispose();
+        }
+
+        // create a new scene
         this.scene = new Scene(this.engine);
-        this.engine.runRenderLoop(() => {
-            this.scene.render();
-        });
+        // make sure there is a default camera and light.
+        this.scene.createDefaultCameraOrLight(true, true, true);
         return Promise.resolve(this.scene);
     }
 
-    protected abstract initCameras(): Promise<Scene>;
-
-    protected abstract initLights(): Promise<Scene>;
+    public loadModel(model: any = this.configuration.model, clearScene: boolean = true): Promise<Scene> {
+        let modelUrl = (typeof model === 'string') ? model : model.url;
+        let parts = modelUrl.split('/');
+        let filename = parts.pop();
+        let base = parts.join('/') + '/';
 
-    public abstract loadModel(model?: string): Promise<Scene>;
+        return Promise.resolve().then(() => {
+            if (!this.scene || clearScene) return this.initScene();
+            else return this.scene;
+        }).then(() => {
+            return new Promise<Array<AbstractMesh>>((resolve, reject) => {
+                SceneLoader.ImportMesh(undefined, base, filename, this.scene, (meshes) => {
+                    resolve(meshes);
+                }, undefined, (e, m, exception) => {
+                    console.log(m, exception);
+                    reject(m);
+                });
+            });
+        }).then((meshes: Array<AbstractMesh>) => {
+            return this.onModelLoaded(meshes);
+        });
+    }
 
     protected onModelLoaded(meshes: Array<AbstractMesh>): Promise<Scene> {
         console.log("model loaded");