Browse Source

merge upstream master

Christopher Yovanovitch 7 years ago
parent
commit
0d4fb516dd

File diff suppressed because it is too large
+ 6351 - 5215
Playground/babylon.d.txt


+ 1 - 1
Viewer/src/configuration/configuration.ts

@@ -267,7 +267,7 @@ export interface IGroundConfiguration {
 export interface ISceneConfiguration {
     debug?: boolean;
     clearColor?: { r: number, g: number, b: number, a: number };
-    mainColor?: { r: number, g: number, b: number };
+    mainColor?: { r?: number, g?: number, b?: number };
     imageProcessingConfiguration?: IImageProcessingConfiguration;
     environmentTexture?: string;
     colorGrading?: IColorGradingConfiguration;

+ 3 - 3
Viewer/src/viewer/sceneManager.ts

@@ -374,7 +374,7 @@ export class SceneManager {
         }
 
         // optimizer
-        if (newConfiguration.optimizer) {
+        if (newConfiguration.optimizer !== undefined) {
             this._configureOptimizer(newConfiguration.optimizer);
         }
 
@@ -563,9 +563,9 @@ export class SceneManager {
             }
         }
 
-        if (sceneConfig.debug) {
+        if (sceneConfig.debug === true) {
             this.scene.debugLayer.show();
-        } else {
+        } else if (sceneConfig.debug === false) {
             if (this.scene.debugLayer.isVisible()) {
                 this.scene.debugLayer.hide();
             }

+ 314 - 0
Viewer/tests/unit/src/configuration/updateConfiguration.ts

@@ -0,0 +1,314 @@
+import { Helper } from "../../../commons/helper";
+import { assert, expect, should } from "../viewerReference";
+
+export let name = "configuration update";
+
+describe(name + " scene", () => {
+
+    it("should be used as a template for the following tests", (done) => {
+        let viewer = Helper.getNewViewerInstance(undefined, { extends: "none" });
+
+        viewer.onInitDoneObservable.add(() => {
+
+            viewer.dispose();
+            done();
+        });
+    });
+
+    it("should enable and disable the debug layer", (done) => {
+        let viewer = Helper.getNewViewerInstance(undefined, { extends: "none" });
+        let showCalled = 0;
+        let hideCalled = 0;
+        let isVisible = false;
+        viewer.onSceneInitObservable.add((scene) => {
+            scene.debugLayer.show = () => {
+                showCalled++;
+                isVisible = true;
+            }
+
+            scene.debugLayer.hide = () => {
+                hideCalled++;
+                isVisible = false;
+            }
+
+            scene.debugLayer.isVisible = () => {
+                return isVisible;
+            }
+        })
+        viewer.onInitDoneObservable.add(() => {
+            assert.isUndefined(viewer.configuration.scene);
+            assert.equal(showCalled, 0);
+            assert.equal(hideCalled, 0);
+            viewer.updateConfiguration({
+                scene: {
+                    debug: true
+                }
+            });
+            assert.equal(showCalled, 1);
+
+            viewer.updateConfiguration({
+                scene: {
+                    debug: false
+                }
+            });
+            assert.equal(showCalled, 1);
+            assert.equal(hideCalled, 1);
+            viewer.dispose();
+            done();
+        });
+    });
+
+    it("should update the image processing configuration values", (done) => {
+        let viewer = Helper.getNewViewerInstance(undefined, { extends: "none" });
+
+        viewer.onInitDoneObservable.add(() => {
+
+            // check babylon defaults
+            assert.isFalse(viewer.sceneManager.scene.imageProcessingConfiguration.applyByPostProcess);
+            assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.exposure, 1);
+            assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.contrast, 1);
+            assert.isFalse(viewer.sceneManager.scene.imageProcessingConfiguration.colorGradingEnabled);
+            if (viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves) {
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.globalDensity, 0);
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.globalHue, 30);
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.globalSaturation, 0);
+            } else {
+                assert.fail(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves, {}, "color curves was not initialized");
+            }
+
+            // update with fixed values
+
+            viewer.updateConfiguration({
+                scene: {
+                    imageProcessingConfiguration: {
+                        applyByPostProcess: true,
+                        exposure: 0,
+                        contrast: 0,
+                        colorGradingEnabled: true,
+                        colorCurves: {
+                            globalDensity: 1,
+                            globalHue: 0.2,
+                            globalSaturation: 0.5
+                        }
+
+                    }
+                }
+            });
+
+            assert.isTrue(viewer.sceneManager.scene.imageProcessingConfiguration.applyByPostProcess, "apply by post process should be true");
+            assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.exposure, 0);
+            assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.contrast, 0);
+            assert.isTrue(viewer.sceneManager.scene.imageProcessingConfiguration.colorGradingEnabled);
+            if (viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves) {
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.globalDensity, 1);
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.globalHue, 0.2);
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.globalSaturation, 0.5);
+            } else {
+                assert.fail(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves, {}, "color curves was not initialized");
+            }
+
+            let randoms = [0, 1, 2, 3, 4].map(n => Math.random());
+
+            viewer.updateConfiguration({
+                scene: {
+                    imageProcessingConfiguration: {
+                        exposure: randoms[0],
+                        contrast: randoms[1],
+                        colorCurves: {
+                            highlightsDensity: randoms[2],
+                            highlightsHue: randoms[3],
+                            highlightsSaturation: randoms[4]
+                        }
+
+                    }
+                }
+            });
+
+            assert.isTrue(viewer.sceneManager.scene.imageProcessingConfiguration.applyByPostProcess, "apply by post process should be true");
+            assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.exposure, randoms[0]);
+            assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.contrast, randoms[1]);
+            assert.isTrue(viewer.sceneManager.scene.imageProcessingConfiguration.colorGradingEnabled);
+            if (viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves) {
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.highlightsDensity, randoms[2]);
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.highlightsHue, randoms[3]);
+                assert.equal(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves.highlightsSaturation, randoms[4]);
+            } else {
+                assert.fail(viewer.sceneManager.scene.imageProcessingConfiguration.colorCurves, {}, "color curves was not initialized");
+            }
+
+            viewer.dispose();
+            done();
+        });
+    });
+
+    it("should update main color and reflection color", (done) => {
+        let viewer = Helper.getNewViewerInstance(undefined, { extends: "none" });
+
+        viewer.onInitDoneObservable.add(() => {
+
+            assert.equal(viewer.sceneManager.mainColor.r, 1);
+            assert.equal(viewer.sceneManager.mainColor.g, 1);
+            assert.equal(viewer.sceneManager.mainColor.b, 1);
+
+            assert.equal(viewer.sceneManager.reflectionColor.r, 1);
+            assert.equal(viewer.sceneManager.reflectionColor.g, 1);
+            assert.equal(viewer.sceneManager.reflectionColor.b, 1);
+
+            viewer.updateConfiguration({
+                scene: {
+                    mainColor: {
+                        r: 0.5,
+                        g: 0.5,
+                        b: 0.5
+                    }
+                },
+                lab: {
+                    environmentMap: {
+                        tintLevel: 1,
+                        texture: "",
+                        rotationY: 0
+                    }
+                }
+            });
+
+            assert.equal(viewer.sceneManager.mainColor.r, 0.5);
+            assert.equal(viewer.sceneManager.mainColor.g, 0.5);
+            assert.equal(viewer.sceneManager.mainColor.b, 0.5);
+
+            // to black
+            viewer.updateConfiguration({
+                scene: {
+                    mainColor: {
+                        r: 0,
+                        g: 0,
+                        b: 0
+                    }
+                }
+            });
+
+            assert.equal(viewer.sceneManager.mainColor.r, 0);
+            assert.equal(viewer.sceneManager.mainColor.g, 0);
+            assert.equal(viewer.sceneManager.mainColor.b, 0);
+
+            assert.equal(viewer.sceneManager.reflectionColor.r, 0);
+            assert.equal(viewer.sceneManager.reflectionColor.g, 0);
+            assert.equal(viewer.sceneManager.reflectionColor.b, 0);
+
+            let randomColor = Math.random();
+
+            //only update red
+            viewer.updateConfiguration({
+                scene: {
+                    mainColor: {
+                        r: randomColor
+                    }
+                }
+            });
+
+            assert.equal(viewer.sceneManager.mainColor.r, randomColor);
+            assert.equal(viewer.sceneManager.mainColor.g, 0);
+            assert.equal(viewer.sceneManager.mainColor.b, 0);
+
+            viewer.dispose();
+            done();
+        });
+    });
+
+    it("should update the flags correctly", (done) => {
+        let viewer = Helper.getNewViewerInstance(undefined, { extends: "none" });
+
+        viewer.onInitDoneObservable.add(() => {
+
+            viewer.updateConfiguration({
+                scene: {
+                    flags: {
+                        audioEnabled: false
+                    }
+                }
+            });
+
+            assert.isFalse(viewer.sceneManager.scene.audioEnabled);
+
+            viewer.updateConfiguration({
+                scene: {
+                    flags: {
+                        audioEnabled: true,
+                        lightsEnabled: false
+                    }
+                }
+            });
+
+            assert.isTrue(viewer.sceneManager.scene.audioEnabled);
+            assert.isFalse(viewer.sceneManager.scene.lightsEnabled);
+
+            viewer.updateConfiguration({
+                scene: {
+                    flags: {
+                        lightsEnabled: true,
+                        shadowsEnabled: false
+                    }
+                }
+            });
+
+            assert.isTrue(viewer.sceneManager.scene.audioEnabled);
+            assert.isTrue(viewer.sceneManager.scene.lightsEnabled);
+            assert.isFalse(viewer.sceneManager.scene.shadowsEnabled);
+
+            viewer.dispose();
+            done();
+        });
+    });
+});
+
+describe(name + " scene optimizer", () => {
+
+    it("should be enabled and disabled with booleans", (done) => {
+        let viewer = Helper.getNewViewerInstance(undefined, { extends: "none" });
+
+        let started = false;
+        let constructed = false;
+
+        let optimizerFunction = BABYLON.SceneOptimizer;
+
+        //mock!
+        (<any>BABYLON.SceneOptimizer) = function () {
+            constructed = true;
+        }
+
+        BABYLON.SceneOptimizer.prototype.start = function () {
+            started = true;
+        }
+
+        BABYLON.SceneOptimizer.prototype.stop = function () {
+            started = false;
+        }
+
+        BABYLON.SceneOptimizer.prototype.dispose = function () {
+        }
+
+        viewer.onInitDoneObservable.add(() => {
+
+            assert.isUndefined(viewer.sceneManager.sceneOptimizer);
+
+            viewer.updateConfiguration({
+                optimizer: true
+            });
+
+            assert.isDefined(viewer.sceneManager.sceneOptimizer);
+            assert.isTrue(started);
+            assert.isTrue(constructed);
+
+            viewer.updateConfiguration({
+                optimizer: false
+            });
+
+            assert.isUndefined(viewer.sceneManager.sceneOptimizer);
+            assert.isFalse(started);
+
+            BABYLON.SceneOptimizer = optimizerFunction;
+
+            viewer.dispose();
+            done();
+        });
+    });
+});

+ 1 - 0
Viewer/tests/unit/src/index.ts

@@ -7,4 +7,5 @@ import './viewer/viewerManager';
 import './configuration/mappers';
 import './configuration/loader';
 import './helper';
+import './configuration/updateConfiguration';
 export * from '../../../src'

File diff suppressed because it is too large
+ 2556 - 316
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 33 - 7
dist/preview release/babylon.js


+ 52 - 13
dist/preview release/babylon.max.js

@@ -15580,13 +15580,15 @@ var BABYLON;
          * @param onError defines an optional callback raised if there is an issue to load the texture
          * @param format defines the format of the data
          * @param forcedExtension defines the extension to use to pick the right loader
+         * @param createPolynomials defines wheter or not to create polynomails harmonics for the texture
          * @returns the cube texture as an InternalTexture
          */
-        Engine.prototype.createPrefilteredCubeTexture = function (rootUrl, scene, scale, offset, onLoad, onError, format, forcedExtension) {
+        Engine.prototype.createPrefilteredCubeTexture = function (rootUrl, scene, scale, offset, onLoad, onError, format, forcedExtension, createPolynomials) {
             var _this = this;
             if (onLoad === void 0) { onLoad = null; }
             if (onError === void 0) { onError = null; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (createPolynomials === void 0) { createPolynomials = true; }
             var callback = function (loadData) {
                 if (!loadData) {
                     if (onLoad) {
@@ -15595,7 +15597,10 @@ var BABYLON;
                     return;
                 }
                 var texture = loadData.texture;
-                if (loadData.info.sphericalPolynomial) {
+                if (!createPolynomials) {
+                    texture._sphericalPolynomial = new BABYLON.SphericalPolynomial();
+                }
+                else if (loadData.info.sphericalPolynomial) {
                     texture._sphericalPolynomial = loadData.info.sphericalPolynomial;
                 }
                 texture._dataSource = BABYLON.InternalTexture.DATASOURCE_CUBEPREFILTERED;
@@ -15654,7 +15659,7 @@ var BABYLON;
                     onLoad(texture);
                 }
             };
-            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, true);
+            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, createPolynomials);
         };
         /**
          * Creates a cube texture
@@ -20373,10 +20378,12 @@ var BABYLON;
         /**
          * Return the minimum and maximum world vectors of the entire hierarchy under current mesh
          * @param includeDescendants Include bounding info from descendants as well (true by default)
+         * @param predicate defines a callback function that can be customize to filter what meshes should be included in the list used to compute the bounding vectors
          * @returns the new bounding vectors
          */
-        AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants) {
+        AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants, predicate) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            if (predicate === void 0) { predicate = null; }
             // Ensures that all world matrix will be recomputed.
             this.getScene().incrementRenderId();
             this.computeWorldMatrix(true);
@@ -20397,6 +20404,10 @@ var BABYLON;
                     var descendant = descendants_1[_i];
                     var childMesh = descendant;
                     childMesh.computeWorldMatrix(true);
+                    // Filters meshes based on custom predicate function.
+                    if (predicate && !predicate(childMesh)) {
+                        continue;
+                    }
                     //make sure we have the needed params to get mix and max
                     if (!childMesh.getBoundingInfo || childMesh.getTotalVertices() === 0) {
                         continue;
@@ -30100,6 +30111,7 @@ var BABYLON;
                         }
                         _this.isReady = true;
                     }, null, this.format, this._extension);
+                    proxy._sphericalPolynomial = this._sphericalPolynomial;
                     return;
             }
         };
@@ -31185,15 +31197,15 @@ var BABYLON;
             _this._source = null;
             scene = _this.getScene();
             if (source) {
-                // Source mesh
-                _this._source = source;
                 // Geometry
                 if (source._geometry) {
                     source._geometry.applyToMesh(_this);
                 }
                 // Deep copy
                 BABYLON.Tools.DeepCopy(source, _this, ["name", "material", "skeleton", "instances", "parent", "uniqueId",
-                    "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen"], ["_poseMatrix", "_source"]);
+                    "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen"], ["_poseMatrix"]);
+                // Source mesh
+                _this._source = source;
                 // Metadata
                 if (source.metadata && source.metadata.clone) {
                     _this.metadata = source.metadata.clone();
@@ -48815,7 +48827,7 @@ var BABYLON;
                     up = up.clone();
                     up = up.negate();
                 }
-                BABYLON.Matrix.LookAtLHToRef(_this.position, target, up, _this._viewMatrix);
+                _this._computeViewMatrix(_this.position, target, up);
                 _this._viewMatrix.m[12] += _this.targetScreenOffset.x;
                 _this._viewMatrix.m[13] += _this.targetScreenOffset.y;
                 _this._collisionTriggered = false;
@@ -63556,7 +63568,23 @@ var BABYLON;
 (function (BABYLON) {
     var CubeTexture = /** @class */ (function (_super) {
         __extends(CubeTexture, _super);
-        function CubeTexture(rootUrl, scene, extensions, noMipmap, files, onLoad, onError, format, prefiltered, forcedExtension) {
+        /**
+         * Creates a cube texture to use with reflection for instance. It can be based upon dds or six images as well
+         * as prefiltered data.
+         * @param rootUrl defines the url of the texture or the root name of the six images
+         * @param scene defines the scene the texture is attached to
+         * @param extensions defines the suffixes add to the picture name in case six images are in use like _px.jpg...
+         * @param noMipmap defines if mipmaps should be created or not
+         * @param files defines the six files to load for the different faces
+         * @param onLoad defines a callback triggered at the end of the file load if no errors occured
+         * @param onError defines a callback triggered in case of error during load
+         * @param format defines the internal format to use for the texture once loaded
+         * @param prefiltered defines whether or not the texture is created from prefiltered data
+         * @param forcedExtension defines the extensions to use (force a special type of file to load) in case it is different from the file name
+         * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
+         * @return the cube texture
+         */
+        function CubeTexture(rootUrl, scene, extensions, noMipmap, files, onLoad, onError, format, prefiltered, forcedExtension, createPolynomials) {
             if (extensions === void 0) { extensions = null; }
             if (noMipmap === void 0) { noMipmap = false; }
             if (files === void 0) { files = null; }
@@ -63565,6 +63593,7 @@ var BABYLON;
             if (format === void 0) { format = BABYLON.Engine.TEXTUREFORMAT_RGBA; }
             if (prefiltered === void 0) { prefiltered = false; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (createPolynomials === void 0) { createPolynomials = false; }
             var _this = _super.call(this, scene) || this;
             _this.coordinatesMode = BABYLON.Texture.CUBIC_MODE;
             /**
@@ -63581,6 +63610,7 @@ var BABYLON;
             _this._prefiltered = prefiltered;
             _this.isCube = true;
             _this._textureMatrix = BABYLON.Matrix.Identity();
+            _this._createPolynomials = createPolynomials;
             if (prefiltered) {
                 _this.gammaSpace = false;
             }
@@ -63606,7 +63636,7 @@ var BABYLON;
             if (!_this._texture) {
                 if (!scene.useDelayedTextureLoading) {
                     if (prefiltered) {
-                        _this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, _this.lodGenerationScale, _this.lodGenerationOffset, onLoad, onError, format, forcedExtension);
+                        _this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, _this.lodGenerationScale, _this.lodGenerationOffset, onLoad, onError, format, forcedExtension, _this._createPolynomials);
                     }
                     else {
                         _this._texture = scene.getEngine().createCubeTexture(rootUrl, scene, files, noMipmap, onLoad, onError, _this._format, forcedExtension);
@@ -63671,9 +63701,18 @@ var BABYLON;
             files.forEach(function (url) { return rootUrlKey += url; });
             return new CubeTexture(rootUrlKey, scene, null, noMipmap, files);
         };
-        CubeTexture.CreateFromPrefilteredData = function (url, scene, forcedExtension) {
+        /**
+         * Creates and return a texture created from prefilterd data by tools like IBL Baker or Lys.
+         * @param url defines the url of the prefiltered texture
+         * @param scene defines the scene the texture is attached to
+         * @param forcedExtension defines the extension of the file if different from the url
+         * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
+         * @return the prefiltered texture
+         */
+        CubeTexture.CreateFromPrefilteredData = function (url, scene, forcedExtension, createPolynomials) {
             if (forcedExtension === void 0) { forcedExtension = null; }
-            return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension);
+            if (createPolynomials === void 0) { createPolynomials = true; }
+            return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension, createPolynomials);
         };
         // Methods
         CubeTexture.prototype.delayLoad = function () {
@@ -63688,7 +63727,7 @@ var BABYLON;
             this._texture = this._getFromCache(this.url, this._noMipmap);
             if (!this._texture) {
                 if (this._prefiltered) {
-                    this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format);
+                    this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format, undefined, this._createPolynomials);
                 }
                 else {
                     this._texture = scene.getEngine().createCubeTexture(this.url, scene, this._files, this._noMipmap, undefined, undefined, this._format);

+ 52 - 13
dist/preview release/babylon.no-module.max.js

@@ -15547,13 +15547,15 @@ var BABYLON;
          * @param onError defines an optional callback raised if there is an issue to load the texture
          * @param format defines the format of the data
          * @param forcedExtension defines the extension to use to pick the right loader
+         * @param createPolynomials defines wheter or not to create polynomails harmonics for the texture
          * @returns the cube texture as an InternalTexture
          */
-        Engine.prototype.createPrefilteredCubeTexture = function (rootUrl, scene, scale, offset, onLoad, onError, format, forcedExtension) {
+        Engine.prototype.createPrefilteredCubeTexture = function (rootUrl, scene, scale, offset, onLoad, onError, format, forcedExtension, createPolynomials) {
             var _this = this;
             if (onLoad === void 0) { onLoad = null; }
             if (onError === void 0) { onError = null; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (createPolynomials === void 0) { createPolynomials = true; }
             var callback = function (loadData) {
                 if (!loadData) {
                     if (onLoad) {
@@ -15562,7 +15564,10 @@ var BABYLON;
                     return;
                 }
                 var texture = loadData.texture;
-                if (loadData.info.sphericalPolynomial) {
+                if (!createPolynomials) {
+                    texture._sphericalPolynomial = new BABYLON.SphericalPolynomial();
+                }
+                else if (loadData.info.sphericalPolynomial) {
                     texture._sphericalPolynomial = loadData.info.sphericalPolynomial;
                 }
                 texture._dataSource = BABYLON.InternalTexture.DATASOURCE_CUBEPREFILTERED;
@@ -15621,7 +15626,7 @@ var BABYLON;
                     onLoad(texture);
                 }
             };
-            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, true);
+            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, createPolynomials);
         };
         /**
          * Creates a cube texture
@@ -20340,10 +20345,12 @@ var BABYLON;
         /**
          * Return the minimum and maximum world vectors of the entire hierarchy under current mesh
          * @param includeDescendants Include bounding info from descendants as well (true by default)
+         * @param predicate defines a callback function that can be customize to filter what meshes should be included in the list used to compute the bounding vectors
          * @returns the new bounding vectors
          */
-        AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants) {
+        AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants, predicate) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            if (predicate === void 0) { predicate = null; }
             // Ensures that all world matrix will be recomputed.
             this.getScene().incrementRenderId();
             this.computeWorldMatrix(true);
@@ -20364,6 +20371,10 @@ var BABYLON;
                     var descendant = descendants_1[_i];
                     var childMesh = descendant;
                     childMesh.computeWorldMatrix(true);
+                    // Filters meshes based on custom predicate function.
+                    if (predicate && !predicate(childMesh)) {
+                        continue;
+                    }
                     //make sure we have the needed params to get mix and max
                     if (!childMesh.getBoundingInfo || childMesh.getTotalVertices() === 0) {
                         continue;
@@ -30067,6 +30078,7 @@ var BABYLON;
                         }
                         _this.isReady = true;
                     }, null, this.format, this._extension);
+                    proxy._sphericalPolynomial = this._sphericalPolynomial;
                     return;
             }
         };
@@ -31152,15 +31164,15 @@ var BABYLON;
             _this._source = null;
             scene = _this.getScene();
             if (source) {
-                // Source mesh
-                _this._source = source;
                 // Geometry
                 if (source._geometry) {
                     source._geometry.applyToMesh(_this);
                 }
                 // Deep copy
                 BABYLON.Tools.DeepCopy(source, _this, ["name", "material", "skeleton", "instances", "parent", "uniqueId",
-                    "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen"], ["_poseMatrix", "_source"]);
+                    "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen"], ["_poseMatrix"]);
+                // Source mesh
+                _this._source = source;
                 // Metadata
                 if (source.metadata && source.metadata.clone) {
                     _this.metadata = source.metadata.clone();
@@ -48782,7 +48794,7 @@ var BABYLON;
                     up = up.clone();
                     up = up.negate();
                 }
-                BABYLON.Matrix.LookAtLHToRef(_this.position, target, up, _this._viewMatrix);
+                _this._computeViewMatrix(_this.position, target, up);
                 _this._viewMatrix.m[12] += _this.targetScreenOffset.x;
                 _this._viewMatrix.m[13] += _this.targetScreenOffset.y;
                 _this._collisionTriggered = false;
@@ -63523,7 +63535,23 @@ var BABYLON;
 (function (BABYLON) {
     var CubeTexture = /** @class */ (function (_super) {
         __extends(CubeTexture, _super);
-        function CubeTexture(rootUrl, scene, extensions, noMipmap, files, onLoad, onError, format, prefiltered, forcedExtension) {
+        /**
+         * Creates a cube texture to use with reflection for instance. It can be based upon dds or six images as well
+         * as prefiltered data.
+         * @param rootUrl defines the url of the texture or the root name of the six images
+         * @param scene defines the scene the texture is attached to
+         * @param extensions defines the suffixes add to the picture name in case six images are in use like _px.jpg...
+         * @param noMipmap defines if mipmaps should be created or not
+         * @param files defines the six files to load for the different faces
+         * @param onLoad defines a callback triggered at the end of the file load if no errors occured
+         * @param onError defines a callback triggered in case of error during load
+         * @param format defines the internal format to use for the texture once loaded
+         * @param prefiltered defines whether or not the texture is created from prefiltered data
+         * @param forcedExtension defines the extensions to use (force a special type of file to load) in case it is different from the file name
+         * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
+         * @return the cube texture
+         */
+        function CubeTexture(rootUrl, scene, extensions, noMipmap, files, onLoad, onError, format, prefiltered, forcedExtension, createPolynomials) {
             if (extensions === void 0) { extensions = null; }
             if (noMipmap === void 0) { noMipmap = false; }
             if (files === void 0) { files = null; }
@@ -63532,6 +63560,7 @@ var BABYLON;
             if (format === void 0) { format = BABYLON.Engine.TEXTUREFORMAT_RGBA; }
             if (prefiltered === void 0) { prefiltered = false; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (createPolynomials === void 0) { createPolynomials = false; }
             var _this = _super.call(this, scene) || this;
             _this.coordinatesMode = BABYLON.Texture.CUBIC_MODE;
             /**
@@ -63548,6 +63577,7 @@ var BABYLON;
             _this._prefiltered = prefiltered;
             _this.isCube = true;
             _this._textureMatrix = BABYLON.Matrix.Identity();
+            _this._createPolynomials = createPolynomials;
             if (prefiltered) {
                 _this.gammaSpace = false;
             }
@@ -63573,7 +63603,7 @@ var BABYLON;
             if (!_this._texture) {
                 if (!scene.useDelayedTextureLoading) {
                     if (prefiltered) {
-                        _this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, _this.lodGenerationScale, _this.lodGenerationOffset, onLoad, onError, format, forcedExtension);
+                        _this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, _this.lodGenerationScale, _this.lodGenerationOffset, onLoad, onError, format, forcedExtension, _this._createPolynomials);
                     }
                     else {
                         _this._texture = scene.getEngine().createCubeTexture(rootUrl, scene, files, noMipmap, onLoad, onError, _this._format, forcedExtension);
@@ -63638,9 +63668,18 @@ var BABYLON;
             files.forEach(function (url) { return rootUrlKey += url; });
             return new CubeTexture(rootUrlKey, scene, null, noMipmap, files);
         };
-        CubeTexture.CreateFromPrefilteredData = function (url, scene, forcedExtension) {
+        /**
+         * Creates and return a texture created from prefilterd data by tools like IBL Baker or Lys.
+         * @param url defines the url of the prefiltered texture
+         * @param scene defines the scene the texture is attached to
+         * @param forcedExtension defines the extension of the file if different from the url
+         * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
+         * @return the prefiltered texture
+         */
+        CubeTexture.CreateFromPrefilteredData = function (url, scene, forcedExtension, createPolynomials) {
             if (forcedExtension === void 0) { forcedExtension = null; }
-            return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension);
+            if (createPolynomials === void 0) { createPolynomials = true; }
+            return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension, createPolynomials);
         };
         // Methods
         CubeTexture.prototype.delayLoad = function () {
@@ -63655,7 +63694,7 @@ var BABYLON;
             this._texture = this._getFromCache(this.url, this._noMipmap);
             if (!this._texture) {
                 if (this._prefiltered) {
-                    this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format);
+                    this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format, undefined, this._createPolynomials);
                 }
                 else {
                     this._texture = scene.getEngine().createCubeTexture(this.url, scene, this._files, this._noMipmap, undefined, undefined, this._format);

File diff suppressed because it is too large
+ 33 - 7
dist/preview release/babylon.worker.js


+ 52 - 13
dist/preview release/es6.js

@@ -15547,13 +15547,15 @@ var BABYLON;
          * @param onError defines an optional callback raised if there is an issue to load the texture
          * @param format defines the format of the data
          * @param forcedExtension defines the extension to use to pick the right loader
+         * @param createPolynomials defines wheter or not to create polynomails harmonics for the texture
          * @returns the cube texture as an InternalTexture
          */
-        Engine.prototype.createPrefilteredCubeTexture = function (rootUrl, scene, scale, offset, onLoad, onError, format, forcedExtension) {
+        Engine.prototype.createPrefilteredCubeTexture = function (rootUrl, scene, scale, offset, onLoad, onError, format, forcedExtension, createPolynomials) {
             var _this = this;
             if (onLoad === void 0) { onLoad = null; }
             if (onError === void 0) { onError = null; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (createPolynomials === void 0) { createPolynomials = true; }
             var callback = function (loadData) {
                 if (!loadData) {
                     if (onLoad) {
@@ -15562,7 +15564,10 @@ var BABYLON;
                     return;
                 }
                 var texture = loadData.texture;
-                if (loadData.info.sphericalPolynomial) {
+                if (!createPolynomials) {
+                    texture._sphericalPolynomial = new BABYLON.SphericalPolynomial();
+                }
+                else if (loadData.info.sphericalPolynomial) {
                     texture._sphericalPolynomial = loadData.info.sphericalPolynomial;
                 }
                 texture._dataSource = BABYLON.InternalTexture.DATASOURCE_CUBEPREFILTERED;
@@ -15621,7 +15626,7 @@ var BABYLON;
                     onLoad(texture);
                 }
             };
-            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, true);
+            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, createPolynomials);
         };
         /**
          * Creates a cube texture
@@ -20340,10 +20345,12 @@ var BABYLON;
         /**
          * Return the minimum and maximum world vectors of the entire hierarchy under current mesh
          * @param includeDescendants Include bounding info from descendants as well (true by default)
+         * @param predicate defines a callback function that can be customize to filter what meshes should be included in the list used to compute the bounding vectors
          * @returns the new bounding vectors
          */
-        AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants) {
+        AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants, predicate) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            if (predicate === void 0) { predicate = null; }
             // Ensures that all world matrix will be recomputed.
             this.getScene().incrementRenderId();
             this.computeWorldMatrix(true);
@@ -20364,6 +20371,10 @@ var BABYLON;
                     var descendant = descendants_1[_i];
                     var childMesh = descendant;
                     childMesh.computeWorldMatrix(true);
+                    // Filters meshes based on custom predicate function.
+                    if (predicate && !predicate(childMesh)) {
+                        continue;
+                    }
                     //make sure we have the needed params to get mix and max
                     if (!childMesh.getBoundingInfo || childMesh.getTotalVertices() === 0) {
                         continue;
@@ -30067,6 +30078,7 @@ var BABYLON;
                         }
                         _this.isReady = true;
                     }, null, this.format, this._extension);
+                    proxy._sphericalPolynomial = this._sphericalPolynomial;
                     return;
             }
         };
@@ -31152,15 +31164,15 @@ var BABYLON;
             _this._source = null;
             scene = _this.getScene();
             if (source) {
-                // Source mesh
-                _this._source = source;
                 // Geometry
                 if (source._geometry) {
                     source._geometry.applyToMesh(_this);
                 }
                 // Deep copy
                 BABYLON.Tools.DeepCopy(source, _this, ["name", "material", "skeleton", "instances", "parent", "uniqueId",
-                    "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen"], ["_poseMatrix", "_source"]);
+                    "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen"], ["_poseMatrix"]);
+                // Source mesh
+                _this._source = source;
                 // Metadata
                 if (source.metadata && source.metadata.clone) {
                     _this.metadata = source.metadata.clone();
@@ -48782,7 +48794,7 @@ var BABYLON;
                     up = up.clone();
                     up = up.negate();
                 }
-                BABYLON.Matrix.LookAtLHToRef(_this.position, target, up, _this._viewMatrix);
+                _this._computeViewMatrix(_this.position, target, up);
                 _this._viewMatrix.m[12] += _this.targetScreenOffset.x;
                 _this._viewMatrix.m[13] += _this.targetScreenOffset.y;
                 _this._collisionTriggered = false;
@@ -63523,7 +63535,23 @@ var BABYLON;
 (function (BABYLON) {
     var CubeTexture = /** @class */ (function (_super) {
         __extends(CubeTexture, _super);
-        function CubeTexture(rootUrl, scene, extensions, noMipmap, files, onLoad, onError, format, prefiltered, forcedExtension) {
+        /**
+         * Creates a cube texture to use with reflection for instance. It can be based upon dds or six images as well
+         * as prefiltered data.
+         * @param rootUrl defines the url of the texture or the root name of the six images
+         * @param scene defines the scene the texture is attached to
+         * @param extensions defines the suffixes add to the picture name in case six images are in use like _px.jpg...
+         * @param noMipmap defines if mipmaps should be created or not
+         * @param files defines the six files to load for the different faces
+         * @param onLoad defines a callback triggered at the end of the file load if no errors occured
+         * @param onError defines a callback triggered in case of error during load
+         * @param format defines the internal format to use for the texture once loaded
+         * @param prefiltered defines whether or not the texture is created from prefiltered data
+         * @param forcedExtension defines the extensions to use (force a special type of file to load) in case it is different from the file name
+         * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
+         * @return the cube texture
+         */
+        function CubeTexture(rootUrl, scene, extensions, noMipmap, files, onLoad, onError, format, prefiltered, forcedExtension, createPolynomials) {
             if (extensions === void 0) { extensions = null; }
             if (noMipmap === void 0) { noMipmap = false; }
             if (files === void 0) { files = null; }
@@ -63532,6 +63560,7 @@ var BABYLON;
             if (format === void 0) { format = BABYLON.Engine.TEXTUREFORMAT_RGBA; }
             if (prefiltered === void 0) { prefiltered = false; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (createPolynomials === void 0) { createPolynomials = false; }
             var _this = _super.call(this, scene) || this;
             _this.coordinatesMode = BABYLON.Texture.CUBIC_MODE;
             /**
@@ -63548,6 +63577,7 @@ var BABYLON;
             _this._prefiltered = prefiltered;
             _this.isCube = true;
             _this._textureMatrix = BABYLON.Matrix.Identity();
+            _this._createPolynomials = createPolynomials;
             if (prefiltered) {
                 _this.gammaSpace = false;
             }
@@ -63573,7 +63603,7 @@ var BABYLON;
             if (!_this._texture) {
                 if (!scene.useDelayedTextureLoading) {
                     if (prefiltered) {
-                        _this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, _this.lodGenerationScale, _this.lodGenerationOffset, onLoad, onError, format, forcedExtension);
+                        _this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, _this.lodGenerationScale, _this.lodGenerationOffset, onLoad, onError, format, forcedExtension, _this._createPolynomials);
                     }
                     else {
                         _this._texture = scene.getEngine().createCubeTexture(rootUrl, scene, files, noMipmap, onLoad, onError, _this._format, forcedExtension);
@@ -63638,9 +63668,18 @@ var BABYLON;
             files.forEach(function (url) { return rootUrlKey += url; });
             return new CubeTexture(rootUrlKey, scene, null, noMipmap, files);
         };
-        CubeTexture.CreateFromPrefilteredData = function (url, scene, forcedExtension) {
+        /**
+         * Creates and return a texture created from prefilterd data by tools like IBL Baker or Lys.
+         * @param url defines the url of the prefiltered texture
+         * @param scene defines the scene the texture is attached to
+         * @param forcedExtension defines the extension of the file if different from the url
+         * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
+         * @return the prefiltered texture
+         */
+        CubeTexture.CreateFromPrefilteredData = function (url, scene, forcedExtension, createPolynomials) {
             if (forcedExtension === void 0) { forcedExtension = null; }
-            return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension);
+            if (createPolynomials === void 0) { createPolynomials = true; }
+            return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension, createPolynomials);
         };
         // Methods
         CubeTexture.prototype.delayLoad = function () {
@@ -63655,7 +63694,7 @@ var BABYLON;
             this._texture = this._getFromCache(this.url, this._noMipmap);
             if (!this._texture) {
                 if (this._prefiltered) {
-                    this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format);
+                    this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format, undefined, this._createPolynomials);
                 }
                 else {
                     this._texture = scene.getEngine().createCubeTexture(this.url, scene, this._files, this._noMipmap, undefined, undefined, this._format);

+ 2 - 24
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 4313,
+  "errors": 4309,
   "babylon.typedoc.json": {
-    "errors": 4313,
+    "errors": 4309,
     "Animatable": {
       "Class": {
         "Comments": {
@@ -4721,28 +4721,6 @@
             }
           }
         },
-        "CreateFromPrefilteredData": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "url": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "scene": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "forcedExtension": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "Parse": {
           "Comments": {
             "MissingText": true

File diff suppressed because it is too large
+ 2288 - 0
dist/preview release/viewer/babylon.viewer.d.ts


File diff suppressed because it is too large
+ 50 - 0
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 4711 - 26
dist/preview release/viewer/babylon.viewer.max.js


File diff suppressed because it is too large
+ 2317 - 0
dist/preview release/viewer/babylon.viewer.module.d.ts


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

@@ -9,6 +9,9 @@
 - Add the choice of [forming a closed loop](http://doc.babylonjs.com/how_to/how_to_use_curve3#catmull-rom-spline) to the catamull-rom-spline curve3 ([johnk](https://github.com/babylonjsguide))
 - Add support for specifying the center of rotation to textures ([bghgary](http://www.github.com/bghgary))
 - Add webVR support for Oculus Go ([TrevorDev](https://github.com/TrevorDev))
+- Add ability to not generate polynomials harmonics upon prefiltered texture creation ([sebavan](http://www.github.com/sebavan))
+- Add predicate function to customize the list of mesh included in the computation of bounding vectors in the ```getHierarchyBoundingVectors``` method ([sebavan](http://www.github.com/sebavan))
+- Add webVR constructor options: disable laser pointer toggle, teleportation floor meshes ([TrevorDev](https://github.com/TrevorDev))
 
 ### glTF Loader
 
@@ -17,7 +20,7 @@
 ### Viewer
 
 - No fullscreen button on small devices ([RaananW](https://github.com/RaananW))
-- Nav-Bar is now disaplayed on fullscreen per default  ([RaananW](https://github.com/RaananW))
+- Nav-Bar is now disaplayed on fullscreen per default ([RaananW](https://github.com/RaananW))
 - Viewer configuration supports deprecated values using the new configurationCompatibility processor  ([RaananW](https://github.com/RaananW))
 
 ## Bug fixes
@@ -27,6 +30,7 @@
 - Fix ```shadowEnabled``` property on lights. Shadows are not visble anymore when disabled ([sebavan](http://www.github.com/sebavan))
 - Physics `unregisterOnPhysicsCollide` didn't remove callback correctly [#4291](https://github.com/BabylonJS/Babylon.js/issues/4291) ([RaananW](https://github.com/RaananW))
 - Added missing getter and setter for global exposure in ColorCurves ([RaananW](https://github.com/RaananW))
+- Fixed an issue with view matrix when `ArcRotateCamera` was used with collisions ([Deltakosh](https://github.com/deltakosh)) 
 
 ### Viewer
 

+ 31 - 14
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -18,13 +18,21 @@ module BABYLON {
      */
     export interface VRExperienceHelperOptions extends WebVROptions {
         /**
-         * Create a DeviceOrientationCamera to be used as your out of vr camera.
+         * Create a DeviceOrientationCamera to be used as your out of vr camera. (default: true)
          */
         createDeviceOrientationCamera?: boolean;
         /**
-         * Create a VRDeviceOrientationFreeCamera to be used for VR when no external HMD is found.
+         * Create a VRDeviceOrientationFreeCamera to be used for VR when no external HMD is found. (default: true)
          */
         createFallbackVRDeviceOrientationFreeCamera?: boolean;
+        /**
+         * Uses the main button on the controller to toggle the laser casted. (default: true)
+         */
+        laserToggle?:boolean;
+        /**
+         * A list of meshes to be used as the teleportation floor. If specified, teleportation will be enabled (default: undefined)
+         */
+        floorMeshes?: Mesh[];
     }
 
     class VRExperienceHelperGazer implements IDisposable {
@@ -509,6 +517,9 @@ module BABYLON {
             if (webVROptions.createDeviceOrientationCamera === undefined) {
                 webVROptions.createDeviceOrientationCamera = true;
             }
+            if (webVROptions.laserToggle === undefined) {
+                webVROptions.laserToggle = true;
+            }
             if (webVROptions.defaultHeight === undefined) {
                 webVROptions.defaultHeight = 1.7;
             }
@@ -668,6 +679,10 @@ module BABYLON {
             //create easing functions
             this._circleEase = new CircleEase();
             this._circleEase.setEasingMode(EasingFunction.EASINGMODE_EASEINOUT);
+
+            if(this.webVROptions.floorMeshes){
+                this.enableTeleportation({floorMeshes: this.webVROptions.floorMeshes});
+            }
         }
 
         // Raised when one of the controller has loaded successfully its associated default mesh
@@ -1108,19 +1123,21 @@ module BABYLON {
                 
                 controller._interactionsEnabled = true;
                 controller._activatePointer();
-                controller.webVRController.onMainButtonStateChangedObservable.add((stateObject) => {
-                    // Enabling / disabling laserPointer 
-                    if (this._displayLaserPointer && stateObject.value === 1) {
-                        if(controller._activePointer){
-                            controller._deactivatePointer();
-                        }else{
-                            controller._activatePointer();
-                        }
-                        if(this.displayGaze){
-                            controller._gazeTracker.isVisible = controller._activePointer;
+                if(this.webVROptions.laserToggle){
+                    controller.webVRController.onMainButtonStateChangedObservable.add((stateObject) => {
+                        // Enabling / disabling laserPointer 
+                        if (this._displayLaserPointer && stateObject.value === 1) {
+                            if(controller._activePointer){
+                                controller._deactivatePointer();
+                            }else{
+                                controller._activatePointer();
+                            }
+                            if(this.displayGaze){
+                                controller._gazeTracker.isVisible = controller._activePointer;
+                            }
                         }
-                    }
-                });
+                    });
+                }
                 controller.webVRController.onTriggerStateChangedObservable.add((stateObject) => {
                     if (!controller._pointerDownOnMeshAsked) {
                         if (stateObject.value > this._padSensibilityUp) {

+ 1 - 1
src/Cameras/babylon.arcRotateCamera.ts

@@ -718,7 +718,7 @@
                 up = up.negate();
             }
 
-            Matrix.LookAtLHToRef(this.position, target, up, this._viewMatrix);
+            this._computeViewMatrix(this.position, target, up);
             this._viewMatrix.m[12] += this.targetScreenOffset.x;
             this._viewMatrix.m[13] += this.targetScreenOffset.y;
 

+ 8 - 3
src/Engine/babylon.engine.ts

@@ -5351,11 +5351,13 @@
          * @param onError defines an optional callback raised if there is an issue to load the texture
          * @param format defines the format of the data
          * @param forcedExtension defines the extension to use to pick the right loader
+         * @param createPolynomials defines wheter or not to create polynomails harmonics for the texture
          * @returns the cube texture as an InternalTexture
          */
         public createPrefilteredCubeTexture(rootUrl: string, scene: Nullable<Scene>, scale: number, offset: number,
             onLoad: Nullable<(internalTexture: Nullable<InternalTexture>) => void> = null,
-            onError: Nullable<(message?: string, exception?: any) => void> = null, format?: number, forcedExtension: any = null): InternalTexture {
+            onError: Nullable<(message?: string, exception?: any) => void> = null, format?: number, forcedExtension: any = null,
+            createPolynomials: boolean = true): InternalTexture {
             var callback = (loadData: any) => {
                 if (!loadData) {
                     if (onLoad) {
@@ -5365,7 +5367,10 @@
                 }
 
                 let texture = loadData.texture as InternalTexture;
-                if(loadData.info.sphericalPolynomial){
+                if (!createPolynomials) {
+                    texture._sphericalPolynomial = new BABYLON.SphericalPolynomial();
+                }
+                else if(loadData.info.sphericalPolynomial){
                     texture._sphericalPolynomial = loadData.info.sphericalPolynomial;
                 }
                 texture._dataSource = InternalTexture.DATASOURCE_CUBEPREFILTERED;
@@ -5440,7 +5445,7 @@
                 }
             };
 
-            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, true);
+            return this.createCubeTexture(rootUrl, scene, null, false, callback, onError, format, forcedExtension, createPolynomials);
         }
 
         /**

+ 32 - 5
src/Materials/Textures/babylon.cubeTexture.ts

@@ -54,6 +54,7 @@
         private _textureMatrix: Matrix;
         private _format: number;
         private _prefiltered: boolean;
+        private _createPolynomials: boolean;
 
         public static CreateFromImages(files: string[], scene: Scene, noMipmap?: boolean) {
             let rootUrlKey = "";
@@ -63,12 +64,37 @@
             return new CubeTexture(rootUrlKey, scene, null, noMipmap, files);
         }
 
-        public static CreateFromPrefilteredData(url: string, scene: Scene, forcedExtension: any = null) {
-            return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension);
+        /**
+         * Creates and return a texture created from prefilterd data by tools like IBL Baker or Lys.
+         * @param url defines the url of the prefiltered texture
+         * @param scene defines the scene the texture is attached to
+         * @param forcedExtension defines the extension of the file if different from the url
+         * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
+         * @return the prefiltered texture
+         */
+        public static CreateFromPrefilteredData(url: string, scene: Scene, forcedExtension: any = null, createPolynomials: boolean = true) {
+            return new CubeTexture(url, scene, null, false, null, null, null, undefined, true, forcedExtension, createPolynomials);
         }
 
+        /**
+         * Creates a cube texture to use with reflection for instance. It can be based upon dds or six images as well
+         * as prefiltered data.
+         * @param rootUrl defines the url of the texture or the root name of the six images
+         * @param scene defines the scene the texture is attached to
+         * @param extensions defines the suffixes add to the picture name in case six images are in use like _px.jpg...
+         * @param noMipmap defines if mipmaps should be created or not
+         * @param files defines the six files to load for the different faces
+         * @param onLoad defines a callback triggered at the end of the file load if no errors occured
+         * @param onError defines a callback triggered in case of error during load
+         * @param format defines the internal format to use for the texture once loaded
+         * @param prefiltered defines whether or not the texture is created from prefiltered data
+         * @param forcedExtension defines the extensions to use (force a special type of file to load) in case it is different from the file name
+         * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary
+         * @return the cube texture
+         */
         constructor(rootUrl: string, scene: Scene, extensions: Nullable<string[]> = null, noMipmap: boolean = false, files: Nullable<string[]> = null,
-            onLoad: Nullable<() => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format: number = Engine.TEXTUREFORMAT_RGBA, prefiltered = false, forcedExtension: any = null) {
+            onLoad: Nullable<() => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null, format: number = Engine.TEXTUREFORMAT_RGBA, prefiltered = false, 
+            forcedExtension: any = null, createPolynomials: boolean = false) {
             super(scene);
 
             this.name = rootUrl;
@@ -79,6 +105,7 @@
             this._prefiltered = prefiltered;
             this.isCube = true;
             this._textureMatrix = Matrix.Identity();
+            this._createPolynomials = createPolynomials;
             if (prefiltered) {
                 this.gammaSpace = false;
             }
@@ -113,7 +140,7 @@
             if (!this._texture) {
                 if (!scene.useDelayedTextureLoading) {
                     if (prefiltered) {
-                        this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, this.lodGenerationScale, this.lodGenerationOffset, onLoad, onError, format, forcedExtension);
+                        this._texture = scene.getEngine().createPrefilteredCubeTexture(rootUrl, scene, this.lodGenerationScale, this.lodGenerationOffset, onLoad, onError, format, forcedExtension, this._createPolynomials);
                     }
                     else {
                         this._texture = scene.getEngine().createCubeTexture(rootUrl, scene, files, noMipmap, onLoad, onError, this._format, forcedExtension);
@@ -146,7 +173,7 @@
 
             if (!this._texture) {
                 if (this._prefiltered) {
-                    this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format);
+                    this._texture = scene.getEngine().createPrefilteredCubeTexture(this.url, scene, this.lodGenerationScale, this.lodGenerationOffset, undefined, undefined, this._format, undefined, this._createPolynomials);
                 }
                 else {
                     this._texture = scene.getEngine().createCubeTexture(this.url, scene, this._files, this._noMipmap, undefined, undefined, this._format);

+ 1 - 0
src/Materials/Textures/babylon.internalTexture.ts

@@ -353,6 +353,7 @@ module BABYLON {
 
                         this.isReady = true;
                     }, null, this.format, this._extension);
+                    proxy._sphericalPolynomial = this._sphericalPolynomial;
                     return;
             }
         }

+ 7 - 2
src/Mesh/babylon.abstractMesh.ts

@@ -1056,9 +1056,10 @@
         /**
          * Return the minimum and maximum world vectors of the entire hierarchy under current mesh
          * @param includeDescendants Include bounding info from descendants as well (true by default)
+         * @param predicate defines a callback function that can be customize to filter what meshes should be included in the list used to compute the bounding vectors
          * @returns the new bounding vectors
          */
-        public getHierarchyBoundingVectors(includeDescendants = true): { min: Vector3, max: Vector3 } {
+        public getHierarchyBoundingVectors(includeDescendants = true, predicate: Nullable<(abstractMesh: AbstractMesh) => boolean> = null): { min: Vector3, max: Vector3 } {
             // Ensures that all world matrix will be recomputed.
             this.getScene().incrementRenderId();
 
@@ -1081,9 +1082,13 @@
 
                 for (var descendant of descendants) {
                     let childMesh = <AbstractMesh>descendant;
-
                     childMesh.computeWorldMatrix(true);
 
+                    // Filters meshes based on custom predicate function.
+                    if (predicate && !predicate(childMesh)) {
+                        continue;
+                    }
+
                     //make sure we have the needed params to get mix and max
                     if (!childMesh.getBoundingInfo || childMesh.getTotalVertices() === 0) {
                         continue;

+ 4 - 4
src/Mesh/babylon.mesh.ts

@@ -177,9 +177,6 @@
             scene = this.getScene();
 
             if (source) {
-                // Source mesh
-                this._source = source;
-
                 // Geometry
                 if (source._geometry) {
                     source._geometry.applyToMesh(this);
@@ -188,7 +185,10 @@
                 // Deep copy
                 Tools.DeepCopy(source, this, ["name", "material", "skeleton", "instances", "parent", "uniqueId", 
                                               "source", "metadata", "hasLODLevels", "geometry", "isBlocked", "areNormalsFrozen"], 
-                                              ["_poseMatrix", "_source"]);
+                                              ["_poseMatrix"]);
+
+                // Source mesh
+                this._source = source;
 
                 // Metadata
                 if (source.metadata && source.metadata.clone) {