|
@@ -1,5 +1,6 @@
|
|
|
|
+import { Template } from './../templateManager';
|
|
import { AbstractViewer } from './viewer';
|
|
import { AbstractViewer } from './viewer';
|
|
-import { Observable, Engine, Scene, ArcRotateCamera, Vector3, SceneLoader, Mesh, HemisphericLight } from 'babylonjs';
|
|
|
|
|
|
+import { Observable, Engine, Scene, StandardMaterial, ShadowOnlyMaterial, ArcRotateCamera, ImageProcessingConfiguration, Color3, Vector3, SceneLoader, Mesh, HemisphericLight } from 'babylonjs';
|
|
|
|
|
|
// A small hack for the inspector. to be removed!
|
|
// A small hack for the inspector. to be removed!
|
|
import * as BABYLON from 'babylonjs';
|
|
import * as BABYLON from 'babylonjs';
|
|
@@ -8,8 +9,10 @@ window['BABYLON'] = BABYLON;
|
|
export class DefaultViewer extends AbstractViewer {
|
|
export class DefaultViewer extends AbstractViewer {
|
|
|
|
|
|
protected initScene() {
|
|
protected initScene() {
|
|
- return super.initScene();
|
|
|
|
-
|
|
|
|
|
|
+ return super.initScene().then(() => {
|
|
|
|
+ this.scene.createDefaultCameraOrLight(true, true, true);
|
|
|
|
+ return this.scene;
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
protected onTemplatesLoaded() {
|
|
protected onTemplatesLoaded() {
|
|
@@ -32,17 +35,11 @@ export class DefaultViewer extends AbstractViewer {
|
|
}
|
|
}
|
|
|
|
|
|
protected prepareContainerElement() {
|
|
protected prepareContainerElement() {
|
|
|
|
+ this.containerElement.style.position = 'relative';
|
|
this.containerElement.style.display = 'flex';
|
|
this.containerElement.style.display = 'flex';
|
|
}
|
|
}
|
|
|
|
|
|
protected initCameras(): Promise<Scene> {
|
|
protected initCameras(): Promise<Scene> {
|
|
- var camera = new BABYLON.ArcRotateCamera("camera", 4.712, 1.571, 0.05, BABYLON.Vector3.Zero(), this.scene);
|
|
|
|
- camera.attachControl(this.engine.getRenderingCanvas(), true);
|
|
|
|
- camera.wheelPrecision = 100.0;
|
|
|
|
- camera.minZ = 0.01;
|
|
|
|
- camera.maxZ = 1000;
|
|
|
|
- camera.useFramingBehavior = true;
|
|
|
|
-
|
|
|
|
return Promise.resolve(this.scene);
|
|
return Promise.resolve(this.scene);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -62,21 +59,10 @@ export class DefaultViewer extends AbstractViewer {
|
|
let base = parts.join('/') + '/';
|
|
let base = parts.join('/') + '/';
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
return new Promise((resolve, reject) => {
|
|
- SceneLoader.Append(base, filename, this.scene, (scene) => {
|
|
|
|
- console.log("scene loaded");
|
|
|
|
- //this.scene.debugLayer.show();
|
|
|
|
-
|
|
|
|
- // TODO do it better, no casting!
|
|
|
|
- let camera: ArcRotateCamera = <ArcRotateCamera>this.scene.activeCamera;
|
|
|
|
-
|
|
|
|
- camera.setTarget(scene.meshes[0]);
|
|
|
|
-
|
|
|
|
- this.engine.runRenderLoop(() => {
|
|
|
|
- this.scene.render();
|
|
|
|
- });
|
|
|
|
|
|
+ SceneLoader.ImportMesh(undefined, base, filename, this.scene, (meshes) => {
|
|
|
|
+ console.log("model loaded");
|
|
|
|
|
|
- this.hideLoadingScreen();
|
|
|
|
- this.showViewer().then(() => {
|
|
|
|
|
|
+ this.onModelLoaded(meshes).then(() => {
|
|
resolve(this.scene);
|
|
resolve(this.scene);
|
|
});
|
|
});
|
|
|
|
|
|
@@ -85,22 +71,116 @@ export class DefaultViewer extends AbstractViewer {
|
|
reject(m);
|
|
reject(m);
|
|
});
|
|
});
|
|
})
|
|
})
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ public onModelLoaded(meshes) {
|
|
|
|
+ this.hideLoadingScreen();
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ this.scene.createDefaultCameraOrLight(true, true, true);
|
|
|
|
|
|
- public showLoadingScreen() {
|
|
|
|
- return this.templateManager.getTemplate('loadingScreen').show();
|
|
|
|
|
|
+ // TODO do it better, no casting!
|
|
|
|
+ let camera: ArcRotateCamera = <ArcRotateCamera>this.scene.activeCamera;
|
|
|
|
+
|
|
|
|
+ // We want framing to move the camera at the best spot
|
|
|
|
+ camera.useFramingBehavior = true;
|
|
|
|
+ camera.useAutoRotationBehavior = true;
|
|
|
|
+
|
|
|
|
+ // 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();
|
|
|
|
+ camera.framingBehavior.zoomOnBoundingInfo(bounding.min, bounding.max);
|
|
|
|
+
|
|
|
|
+ // Remove default light and create a new one to have a dynamic shadow
|
|
|
|
+ this.scene.lights[0].dispose();
|
|
|
|
+ var light = new BABYLON.DirectionalLight('light', new BABYLON.Vector3(-0.2, -1, 0), this.scene)
|
|
|
|
+ light.position = new BABYLON.Vector3(bounding.max.x * 0.2, bounding.max.y * 2, 0)
|
|
|
|
+ light.intensity = 4.5;
|
|
|
|
+
|
|
|
|
+ // TODO - move it away from here.
|
|
|
|
+
|
|
|
|
+ let ground = this.scene.getMeshByName('ground');
|
|
|
|
+ ground.position.y = bounding.min.y;
|
|
|
|
+
|
|
|
|
+ var shadowGenerator = new BABYLON.ShadowGenerator(512, light)
|
|
|
|
+ shadowGenerator.useBlurExponentialShadowMap = true;
|
|
|
|
+ shadowGenerator.useKernelBlur = true;
|
|
|
|
+ shadowGenerator.blurKernel = 64;
|
|
|
|
+ shadowGenerator.blurScale = 4;
|
|
|
|
+
|
|
|
|
+ // Add the bus in the casters
|
|
|
|
+ for (var index = 0; index < meshes.length; index++) {
|
|
|
|
+ shadowGenerator.getShadowMap().renderList.push(meshes[index]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return Promise.resolve(this.scene);
|
|
}
|
|
}
|
|
|
|
|
|
- public hideLoadingScreen() {
|
|
|
|
- return this.templateManager.getTemplate('loadingScreen').hide();
|
|
|
|
|
|
+ public initEnvironment(): Promise<Scene> {
|
|
|
|
+ this.scene.imageProcessingConfiguration.exposure = 1.4;
|
|
|
|
+ this.scene.imageProcessingConfiguration.contrast = 1.66;
|
|
|
|
+ this.scene.imageProcessingConfiguration.toneMappingEnabled = true;
|
|
|
|
+
|
|
|
|
+ // Define a general environment textue
|
|
|
|
+ /*var hdrTexture = BABYLON.CubeTexture.CreateFromPrefilteredData("https://playground.babylonjs.com/textures/environment.dds", this.scene);
|
|
|
|
+ hdrTexture.gammaSpace = false;
|
|
|
|
+
|
|
|
|
+ // Let's create a color curve to play with background color
|
|
|
|
+ var curve = new BABYLON.ColorCurves();
|
|
|
|
+ curve.globalHue = 58.88;
|
|
|
|
+ curve.globalDensity = 89;
|
|
|
|
+ curve.globalSaturation = 94;
|
|
|
|
+
|
|
|
|
+ // Create a dedicated background configuration
|
|
|
|
+ var backgroundImageProcessingConfiguration = new ImageProcessingConfiguration();
|
|
|
|
+ backgroundImageProcessingConfiguration.exposure = 1.5;
|
|
|
|
+ backgroundImageProcessingConfiguration.contrast = 1.66;
|
|
|
|
+ backgroundImageProcessingConfiguration.toneMappingEnabled = true;
|
|
|
|
+ backgroundImageProcessingConfiguration.vignetteEnabled = true;
|
|
|
|
+ //backgroundImageProcessingConfiguration.vignetteM = true;
|
|
|
|
+ backgroundImageProcessingConfiguration.vignetteWeight = 5;
|
|
|
|
+ //backgroundImageProcessingConfiguration.vignetteColor = new Color3(0.8, 0.6, 0.4);
|
|
|
|
+ backgroundImageProcessingConfiguration.colorCurves = curve;
|
|
|
|
+ backgroundImageProcessingConfiguration.colorCurvesEnabled = true;*/
|
|
|
|
+
|
|
|
|
+ var ground = Mesh.CreatePlane('ground', 100, this.scene)
|
|
|
|
+ ground.rotation.x = Math.PI / 2
|
|
|
|
+ ground.receiveShadows = true;
|
|
|
|
+ ground.material = new ShadowOnlyMaterial('shadow-only-mat', this.scene)
|
|
|
|
+ ground.material.alpha = 0.4;
|
|
|
|
+
|
|
|
|
+ // Our skybox with the color curve
|
|
|
|
+ /*var box = this.scene.createDefaultSkybox(hdrTexture, true, (this.scene.activeCamera.maxZ - this.scene.activeCamera.minZ) / 2, 0.7);
|
|
|
|
+ box.infiniteDistance = false;
|
|
|
|
+ (<StandardMaterial>box.material).imageProcessingConfiguration = backgroundImageProcessingConfiguration;*/
|
|
|
|
+
|
|
|
|
+ return Promise.resolve(this.scene);
|
|
}
|
|
}
|
|
|
|
|
|
- public showViewer() {
|
|
|
|
- return this.templateManager.getTemplate('viewer').show().then(() => {
|
|
|
|
- this.engine.resize();
|
|
|
|
- });
|
|
|
|
|
|
+ public showLoadingScreen() {
|
|
|
|
+ return this.templateManager.getTemplate('loadingScreen').show((template => {
|
|
|
|
+
|
|
|
|
+ var canvasRect = this.containerElement.getBoundingClientRect();
|
|
|
|
+ var canvasPositioning = window.getComputedStyle(this.containerElement).position;
|
|
|
|
+
|
|
|
|
+ template.parent.style.display = 'flex';
|
|
|
|
+ template.parent.style.width = canvasRect.width + "px";
|
|
|
|
+ template.parent.style.height = canvasRect.height + "px";
|
|
|
|
+ template.parent.style.opacity = "1";
|
|
|
|
+ // from the configuration!!!
|
|
|
|
+ template.parent.style.backgroundColor = "black";
|
|
|
|
+ return Promise.resolve(template);
|
|
|
|
+ }));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public hideLoadingScreen() {
|
|
|
|
+ return this.templateManager.getTemplate('loadingScreen').hide((template => {
|
|
|
|
+ template.parent.style.opacity = "0";
|
|
|
|
+ let onTransitionEnd = () => {
|
|
|
|
+ template.parent.removeEventListener("transitionend", onTransitionEnd);
|
|
|
|
+ template.parent.style.display = 'none';
|
|
|
|
+ }
|
|
|
|
+ template.parent.addEventListener("transitionend", onTransitionEnd);
|
|
|
|
+ return Promise.resolve(template);
|
|
|
|
+ }));
|
|
|
|
+ }
|
|
}
|
|
}
|