Bläddra i källkod

Merge remote-tracking branch 'BabylonJS/master'

MackeyK24 7 år sedan
förälder
incheckning
a5185b3c3c
80 ändrade filer med 128062 tillägg och 30261 borttagningar
  1. 4 4
      .vscode/launch.json
  2. 28 3
      .vscode/tasks.json
  3. 21667 21582
      Playground/babylon.d.txt
  4. 5 2
      Playground/debug.html
  5. 4 1
      Playground/frame.html
  6. 4 1
      Playground/full.html
  7. 5 2
      Playground/index-local.html
  8. 5 2
      Playground/index.html
  9. 5 2
      Playground/indexStable.html
  10. 1 0
      Playground/scenes/dummy3.babylon
  11. 6 2
      Playground/zipContent/index.html
  12. 1 0
      Tools/Gulp/config.json
  13. 4 11
      Tools/Gulp/gulp-addModuleExports.js
  14. 37 0
      Tools/Gulp/gulp-decorateAndExtends.js
  15. 7 1
      Tools/Gulp/gulpfile.js
  16. 1 1
      Viewer/tsconfig.json
  17. 2 2
      Viewer/webpack.config.js
  18. 8095 8010
      dist/preview release/babylon.d.ts
  19. 55 55
      dist/preview release/babylon.js
  20. 315 45
      dist/preview release/babylon.max.js
  21. 96232 0
      dist/preview release/babylon.no-module.max.js
  22. 53 53
      dist/preview release/babylon.worker.js
  23. 30 31
      dist/preview release/draco_decoder.js
  24. BIN
      dist/preview release/draco_decoder.wasm
  25. 115 0
      dist/preview release/draco_wasm_wrapper.js
  26. 313 43
      dist/preview release/es6.js
  27. 2 2
      dist/preview release/gui/babylon.gui.js
  28. 4 4
      dist/preview release/gui/babylon.gui.min.js
  29. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  30. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  31. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  32. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  33. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  34. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  35. 2 2
      dist/preview release/loaders/babylonjs.loaders.js
  36. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  37. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  38. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  39. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  40. 2 2
      dist/preview release/materialsLibrary/babylonjs.materials.js
  41. 5 5
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  42. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  43. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  44. 2 2
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.js
  45. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  46. 2 2
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js
  47. 1 1
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js
  48. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  49. 2 2
      dist/preview release/serializers/babylonjs.serializers.js
  50. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  51. 2 7
      dist/preview release/typedocValidationBaseline.json
  52. 63 63
      dist/preview release/viewer/babylon.viewer.js
  53. 322 52
      dist/preview release/viewer/babylon.viewer.max.js
  54. 4 0
      dist/preview release/what's new.md
  55. 14 9
      loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts
  56. 3 1
      localDev/index.html
  57. 3 1
      sandbox/index-local.html
  58. 5 1
      sandbox/index.html
  59. 4 2
      sandbox/index.js
  60. 11 4
      src/Actions/babylon.actionManager.ts
  61. 29 1
      src/Animations/babylon.animation.ts
  62. 17 3
      src/Animations/babylon.runtimeAnimation.ts
  63. 19 0
      src/Layer/babylon.effectLayer.ts
  64. 3 1
      src/Layer/babylon.glowLayer.ts
  65. 86 0
      src/Layer/babylon.highlightLayer.ts
  66. 8 0
      src/Loading/Plugins/babylon.babylonFileLoader.ts
  67. 17 0
      src/Materials/Textures/babylon.cubeTexture.ts
  68. 2 2
      src/Materials/Textures/babylon.hdrCubeTexture.ts
  69. 13 1
      src/Materials/Textures/babylon.mirrorTexture.ts
  70. 13 0
      src/Materials/babylon.standardMaterial.ts
  71. 73 36
      src/Math/babylon.math.ts
  72. 153 105
      src/Mesh/Compression/babylon.dracoCompression.ts
  73. 6 3
      src/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.ts
  74. 58 55
      src/Shaders/default.fragment.fx
  75. 10 0
      src/Tools/babylon.sceneSerializer.ts
  76. 1 1
      src/Tools/babylon.tools.ts
  77. 16 1
      src/babylon.assetContainer.ts
  78. 53 10
      src/babylon.scene.ts
  79. BIN
      tests/validation/ReferenceImages/enableDisablePostProcess.png
  80. 12 1
      tests/validation/validation.js

+ 4 - 4
.vscode/launch.json

@@ -5,10 +5,10 @@
             "name": "Launch Viewer (Chrome)",
             "type": "chrome",
             "request": "launch",
-            "url": "http://localhost:9000/",
-            "webRoot": "${workspaceRoot}/Viewer/dist/",
+            "url": "http://localhost:9000/basicExample.html",
+            "webRoot": "${workspaceRoot}/Viewer/",
             "sourceMaps": true,
-            //"preLaunchTask": "build-viewer", // TODO - test why this fails.
+            "preLaunchTask": "serve-viewer",
             "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis"
@@ -171,6 +171,6 @@
             "runtimeArgs": [
                 "--enable-unsafe-es3-apis"
             ]
-        },        
+        },
     ]
 }

+ 28 - 3
.vscode/tasks.json

@@ -15,7 +15,7 @@
         "panel": "shared"
     },
     "tasks": [
-        { 
+        {
             "label": "run",
             "group": {
                 "kind": "build",
@@ -40,12 +40,37 @@
                 }
             }
         },
-        { 
+        {
             "taskName": "typescript-all",
             "isBuildCommand": true,
             "problemMatcher": [
                 "$tsc"
             ]
+        },
+        {
+            "label": "serve-viewer",
+            "type": "npm",
+            "script": "start:server",
+            "path": "Viewer/",
+            "problemMatcher": [
+                {
+                    "owner": "webpack-dev-server",
+                    "pattern": {
+                        "regexp": "^([^\\s].*)\\((\\d+|\\,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
+                        "file": 1,
+                        "location": 2,
+                        "severity": 3,
+                        "code": 4,
+                        "message": 5
+                    },
+                    "background": {
+                        "activeOnStart": true,
+                        "beginsPattern": "Project is running at",
+                        "endsPattern": "webpack: Compiled successfully."
+                    }
+                }
+            ],
+            "isBackground": true
         }
     ]
-}
+}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 21667 - 21582
Playground/babylon.d.txt


+ 5 - 2
Playground/debug.html

@@ -33,11 +33,14 @@
     <!-- jszip -->
     <script src="js/libs/jszip.min.js"></script>
     <script src="js/libs/fileSaver.js"></script>
-    <!--Monaco-->
+    <!-- Draco -->
+    <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
+    <script src="https://preview.babylonjs.com/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+    <script src="https://preview.babylonjs.com/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
+    <!-- Monaco -->
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
     <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
     <script src="https://preview.babylonjs.com/babylon.max.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 4 - 1
Playground/frame.html

@@ -24,9 +24,12 @@
     <meta name="theme-color" content="#ffffff">
 
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+    <!-- Draco -->
+    <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
+    <script src="https://preview.babylonjs.com/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+    <script src="https://preview.babylonjs.com/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
     <!-- Babylon.js -->
     <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 4 - 1
Playground/full.html

@@ -24,9 +24,12 @@
         <meta name="theme-color" content="#ffffff">
 
         <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+        <!-- Draco -->
+        <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
+        <script src="https://preview.babylonjs.com/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+        <script src="https://preview.babylonjs.com/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
         <!-- Babylon.js -->
         <script src="https://preview.babylonjs.com/cannon.js"></script>
-        <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 5 - 2
Playground/index-local.html

@@ -17,10 +17,13 @@
         <script src="../dist/preview%20release/cannon.js"></script>
         <script src="../dist/preview%20release/Oimo.js"></script>
         <script src="../dist/preview%20release/earcut.min.js"></script>
-        <!--Monaco-->
+        <!-- Draco -->
+        <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
+        <script src="../dist/preview%20release/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+        <script src="../dist/preview%20release/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
+        <!-- Monaco -->
         <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
         <!-- Babylon.js -->
-        <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
         <script src="../tools/DevLoader/BabylonLoader.js"></script>
 
         <link href="css/index.css" rel="stylesheet" />

+ 5 - 2
Playground/index.html

@@ -37,10 +37,13 @@
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
         <script src="https://preview.babylonjs.com/earcut.min.js"></script>
-        <!--Monaco-->
+        <!-- Draco -->
+        <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
+        <script src="https://preview.babylonjs.com/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+        <script src="https://preview.babylonjs.com/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
+        <!-- Monaco -->
         <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
         <!-- Babylon.js -->
-        <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
 

+ 5 - 2
Playground/indexStable.html

@@ -36,10 +36,13 @@
         <!-- Physics -->
         <script src="https://cdn.babylonjs.com/cannon.js"></script>
         <script src="https://cdn.babylonjs.com/Oimo.js"></script>
-        <!--Monaco-->
+        <!-- Draco -->
+        <script src="https://cdn.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
+        <script src="https://cdn.babylonjs.com/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+        <script src="https://cdn.babylonjs.com/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
+        <!-- Monaco -->
         <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
         <!-- Babylon.js -->
-        <script src="https://cdn.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
         <script src="https://cdn.babylonjs.com/babylon.js"></script>
         <script src="https://cdn.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
Playground/scenes/dummy3.babylon


+ 6 - 2
Playground/zipContent/index.html

@@ -4,14 +4,18 @@
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 
         <title>Babylon.js sample code</title>
+
+        <!-- Draco -->
+        <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
+        <script src="https://preview.babylonjs.com/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+        <script src="https://preview.babylonjs.com/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
         <!-- Babylon.js -->
         <script src="https://www.babylonjs.com/hand.minified-1.2.js"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
         <script src="https://preview.babylonjs.com/cannon.js"></script>
-        <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
         <script src="https://preview.babylonjs.com/oimo.js"></script>
-        
+
         <style>
             html, body {
                 overflow: hidden;

+ 1 - 0
Tools/Gulp/config.json

@@ -3,6 +3,7 @@
         "filename": "babylon.max.js",
         "minFilename": "babylon.js",
         "minWorkerFilename": "babylon.worker.js",
+        "noModuleFilename": "babylon.no-module.max.js",
         "declarationFilename": "babylon.d.ts",
         "declarationModuleFilename": "babylon.module.d.ts",
         "outputDirectory": "../../dist/preview release",

+ 4 - 11
Tools/Gulp/gulp-addModuleExports.js

@@ -87,13 +87,6 @@ if(typeof earcut !== 'undefined') {
 `;
         }
 
-        var extendsAddition =
-            `var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
-`;
-
-        var decorateAddition = `var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-`;
-
         if (file.isNull()) {
             cb(null, file);
             return;
@@ -105,12 +98,12 @@ if(typeof earcut !== 'undefined') {
         }
 
         try {
-            if (config.externalUsingBabylon) {
-                file.contents = new Buffer(String('').concat(moduleExportAddition(varName)));
-            } else {
+            //if (config.externalUsingBabylon) {
+            file.contents = new Buffer(String('').concat(moduleExportAddition(varName)));
+            /*} else {
                 let pretext = '';
                 file.contents = new Buffer(decorateAddition.concat(new Buffer(extendsAddition.concat(String('')).concat(moduleExportAddition(varName)))));
-            }
+            }*/
             this.push(file);
         } catch (err) {
             this.emit('error', new gutil.PluginError('gulp-add-module-exports', err, { fileName: file.path }));

+ 37 - 0
Tools/Gulp/gulp-decorateAndExtends.js

@@ -0,0 +1,37 @@
+var gutil = require('gulp-util');
+var through = require('through2');
+
+/**
+ * The parameters for this function has grown during development.
+ * Eventually, this function will need to be reorganized. 
+ */
+//  subModule, extendsRoot, externalUsingBabylon, noBabylonInit
+module.exports = function (varName, config) {
+    return through.obj(function (file, enc, cb) {
+
+        var extendsAddition =
+            `var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
+`;
+
+        var decorateAddition = `var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+`;
+
+        if (file.isNull()) {
+            cb(null, file);
+            return;
+        }
+
+        if (file.isStream()) {
+            //streams not supported, no need for now.
+            return;
+        }
+
+        try {
+            file.contents = new Buffer(decorateAddition.concat(extendsAddition).concat(file.contents));
+            this.push(file);
+        } catch (err) {
+            this.emit('error', new gutil.PluginError('gulp-decorate-and-extends', err, { fileName: file.path }));
+        }
+        cb();
+    });
+};

+ 7 - 1
Tools/Gulp/gulpfile.js

@@ -5,6 +5,7 @@ var sourcemaps = require("gulp-sourcemaps");
 var srcToVariable = require("gulp-content-to-variable");
 var appendSrcToVariable = require("./gulp-appendSrcToVariable");
 var addDtsExport = require("./gulp-addDtsExport");
+var addDecorateAndExtends = require("./gulp-decorateAndExtends");
 var addModuleExports = require("./gulp-addModuleExports");
 var addES6Exports = require("./gulp-addES6Exports");
 var babylonModuleExports = require("./gulp-babylonModule");
@@ -239,10 +240,13 @@ gulp.task("build", ["shaders"], function () {
     )
     return merge2(
         mergedStreams
-            .pipe(concat(config.build.filename))
+            .pipe(concat(config.build.noModuleFilename))
             .pipe(cleants())
             .pipe(replace(extendsSearchRegex, ""))
             .pipe(replace(decorateSearchRegex, ""))
+            .pipe(addDecorateAndExtends())
+            .pipe(gulp.dest(config.build.outputDirectory))
+            .pipe(rename(config.build.filename))
             .pipe(addModuleExports("BABYLON", {
                 dependencies: config.build.dependencies
             }))
@@ -322,6 +326,7 @@ var buildExternalLibraries = function (settings) {
                 .pipe(replace(extendsSearchRegex, ""))
                 .pipe(replace(decorateSearchRegex, ""))
                 .pipe(replace(referenceSearchRegex, ""))
+                .pipe(addDecorateAndExtends())
                 .pipe(addModuleExports(settings.build.moduleDeclaration, { subModule: true, extendsRoot: settings.build.extendsRoot }))
                 .pipe(gulp.dest(outputDirectory))
                 .pipe(cleants())
@@ -405,6 +410,7 @@ var buildExternalLibrary = function (library, settings, watch) {
         if (library.buildAsModule) {
             code = code.pipe(replace(extendsSearchRegex, ""))
                 .pipe(replace(decorateSearchRegex, ""))
+                .pipe(addDecorateAndExtends())
                 .pipe(addModuleExports(library.moduleDeclaration, { subModule: true, extendsRoot: library.extendsRoot }))
         }
 

+ 1 - 1
Viewer/tsconfig.json

@@ -7,7 +7,7 @@
         "strictNullChecks": true,
         "removeComments": true,
         "preserveConstEnums": true,
-        "sourceMap": false,
+        "sourceMap": true,
         "experimentalDecorators": true,
         "isolatedModules": false,
         "declaration": false,

+ 2 - 2
Viewer/webpack.config.js

@@ -11,7 +11,7 @@ module.exports = {
         libraryTarget: 'umd',
         library: 'BabylonViewer',
         umdNamedDefine: true,
-        devtoolModuleFilenameTemplate: '[absolute-resource-path]'
+        devtoolModuleFilenameTemplate: '[relative-resource-path]'
     },
     resolve: {
         extensions: ['.ts', '.js'],
@@ -57,7 +57,7 @@ module.exports = {
     },
     devServer: {
         contentBase: path.join(__dirname, "dist"),
-        compress: true,
+        compress: false,
         //open: true,
         port: 9000
     }

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 8095 - 8010
dist/preview release/babylon.d.ts


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 55 - 55
dist/preview release/babylon.js


+ 315 - 45
dist/preview release/babylon.max.js

@@ -1,5 +1,3 @@
-var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 
 
 (function universalModuleDefinition(root, factory) {
@@ -33,6 +31,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
   OIMO = OIMO || this.OIMO;
   earcut = earcut || this.earcut;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 var BABYLON;
 (function (BABYLON) {
@@ -4724,7 +4724,6 @@ var BABYLON;
         Quaternion.SlerpToRef = function (left, right, amount, result) {
             var num2;
             var num3;
-            var num = amount;
             var num4 = (((left.x * right.x) + (left.y * right.y)) + (left.z * right.z)) + (left.w * right.w);
             var flag = false;
             if (num4 < 0) {
@@ -4732,14 +4731,14 @@ var BABYLON;
                 num4 = -num4;
             }
             if (num4 > 0.999999) {
-                num3 = 1 - num;
-                num2 = flag ? -num : num;
+                num3 = 1 - amount;
+                num2 = flag ? -amount : amount;
             }
             else {
                 var num5 = Math.acos(num4);
                 var num6 = (1.0 / Math.sin(num5));
-                num3 = (Math.sin((1.0 - num) * num5)) * num6;
-                num2 = flag ? ((-Math.sin(num * num5)) * num6) : ((Math.sin(num * num5)) * num6);
+                num3 = (Math.sin((1.0 - amount) * num5)) * num6;
+                num2 = flag ? ((-Math.sin(amount * num5)) * num6) : ((Math.sin(amount * num5)) * num6);
             }
             result.x = (num3 * left.x) + (num2 * right.x);
             result.y = (num3 * left.y) + (num2 * right.y);
@@ -5165,24 +5164,28 @@ var BABYLON;
          * @returns true if operation was successful
          */
         Matrix.prototype.decompose = function (scale, rotation, translation) {
-            translation.x = this.m[12];
-            translation.y = this.m[13];
-            translation.z = this.m[14];
+            if (translation) {
+                translation.x = this.m[12];
+                translation.y = this.m[13];
+                translation.z = this.m[14];
+            }
             scale.x = Math.sqrt(this.m[0] * this.m[0] + this.m[1] * this.m[1] + this.m[2] * this.m[2]);
             scale.y = Math.sqrt(this.m[4] * this.m[4] + this.m[5] * this.m[5] + this.m[6] * this.m[6]);
             scale.z = Math.sqrt(this.m[8] * this.m[8] + this.m[9] * this.m[9] + this.m[10] * this.m[10]);
             if (this.determinant() <= 0) {
                 scale.y *= -1;
             }
-            if (scale.x === 0 || scale.y === 0 || scale.z === 0) {
-                rotation.x = 0;
-                rotation.y = 0;
-                rotation.z = 0;
-                rotation.w = 1;
-                return false;
+            if (rotation) {
+                if (scale.x === 0 || scale.y === 0 || scale.z === 0) {
+                    rotation.x = 0;
+                    rotation.y = 0;
+                    rotation.z = 0;
+                    rotation.w = 1;
+                    return false;
+                }
+                Matrix.FromValuesToRef(this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0, this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0, this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0, 0, 0, 0, 1, MathTmp.Matrix[0]);
+                Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
             }
-            Matrix.FromValuesToRef(this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0, this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0, this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0, 0, 0, 0, 1, MathTmp.Matrix[0]);
-            Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
             return true;
         };
         /**
@@ -5772,18 +5775,36 @@ var BABYLON;
          * @returns the new matrix
          */
         Matrix.DecomposeLerp = function (startValue, endValue, gradient) {
-            var startScale = new Vector3(0, 0, 0);
-            var startRotation = new Quaternion();
-            var startTranslation = new Vector3(0, 0, 0);
+            var result = Matrix.Zero();
+            Matrix.DecomposeLerpToRef(startValue, endValue, gradient, result);
+            return result;
+        };
+        /**
+         * Update a matrix to values which are computed by:
+         * * decomposing the the "startValue" and "endValue" matrices into their respective scale, rotation and translation matrices
+         * * interpolating for "gradient" (float) the values between each of these decomposed matrices between the start and the end
+         * * recomposing a new matrix from these 3 interpolated scale, rotation and translation matrices
+         * @param startValue defines the first matrix
+         * @param endValue defines the second matrix
+         * @param gradient defines the gradient between the two matrices
+         * @param result defines the target matrix
+         */
+        Matrix.DecomposeLerpToRef = function (startValue, endValue, gradient, result) {
+            var startScale = MathTmp.Vector3[0];
+            var startRotation = MathTmp.Quaternion[0];
+            var startTranslation = MathTmp.Vector3[1];
             startValue.decompose(startScale, startRotation, startTranslation);
-            var endScale = new Vector3(0, 0, 0);
-            var endRotation = new Quaternion();
-            var endTranslation = new Vector3(0, 0, 0);
+            var endScale = MathTmp.Vector3[2];
+            var endRotation = MathTmp.Quaternion[1];
+            var endTranslation = MathTmp.Vector3[3];
             endValue.decompose(endScale, endRotation, endTranslation);
-            var resultScale = Vector3.Lerp(startScale, endScale, gradient);
-            var resultRotation = Quaternion.Slerp(startRotation, endRotation, gradient);
-            var resultTranslation = Vector3.Lerp(startTranslation, endTranslation, gradient);
-            return Matrix.Compose(resultScale, resultRotation, resultTranslation);
+            var resultScale = MathTmp.Vector3[4];
+            Vector3.LerpToRef(startScale, endScale, gradient, resultScale);
+            var resultRotation = MathTmp.Quaternion[2];
+            Quaternion.SlerpToRef(startRotation, endRotation, gradient, resultRotation);
+            var resultTranslation = MathTmp.Vector3[5];
+            Vector3.LerpToRef(startTranslation, endTranslation, gradient, resultTranslation);
+            Matrix.ComposeToRef(resultScale, resultRotation, resultTranslation, result);
         };
         /**
          * Gets a new rotation matrix used to rotate an entity so as it looks at the target vector3, from the eye vector3 position, the up vector3 being oriented like "up"
@@ -7105,9 +7126,9 @@ var BABYLON;
     var MathTmp = /** @class */ (function () {
         function MathTmp() {
         }
-        MathTmp.Vector3 = [Vector3.Zero()];
+        MathTmp.Vector3 = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];
         MathTmp.Matrix = [Matrix.Zero(), Matrix.Zero()];
-        MathTmp.Quaternion = [Quaternion.Zero()];
+        MathTmp.Quaternion = [Quaternion.Zero(), Quaternion.Zero(), Quaternion.Zero()];
         return MathTmp;
     }());
 })(BABYLON || (BABYLON = {}));
@@ -25322,16 +25343,22 @@ var BABYLON;
                 var target = this._registeredForLateAnimationBindings.data[index];
                 for (var path in target._lateAnimationHolders) {
                     var holder = target._lateAnimationHolders[path];
+                    var originalValue = holder.animations[0].originalValue;
                     // Sanity check
-                    if (!holder.animations[0].originalValue.scaleAndAddToRef) {
+                    if (!originalValue.scaleAndAddToRef) {
                         continue;
                     }
+                    var matrixDecomposeMode = BABYLON.Animation.AllowMatrixDecomposeForInterpolation && originalValue.m; // ie. data is matrix
                     var normalizer = 1.0;
                     var finalValue = void 0;
                     if (holder.totalWeight < 1.0) {
-                        // We need to mix the original value in
-                        var originalValue = holder.animations[0].originalValue;
-                        finalValue = originalValue.scale(1.0 - holder.totalWeight);
+                        // We need to mix the original value in     
+                        if (matrixDecomposeMode) {
+                            finalValue = originalValue.clone();
+                        }
+                        else {
+                            finalValue = originalValue.scale(1.0 - holder.totalWeight);
+                        }
                     }
                     else {
                         // We need to normalize the weights
@@ -25339,11 +25366,27 @@ var BABYLON;
                     }
                     for (var animIndex = 0; animIndex < holder.animations.length; animIndex++) {
                         var runtimeAnimation = holder.animations[animIndex];
+                        var scale = runtimeAnimation.weight / normalizer;
                         if (finalValue) {
-                            runtimeAnimation.currentValue.scaleAndAddToRef(runtimeAnimation.weight / normalizer, finalValue);
+                            if (matrixDecomposeMode) {
+                                BABYLON.Matrix.DecomposeLerpToRef(finalValue, runtimeAnimation.currentValue, scale, finalValue);
+                            }
+                            else {
+                                runtimeAnimation.currentValue.scaleAndAddToRef(scale, finalValue);
+                            }
                         }
                         else {
-                            finalValue = runtimeAnimation.currentValue.scale(runtimeAnimation.weight / normalizer);
+                            if (scale !== 1) {
+                                if (matrixDecomposeMode) {
+                                    finalValue = runtimeAnimation.currentValue.clone();
+                                }
+                                else {
+                                    finalValue = runtimeAnimation.currentValue.scale(scale);
+                                }
+                            }
+                            else {
+                                finalValue = runtimeAnimation.currentValue;
+                            }
                         }
                     }
                     runtimeAnimation.target[path] = finalValue;
@@ -25657,6 +25700,18 @@ var BABYLON;
             return index;
         };
         /**
+         * Removes the given effect layer from this scene.
+         * @param toRemove defines the effect layer to remove
+         * @returns the index of the removed effect layer
+         */
+        Scene.prototype.removeEffectLayer = function (toRemove) {
+            var index = this.effectLayers.indexOf(toRemove);
+            if (index !== -1) {
+                this.effectLayers.splice(index, 1);
+            }
+            return index;
+        };
+        /**
          * Removes the given texture from this scene.
          * @param toRemove The texture to remove
          * @returns The index of the removed texture
@@ -25765,6 +25820,13 @@ var BABYLON;
             this.lensFlareSystems.push(newLensFlareSystem);
         };
         /**
+         * Adds the given effect layer to this scene
+         * @param newEffectLayer defines the effect layer to add
+         */
+        Scene.prototype.addEffectLayer = function (newEffectLayer) {
+            this.effectLayers.push(newEffectLayer);
+        };
+        /**
          * Adds the given action manager to this scene
          * @param newActionManager The action manager to add
          */
@@ -26844,7 +26906,10 @@ var BABYLON;
                                 action._executeCurrent(BABYLON.ActionEvent.CreateNew(sourceMesh, undefined, otherMesh));
                             }
                             //if this is an exit trigger, or no exit trigger exists, remove the id from the intersection in progress array.
-                            if (!sourceMesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger) || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
+                            if (!sourceMesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger, function (parameter) {
+                                var parameterMesh = parameter instanceof BABYLON.AbstractMesh ? parameter : parameter.mesh;
+                                return otherMesh === parameterMesh;
+                            }) || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
                                 sourceMesh._intersectionsInProgress.splice(currentIntersectionInProgress, 1);
                             }
                         }
@@ -28253,6 +28318,10 @@ var BABYLON;
              * Textures to keep.
              */
             this.textures = new Array();
+            /**
+             * Effect layers to keep.
+             */
+            this.effectLayers = new Array();
         }
         return KeepAssets;
     }());
@@ -28335,6 +28404,10 @@ var BABYLON;
              * Textures populated in the container.
              */
             this.textures = new Array();
+            /**
+             * Effect layers populated in the container.
+             */
+            this.effectLayers = new Array();
             this.scene = scene;
         }
         /**
@@ -28390,7 +28463,10 @@ var BABYLON;
                 _this.scene.mainSoundTrack.AddSound(o);
             });
             this.textures.forEach(function (o) {
-                _this.scene.addTexture;
+                _this.scene.addTexture(o);
+            });
+            this.effectLayers.forEach(function (o) {
+                _this.scene.addEffectLayer(o);
             });
         };
         /**
@@ -28448,6 +28524,9 @@ var BABYLON;
             this.textures.forEach(function (o) {
                 _this.scene.removeTexture(o);
             });
+            this.effectLayers.forEach(function (o) {
+                _this.scene.removeEffectLayer(o);
+            });
         };
         AssetContainer.prototype._moveAssets = function (sourceAssets, targetAssets, keepAssets) {
             for (var _i = 0, sourceAssets_1 = sourceAssets; _i < sourceAssets_1.length; _i++) {
@@ -28489,6 +28568,7 @@ var BABYLON;
             this._moveAssets(this.scene.mainSoundTrack.soundCollection, this.sounds, keepAssets.sounds);
             this._moveAssets(this.scene.transformNodes, this.transformNodes, keepAssets.transformNodes);
             this._moveAssets(this.scene.textures, this.textures, keepAssets.textures);
+            this._moveAssets(this.scene.effectLayers, this.effectLayers, keepAssets.effectLayers);
             this.removeAllFromScene();
         };
         return AssetContainer;
@@ -49879,6 +49959,9 @@ var BABYLON;
             return BABYLON.Color3.Lerp(startValue, endValue, gradient);
         };
         Animation.prototype.matrixInterpolateFunction = function (startValue, endValue, gradient) {
+            if (Animation.AllowMatrixDecomposeForInterpolation) {
+                return BABYLON.Matrix.DecomposeLerp(startValue, endValue, gradient);
+            }
             return BABYLON.Matrix.Lerp(startValue, endValue, gradient);
         };
         Animation.prototype.clone = function () {
@@ -50097,7 +50180,14 @@ var BABYLON;
                 }
             }
         };
+        /**
+         * Use matrix interpolation instead of using direct key value when animating matrices
+         */
         Animation.AllowMatricesInterpolation = false;
+        /**
+         * When matrix interpolation is enabled, this boolean forces the system to use Matrix.DecomposeLerp instead of Matrix.Lerp. Interpolation is more precise but slower
+         */
+        Animation.AllowMatrixDecomposeForInterpolation = true;
         // Statics
         Animation._ANIMATIONTYPE_FLOAT = 0;
         Animation._ANIMATIONTYPE_VECTOR3 = 1;
@@ -50694,7 +50784,22 @@ var BABYLON;
                     }
                 }
                 else if (this._originalBlendValue.m) {
-                    this._currentValue = BABYLON.Matrix.Lerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                    if (BABYLON.Animation.AllowMatrixDecomposeForInterpolation) {
+                        if (this._currentValue) {
+                            BABYLON.Matrix.DecomposeLerpToRef(this._originalBlendValue, currentValue, this._blendingFactor, this._currentValue);
+                        }
+                        else {
+                            this._currentValue = BABYLON.Matrix.DecomposeLerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                        }
+                    }
+                    else {
+                        if (this._currentValue) {
+                            BABYLON.Matrix.LerpToRef(this._originalBlendValue, currentValue, this._blendingFactor, this._currentValue);
+                        }
+                        else {
+                            this._currentValue = BABYLON.Matrix.Lerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                        }
+                    }
                 }
                 else {
                     this._currentValue = this._originalBlendValue * (1.0 - this._blendingFactor) + this._blendingFactor * currentValue;
@@ -52105,14 +52210,22 @@ var BABYLON;
         };
         /**
          * Does this action manager handles actions of a given trigger
-         * @param {number} trigger - the trigger to be tested
-         * @return {boolean} whether the trigger is handeled
+         * @param trigger defines the trigger to be tested
+         * @param parameterPredicate defines an optional predicate to filter triggers by parameter
+         * @return whether the trigger is handled
          */
-        ActionManager.prototype.hasSpecificTrigger = function (trigger) {
+        ActionManager.prototype.hasSpecificTrigger = function (trigger, parameterPredicate) {
             for (var index = 0; index < this.actions.length; index++) {
                 var action = this.actions[index];
                 if (action.trigger === trigger) {
-                    return true;
+                    if (parameterPredicate) {
+                        if (parameterPredicate(action.getTriggerParameter())) {
+                            return true;
+                        }
+                    }
+                    else {
+                        return true;
+                    }
                 }
             }
             return false;
@@ -61733,6 +61846,11 @@ var BABYLON;
 
 "use strict";
 
+
+
+
+
+
 var BABYLON;
 (function (BABYLON) {
     var CubeTexture = /** @class */ (function (_super) {
@@ -61753,6 +61871,7 @@ var BABYLON;
              * It must define where the camera used to render the texture was set
              */
             _this.boundingBoxPosition = BABYLON.Vector3.Zero();
+            _this._rotationY = 0;
             _this.name = rootUrl;
             _this.url = rootUrl;
             _this._noMipmap = noMipmap;
@@ -61829,6 +61948,23 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(CubeTexture.prototype, "rotationY", {
+            /**
+             * Gets texture matrix rotation angle around Y axis radians.
+             */
+            get: function () {
+                return this._rotationY;
+            },
+            /**
+             * Sets texture matrix rotation angle around Y axis in radians.
+             */
+            set: function (value) {
+                this._rotationY = value;
+                this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
+            },
+            enumerable: true,
+            configurable: true
+        });
         CubeTexture.CreateFromImages = function (files, scene, noMipmap) {
             var rootUrlKey = "";
             files.forEach(function (url) { return rootUrlKey += url; });
@@ -61894,6 +62030,9 @@ var BABYLON;
                 return new CubeTexture(_this.url, scene, _this._extensions, _this._noMipmap, _this._files);
             }, this);
         };
+        __decorate([
+            BABYLON.serialize("rotationY")
+        ], CubeTexture.prototype, "_rotationY", void 0);
         return CubeTexture;
     }(BABYLON.BaseTexture));
     BABYLON.CubeTexture = CubeTexture;
@@ -66429,6 +66568,13 @@ var BABYLON;
                     light_2._includedOnlyMeshesIds = [];
                 }
             }
+            // Effect layers
+            if (parsedData.effectLayers) {
+                for (index = 0; index < parsedData.effectLayers.length; index++) {
+                    var effectLayer = BABYLON.EffectLayer.Parse(parsedData.effectLayers[index], scene, rootUrl);
+                    container.effectLayers.push(effectLayer);
+                }
+            }
             // Actions (scene)
             if (parsedData.actions !== undefined && parsedData.actions !== null) {
                 BABYLON.ActionManager.Parse(parsedData.actions, null, scene);
@@ -73892,7 +74038,7 @@ var BABYLON;
                 return this._circleOfConfusion.focalLength;
             },
             /**
-             * The focal the length of the camera used in the effect
+             * The focal the length of the camera used in the effect in scene units/1000 (eg. millimeter)
              */
             set: function (value) {
                 this._circleOfConfusion.focalLength = value;
@@ -78768,6 +78914,7 @@ var BABYLON;
              */
             _this.isPMREM = false;
             _this._isBlocking = true;
+            _this._rotationY = 0;
             /**
              * Gets or sets the center of the bounding box associated with the cube texture
              * It must define where the camera used to render the texture was set
@@ -78830,6 +78977,23 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(HDRCubeTexture.prototype, "rotationY", {
+            /**
+             * Gets texture matrix rotation angle around Y axis radians.
+             */
+            get: function () {
+                return this._rotationY;
+            },
+            /**
+             * Sets texture matrix rotation angle around Y axis in radians.
+             */
+            set: function (value) {
+                this._rotationY = value;
+                this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(HDRCubeTexture.prototype, "boundingBoxSize", {
             get: function () {
                 return this._boundingBoxSize;
@@ -79123,6 +79287,9 @@ var BABYLON;
                 if (parsedTexture.boundingBoxSize) {
                     texture.boundingBoxSize = BABYLON.Vector3.FromArray(parsedTexture.boundingBoxSize);
                 }
+                if (parsedTexture.rotationY) {
+                    texture.rotationY = parsedTexture.rotationY;
+                }
             }
             return texture;
         };
@@ -79144,6 +79311,7 @@ var BABYLON;
             serializationObject.customType = "BABYLON.HDRCubeTexture";
             serializationObject.noMipmap = this._noMipmap;
             serializationObject.isBlocking = this._isBlocking;
+            serializationObject.rotationY = this._rotationY;
             return serializationObject;
         };
         /**
@@ -90153,6 +90321,17 @@ var BABYLON;
         EffectLayer.prototype.getClassName = function () {
             return "EffectLayer";
         };
+        /**
+         * Creates an effect layer from parsed effect layer data
+         * @param parsedEffectLayer defines effect layer data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing the effect layer information
+         * @returns a parsed effect Layer
+         */
+        EffectLayer.Parse = function (parsedEffectLayer, scene, rootUrl) {
+            var effectLayerType = BABYLON.Tools.Instantiate(parsedEffectLayer.customType);
+            return effectLayerType.Parse(parsedEffectLayer, scene, rootUrl);
+        };
         __decorate([
             BABYLON.serialize()
         ], EffectLayer.prototype, "name", void 0);
@@ -90640,6 +90819,73 @@ var BABYLON;
             _super.prototype.dispose.call(this);
         };
         /**
+          * Gets the class name of the effect layer
+          * @returns the string with the class name of the effect layer
+          */
+        HighlightLayer.prototype.getClassName = function () {
+            return "HighlightLayer";
+        };
+        /**
+         * Serializes this Highlight layer
+         * @returns a serialized Highlight layer object
+         */
+        HighlightLayer.prototype.serialize = function () {
+            var serializationObject = BABYLON.SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.HighlightLayer";
+            // Highlighted meshes
+            serializationObject.meshes = [];
+            if (this._meshes) {
+                for (var m in this._meshes) {
+                    var mesh = this._meshes[m];
+                    if (mesh) {
+                        serializationObject.meshes.push({
+                            glowEmissiveOnly: mesh.glowEmissiveOnly,
+                            color: mesh.color.asArray(),
+                            meshId: mesh.mesh.id
+                        });
+                    }
+                }
+            }
+            // Excluded meshes
+            serializationObject.excludedMeshes = [];
+            if (this._excludedMeshes) {
+                for (var e in this._excludedMeshes) {
+                    var excludedMesh = this._excludedMeshes[e];
+                    if (excludedMesh) {
+                        serializationObject.excludedMeshes.push(excludedMesh.mesh.id);
+                    }
+                }
+            }
+            return serializationObject;
+        };
+        /**
+         * Creates a Highlight layer from parsed Highlight layer data
+         * @param parsedHightlightLayer defines the Highlight layer data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing the Highlight layer information
+         * @returns a parsed Highlight layer
+         */
+        HighlightLayer.Parse = function (parsedHightlightLayer, scene, rootUrl) {
+            var hl = BABYLON.SerializationHelper.Parse(function () { return new HighlightLayer(parsedHightlightLayer.name, scene, parsedHightlightLayer.options); }, parsedHightlightLayer, scene, rootUrl);
+            var index;
+            // Excluded meshes
+            for (index = 0; index < parsedHightlightLayer.excludedMeshes.length; index++) {
+                var mesh = scene.getMeshByID(parsedHightlightLayer.excludedMeshes[index]);
+                if (mesh) {
+                    hl.addExcludedMesh(mesh);
+                }
+            }
+            // Included meshes
+            for (index = 0; index < parsedHightlightLayer.meshes.length; index++) {
+                var highlightedMesh = parsedHightlightLayer.meshes[index];
+                var mesh = scene.getMeshByID(highlightedMesh.meshId);
+                if (mesh) {
+                    hl.addMesh(mesh, BABYLON.Color3.FromArray(highlightedMesh.color), highlightedMesh.glowEmissiveOnly);
+                }
+            }
+            return hl;
+        };
+        /**
          * Effect Name of the highlight layer.
          */
         HighlightLayer.EffectName = "HighlightLayer";
@@ -90656,6 +90902,21 @@ var BABYLON;
          * Stencil value used for the other meshes in the scene.
          */
         HighlightLayer.NormalMeshStencilReference = 0x01;
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "innerGlow", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "outerGlow", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "blurHorizontalSize", null);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "blurVerticalSize", null);
+        __decorate([
+            BABYLON.serialize("options")
+        ], HighlightLayer.prototype, "_options", void 0);
         return HighlightLayer;
     }(BABYLON.EffectLayer));
     BABYLON.HighlightLayer = HighlightLayer;
@@ -90992,6 +91253,7 @@ var BABYLON;
          */
         GlowLayer.prototype.serialize = function () {
             var serializationObject = BABYLON.SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.GlowLayer";
             var index;
             // Included meshes
             serializationObject.includedMeshes = [];
@@ -91060,7 +91322,7 @@ var BABYLON;
             BABYLON.serialize()
         ], GlowLayer.prototype, "intensity", null);
         __decorate([
-            BABYLON.serialize('options')
+            BABYLON.serialize("options")
         ], GlowLayer.prototype, "_options", void 0);
         return GlowLayer;
     }(BABYLON.EffectLayer));
@@ -92113,6 +92375,14 @@ var BABYLON;
                     serializationObject.sounds.push(soundtrack.soundCollection[soundId].serialize());
                 }
             }
+            // Effect layers
+            serializationObject.effectLayers = [];
+            for (index = 0; index < scene.effectLayers.length; index++) {
+                var layer = scene.effectLayers[index];
+                if (layer.serialize) {
+                    serializationObject.effectLayers.push(layer.serialize());
+                }
+            }
             return serializationObject;
         };
         SceneSerializer.SerializeMesh = function (toSerialize /* Mesh || Mesh[] */, withParents, withChildren) {

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 96232 - 0
dist/preview release/babylon.no-module.max.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 53 - 53
dist/preview release/babylon.worker.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 30 - 31
dist/preview release/draco_decoder.js


BIN
dist/preview release/draco_decoder.wasm


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 115 - 0
dist/preview release/draco_wasm_wrapper.js


+ 313 - 43
dist/preview release/es6.js

@@ -4691,7 +4691,6 @@ var BABYLON;
         Quaternion.SlerpToRef = function (left, right, amount, result) {
             var num2;
             var num3;
-            var num = amount;
             var num4 = (((left.x * right.x) + (left.y * right.y)) + (left.z * right.z)) + (left.w * right.w);
             var flag = false;
             if (num4 < 0) {
@@ -4699,14 +4698,14 @@ var BABYLON;
                 num4 = -num4;
             }
             if (num4 > 0.999999) {
-                num3 = 1 - num;
-                num2 = flag ? -num : num;
+                num3 = 1 - amount;
+                num2 = flag ? -amount : amount;
             }
             else {
                 var num5 = Math.acos(num4);
                 var num6 = (1.0 / Math.sin(num5));
-                num3 = (Math.sin((1.0 - num) * num5)) * num6;
-                num2 = flag ? ((-Math.sin(num * num5)) * num6) : ((Math.sin(num * num5)) * num6);
+                num3 = (Math.sin((1.0 - amount) * num5)) * num6;
+                num2 = flag ? ((-Math.sin(amount * num5)) * num6) : ((Math.sin(amount * num5)) * num6);
             }
             result.x = (num3 * left.x) + (num2 * right.x);
             result.y = (num3 * left.y) + (num2 * right.y);
@@ -5132,24 +5131,28 @@ var BABYLON;
          * @returns true if operation was successful
          */
         Matrix.prototype.decompose = function (scale, rotation, translation) {
-            translation.x = this.m[12];
-            translation.y = this.m[13];
-            translation.z = this.m[14];
+            if (translation) {
+                translation.x = this.m[12];
+                translation.y = this.m[13];
+                translation.z = this.m[14];
+            }
             scale.x = Math.sqrt(this.m[0] * this.m[0] + this.m[1] * this.m[1] + this.m[2] * this.m[2]);
             scale.y = Math.sqrt(this.m[4] * this.m[4] + this.m[5] * this.m[5] + this.m[6] * this.m[6]);
             scale.z = Math.sqrt(this.m[8] * this.m[8] + this.m[9] * this.m[9] + this.m[10] * this.m[10]);
             if (this.determinant() <= 0) {
                 scale.y *= -1;
             }
-            if (scale.x === 0 || scale.y === 0 || scale.z === 0) {
-                rotation.x = 0;
-                rotation.y = 0;
-                rotation.z = 0;
-                rotation.w = 1;
-                return false;
+            if (rotation) {
+                if (scale.x === 0 || scale.y === 0 || scale.z === 0) {
+                    rotation.x = 0;
+                    rotation.y = 0;
+                    rotation.z = 0;
+                    rotation.w = 1;
+                    return false;
+                }
+                Matrix.FromValuesToRef(this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0, this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0, this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0, 0, 0, 0, 1, MathTmp.Matrix[0]);
+                Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
             }
-            Matrix.FromValuesToRef(this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0, this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0, this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0, 0, 0, 0, 1, MathTmp.Matrix[0]);
-            Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
             return true;
         };
         /**
@@ -5739,18 +5742,36 @@ var BABYLON;
          * @returns the new matrix
          */
         Matrix.DecomposeLerp = function (startValue, endValue, gradient) {
-            var startScale = new Vector3(0, 0, 0);
-            var startRotation = new Quaternion();
-            var startTranslation = new Vector3(0, 0, 0);
+            var result = Matrix.Zero();
+            Matrix.DecomposeLerpToRef(startValue, endValue, gradient, result);
+            return result;
+        };
+        /**
+         * Update a matrix to values which are computed by:
+         * * decomposing the the "startValue" and "endValue" matrices into their respective scale, rotation and translation matrices
+         * * interpolating for "gradient" (float) the values between each of these decomposed matrices between the start and the end
+         * * recomposing a new matrix from these 3 interpolated scale, rotation and translation matrices
+         * @param startValue defines the first matrix
+         * @param endValue defines the second matrix
+         * @param gradient defines the gradient between the two matrices
+         * @param result defines the target matrix
+         */
+        Matrix.DecomposeLerpToRef = function (startValue, endValue, gradient, result) {
+            var startScale = MathTmp.Vector3[0];
+            var startRotation = MathTmp.Quaternion[0];
+            var startTranslation = MathTmp.Vector3[1];
             startValue.decompose(startScale, startRotation, startTranslation);
-            var endScale = new Vector3(0, 0, 0);
-            var endRotation = new Quaternion();
-            var endTranslation = new Vector3(0, 0, 0);
+            var endScale = MathTmp.Vector3[2];
+            var endRotation = MathTmp.Quaternion[1];
+            var endTranslation = MathTmp.Vector3[3];
             endValue.decompose(endScale, endRotation, endTranslation);
-            var resultScale = Vector3.Lerp(startScale, endScale, gradient);
-            var resultRotation = Quaternion.Slerp(startRotation, endRotation, gradient);
-            var resultTranslation = Vector3.Lerp(startTranslation, endTranslation, gradient);
-            return Matrix.Compose(resultScale, resultRotation, resultTranslation);
+            var resultScale = MathTmp.Vector3[4];
+            Vector3.LerpToRef(startScale, endScale, gradient, resultScale);
+            var resultRotation = MathTmp.Quaternion[2];
+            Quaternion.SlerpToRef(startRotation, endRotation, gradient, resultRotation);
+            var resultTranslation = MathTmp.Vector3[5];
+            Vector3.LerpToRef(startTranslation, endTranslation, gradient, resultTranslation);
+            Matrix.ComposeToRef(resultScale, resultRotation, resultTranslation, result);
         };
         /**
          * Gets a new rotation matrix used to rotate an entity so as it looks at the target vector3, from the eye vector3 position, the up vector3 being oriented like "up"
@@ -7072,9 +7093,9 @@ var BABYLON;
     var MathTmp = /** @class */ (function () {
         function MathTmp() {
         }
-        MathTmp.Vector3 = [Vector3.Zero()];
+        MathTmp.Vector3 = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];
         MathTmp.Matrix = [Matrix.Zero(), Matrix.Zero()];
-        MathTmp.Quaternion = [Quaternion.Zero()];
+        MathTmp.Quaternion = [Quaternion.Zero(), Quaternion.Zero(), Quaternion.Zero()];
         return MathTmp;
     }());
 })(BABYLON || (BABYLON = {}));
@@ -25289,16 +25310,22 @@ var BABYLON;
                 var target = this._registeredForLateAnimationBindings.data[index];
                 for (var path in target._lateAnimationHolders) {
                     var holder = target._lateAnimationHolders[path];
+                    var originalValue = holder.animations[0].originalValue;
                     // Sanity check
-                    if (!holder.animations[0].originalValue.scaleAndAddToRef) {
+                    if (!originalValue.scaleAndAddToRef) {
                         continue;
                     }
+                    var matrixDecomposeMode = BABYLON.Animation.AllowMatrixDecomposeForInterpolation && originalValue.m; // ie. data is matrix
                     var normalizer = 1.0;
                     var finalValue = void 0;
                     if (holder.totalWeight < 1.0) {
-                        // We need to mix the original value in
-                        var originalValue = holder.animations[0].originalValue;
-                        finalValue = originalValue.scale(1.0 - holder.totalWeight);
+                        // We need to mix the original value in     
+                        if (matrixDecomposeMode) {
+                            finalValue = originalValue.clone();
+                        }
+                        else {
+                            finalValue = originalValue.scale(1.0 - holder.totalWeight);
+                        }
                     }
                     else {
                         // We need to normalize the weights
@@ -25306,11 +25333,27 @@ var BABYLON;
                     }
                     for (var animIndex = 0; animIndex < holder.animations.length; animIndex++) {
                         var runtimeAnimation = holder.animations[animIndex];
+                        var scale = runtimeAnimation.weight / normalizer;
                         if (finalValue) {
-                            runtimeAnimation.currentValue.scaleAndAddToRef(runtimeAnimation.weight / normalizer, finalValue);
+                            if (matrixDecomposeMode) {
+                                BABYLON.Matrix.DecomposeLerpToRef(finalValue, runtimeAnimation.currentValue, scale, finalValue);
+                            }
+                            else {
+                                runtimeAnimation.currentValue.scaleAndAddToRef(scale, finalValue);
+                            }
                         }
                         else {
-                            finalValue = runtimeAnimation.currentValue.scale(runtimeAnimation.weight / normalizer);
+                            if (scale !== 1) {
+                                if (matrixDecomposeMode) {
+                                    finalValue = runtimeAnimation.currentValue.clone();
+                                }
+                                else {
+                                    finalValue = runtimeAnimation.currentValue.scale(scale);
+                                }
+                            }
+                            else {
+                                finalValue = runtimeAnimation.currentValue;
+                            }
                         }
                     }
                     runtimeAnimation.target[path] = finalValue;
@@ -25624,6 +25667,18 @@ var BABYLON;
             return index;
         };
         /**
+         * Removes the given effect layer from this scene.
+         * @param toRemove defines the effect layer to remove
+         * @returns the index of the removed effect layer
+         */
+        Scene.prototype.removeEffectLayer = function (toRemove) {
+            var index = this.effectLayers.indexOf(toRemove);
+            if (index !== -1) {
+                this.effectLayers.splice(index, 1);
+            }
+            return index;
+        };
+        /**
          * Removes the given texture from this scene.
          * @param toRemove The texture to remove
          * @returns The index of the removed texture
@@ -25732,6 +25787,13 @@ var BABYLON;
             this.lensFlareSystems.push(newLensFlareSystem);
         };
         /**
+         * Adds the given effect layer to this scene
+         * @param newEffectLayer defines the effect layer to add
+         */
+        Scene.prototype.addEffectLayer = function (newEffectLayer) {
+            this.effectLayers.push(newEffectLayer);
+        };
+        /**
          * Adds the given action manager to this scene
          * @param newActionManager The action manager to add
          */
@@ -26811,7 +26873,10 @@ var BABYLON;
                                 action._executeCurrent(BABYLON.ActionEvent.CreateNew(sourceMesh, undefined, otherMesh));
                             }
                             //if this is an exit trigger, or no exit trigger exists, remove the id from the intersection in progress array.
-                            if (!sourceMesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger) || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
+                            if (!sourceMesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger, function (parameter) {
+                                var parameterMesh = parameter instanceof BABYLON.AbstractMesh ? parameter : parameter.mesh;
+                                return otherMesh === parameterMesh;
+                            }) || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
                                 sourceMesh._intersectionsInProgress.splice(currentIntersectionInProgress, 1);
                             }
                         }
@@ -28220,6 +28285,10 @@ var BABYLON;
              * Textures to keep.
              */
             this.textures = new Array();
+            /**
+             * Effect layers to keep.
+             */
+            this.effectLayers = new Array();
         }
         return KeepAssets;
     }());
@@ -28302,6 +28371,10 @@ var BABYLON;
              * Textures populated in the container.
              */
             this.textures = new Array();
+            /**
+             * Effect layers populated in the container.
+             */
+            this.effectLayers = new Array();
             this.scene = scene;
         }
         /**
@@ -28357,7 +28430,10 @@ var BABYLON;
                 _this.scene.mainSoundTrack.AddSound(o);
             });
             this.textures.forEach(function (o) {
-                _this.scene.addTexture;
+                _this.scene.addTexture(o);
+            });
+            this.effectLayers.forEach(function (o) {
+                _this.scene.addEffectLayer(o);
             });
         };
         /**
@@ -28415,6 +28491,9 @@ var BABYLON;
             this.textures.forEach(function (o) {
                 _this.scene.removeTexture(o);
             });
+            this.effectLayers.forEach(function (o) {
+                _this.scene.removeEffectLayer(o);
+            });
         };
         AssetContainer.prototype._moveAssets = function (sourceAssets, targetAssets, keepAssets) {
             for (var _i = 0, sourceAssets_1 = sourceAssets; _i < sourceAssets_1.length; _i++) {
@@ -28456,6 +28535,7 @@ var BABYLON;
             this._moveAssets(this.scene.mainSoundTrack.soundCollection, this.sounds, keepAssets.sounds);
             this._moveAssets(this.scene.transformNodes, this.transformNodes, keepAssets.transformNodes);
             this._moveAssets(this.scene.textures, this.textures, keepAssets.textures);
+            this._moveAssets(this.scene.effectLayers, this.effectLayers, keepAssets.effectLayers);
             this.removeAllFromScene();
         };
         return AssetContainer;
@@ -49846,6 +49926,9 @@ var BABYLON;
             return BABYLON.Color3.Lerp(startValue, endValue, gradient);
         };
         Animation.prototype.matrixInterpolateFunction = function (startValue, endValue, gradient) {
+            if (Animation.AllowMatrixDecomposeForInterpolation) {
+                return BABYLON.Matrix.DecomposeLerp(startValue, endValue, gradient);
+            }
             return BABYLON.Matrix.Lerp(startValue, endValue, gradient);
         };
         Animation.prototype.clone = function () {
@@ -50064,7 +50147,14 @@ var BABYLON;
                 }
             }
         };
+        /**
+         * Use matrix interpolation instead of using direct key value when animating matrices
+         */
         Animation.AllowMatricesInterpolation = false;
+        /**
+         * When matrix interpolation is enabled, this boolean forces the system to use Matrix.DecomposeLerp instead of Matrix.Lerp. Interpolation is more precise but slower
+         */
+        Animation.AllowMatrixDecomposeForInterpolation = true;
         // Statics
         Animation._ANIMATIONTYPE_FLOAT = 0;
         Animation._ANIMATIONTYPE_VECTOR3 = 1;
@@ -50661,7 +50751,22 @@ var BABYLON;
                     }
                 }
                 else if (this._originalBlendValue.m) {
-                    this._currentValue = BABYLON.Matrix.Lerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                    if (BABYLON.Animation.AllowMatrixDecomposeForInterpolation) {
+                        if (this._currentValue) {
+                            BABYLON.Matrix.DecomposeLerpToRef(this._originalBlendValue, currentValue, this._blendingFactor, this._currentValue);
+                        }
+                        else {
+                            this._currentValue = BABYLON.Matrix.DecomposeLerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                        }
+                    }
+                    else {
+                        if (this._currentValue) {
+                            BABYLON.Matrix.LerpToRef(this._originalBlendValue, currentValue, this._blendingFactor, this._currentValue);
+                        }
+                        else {
+                            this._currentValue = BABYLON.Matrix.Lerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                        }
+                    }
                 }
                 else {
                     this._currentValue = this._originalBlendValue * (1.0 - this._blendingFactor) + this._blendingFactor * currentValue;
@@ -52072,14 +52177,22 @@ var BABYLON;
         };
         /**
          * Does this action manager handles actions of a given trigger
-         * @param {number} trigger - the trigger to be tested
-         * @return {boolean} whether the trigger is handeled
+         * @param trigger defines the trigger to be tested
+         * @param parameterPredicate defines an optional predicate to filter triggers by parameter
+         * @return whether the trigger is handled
          */
-        ActionManager.prototype.hasSpecificTrigger = function (trigger) {
+        ActionManager.prototype.hasSpecificTrigger = function (trigger, parameterPredicate) {
             for (var index = 0; index < this.actions.length; index++) {
                 var action = this.actions[index];
                 if (action.trigger === trigger) {
-                    return true;
+                    if (parameterPredicate) {
+                        if (parameterPredicate(action.getTriggerParameter())) {
+                            return true;
+                        }
+                    }
+                    else {
+                        return true;
+                    }
                 }
             }
             return false;
@@ -61700,6 +61813,11 @@ var BABYLON;
 
 "use strict";
 
+
+
+
+
+
 var BABYLON;
 (function (BABYLON) {
     var CubeTexture = /** @class */ (function (_super) {
@@ -61720,6 +61838,7 @@ var BABYLON;
              * It must define where the camera used to render the texture was set
              */
             _this.boundingBoxPosition = BABYLON.Vector3.Zero();
+            _this._rotationY = 0;
             _this.name = rootUrl;
             _this.url = rootUrl;
             _this._noMipmap = noMipmap;
@@ -61796,6 +61915,23 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(CubeTexture.prototype, "rotationY", {
+            /**
+             * Gets texture matrix rotation angle around Y axis radians.
+             */
+            get: function () {
+                return this._rotationY;
+            },
+            /**
+             * Sets texture matrix rotation angle around Y axis in radians.
+             */
+            set: function (value) {
+                this._rotationY = value;
+                this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
+            },
+            enumerable: true,
+            configurable: true
+        });
         CubeTexture.CreateFromImages = function (files, scene, noMipmap) {
             var rootUrlKey = "";
             files.forEach(function (url) { return rootUrlKey += url; });
@@ -61861,6 +61997,9 @@ var BABYLON;
                 return new CubeTexture(_this.url, scene, _this._extensions, _this._noMipmap, _this._files);
             }, this);
         };
+        __decorate([
+            BABYLON.serialize("rotationY")
+        ], CubeTexture.prototype, "_rotationY", void 0);
         return CubeTexture;
     }(BABYLON.BaseTexture));
     BABYLON.CubeTexture = CubeTexture;
@@ -66396,6 +66535,13 @@ var BABYLON;
                     light_2._includedOnlyMeshesIds = [];
                 }
             }
+            // Effect layers
+            if (parsedData.effectLayers) {
+                for (index = 0; index < parsedData.effectLayers.length; index++) {
+                    var effectLayer = BABYLON.EffectLayer.Parse(parsedData.effectLayers[index], scene, rootUrl);
+                    container.effectLayers.push(effectLayer);
+                }
+            }
             // Actions (scene)
             if (parsedData.actions !== undefined && parsedData.actions !== null) {
                 BABYLON.ActionManager.Parse(parsedData.actions, null, scene);
@@ -73859,7 +74005,7 @@ var BABYLON;
                 return this._circleOfConfusion.focalLength;
             },
             /**
-             * The focal the length of the camera used in the effect
+             * The focal the length of the camera used in the effect in scene units/1000 (eg. millimeter)
              */
             set: function (value) {
                 this._circleOfConfusion.focalLength = value;
@@ -78735,6 +78881,7 @@ var BABYLON;
              */
             _this.isPMREM = false;
             _this._isBlocking = true;
+            _this._rotationY = 0;
             /**
              * Gets or sets the center of the bounding box associated with the cube texture
              * It must define where the camera used to render the texture was set
@@ -78797,6 +78944,23 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(HDRCubeTexture.prototype, "rotationY", {
+            /**
+             * Gets texture matrix rotation angle around Y axis radians.
+             */
+            get: function () {
+                return this._rotationY;
+            },
+            /**
+             * Sets texture matrix rotation angle around Y axis in radians.
+             */
+            set: function (value) {
+                this._rotationY = value;
+                this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(HDRCubeTexture.prototype, "boundingBoxSize", {
             get: function () {
                 return this._boundingBoxSize;
@@ -79090,6 +79254,9 @@ var BABYLON;
                 if (parsedTexture.boundingBoxSize) {
                     texture.boundingBoxSize = BABYLON.Vector3.FromArray(parsedTexture.boundingBoxSize);
                 }
+                if (parsedTexture.rotationY) {
+                    texture.rotationY = parsedTexture.rotationY;
+                }
             }
             return texture;
         };
@@ -79111,6 +79278,7 @@ var BABYLON;
             serializationObject.customType = "BABYLON.HDRCubeTexture";
             serializationObject.noMipmap = this._noMipmap;
             serializationObject.isBlocking = this._isBlocking;
+            serializationObject.rotationY = this._rotationY;
             return serializationObject;
         };
         /**
@@ -90120,6 +90288,17 @@ var BABYLON;
         EffectLayer.prototype.getClassName = function () {
             return "EffectLayer";
         };
+        /**
+         * Creates an effect layer from parsed effect layer data
+         * @param parsedEffectLayer defines effect layer data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing the effect layer information
+         * @returns a parsed effect Layer
+         */
+        EffectLayer.Parse = function (parsedEffectLayer, scene, rootUrl) {
+            var effectLayerType = BABYLON.Tools.Instantiate(parsedEffectLayer.customType);
+            return effectLayerType.Parse(parsedEffectLayer, scene, rootUrl);
+        };
         __decorate([
             BABYLON.serialize()
         ], EffectLayer.prototype, "name", void 0);
@@ -90607,6 +90786,73 @@ var BABYLON;
             _super.prototype.dispose.call(this);
         };
         /**
+          * Gets the class name of the effect layer
+          * @returns the string with the class name of the effect layer
+          */
+        HighlightLayer.prototype.getClassName = function () {
+            return "HighlightLayer";
+        };
+        /**
+         * Serializes this Highlight layer
+         * @returns a serialized Highlight layer object
+         */
+        HighlightLayer.prototype.serialize = function () {
+            var serializationObject = BABYLON.SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.HighlightLayer";
+            // Highlighted meshes
+            serializationObject.meshes = [];
+            if (this._meshes) {
+                for (var m in this._meshes) {
+                    var mesh = this._meshes[m];
+                    if (mesh) {
+                        serializationObject.meshes.push({
+                            glowEmissiveOnly: mesh.glowEmissiveOnly,
+                            color: mesh.color.asArray(),
+                            meshId: mesh.mesh.id
+                        });
+                    }
+                }
+            }
+            // Excluded meshes
+            serializationObject.excludedMeshes = [];
+            if (this._excludedMeshes) {
+                for (var e in this._excludedMeshes) {
+                    var excludedMesh = this._excludedMeshes[e];
+                    if (excludedMesh) {
+                        serializationObject.excludedMeshes.push(excludedMesh.mesh.id);
+                    }
+                }
+            }
+            return serializationObject;
+        };
+        /**
+         * Creates a Highlight layer from parsed Highlight layer data
+         * @param parsedHightlightLayer defines the Highlight layer data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing the Highlight layer information
+         * @returns a parsed Highlight layer
+         */
+        HighlightLayer.Parse = function (parsedHightlightLayer, scene, rootUrl) {
+            var hl = BABYLON.SerializationHelper.Parse(function () { return new HighlightLayer(parsedHightlightLayer.name, scene, parsedHightlightLayer.options); }, parsedHightlightLayer, scene, rootUrl);
+            var index;
+            // Excluded meshes
+            for (index = 0; index < parsedHightlightLayer.excludedMeshes.length; index++) {
+                var mesh = scene.getMeshByID(parsedHightlightLayer.excludedMeshes[index]);
+                if (mesh) {
+                    hl.addExcludedMesh(mesh);
+                }
+            }
+            // Included meshes
+            for (index = 0; index < parsedHightlightLayer.meshes.length; index++) {
+                var highlightedMesh = parsedHightlightLayer.meshes[index];
+                var mesh = scene.getMeshByID(highlightedMesh.meshId);
+                if (mesh) {
+                    hl.addMesh(mesh, BABYLON.Color3.FromArray(highlightedMesh.color), highlightedMesh.glowEmissiveOnly);
+                }
+            }
+            return hl;
+        };
+        /**
          * Effect Name of the highlight layer.
          */
         HighlightLayer.EffectName = "HighlightLayer";
@@ -90623,6 +90869,21 @@ var BABYLON;
          * Stencil value used for the other meshes in the scene.
          */
         HighlightLayer.NormalMeshStencilReference = 0x01;
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "innerGlow", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "outerGlow", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "blurHorizontalSize", null);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "blurVerticalSize", null);
+        __decorate([
+            BABYLON.serialize("options")
+        ], HighlightLayer.prototype, "_options", void 0);
         return HighlightLayer;
     }(BABYLON.EffectLayer));
     BABYLON.HighlightLayer = HighlightLayer;
@@ -90959,6 +91220,7 @@ var BABYLON;
          */
         GlowLayer.prototype.serialize = function () {
             var serializationObject = BABYLON.SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.GlowLayer";
             var index;
             // Included meshes
             serializationObject.includedMeshes = [];
@@ -91027,7 +91289,7 @@ var BABYLON;
             BABYLON.serialize()
         ], GlowLayer.prototype, "intensity", null);
         __decorate([
-            BABYLON.serialize('options')
+            BABYLON.serialize("options")
         ], GlowLayer.prototype, "_options", void 0);
         return GlowLayer;
     }(BABYLON.EffectLayer));
@@ -92080,6 +92342,14 @@ var BABYLON;
                     serializationObject.sounds.push(soundtrack.soundCollection[soundId].serialize());
                 }
             }
+            // Effect layers
+            serializationObject.effectLayers = [];
+            for (index = 0; index < scene.effectLayers.length; index++) {
+                var layer = scene.effectLayers[index];
+                if (layer.serialize) {
+                    serializationObject.effectLayers.push(layer.serialize());
+                }
+            }
             return serializationObject;
         };
         SceneSerializer.SerializeMesh = function (toSerialize /* Mesh || Mesh[] */, withParents, withChildren) {

+ 2 - 2
dist/preview release/gui/babylon.gui.js

@@ -1,5 +1,3 @@
-var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 
 
 (function universalModuleDefinition(root, factory) {
@@ -23,6 +21,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
 })(this, function(BABYLON) {
   BABYLON = BABYLON || this.BABYLON;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 /// <reference path="../../dist/preview release/babylon.d.ts"/>
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 4 - 4
dist/preview release/gui/babylon.gui.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 2 - 2
dist/preview release/loaders/babylonjs.loaders.js

@@ -1,5 +1,3 @@
-var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 
 
 (function universalModuleDefinition(root, factory) {
@@ -23,6 +21,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
 })(this, function(BABYLON) {
   BABYLON = BABYLON || this.BABYLON;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 
 var BABYLON;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


+ 2 - 2
dist/preview release/materialsLibrary/babylonjs.materials.js

@@ -1,5 +1,3 @@
-var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 
 
 (function universalModuleDefinition(root, factory) {
@@ -23,6 +21,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
 })(this, function(BABYLON) {
   BABYLON = BABYLON || this.BABYLON;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 5 - 5
dist/preview release/materialsLibrary/babylonjs.materials.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


+ 2 - 2
dist/preview release/postProcessesLibrary/babylonjs.postProcess.js

@@ -1,5 +1,3 @@
-var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 
 
 (function universalModuleDefinition(root, factory) {
@@ -23,6 +21,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
 })(this, function(BABYLON) {
   BABYLON = BABYLON || this.BABYLON;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


+ 2 - 2
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js

@@ -1,5 +1,3 @@
-var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 
 
 (function universalModuleDefinition(root, factory) {
@@ -23,6 +21,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
 })(this, function(BABYLON) {
   BABYLON = BABYLON || this.BABYLON;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


+ 2 - 2
dist/preview release/serializers/babylonjs.serializers.js

@@ -1,5 +1,3 @@
-var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 
 
 (function universalModuleDefinition(root, factory) {
@@ -23,6 +21,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
 })(this, function(BABYLON) {
   BABYLON = BABYLON || this.BABYLON;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 
 var BABYLON;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


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

@@ -1,7 +1,7 @@
 {
-  "errors": 5492,
+  "errors": 5491,
   "babylon.typedoc.json": {
-    "errors": 5492,
+    "errors": 5491,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {
@@ -2312,11 +2312,6 @@
           "Comments": {
             "MissingText": true
           }
-        },
-        "AllowMatricesInterpolation": {
-          "Comments": {
-            "MissingText": true
-          }
         }
       },
       "Method": {

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 63 - 63
dist/preview release/viewer/babylon.viewer.js


+ 322 - 52
dist/preview release/viewer/babylon.viewer.max.js

@@ -86,9 +86,7 @@ var BabylonViewer =
 /* 0 */
 /***/ (function(module, exports, __webpack_require__) {
 
-/* WEBPACK VAR INJECTION */(function(global) {var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
-
+/* WEBPACK VAR INJECTION */(function(global) {
 
 (function universalModuleDefinition(root, factory) {
     var amdDependencies = [];
@@ -121,6 +119,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
   OIMO = OIMO || this.OIMO;
   earcut = earcut || this.earcut;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 var BABYLON;
 (function (BABYLON) {
@@ -4812,7 +4812,6 @@ var BABYLON;
         Quaternion.SlerpToRef = function (left, right, amount, result) {
             var num2;
             var num3;
-            var num = amount;
             var num4 = (((left.x * right.x) + (left.y * right.y)) + (left.z * right.z)) + (left.w * right.w);
             var flag = false;
             if (num4 < 0) {
@@ -4820,14 +4819,14 @@ var BABYLON;
                 num4 = -num4;
             }
             if (num4 > 0.999999) {
-                num3 = 1 - num;
-                num2 = flag ? -num : num;
+                num3 = 1 - amount;
+                num2 = flag ? -amount : amount;
             }
             else {
                 var num5 = Math.acos(num4);
                 var num6 = (1.0 / Math.sin(num5));
-                num3 = (Math.sin((1.0 - num) * num5)) * num6;
-                num2 = flag ? ((-Math.sin(num * num5)) * num6) : ((Math.sin(num * num5)) * num6);
+                num3 = (Math.sin((1.0 - amount) * num5)) * num6;
+                num2 = flag ? ((-Math.sin(amount * num5)) * num6) : ((Math.sin(amount * num5)) * num6);
             }
             result.x = (num3 * left.x) + (num2 * right.x);
             result.y = (num3 * left.y) + (num2 * right.y);
@@ -5253,24 +5252,28 @@ var BABYLON;
          * @returns true if operation was successful
          */
         Matrix.prototype.decompose = function (scale, rotation, translation) {
-            translation.x = this.m[12];
-            translation.y = this.m[13];
-            translation.z = this.m[14];
+            if (translation) {
+                translation.x = this.m[12];
+                translation.y = this.m[13];
+                translation.z = this.m[14];
+            }
             scale.x = Math.sqrt(this.m[0] * this.m[0] + this.m[1] * this.m[1] + this.m[2] * this.m[2]);
             scale.y = Math.sqrt(this.m[4] * this.m[4] + this.m[5] * this.m[5] + this.m[6] * this.m[6]);
             scale.z = Math.sqrt(this.m[8] * this.m[8] + this.m[9] * this.m[9] + this.m[10] * this.m[10]);
             if (this.determinant() <= 0) {
                 scale.y *= -1;
             }
-            if (scale.x === 0 || scale.y === 0 || scale.z === 0) {
-                rotation.x = 0;
-                rotation.y = 0;
-                rotation.z = 0;
-                rotation.w = 1;
-                return false;
+            if (rotation) {
+                if (scale.x === 0 || scale.y === 0 || scale.z === 0) {
+                    rotation.x = 0;
+                    rotation.y = 0;
+                    rotation.z = 0;
+                    rotation.w = 1;
+                    return false;
+                }
+                Matrix.FromValuesToRef(this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0, this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0, this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0, 0, 0, 0, 1, MathTmp.Matrix[0]);
+                Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
             }
-            Matrix.FromValuesToRef(this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0, this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0, this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0, 0, 0, 0, 1, MathTmp.Matrix[0]);
-            Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
             return true;
         };
         /**
@@ -5860,18 +5863,36 @@ var BABYLON;
          * @returns the new matrix
          */
         Matrix.DecomposeLerp = function (startValue, endValue, gradient) {
-            var startScale = new Vector3(0, 0, 0);
-            var startRotation = new Quaternion();
-            var startTranslation = new Vector3(0, 0, 0);
+            var result = Matrix.Zero();
+            Matrix.DecomposeLerpToRef(startValue, endValue, gradient, result);
+            return result;
+        };
+        /**
+         * Update a matrix to values which are computed by:
+         * * decomposing the the "startValue" and "endValue" matrices into their respective scale, rotation and translation matrices
+         * * interpolating for "gradient" (float) the values between each of these decomposed matrices between the start and the end
+         * * recomposing a new matrix from these 3 interpolated scale, rotation and translation matrices
+         * @param startValue defines the first matrix
+         * @param endValue defines the second matrix
+         * @param gradient defines the gradient between the two matrices
+         * @param result defines the target matrix
+         */
+        Matrix.DecomposeLerpToRef = function (startValue, endValue, gradient, result) {
+            var startScale = MathTmp.Vector3[0];
+            var startRotation = MathTmp.Quaternion[0];
+            var startTranslation = MathTmp.Vector3[1];
             startValue.decompose(startScale, startRotation, startTranslation);
-            var endScale = new Vector3(0, 0, 0);
-            var endRotation = new Quaternion();
-            var endTranslation = new Vector3(0, 0, 0);
+            var endScale = MathTmp.Vector3[2];
+            var endRotation = MathTmp.Quaternion[1];
+            var endTranslation = MathTmp.Vector3[3];
             endValue.decompose(endScale, endRotation, endTranslation);
-            var resultScale = Vector3.Lerp(startScale, endScale, gradient);
-            var resultRotation = Quaternion.Slerp(startRotation, endRotation, gradient);
-            var resultTranslation = Vector3.Lerp(startTranslation, endTranslation, gradient);
-            return Matrix.Compose(resultScale, resultRotation, resultTranslation);
+            var resultScale = MathTmp.Vector3[4];
+            Vector3.LerpToRef(startScale, endScale, gradient, resultScale);
+            var resultRotation = MathTmp.Quaternion[2];
+            Quaternion.SlerpToRef(startRotation, endRotation, gradient, resultRotation);
+            var resultTranslation = MathTmp.Vector3[5];
+            Vector3.LerpToRef(startTranslation, endTranslation, gradient, resultTranslation);
+            Matrix.ComposeToRef(resultScale, resultRotation, resultTranslation, result);
         };
         /**
          * Gets a new rotation matrix used to rotate an entity so as it looks at the target vector3, from the eye vector3 position, the up vector3 being oriented like "up"
@@ -7193,9 +7214,9 @@ var BABYLON;
     var MathTmp = /** @class */ (function () {
         function MathTmp() {
         }
-        MathTmp.Vector3 = [Vector3.Zero()];
+        MathTmp.Vector3 = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];
         MathTmp.Matrix = [Matrix.Zero(), Matrix.Zero()];
-        MathTmp.Quaternion = [Quaternion.Zero()];
+        MathTmp.Quaternion = [Quaternion.Zero(), Quaternion.Zero(), Quaternion.Zero()];
         return MathTmp;
     }());
 })(BABYLON || (BABYLON = {}));
@@ -25410,16 +25431,22 @@ var BABYLON;
                 var target = this._registeredForLateAnimationBindings.data[index];
                 for (var path in target._lateAnimationHolders) {
                     var holder = target._lateAnimationHolders[path];
+                    var originalValue = holder.animations[0].originalValue;
                     // Sanity check
-                    if (!holder.animations[0].originalValue.scaleAndAddToRef) {
+                    if (!originalValue.scaleAndAddToRef) {
                         continue;
                     }
+                    var matrixDecomposeMode = BABYLON.Animation.AllowMatrixDecomposeForInterpolation && originalValue.m; // ie. data is matrix
                     var normalizer = 1.0;
                     var finalValue = void 0;
                     if (holder.totalWeight < 1.0) {
-                        // We need to mix the original value in
-                        var originalValue = holder.animations[0].originalValue;
-                        finalValue = originalValue.scale(1.0 - holder.totalWeight);
+                        // We need to mix the original value in     
+                        if (matrixDecomposeMode) {
+                            finalValue = originalValue.clone();
+                        }
+                        else {
+                            finalValue = originalValue.scale(1.0 - holder.totalWeight);
+                        }
                     }
                     else {
                         // We need to normalize the weights
@@ -25427,11 +25454,27 @@ var BABYLON;
                     }
                     for (var animIndex = 0; animIndex < holder.animations.length; animIndex++) {
                         var runtimeAnimation = holder.animations[animIndex];
+                        var scale = runtimeAnimation.weight / normalizer;
                         if (finalValue) {
-                            runtimeAnimation.currentValue.scaleAndAddToRef(runtimeAnimation.weight / normalizer, finalValue);
+                            if (matrixDecomposeMode) {
+                                BABYLON.Matrix.DecomposeLerpToRef(finalValue, runtimeAnimation.currentValue, scale, finalValue);
+                            }
+                            else {
+                                runtimeAnimation.currentValue.scaleAndAddToRef(scale, finalValue);
+                            }
                         }
                         else {
-                            finalValue = runtimeAnimation.currentValue.scale(runtimeAnimation.weight / normalizer);
+                            if (scale !== 1) {
+                                if (matrixDecomposeMode) {
+                                    finalValue = runtimeAnimation.currentValue.clone();
+                                }
+                                else {
+                                    finalValue = runtimeAnimation.currentValue.scale(scale);
+                                }
+                            }
+                            else {
+                                finalValue = runtimeAnimation.currentValue;
+                            }
                         }
                     }
                     runtimeAnimation.target[path] = finalValue;
@@ -25745,6 +25788,18 @@ var BABYLON;
             return index;
         };
         /**
+         * Removes the given effect layer from this scene.
+         * @param toRemove defines the effect layer to remove
+         * @returns the index of the removed effect layer
+         */
+        Scene.prototype.removeEffectLayer = function (toRemove) {
+            var index = this.effectLayers.indexOf(toRemove);
+            if (index !== -1) {
+                this.effectLayers.splice(index, 1);
+            }
+            return index;
+        };
+        /**
          * Removes the given texture from this scene.
          * @param toRemove The texture to remove
          * @returns The index of the removed texture
@@ -25853,6 +25908,13 @@ var BABYLON;
             this.lensFlareSystems.push(newLensFlareSystem);
         };
         /**
+         * Adds the given effect layer to this scene
+         * @param newEffectLayer defines the effect layer to add
+         */
+        Scene.prototype.addEffectLayer = function (newEffectLayer) {
+            this.effectLayers.push(newEffectLayer);
+        };
+        /**
          * Adds the given action manager to this scene
          * @param newActionManager The action manager to add
          */
@@ -26932,7 +26994,10 @@ var BABYLON;
                                 action._executeCurrent(BABYLON.ActionEvent.CreateNew(sourceMesh, undefined, otherMesh));
                             }
                             //if this is an exit trigger, or no exit trigger exists, remove the id from the intersection in progress array.
-                            if (!sourceMesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger) || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
+                            if (!sourceMesh.actionManager.hasSpecificTrigger(BABYLON.ActionManager.OnIntersectionExitTrigger, function (parameter) {
+                                var parameterMesh = parameter instanceof BABYLON.AbstractMesh ? parameter : parameter.mesh;
+                                return otherMesh === parameterMesh;
+                            }) || action.trigger === BABYLON.ActionManager.OnIntersectionExitTrigger) {
                                 sourceMesh._intersectionsInProgress.splice(currentIntersectionInProgress, 1);
                             }
                         }
@@ -28341,6 +28406,10 @@ var BABYLON;
              * Textures to keep.
              */
             this.textures = new Array();
+            /**
+             * Effect layers to keep.
+             */
+            this.effectLayers = new Array();
         }
         return KeepAssets;
     }());
@@ -28423,6 +28492,10 @@ var BABYLON;
              * Textures populated in the container.
              */
             this.textures = new Array();
+            /**
+             * Effect layers populated in the container.
+             */
+            this.effectLayers = new Array();
             this.scene = scene;
         }
         /**
@@ -28478,7 +28551,10 @@ var BABYLON;
                 _this.scene.mainSoundTrack.AddSound(o);
             });
             this.textures.forEach(function (o) {
-                _this.scene.addTexture;
+                _this.scene.addTexture(o);
+            });
+            this.effectLayers.forEach(function (o) {
+                _this.scene.addEffectLayer(o);
             });
         };
         /**
@@ -28536,6 +28612,9 @@ var BABYLON;
             this.textures.forEach(function (o) {
                 _this.scene.removeTexture(o);
             });
+            this.effectLayers.forEach(function (o) {
+                _this.scene.removeEffectLayer(o);
+            });
         };
         AssetContainer.prototype._moveAssets = function (sourceAssets, targetAssets, keepAssets) {
             for (var _i = 0, sourceAssets_1 = sourceAssets; _i < sourceAssets_1.length; _i++) {
@@ -28577,6 +28656,7 @@ var BABYLON;
             this._moveAssets(this.scene.mainSoundTrack.soundCollection, this.sounds, keepAssets.sounds);
             this._moveAssets(this.scene.transformNodes, this.transformNodes, keepAssets.transformNodes);
             this._moveAssets(this.scene.textures, this.textures, keepAssets.textures);
+            this._moveAssets(this.scene.effectLayers, this.effectLayers, keepAssets.effectLayers);
             this.removeAllFromScene();
         };
         return AssetContainer;
@@ -49967,6 +50047,9 @@ var BABYLON;
             return BABYLON.Color3.Lerp(startValue, endValue, gradient);
         };
         Animation.prototype.matrixInterpolateFunction = function (startValue, endValue, gradient) {
+            if (Animation.AllowMatrixDecomposeForInterpolation) {
+                return BABYLON.Matrix.DecomposeLerp(startValue, endValue, gradient);
+            }
             return BABYLON.Matrix.Lerp(startValue, endValue, gradient);
         };
         Animation.prototype.clone = function () {
@@ -50185,7 +50268,14 @@ var BABYLON;
                 }
             }
         };
+        /**
+         * Use matrix interpolation instead of using direct key value when animating matrices
+         */
         Animation.AllowMatricesInterpolation = false;
+        /**
+         * When matrix interpolation is enabled, this boolean forces the system to use Matrix.DecomposeLerp instead of Matrix.Lerp. Interpolation is more precise but slower
+         */
+        Animation.AllowMatrixDecomposeForInterpolation = true;
         // Statics
         Animation._ANIMATIONTYPE_FLOAT = 0;
         Animation._ANIMATIONTYPE_VECTOR3 = 1;
@@ -50782,7 +50872,22 @@ var BABYLON;
                     }
                 }
                 else if (this._originalBlendValue.m) {
-                    this._currentValue = BABYLON.Matrix.Lerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                    if (BABYLON.Animation.AllowMatrixDecomposeForInterpolation) {
+                        if (this._currentValue) {
+                            BABYLON.Matrix.DecomposeLerpToRef(this._originalBlendValue, currentValue, this._blendingFactor, this._currentValue);
+                        }
+                        else {
+                            this._currentValue = BABYLON.Matrix.DecomposeLerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                        }
+                    }
+                    else {
+                        if (this._currentValue) {
+                            BABYLON.Matrix.LerpToRef(this._originalBlendValue, currentValue, this._blendingFactor, this._currentValue);
+                        }
+                        else {
+                            this._currentValue = BABYLON.Matrix.Lerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                        }
+                    }
                 }
                 else {
                     this._currentValue = this._originalBlendValue * (1.0 - this._blendingFactor) + this._blendingFactor * currentValue;
@@ -52193,14 +52298,22 @@ var BABYLON;
         };
         /**
          * Does this action manager handles actions of a given trigger
-         * @param {number} trigger - the trigger to be tested
-         * @return {boolean} whether the trigger is handeled
+         * @param trigger defines the trigger to be tested
+         * @param parameterPredicate defines an optional predicate to filter triggers by parameter
+         * @return whether the trigger is handled
          */
-        ActionManager.prototype.hasSpecificTrigger = function (trigger) {
+        ActionManager.prototype.hasSpecificTrigger = function (trigger, parameterPredicate) {
             for (var index = 0; index < this.actions.length; index++) {
                 var action = this.actions[index];
                 if (action.trigger === trigger) {
-                    return true;
+                    if (parameterPredicate) {
+                        if (parameterPredicate(action.getTriggerParameter())) {
+                            return true;
+                        }
+                    }
+                    else {
+                        return true;
+                    }
                 }
             }
             return false;
@@ -61821,6 +61934,11 @@ var BABYLON;
 
 "use strict";
 
+
+
+
+
+
 var BABYLON;
 (function (BABYLON) {
     var CubeTexture = /** @class */ (function (_super) {
@@ -61841,6 +61959,7 @@ var BABYLON;
              * It must define where the camera used to render the texture was set
              */
             _this.boundingBoxPosition = BABYLON.Vector3.Zero();
+            _this._rotationY = 0;
             _this.name = rootUrl;
             _this.url = rootUrl;
             _this._noMipmap = noMipmap;
@@ -61917,6 +62036,23 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(CubeTexture.prototype, "rotationY", {
+            /**
+             * Gets texture matrix rotation angle around Y axis radians.
+             */
+            get: function () {
+                return this._rotationY;
+            },
+            /**
+             * Sets texture matrix rotation angle around Y axis in radians.
+             */
+            set: function (value) {
+                this._rotationY = value;
+                this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
+            },
+            enumerable: true,
+            configurable: true
+        });
         CubeTexture.CreateFromImages = function (files, scene, noMipmap) {
             var rootUrlKey = "";
             files.forEach(function (url) { return rootUrlKey += url; });
@@ -61982,6 +62118,9 @@ var BABYLON;
                 return new CubeTexture(_this.url, scene, _this._extensions, _this._noMipmap, _this._files);
             }, this);
         };
+        __decorate([
+            BABYLON.serialize("rotationY")
+        ], CubeTexture.prototype, "_rotationY", void 0);
         return CubeTexture;
     }(BABYLON.BaseTexture));
     BABYLON.CubeTexture = CubeTexture;
@@ -66517,6 +66656,13 @@ var BABYLON;
                     light_2._includedOnlyMeshesIds = [];
                 }
             }
+            // Effect layers
+            if (parsedData.effectLayers) {
+                for (index = 0; index < parsedData.effectLayers.length; index++) {
+                    var effectLayer = BABYLON.EffectLayer.Parse(parsedData.effectLayers[index], scene, rootUrl);
+                    container.effectLayers.push(effectLayer);
+                }
+            }
             // Actions (scene)
             if (parsedData.actions !== undefined && parsedData.actions !== null) {
                 BABYLON.ActionManager.Parse(parsedData.actions, null, scene);
@@ -73980,7 +74126,7 @@ var BABYLON;
                 return this._circleOfConfusion.focalLength;
             },
             /**
-             * The focal the length of the camera used in the effect
+             * The focal the length of the camera used in the effect in scene units/1000 (eg. millimeter)
              */
             set: function (value) {
                 this._circleOfConfusion.focalLength = value;
@@ -78856,6 +79002,7 @@ var BABYLON;
              */
             _this.isPMREM = false;
             _this._isBlocking = true;
+            _this._rotationY = 0;
             /**
              * Gets or sets the center of the bounding box associated with the cube texture
              * It must define where the camera used to render the texture was set
@@ -78918,6 +79065,23 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(HDRCubeTexture.prototype, "rotationY", {
+            /**
+             * Gets texture matrix rotation angle around Y axis radians.
+             */
+            get: function () {
+                return this._rotationY;
+            },
+            /**
+             * Sets texture matrix rotation angle around Y axis in radians.
+             */
+            set: function (value) {
+                this._rotationY = value;
+                this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(HDRCubeTexture.prototype, "boundingBoxSize", {
             get: function () {
                 return this._boundingBoxSize;
@@ -79211,6 +79375,9 @@ var BABYLON;
                 if (parsedTexture.boundingBoxSize) {
                     texture.boundingBoxSize = BABYLON.Vector3.FromArray(parsedTexture.boundingBoxSize);
                 }
+                if (parsedTexture.rotationY) {
+                    texture.rotationY = parsedTexture.rotationY;
+                }
             }
             return texture;
         };
@@ -79232,6 +79399,7 @@ var BABYLON;
             serializationObject.customType = "BABYLON.HDRCubeTexture";
             serializationObject.noMipmap = this._noMipmap;
             serializationObject.isBlocking = this._isBlocking;
+            serializationObject.rotationY = this._rotationY;
             return serializationObject;
         };
         /**
@@ -90241,6 +90409,17 @@ var BABYLON;
         EffectLayer.prototype.getClassName = function () {
             return "EffectLayer";
         };
+        /**
+         * Creates an effect layer from parsed effect layer data
+         * @param parsedEffectLayer defines effect layer data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing the effect layer information
+         * @returns a parsed effect Layer
+         */
+        EffectLayer.Parse = function (parsedEffectLayer, scene, rootUrl) {
+            var effectLayerType = BABYLON.Tools.Instantiate(parsedEffectLayer.customType);
+            return effectLayerType.Parse(parsedEffectLayer, scene, rootUrl);
+        };
         __decorate([
             BABYLON.serialize()
         ], EffectLayer.prototype, "name", void 0);
@@ -90728,6 +90907,73 @@ var BABYLON;
             _super.prototype.dispose.call(this);
         };
         /**
+          * Gets the class name of the effect layer
+          * @returns the string with the class name of the effect layer
+          */
+        HighlightLayer.prototype.getClassName = function () {
+            return "HighlightLayer";
+        };
+        /**
+         * Serializes this Highlight layer
+         * @returns a serialized Highlight layer object
+         */
+        HighlightLayer.prototype.serialize = function () {
+            var serializationObject = BABYLON.SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.HighlightLayer";
+            // Highlighted meshes
+            serializationObject.meshes = [];
+            if (this._meshes) {
+                for (var m in this._meshes) {
+                    var mesh = this._meshes[m];
+                    if (mesh) {
+                        serializationObject.meshes.push({
+                            glowEmissiveOnly: mesh.glowEmissiveOnly,
+                            color: mesh.color.asArray(),
+                            meshId: mesh.mesh.id
+                        });
+                    }
+                }
+            }
+            // Excluded meshes
+            serializationObject.excludedMeshes = [];
+            if (this._excludedMeshes) {
+                for (var e in this._excludedMeshes) {
+                    var excludedMesh = this._excludedMeshes[e];
+                    if (excludedMesh) {
+                        serializationObject.excludedMeshes.push(excludedMesh.mesh.id);
+                    }
+                }
+            }
+            return serializationObject;
+        };
+        /**
+         * Creates a Highlight layer from parsed Highlight layer data
+         * @param parsedHightlightLayer defines the Highlight layer data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing the Highlight layer information
+         * @returns a parsed Highlight layer
+         */
+        HighlightLayer.Parse = function (parsedHightlightLayer, scene, rootUrl) {
+            var hl = BABYLON.SerializationHelper.Parse(function () { return new HighlightLayer(parsedHightlightLayer.name, scene, parsedHightlightLayer.options); }, parsedHightlightLayer, scene, rootUrl);
+            var index;
+            // Excluded meshes
+            for (index = 0; index < parsedHightlightLayer.excludedMeshes.length; index++) {
+                var mesh = scene.getMeshByID(parsedHightlightLayer.excludedMeshes[index]);
+                if (mesh) {
+                    hl.addExcludedMesh(mesh);
+                }
+            }
+            // Included meshes
+            for (index = 0; index < parsedHightlightLayer.meshes.length; index++) {
+                var highlightedMesh = parsedHightlightLayer.meshes[index];
+                var mesh = scene.getMeshByID(highlightedMesh.meshId);
+                if (mesh) {
+                    hl.addMesh(mesh, BABYLON.Color3.FromArray(highlightedMesh.color), highlightedMesh.glowEmissiveOnly);
+                }
+            }
+            return hl;
+        };
+        /**
          * Effect Name of the highlight layer.
          */
         HighlightLayer.EffectName = "HighlightLayer";
@@ -90744,6 +90990,21 @@ var BABYLON;
          * Stencil value used for the other meshes in the scene.
          */
         HighlightLayer.NormalMeshStencilReference = 0x01;
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "innerGlow", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "outerGlow", void 0);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "blurHorizontalSize", null);
+        __decorate([
+            BABYLON.serialize()
+        ], HighlightLayer.prototype, "blurVerticalSize", null);
+        __decorate([
+            BABYLON.serialize("options")
+        ], HighlightLayer.prototype, "_options", void 0);
         return HighlightLayer;
     }(BABYLON.EffectLayer));
     BABYLON.HighlightLayer = HighlightLayer;
@@ -91080,6 +91341,7 @@ var BABYLON;
          */
         GlowLayer.prototype.serialize = function () {
             var serializationObject = BABYLON.SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.GlowLayer";
             var index;
             // Included meshes
             serializationObject.includedMeshes = [];
@@ -91148,7 +91410,7 @@ var BABYLON;
             BABYLON.serialize()
         ], GlowLayer.prototype, "intensity", null);
         __decorate([
-            BABYLON.serialize('options')
+            BABYLON.serialize("options")
         ], GlowLayer.prototype, "_options", void 0);
         return GlowLayer;
     }(BABYLON.EffectLayer));
@@ -92201,6 +92463,14 @@ var BABYLON;
                     serializationObject.sounds.push(soundtrack.soundCollection[soundId].serialize());
                 }
             }
+            // Effect layers
+            serializationObject.effectLayers = [];
+            for (index = 0; index < scene.effectLayers.length; index++) {
+                var layer = scene.effectLayers[index];
+                if (layer.serialize) {
+                    serializationObject.effectLayers.push(layer.serialize());
+                }
+            }
             return serializationObject;
         };
         SceneSerializer.SerializeMesh = function (toSerialize /* Mesh || Mesh[] */, withParents, withChildren) {
@@ -99396,8 +99666,6 @@ module.exports = "SHARE";
 /* 34 */
 /***/ (function(module, exports, __webpack_require__) {
 
-var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 
 
 (function universalModuleDefinition(root, factory) {
@@ -99421,6 +99689,8 @@ var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__p
 })(this, function(BABYLON) {
   BABYLON = BABYLON || this.BABYLON;
 
+var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
+var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
 "use strict";
 
 var BABYLON;
@@ -103219,7 +103489,7 @@ var BABYLON;
                     _this._babylonScene = scene;
                     _this._rootUrl = rootUrl;
                     _this._progressCallback = onProgress;
-                    _this._state = BABYLON.GLTFLoaderState.Loading;
+                    _this._state = BABYLON.GLTFLoaderState.LOADING;
                     _this._loadData(data);
                     _this._checkExtensions();
                     var promises = new Array();
@@ -103237,7 +103507,7 @@ var BABYLON;
                         promises.push(_this._compileShadowGeneratorsAsync());
                     }
                     var resultPromise = Promise.all(promises).then(function () {
-                        _this._state = BABYLON.GLTFLoaderState.Ready;
+                        _this._state = BABYLON.GLTFLoaderState.READY;
                         _this._startAnimations();
                     });
                     resultPromise.then(function () {
@@ -103245,7 +103515,7 @@ var BABYLON;
                         BABYLON.Tools.SetImmediate(function () {
                             if (!_this._disposed) {
                                 Promise.all(_this._completePromises).then(function () {
-                                    _this._state = BABYLON.GLTFLoaderState.Complete;
+                                    _this._state = BABYLON.GLTFLoaderState.COMPLETE;
                                     _this.onCompleteObservable.notifyObservers(_this);
                                     _this.onCompleteObservable.clear();
                                     _this._clear();
@@ -104283,7 +104553,7 @@ var BABYLON;
                     }, function (event) {
                         if (!_this._disposed) {
                             try {
-                                if (request && _this._state === BABYLON.GLTFLoaderState.Loading) {
+                                if (request && _this._state === BABYLON.GLTFLoaderState.LOADING) {
                                     request._lengthComputable = event.lengthComputable;
                                     request._loaded = event.loaded;
                                     request._total = event.total;

+ 4 - 0
dist/preview release/what's new.md

@@ -30,6 +30,7 @@
 
 ## Updates
 
+- Improved [animation blending](https://www.babylonjs-playground.com/#DMLMIP#1) ([deltakosh](https://github.com/deltakosh))
 - New [particle system emitter shapes](http://doc.babylonjs.com/babylon101/particles#particles-shapes): cone and sphere ([IbraheemOsama](https://github.com/IbraheemOsama))
 - Added support for 16bits TGA ([deltakosh](https://github.com/deltakosh))
 - New `AnimationPropertiesOverride` class used to simplify setting animation properties on child animations. [Documentation](http://doc.babylonjs.com/babylon101/animations#overriding-properties) ([deltakosh](https://github.com/deltakosh))
@@ -112,6 +113,7 @@
 - Add support for normalized and non-float data to `Buffer` and `VertexBuffer`. ([bghgary](https://github.com/bghgary)]
 - Added unlit material extension support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
 - (Viewer) Viewer's declaration file automatically generated ([RaananW](https://github.com/RaananW))
+- New serialize and parse functions for effect layers (Highlight and Glow layers) ([julien-moreau](https://github.com/julien-moreau))
 
 ## Bug fixes
 
@@ -131,6 +133,8 @@
 - Add onLoadObservable on VideoTexture - [#3845](https://github.com/BabylonJS/Babylon.js/issues/3845) ([sebavan](https://github.com/sebavan))
 - beforeRender is now triggered after the camera updated its state - [#3873](https://github.com/BabylonJS/Babylon.js/issues/3873) ([RaananW](https://github.com/RaananW))
 - Tools.DeepCopy no longer copying getter-only elements - [#3929](https://github.com/BabylonJS/Babylon.js/issues/3929) ([RaananW](https://github.com/RaananW))
+- Reflection and refraction no longer apply a toLinear conversion twice when applying image processing as a post process - [#4060](https://github.com/BabylonJS/Babylon.js/issues/4060) ([trevordev](https://github.com/trevordev))
+- Fix ember.js compatibility in ```PostProcessRenderEffect``` ([sebavan](https://github.com/sebavan))
 
 ## Breaking changes
 

+ 14 - 9
loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts

@@ -10,6 +10,10 @@ module BABYLON.GLTF2.Extensions {
         attributes: { [name: string]: number };
     }
 
+    interface ILoaderBufferViewDraco extends ILoaderBufferView {
+        _dracoBabylonGeometry?: Promise<Geometry>;
+    }
+
     export class KHR_draco_mesh_compression extends GLTFLoaderExtension {
         public readonly name = NAME;
 
@@ -19,7 +23,7 @@ module BABYLON.GLTF2.Extensions {
             super(loader);
 
             // Disable extension if decoder is not available.
-            if (!DracoCompression.DecoderUrl) {
+            if (!DracoCompression.DecoderAvailable) {
                 this.enabled = false;
             }
         }
@@ -70,9 +74,9 @@ module BABYLON.GLTF2.Extensions {
                 loadAttribute("WEIGHTS_0", VertexBuffer.MatricesWeightsKind);
                 loadAttribute("COLOR_0", VertexBuffer.ColorKind);
 
-                var bufferView = GLTFLoader._GetProperty(extensionContext, this._loader._gltf.bufferViews, extension.bufferView);
-                return this._loader._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView).then(data => {
-                    try {
+                var bufferView = GLTFLoader._GetProperty(extensionContext, this._loader._gltf.bufferViews, extension.bufferView) as ILoaderBufferViewDraco;
+                if (!bufferView._dracoBabylonGeometry) {
+                    bufferView._dracoBabylonGeometry = this._loader._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView).then(data => {
                         if (!this._dracoCompression) {
                             this._dracoCompression = new DracoCompression();
                         }
@@ -81,12 +85,13 @@ module BABYLON.GLTF2.Extensions {
                             const babylonGeometry = new Geometry(babylonMesh.name, this._loader._babylonScene);
                             babylonVertexData.applyToGeometry(babylonGeometry);
                             return babylonGeometry;
+                        }).catch(error => {
+                            throw new Error(`${context}: ${error.message}`);
                         });
-                    }
-                    catch (e) {
-                        throw new Error(`${context}: ${e.message}`);
-                    }
-                });
+                    });
+                }
+
+                return bufferView._dracoBabylonGeometry;
             });
         }
     }

+ 3 - 1
localDev/index.html

@@ -7,8 +7,10 @@
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
     <script src="../dist/preview%20release/cannon.js"></script>
-    <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="../dist/preview%20release/Oimo.js"></script>
+    <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
+    <script src="../dist/preview%20release/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+    <script src="../dist/preview%20release/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>
     <script src="src/webgl-debug.js"></script>
 

+ 3 - 1
sandbox/index-local.html

@@ -4,8 +4,10 @@
     <title>BabylonJS - Sandbox</title>
     <link href="index.css" rel="stylesheet" />
     <script src="../dist/preview%20release/cannon.js"></script>
-    <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="../dist/preview%20release/Oimo.js"></script>
+    <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
+    <script src="../dist/preview%20release/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+    <script src="../dist/preview%20release/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>
 </head>
 <body>

+ 5 - 1
sandbox/index.html

@@ -26,8 +26,12 @@
     <link href="index.css" rel="stylesheet" />
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
 
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
+    <!-- Draco -->
     <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
+    <script src="https://preview.babylonjs.com/draco_decoder.wasm" type="text/x-draco-decoder-wasm-binary"></script>
+    <script src="https://preview.babylonjs.com/draco_wasm_wrapper.js" type="text/x-draco-decoder-wasm-wrapper"></script>
+
+    <script src="https://preview.babylonjs.com/cannon.js"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 4 - 2
sandbox/index.js

@@ -9,14 +9,16 @@ var indexOf = location.href.indexOf("?");
 if (indexOf !== -1) {
     var params = location.href.substr(indexOf + 1).split("&");
     for (var index = 0; index < params.length; index++) {
-        var [name, value] = params[index].split("=");
+        var param = params[index].split("=");
+        var name = param[0];
+        var value = param[1];
         switch (name) {
             case "assetUrl": {
                 assetUrl = value;
                 break;
             }
             case "cameraPosition": {
-                cameraPosition = BABYLON.Vector3.FromArray(value.split(",").map(component => +component));
+                cameraPosition = BABYLON.Vector3.FromArray(value.split(",").map(function (component) { return +component; }));
                 break;
             }
             case "kiosk": {

+ 11 - 4
src/Actions/babylon.actionManager.ts

@@ -197,15 +197,22 @@
 
         /**
          * Does this action manager handles actions of a given trigger
-         * @param {number} trigger - the trigger to be tested
-         * @return {boolean} whether the trigger is handeled 
+         * @param trigger defines the trigger to be tested
+         * @param parameterPredicate defines an optional predicate to filter triggers by parameter
+         * @return whether the trigger is handled 
          */
-        public hasSpecificTrigger(trigger: number): boolean {
+        public hasSpecificTrigger(trigger: number, parameterPredicate?: (parameter: any) => boolean): boolean {
             for (var index = 0; index < this.actions.length; index++) {
                 var action = this.actions[index];
 
                 if (action.trigger === trigger) {
-                    return true;
+                    if (parameterPredicate) {
+                        if (parameterPredicate(action.getTriggerParameter())) {
+                            return true;
+                        }
+                    } else {
+                        return true;
+                    }
                 }
             }
 

+ 29 - 1
src/Animations/babylon.animation.ts

@@ -97,8 +97,16 @@
     }
 
     export class Animation {
+        /**
+         * Use matrix interpolation instead of using direct key value when animating matrices
+         */
         public static AllowMatricesInterpolation = false;
 
+        /**
+         * When matrix interpolation is enabled, this boolean forces the system to use Matrix.DecomposeLerp instead of Matrix.Lerp. Interpolation is more precise but slower
+         */
+        public static AllowMatrixDecomposeForInterpolation = true;
+
         private _keys: Array<IAnimationKey>;
         private _easingFunction: IEasingFunction;
 
@@ -448,7 +456,27 @@
             return Color3.Lerp(startValue, endValue, gradient);
         }
 
-        public matrixInterpolateFunction(startValue: Matrix, endValue: Matrix, gradient: number): Matrix {
+        /**
+         * Defines the function to use to interpolate matrices
+         * @param startValue defines the start matrix
+         * @param endValue defines the end matrix
+         * @param gradient defines the gradient between both matrices 
+         * @param result defines an optional target matrix where to store the interpolation
+         * @returns the interpolated matrix
+         */
+        public matrixInterpolateFunction(startValue: Matrix, endValue: Matrix, gradient: number, result?: Matrix): Matrix {
+            if (Animation.AllowMatrixDecomposeForInterpolation) {
+                if (result) {
+                    Matrix.DecomposeLerpToRef(startValue, endValue, gradient, result);    
+                    return result;
+                }
+                return Matrix.DecomposeLerp(startValue, endValue, gradient);
+            }
+
+            if (result) {
+                Matrix.LerpToRef(startValue, endValue, gradient, result);
+                return result;
+            }
             return Matrix.Lerp(startValue, endValue, gradient);
         }
 

+ 17 - 3
src/Animations/babylon.runtimeAnimation.ts

@@ -15,6 +15,7 @@
         private _scene: Scene;
 
         private _currentValue: any;
+        private _workValue: any;
         private _activeTarget: any;
         private _targetPath: string = "";
         private _weight = 1.0;
@@ -172,7 +173,7 @@
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
                                     return quatValue;
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
-                                    return quatValue.add(offsetValue.scale(repeatCount));
+                                    return quatValue.addInPlace(offsetValue.scale(repeatCount));
                             }
 
                             return quatValue;
@@ -220,7 +221,8 @@
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
                                     if (Animation.AllowMatricesInterpolation) {
-                                        return this._animation.matrixInterpolateFunction(startValue, endValue, gradient);
+                                        this._workValue = this._animation.matrixInterpolateFunction(startValue, endValue, gradient, this._workValue);
+                                        return this._workValue;
                                     }
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
                                     return startValue;
@@ -308,7 +310,19 @@
                     }
 
                 } else if (this._originalBlendValue.m) { // Matrix
-                    this._currentValue = Matrix.Lerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                    if (Animation.AllowMatrixDecomposeForInterpolation) {
+                        if (this._currentValue) {
+                            Matrix.DecomposeLerpToRef(this._originalBlendValue, currentValue, this._blendingFactor, this._currentValue);
+                        } else {
+                            this._currentValue = Matrix.DecomposeLerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                        }
+                    } else {
+                        if (this._currentValue) {
+                            Matrix.LerpToRef(this._originalBlendValue, currentValue, this._blendingFactor, this._currentValue);
+                        } else {
+                            this._currentValue = Matrix.Lerp(this._originalBlendValue, currentValue, this._blendingFactor);
+                        }
+                    }
                 } else { // Direct value
                     this._currentValue = this._originalBlendValue * (1.0 - this._blendingFactor) + this._blendingFactor * currentValue;
                 }

+ 19 - 0
src/Layer/babylon.effectLayer.ts

@@ -176,6 +176,12 @@
         public abstract _disposeMesh(mesh: Mesh): void;
 
         /**
+         * Serializes this layer (Glow or Highlight for example)
+         * @returns a serialized layer object
+         */
+        public abstract serialize?(): any;
+
+        /**
          * Initializes the effect layer with the required options.
          * @param options Sets of none mandatory options to use with the layer (see IEffectLayerOptions for more information)
          */
@@ -670,5 +676,18 @@
          public getClassName(): string {
             return "EffectLayer";
         }
+
+        /**
+         * Creates an effect layer from parsed effect layer data
+         * @param parsedEffectLayer defines effect layer data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing the effect layer information
+         * @returns a parsed effect Layer
+         */
+        public static Parse(parsedEffectLayer: any, scene: Scene, rootUrl: string): EffectLayer {
+            var effectLayerType = Tools.Instantiate(parsedEffectLayer.customType);
+            
+            return effectLayerType.Parse(parsedEffectLayer, scene, rootUrl);
+        }
     }
 } 

+ 3 - 1
src/Layer/babylon.glowLayer.ts

@@ -88,7 +88,7 @@
             return this._intensity;
         }
 
-        @serialize('options')
+        @serialize("options")
         private _options: IGlowLayerOptions;
 
         private _intensity: number = 1.0;
@@ -460,6 +460,8 @@
          */
         public serialize(): any {
             var serializationObject = SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.GlowLayer";
+
             var index;
 
             // Included meshes

+ 86 - 0
src/Layer/babylon.highlightLayer.ts

@@ -141,11 +141,13 @@
         /**
          * Specifies whether or not the inner glow is ACTIVE in the layer.
          */
+        @serialize()
         public innerGlow: boolean = true;
 
         /**
          * Specifies whether or not the outer glow is ACTIVE in the layer.
          */
+        @serialize()
         public outerGlow: boolean = true;
 
         /**
@@ -165,6 +167,7 @@
         /**
          * Gets the horizontal size of the blur.
          */
+        @serialize()
         public get blurHorizontalSize(): number {
             return this._horizontalBlurPostprocess.kernel
         }
@@ -172,6 +175,7 @@
         /**
          * Gets the vertical size of the blur.
          */
+        @serialize()
         public get blurVerticalSize(): number {
             return this._verticalBlurPostprocess.kernel;
         }
@@ -188,6 +192,7 @@
 
         private _instanceGlowingMeshStencilReference = HighlightLayer.GlowingMeshStencilReference++;
 
+        @serialize("options")
         private _options: IHighlightLayerOptions;
         private _downSamplePostprocess: PassPostProcess;
         private _horizontalBlurPostprocess: GlowBlurPostProcess;
@@ -668,5 +673,86 @@
 
             super.dispose();
         }
+
+        /**
+          * Gets the class name of the effect layer
+          * @returns the string with the class name of the effect layer
+          */
+         public getClassName(): string {
+            return "HighlightLayer";
+        }
+
+        /**
+         * Serializes this Highlight layer
+         * @returns a serialized Highlight layer object
+         */
+        public serialize(): any {
+            var serializationObject = SerializationHelper.Serialize(this);
+            serializationObject.customType = "BABYLON.HighlightLayer";
+
+            // Highlighted meshes
+            serializationObject.meshes = [];
+
+            if (this._meshes) {
+                for (var m in this._meshes) {
+                    var mesh = this._meshes[m];
+
+                    if (mesh) {
+                        serializationObject.meshes.push({
+                            glowEmissiveOnly: mesh.glowEmissiveOnly,
+                            color: mesh.color.asArray(),
+                            meshId: mesh.mesh.id
+                        });
+                    }
+                }
+            }
+
+            // Excluded meshes
+            serializationObject.excludedMeshes = [];
+
+            if (this._excludedMeshes) {
+                for (var e in this._excludedMeshes) {
+                    var excludedMesh = this._excludedMeshes[e];
+
+                    if (excludedMesh) {
+                        serializationObject.excludedMeshes.push(excludedMesh.mesh.id);
+                    }
+                }
+            }
+
+            return serializationObject;
+        }
+
+        /**
+         * Creates a Highlight layer from parsed Highlight layer data
+         * @param parsedHightlightLayer defines the Highlight layer data
+         * @param scene defines the current scene
+         * @param rootUrl defines the root URL containing the Highlight layer information
+         * @returns a parsed Highlight layer
+         */
+        public static Parse(parsedHightlightLayer: any, scene: Scene, rootUrl: string): HighlightLayer {
+            var hl = SerializationHelper.Parse(() => new HighlightLayer(parsedHightlightLayer.name, scene, parsedHightlightLayer.options), parsedHightlightLayer, scene, rootUrl);
+            var index;
+
+            // Excluded meshes
+            for (index = 0; index < parsedHightlightLayer.excludedMeshes.length; index++) {
+                var mesh = scene.getMeshByID(parsedHightlightLayer.excludedMeshes[index]);
+                if (mesh) {
+                    hl.addExcludedMesh(<Mesh> mesh);
+                }
+            }
+
+            // Included meshes
+            for (index = 0; index < parsedHightlightLayer.meshes.length; index++) {
+                var highlightedMesh = parsedHightlightLayer.meshes[index];
+                var mesh = scene.getMeshByID(highlightedMesh.meshId);
+
+                if (mesh) {
+                    hl.addMesh(<Mesh> mesh, Color3.FromArray(highlightedMesh.color), highlightedMesh.glowEmissiveOnly);
+                }
+            }
+
+            return hl;
+        }
     }
 } 

+ 8 - 0
src/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -357,6 +357,14 @@
                 }
             }
 
+            // Effect layers
+            if (parsedData.effectLayers) {
+                for (index = 0; index < parsedData.effectLayers.length; index++) {
+                    var effectLayer = EffectLayer.Parse(parsedData.effectLayers[index], scene, rootUrl);
+                    container.effectLayers.push(effectLayer);
+                }
+            }
+
             // Actions (scene)
             if (parsedData.actions !== undefined && parsedData.actions !== null) {
                 ActionManager.Parse(parsedData.actions, null, scene);

+ 17 - 0
src/Materials/Textures/babylon.cubeTexture.ts

@@ -31,6 +31,23 @@
             return this._boundingBoxSize;
         }
 
+
+        @serialize("rotationY")
+        protected _rotationY: number = 0;
+        /**
+         * Sets texture matrix rotation angle around Y axis in radians.
+         */
+        public set rotationY(value: number) {
+            this._rotationY = value;
+            this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
+        }
+        /**
+         * Gets texture matrix rotation angle around Y axis radians.
+         */
+        public get rotationY(): number {
+            return this._rotationY;
+        }        
+
         private _noMipmap: boolean;
         private _files: string[];
         private _extensions: string[];

+ 2 - 2
src/Materials/Textures/babylon.hdrCubeTexture.ts

@@ -59,14 +59,14 @@ module BABYLON {
 
         protected _rotationY: number = 0;
         /**
-         * Sets texture matrix rotation angle (theta) Y in radians.
+         * Sets texture matrix rotation angle around Y axis in radians.
          */
         public set rotationY(value: number) {
             this._rotationY = value;
             this.setReflectionTextureMatrix(BABYLON.Matrix.RotationY(this._rotationY));
         }
         /**
-         * Gets texture matrix rotation angle (theta) Y radians.
+         * Gets texture matrix rotation angle around Y axis radians.
          */
         public get rotationY(): number {
             return this._rotationY;

+ 13 - 1
src/Materials/Textures/babylon.mirrorTexture.ts

@@ -83,11 +83,18 @@
                 this._autoComputeBlurKernel();
             }
         }
+        private _updateGammaSpace(){
+            this.gammaSpace = !this.scene.imageProcessingConfiguration.isEnabled || !this.scene.imageProcessingConfiguration.applyByPostProcess;
+        }
 
-        constructor(name: string, size: number | { width: number, height: number } | { ratio: number }, scene: Scene, generateMipMaps?: boolean, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, samplingMode = Texture.BILINEAR_SAMPLINGMODE, generateDepthBuffer = true) {
+        private _imageProcessingConfigChangeObserver:Nullable<Observer<ImageProcessingConfiguration>>;
+        constructor(name: string, size: number | { width: number, height: number } | { ratio: number }, private scene: Scene, generateMipMaps?: boolean, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, samplingMode = Texture.BILINEAR_SAMPLINGMODE, generateDepthBuffer = true) {
             super(name, size, scene, generateMipMaps, true, type, false, samplingMode, generateDepthBuffer);
 
             this.ignoreCameraViewport = true;
+            
+            this._updateGammaSpace();
+            this._imageProcessingConfigChangeObserver = scene.imageProcessingConfiguration.onUpdateParameters.add(this._updateGammaSpace)
 
             this.onBeforeRenderObservable.add(() => {
                 Matrix.ReflectionToRef(this.mirrorPlane, this._mirrorMatrix);
@@ -193,5 +200,10 @@
 
             return serializationObject;
         }
+
+        public dispose(){
+            super.dispose();
+            this.scene.imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingConfigChangeObserver);
+        }
     }
 } 

+ 13 - 0
src/Materials/babylon.standardMaterial.ts

@@ -87,6 +87,16 @@ module BABYLON {
         public SAMPLER3DGREENDEPTH = false;
         public SAMPLER3DBGRMAP = false;
         public IMAGEPROCESSINGPOSTPROCESS = false;
+        /**
+         * If the reflection texture on this material is in linear color space
+         * @ignore
+         */
+        public IS_REFLECTION_LINEAR = false;
+        /**
+         * If the refraction texture on this material is in linear color space
+         * @ignore
+         */
+        public IS_REFRACTION_LINEAR = false;
         public EXPOSURE = false;
 
         constructor() {
@@ -724,6 +734,9 @@ module BABYLON {
                 }
 
                 this._imageProcessingConfiguration.prepareDefines(defines);
+
+                defines.IS_REFLECTION_LINEAR = (this.reflectionTexture != null && !this.reflectionTexture.gammaSpace);
+                defines.IS_REFRACTION_LINEAR = (this.refractionTexture != null && !this.refractionTexture.gammaSpace);
             }
 
             if (defines._areFresnelDirty) {

+ 73 - 36
src/Math/babylon.math.ts

@@ -3159,6 +3159,19 @@
         public add(other: Quaternion): Quaternion {
             return new Quaternion(this.x + other.x, this.y + other.y, this.z + other.z, this.w + other.w);
         }
+
+        /**
+         * Add a quaternion to the current one
+         * @param other defines the quaternion to add
+         * @returns the current quaternion  
+         */
+        public addInPlace(other: Quaternion): Quaternion {
+            this.x += other.x;
+            this.y += other.y;
+            this.z += other.z;
+            this.w += other.w;
+            return this;
+        }        
         /**
          * Returns a new Quaternion as the subtraction result of the passed one from the current Quaternion.  
          */
@@ -3552,7 +3565,6 @@
         public static SlerpToRef(left: Quaternion, right: Quaternion, amount: number, result: Quaternion): void {
             var num2;
             var num3;
-            var num = amount;
             var num4 = (((left.x * right.x) + (left.y * right.y)) + (left.z * right.z)) + (left.w * right.w);
             var flag = false;
 
@@ -3562,14 +3574,14 @@
             }
 
             if (num4 > 0.999999) {
-                num3 = 1 - num;
-                num2 = flag ? -num : num;
+                num3 = 1 - amount;
+                num2 = flag ? -amount : amount;
             }
             else {
                 var num5 = Math.acos(num4);
                 var num6 = (1.0 / Math.sin(num5));
-                num3 = (Math.sin((1.0 - num) * num5)) * num6;
-                num2 = flag ? ((-Math.sin(num * num5)) * num6) : ((Math.sin(num * num5)) * num6);
+                num3 = (Math.sin((1.0 - amount) * num5)) * num6;
+                num2 = flag ? ((-Math.sin(amount * num5)) * num6) : ((Math.sin(amount * num5)) * num6);
             }
 
             result.x = (num3 * left.x) + (num2 * right.x);
@@ -4042,7 +4054,8 @@
                 hash = (hash * 397) ^ (this.m[i] || 0);
             }
             return hash;
-        }
+        }     
+
         /**
          * Decomposes the current Matrix into a translation, rotation and scaling components
          * @param scale defines the scale vector3 passed as a reference to update
@@ -4050,10 +4063,12 @@
          * @param translation defines the translation vector3 passed as a reference to update
          * @returns true if operation was successful
          */
-        public decompose(scale: Vector3, rotation: Quaternion, translation: Vector3): boolean {
-            translation.x = this.m[12];
-            translation.y = this.m[13];
-            translation.z = this.m[14];
+        public decompose(scale: Vector3, rotation?: Quaternion, translation?: Vector3): boolean {
+            if (translation) {
+                translation.x = this.m[12];
+                translation.y = this.m[13];
+                translation.z = this.m[14];
+            }
 
             scale.x = Math.sqrt(this.m[0] * this.m[0] + this.m[1] * this.m[1] + this.m[2] * this.m[2]);
             scale.y = Math.sqrt(this.m[4] * this.m[4] + this.m[5] * this.m[5] + this.m[6] * this.m[6]);
@@ -4063,21 +4078,23 @@
                 scale.y *= -1;
             }
 
-            if (scale.x === 0 || scale.y === 0 || scale.z === 0) {
-                rotation.x = 0;
-                rotation.y = 0;
-                rotation.z = 0;
-                rotation.w = 1;
-                return false;
-            }
+            if (rotation) {
+                if (scale.x === 0 || scale.y === 0 || scale.z === 0) {
+                    rotation.x = 0;
+                    rotation.y = 0;
+                    rotation.z = 0;
+                    rotation.w = 1;
+                    return false;
+                }
 
-            Matrix.FromValuesToRef(
-                this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0,
-                this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0,
-                this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0,
-                0, 0, 0, 1, MathTmp.Matrix[0]);
+                Matrix.FromValuesToRef(
+                    this.m[0] / scale.x, this.m[1] / scale.x, this.m[2] / scale.x, 0,
+                    this.m[4] / scale.y, this.m[5] / scale.y, this.m[6] / scale.y, 0,
+                    this.m[8] / scale.z, this.m[9] / scale.z, this.m[10] / scale.z, 0,
+                    0, 0, 0, 1, MathTmp.Matrix[0]);
 
-            Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
+                Quaternion.FromRotationMatrixToRef(MathTmp.Matrix[0], rotation);
+            }
 
             return true;
         }
@@ -4769,22 +4786,42 @@
          * @returns the new matrix
          */
         public static DecomposeLerp(startValue: Matrix, endValue: Matrix, gradient: number): Matrix {
-            var startScale = new Vector3(0, 0, 0);
-            var startRotation = new Quaternion();
-            var startTranslation = new Vector3(0, 0, 0);
+            var result = Matrix.Zero();
+            Matrix.DecomposeLerpToRef(startValue, endValue, gradient, result);
+            return result;
+        }
+
+        /**
+         * Update a matrix to values which are computed by: 
+         * * decomposing the the "startValue" and "endValue" matrices into their respective scale, rotation and translation matrices
+         * * interpolating for "gradient" (float) the values between each of these decomposed matrices between the start and the end
+         * * recomposing a new matrix from these 3 interpolated scale, rotation and translation matrices
+         * @param startValue defines the first matrix
+         * @param endValue defines the second matrix
+         * @param gradient defines the gradient between the two matrices
+         * @param result defines the target matrix
+         */
+        public static DecomposeLerpToRef(startValue: Matrix, endValue: Matrix, gradient: number, result: Matrix) {
+            var startScale = MathTmp.Vector3[0];
+            var startRotation = MathTmp.Quaternion[0];
+            var startTranslation = MathTmp.Vector3[1];
             startValue.decompose(startScale, startRotation, startTranslation);
 
-            var endScale = new Vector3(0, 0, 0);
-            var endRotation = new Quaternion();
-            var endTranslation = new Vector3(0, 0, 0);
+            var endScale = MathTmp.Vector3[2];
+            var endRotation = MathTmp.Quaternion[1];
+            var endTranslation = MathTmp.Vector3[3];
             endValue.decompose(endScale, endRotation, endTranslation);
 
-            var resultScale = Vector3.Lerp(startScale, endScale, gradient);
-            var resultRotation = Quaternion.Slerp(startRotation, endRotation, gradient);
-            var resultTranslation = Vector3.Lerp(startTranslation, endTranslation, gradient);
+            var resultScale = MathTmp.Vector3[4];
+            Vector3.LerpToRef(startScale, endScale, gradient, resultScale);
+            var resultRotation = MathTmp.Quaternion[2];
+            Quaternion.SlerpToRef(startRotation, endRotation, gradient, resultRotation);
+            
+            var resultTranslation = MathTmp.Vector3[5];
+            Vector3.LerpToRef(startTranslation, endTranslation, gradient, resultTranslation);
 
-            return Matrix.Compose(resultScale, resultRotation, resultTranslation);
-        }
+            Matrix.ComposeToRef(resultScale, resultRotation, resultTranslation, result);
+        }        
 
         /**
          * Gets a new rotation matrix used to rotate an entity so as it looks at the target vector3, from the eye vector3 position, the up vector3 being oriented like "up"
@@ -6264,8 +6301,8 @@
     }
     // Same as Tmp but not exported to keep it onyl for math functions to avoid conflicts
     class MathTmp {
-        public static Vector3: Vector3[] = [Vector3.Zero()];
+        public static Vector3: Vector3[] = [Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero(), Vector3.Zero()];
         public static Matrix: Matrix[] = [Matrix.Zero(), Matrix.Zero()];
-        public static Quaternion: Quaternion[] = [Quaternion.Zero()];
+        public static Quaternion: Quaternion[] = [Quaternion.Zero(), Quaternion.Zero(), Quaternion.Zero()];
     }
 }

+ 153 - 105
src/Mesh/Compression/babylon.dracoCompression.ts

@@ -1,43 +1,59 @@
 declare var DracoDecoderModule: any;
+declare var WebAssembly: any;
 
 module BABYLON {
     /**
+     * Configuration for Draco compression
+     */
+    export interface IDracoCompressionConfiguration {
+        /**
+         * Configuration for the JavaScript decoder or null if not available.
+         */
+        decoder: Nullable<{
+            url: string;
+        }>;
+
+        /**
+         * Configuration for the WebAssembly decoder or null if not available.
+         */
+        decoderWasm: Nullable<{
+            binaryUrl: string;
+            wrapperUrl: string;
+        }>;
+    }
+
+    /**
      * Draco compression (https://google.github.io/draco/)
      */
     export class DracoCompression implements IDisposable {
-        private _workerPool: WorkerPool;
+        private static _DecoderModulePromise: Promise<any>;
 
         /**
-         * Gets the url to the draco decoder if available.
+         * Gets the configuration.
          */
-        public static DecoderUrl: Nullable<string> = DracoCompression._GetDefaultDecoderUrl();
+        public static Configuration = DracoCompression._GetDefaultConfig();
 
         /**
-         * Constructor
-         * @param numWorkers The number of workers for async operations
+         * Returns true if the decoder is available.
          */
-        constructor(numWorkers = (navigator.hardwareConcurrency || 4)) {
-            let workerBlobUrl = URL && URL.createObjectURL && URL.createObjectURL(new Blob([`(${DracoCompression._Worker.toString()})()`], { type: "application/javascript" }));
-            if (!workerBlobUrl || !Worker) {
-                Tools.Error("Draco Compression disabled. The current context doesn't support worker creation or URL.createObjectURL");
-                return;
-            }
-            const workers = new Array<Worker>(numWorkers);
-            for (let i = 0; i < workers.length; i++) {
-                const worker = new Worker(workerBlobUrl);
-                worker.postMessage({ id: "initDecoder", url: DracoCompression.DecoderUrl });
-                workers[i] = worker;
-            }
+        public static get DecoderAvailable(): boolean {
+            return (
+                typeof DracoDecoderModule !== "undefined" ||
+                (typeof WebAssembly === "object" && !!DracoCompression.Configuration.decoderWasm) ||
+                !!DracoCompression.Configuration.decoder
+            );
+        }
 
-            this._workerPool = new WorkerPool(workers);
+        /**
+         * Constructor
+         */
+        constructor() {
         }
 
         /**
          * Stop all async operations and release resources.
          */
         public dispose(): void {
-            this._workerPool.dispose();
-            delete this._workerPool;
         }
 
         /**
@@ -47,72 +63,26 @@ module BABYLON {
          * @returns A promise that resolves with the decoded vertex data
          */
         public decodeMeshAsync(data: ArrayBufferView, attributes: { [kind: string]: number }): Promise<VertexData> {
-            return new Promise((resolve, reject) => {
-                this._workerPool.push((worker, onComplete) => {
-                    const vertexData = new VertexData();
-
-                    const onError = (error: ErrorEvent) => {
-                        worker.removeEventListener("error", onError);
-                        worker.removeEventListener("message", onMessage);
-                        reject(error);
-                        onComplete();
-                    };
+            return DracoCompression._GetDecoderModule().then(wrappedModule => {
+                const module = wrappedModule.module;
+                const vertexData = new VertexData();
 
-                    const onMessage = (message: MessageEvent) => {
-                        if (message.data === "done") {
-                            worker.removeEventListener("error", onError);
-                            worker.removeEventListener("message", onMessage);
-                            resolve(vertexData);
-                            onComplete();
-                        }
-                        else if (message.data.id === "indices") {
-                            vertexData.indices = message.data.value;
-                        }
-                        else {
-                            vertexData.set(message.data.value, message.data.id);
-                        }
-                    };
-
-                    worker.addEventListener("error", onError);
-                    worker.addEventListener("message", onMessage);
-
-                    const dataCopy = new Uint8Array(data.byteLength);
-                    dataCopy.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
-
-                    worker.postMessage({ id: "decodeMesh", data: dataCopy, attributes: attributes }, [dataCopy.buffer]);
-                });
-            });
-        }
-
-        /**
-         * The worker function that gets converted to a blob url to pass into a worker.
-         */
-        private static _Worker(): void {
-            // self is actually a DedicatedWorkerGlobalScope
-            const _self = self as any as {
-                onmessage: (event: MessageEvent) => void;
-                postMessage: (message: any, transfer?: any[]) => void;
-                close: () => void;
-            };
-
-            const decodeMesh = (data: ArrayBufferView, attributes: { [kind: string]: number }): void => {
-                const dracoModule = new DracoDecoderModule();
-                const buffer = new dracoModule.DecoderBuffer();
+                const buffer = new module.DecoderBuffer();
                 buffer.Init(data, data.byteLength);
 
-                const decoder = new dracoModule.Decoder();
+                const decoder = new module.Decoder();
                 let geometry: any;
                 let status: any;
 
                 try {
                     const type = decoder.GetEncodedGeometryType(buffer);
                     switch (type) {
-                        case dracoModule.TRIANGULAR_MESH:
-                            geometry = new dracoModule.Mesh();
+                        case module.TRIANGULAR_MESH:
+                            geometry = new module.Mesh();
                             status = decoder.DecodeBufferToMesh(buffer, geometry);
                             break;
-                        case dracoModule.POINT_CLOUD:
-                            geometry = new dracoModule.PointCloud();
+                        case module.POINT_CLOUD:
+                            geometry = new module.PointCloud();
                             status = decoder.DecodeBufferToPointCloud(buffer, geometry);
                             break;
                         default:
@@ -125,9 +95,9 @@ module BABYLON {
 
                     const numPoints = geometry.num_points();
 
-                    if (type === dracoModule.TRIANGULAR_MESH) {
+                    if (type === module.TRIANGULAR_MESH) {
                         const numFaces = geometry.num_faces();
-                        const faceIndices = new dracoModule.DracoInt32Array();
+                        const faceIndices = new module.DracoInt32Array();
                         try {
                             const indices = new Uint32Array(numFaces * 3);
                             for (let i = 0; i < numFaces; i++) {
@@ -137,68 +107,146 @@ module BABYLON {
                                 indices[offset + 1] = faceIndices.GetValue(1);
                                 indices[offset + 2] = faceIndices.GetValue(2);
                             }
-                            _self.postMessage({ id: "indices", value: indices }, [indices.buffer]);
+                            vertexData.indices = indices;
                         }
                         finally {
-                            dracoModule.destroy(faceIndices);
+                            module.destroy(faceIndices);
                         }
                     }
 
                     for (const kind in attributes) {
                         const uniqueId = attributes[kind];
                         const attribute = decoder.GetAttributeByUniqueId(geometry, uniqueId);
-                        const dracoData = new dracoModule.DracoFloat32Array();
+                        const dracoData = new module.DracoFloat32Array();
                         try {
                             decoder.GetAttributeFloatForAllPoints(geometry, attribute, dracoData);
                             const babylonData = new Float32Array(numPoints * attribute.num_components());
                             for (let i = 0; i < babylonData.length; i++) {
                                 babylonData[i] = dracoData.GetValue(i);
                             }
-                            _self.postMessage({ id: kind, value: babylonData }, [babylonData.buffer]);
+                            vertexData.set(babylonData, kind);
                         }
                         finally {
-                            dracoModule.destroy(dracoData);
+                            module.destroy(dracoData);
                         }
                     }
                 }
                 finally {
                     if (geometry) {
-                        dracoModule.destroy(geometry);
+                        module.destroy(geometry);
                     }
 
-                    dracoModule.destroy(decoder);
-                    dracoModule.destroy(buffer);
+                    module.destroy(decoder);
+                    module.destroy(buffer);
                 }
 
-                _self.postMessage("done");
+                return vertexData;
+            });
+        }
+
+        private static _GetDecoderModule(): Promise<any> {
+            if (!DracoCompression._DecoderModulePromise) {
+                let promise: Promise<any>;
+                let config: any = {};
+
+                if (typeof DracoDecoderModule !== "undefined") {
+                    promise = Promise.resolve();
+                }
+                else if (typeof WebAssembly === "object" && DracoCompression.Configuration.decoderWasm) {
+                    promise = Promise.all([
+                        DracoCompression._LoadScriptAsync(DracoCompression.Configuration.decoderWasm.wrapperUrl),
+                        DracoCompression._LoadFileAsync(DracoCompression.Configuration.decoderWasm.binaryUrl).then(data => {
+                            config.wasmBinary = data;
+                        })
+                    ]);
+                }
+                else if (DracoCompression.Configuration.decoder) {
+                    promise = DracoCompression._LoadScriptAsync(DracoCompression.Configuration.decoder.url);
+                }
+                else {
+                    throw new Error("Invalid decoder configuration");
+                }
+
+                DracoCompression._DecoderModulePromise = promise.then(() => {
+                    return new Promise(resolve => {
+                        config.onModuleLoaded = (decoderModule: any) => {
+                            // decoderModule is Promise-like. Wrap before resolving to avoid loop.
+                            resolve({ module: decoderModule });
+                        };
+
+                        DracoDecoderModule(config);
+                    });
+                });
             }
 
-            _self.onmessage = event => {
-                switch (event.data.id) {
-                    case "initDecoder": {
-                        importScripts(event.data.url);
-                        break;
-                    }
-                    case "decodeMesh": {
-                        decodeMesh(event.data.data, event.data.attributes);
-                        break;
+            return DracoCompression._DecoderModulePromise;
+        }
+
+        private static _LoadScriptAsync(url: string): Promise<void> {
+            return new Promise((resolve, reject) => {
+                Tools.LoadScript(url, () => {
+                    resolve();
+                }, message => {
+                    reject(new Error(message));
+                });
+            });
+        }
+
+        private static _LoadFileAsync(url: string): Promise<ArrayBuffer> {
+            return new Promise((resolve, reject) => {
+                Tools.LoadFile(url, data => {
+                    resolve(data as ArrayBuffer);
+                }, undefined, undefined, true, (request, exception) => {
+                    reject(exception);
+                });
+            });
+        }
+
+        private static _GetDefaultConfig(): IDracoCompressionConfiguration {
+            const configuration: IDracoCompressionConfiguration = {
+                decoder: null,
+                decoderWasm: null
+            };
+
+            if (Tools.IsWindowObjectExist()) {
+                let decoderUrl: Nullable<string> = null;
+                let decoderWasmBinaryUrl: Nullable<string> = null;
+                let decoderWasmWrapperUrl: Nullable<string> = null;
+
+                for (let i = 0; i < document.scripts.length; i++) {
+                    const type = document.scripts[i].type;
+                    const src = document.scripts[i].src;
+                    switch (type) {
+                        case "text/x-draco-decoder": {
+                            decoderUrl = src;
+                            break;
+                        }
+                        case "text/x-draco-decoder-wasm-binary": {
+                            decoderWasmBinaryUrl = src;
+                            break;
+                        }
+                        case "text/x-draco-decoder-wasm-wrapper": {
+                            decoderWasmWrapperUrl = src;
+                            break;
+                        }
                     }
                 }
-            };
-        }
 
-        private static _GetDefaultDecoderUrl(): Nullable<string> {
-            if (!Tools.IsWindowObjectExist()) {
-                return null;
-            }
+                if (decoderUrl) {
+                    configuration.decoder = {
+                        url: decoderUrl
+                    };
+                }
 
-            for (let i = 0; i < document.scripts.length; i++) {
-                if (document.scripts[i].type === "text/x-draco-decoder") {
-                    return document.scripts[i].src;
+                if (decoderWasmWrapperUrl && decoderWasmBinaryUrl) {
+                    configuration.decoderWasm = {
+                        binaryUrl: decoderWasmBinaryUrl,
+                        wrapperUrl: decoderWasmWrapperUrl
+                    };
                 }
             }
 
-            return null;
+            return configuration;
         }
     }
 }

+ 6 - 3
src/PostProcess/RenderPipeline/babylon.postProcessRenderEffect.ts

@@ -43,9 +43,12 @@ module BABYLON {
          */
         public get isSupported(): boolean {
             for (var index in this._postProcesses) {
-                for(var ppIndex in this._postProcesses[index]){
-                    if (!this._postProcesses[index][ppIndex].isSupported) {
-                        return false;
+                if (this._postProcesses.hasOwnProperty(index)) {
+                    let pps = this._postProcesses[index];
+                    for(var ppIndex = 0; ppIndex < pps.length; ppIndex++){
+                        if (!pps[ppIndex].isSupported) {
+                            return false;
+                        }
                     }
                 }
             }

+ 58 - 55
src/Shaders/default.fragment.fx

@@ -259,73 +259,76 @@ void main(void) {
 
 #ifdef REFRACTION
 	vec3 refractionVector = normalize(refract(-viewDirectionW, normalW, vRefractionInfos.y));
-#ifdef REFRACTIONMAP_3D
-
-	refractionVector.y = refractionVector.y * vRefractionInfos.w;
+	#ifdef REFRACTIONMAP_3D
+		refractionVector.y = refractionVector.y * vRefractionInfos.w;
 
-	if (dot(refractionVector, viewDirectionW) < 1.0)
-	{
-		refractionColor = textureCube(refractionCubeSampler, refractionVector).rgb * vRefractionInfos.x;
-	}
-#else
-	vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0)));
-
-	vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z;
+		if (dot(refractionVector, viewDirectionW) < 1.0) {
+			refractionColor = textureCube(refractionCubeSampler, refractionVector).rgb;
+		}
+	#else
+		vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0)));
 
-	refractionCoords.y = 1.0 - refractionCoords.y;
+		vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z;
 
-	refractionColor = texture2D(refraction2DSampler, refractionCoords).rgb * vRefractionInfos.x;
-#endif
+		refractionCoords.y = 1.0 - refractionCoords.y;
+		
+		refractionColor = texture2D(refraction2DSampler, refractionCoords).rgb;
+	#endif
+	#ifdef IS_REFRACTION_LINEAR
+		refractionColor = toGammaSpace(refractionColor);
+	#endif
+	refractionColor *= vRefractionInfos.x;
 #endif
 
-	// Reflection
-	vec3 reflectionColor = vec3(0., 0., 0.);
+// Reflection
+vec3 reflectionColor = vec3(0., 0., 0.);
 
 #ifdef REFLECTION
 	vec3 vReflectionUVW = computeReflectionCoords(vec4(vPositionW, 1.0), normalW);
 
-#ifdef REFLECTIONMAP_3D
-#ifdef ROUGHNESS
-	float bias = vReflectionInfos.y;
-
-#ifdef SPECULARTERM
-	#ifdef SPECULAR
-		#ifdef GLOSSINESS
-			bias *= (1.0 - specularMapColor.a);
+	#ifdef REFLECTIONMAP_3D
+		#ifdef ROUGHNESS
+			float bias = vReflectionInfos.y;
+
+			#ifdef SPECULARTERM
+				#ifdef SPECULAR
+					#ifdef GLOSSINESS
+						bias *= (1.0 - specularMapColor.a);
+					#endif
+				#endif
+			#endif
+
+			reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW, bias).rgb;
+		#else
+			reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb;
 		#endif
-	#endif
-#endif
-
-	reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW, bias).rgb * vReflectionInfos.x;
-#else
-	reflectionColor = textureCube(reflectionCubeSampler, vReflectionUVW).rgb * vReflectionInfos.x;
-#endif
-
-#else
-	vec2 coords = vReflectionUVW.xy;
-
-#ifdef REFLECTIONMAP_PROJECTION
-	coords /= vReflectionUVW.z;
-#endif
-
-	coords.y = 1.0 - coords.y;
-
-	reflectionColor = texture2D(reflection2DSampler, coords).rgb * vReflectionInfos.x;
-#endif
+	#else
+		vec2 coords = vReflectionUVW.xy;
 
-#ifdef REFLECTIONFRESNEL
-	float reflectionFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, reflectionRightColor.a, reflectionLeftColor.a);
+		#ifdef REFLECTIONMAP_PROJECTION
+			coords /= vReflectionUVW.z;
+		#endif
 
-#ifdef REFLECTIONFRESNELFROMSPECULAR
-#ifdef SPECULARTERM
-	reflectionColor *= specularColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
-#else
-	reflectionColor *= reflectionLeftColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
-#endif
-#else
-	reflectionColor *= reflectionLeftColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
-#endif
-#endif
+		coords.y = 1.0 - coords.y;
+		reflectionColor = texture2D(reflection2DSampler, coords).rgb;
+	#endif
+	#ifdef IS_REFLECTION_LINEAR
+		reflectionColor = toGammaSpace(reflectionColor);
+	#endif
+	reflectionColor *= vReflectionInfos.x;
+	#ifdef REFLECTIONFRESNEL
+		float reflectionFresnelTerm = computeFresnelTerm(viewDirectionW, normalW, reflectionRightColor.a, reflectionLeftColor.a);
+
+		#ifdef REFLECTIONFRESNELFROMSPECULAR
+			#ifdef SPECULARTERM
+				reflectionColor *= specularColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
+			#else
+				reflectionColor *= reflectionLeftColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
+			#endif
+		#else
+			reflectionColor *= reflectionLeftColor.rgb * (1.0 - reflectionFresnelTerm) + reflectionFresnelTerm * reflectionRightColor.rgb;
+		#endif
+	#endif
 #endif
 
 #ifdef REFRACTIONFRESNEL

+ 10 - 0
src/Tools/babylon.sceneSerializer.ts

@@ -305,6 +305,16 @@
                 }
             }
 
+            // Effect layers
+            serializationObject.effectLayers = [];
+
+            for (index = 0; index < scene.effectLayers.length; index++) {
+                var layer = scene.effectLayers[index];
+                if (layer.serialize) {
+                    serializationObject.effectLayers.push(layer.serialize());
+                }
+            }
+
             return serializationObject;
         }
 

+ 1 - 1
src/Tools/babylon.tools.ts

@@ -716,7 +716,7 @@
 
             script.onerror = (e) => {
                 if (onError) {
-                    onError("Unable to load script", e);
+                    onError(`Unable to load script '${scriptUrl}'`, e);
                 }
             };
 

+ 16 - 1
src/babylon.assetContainer.ts

@@ -71,6 +71,10 @@ module BABYLON {
          * Textures to keep.
          */
         public textures = new Array<Texture>();
+        /**
+         * Effect layers to keep.
+         */
+        public effectLayers = new Array<EffectLayer>();
     }
 
     /**
@@ -151,6 +155,10 @@ module BABYLON {
          * Textures populated in the container.
          */
         public textures = new Array<Texture>();
+        /**
+         * Effect layers populated in the container.
+         */
+        public effectLayers = new Array<EffectLayer>();
 
         /**
          * Instantiates an AssetContainer.
@@ -212,7 +220,10 @@ module BABYLON {
                 this.scene.mainSoundTrack.AddSound(o);
             });
             this.textures.forEach((o) => {
-                this.scene.addTexture
+                this.scene.addTexture(o);
+            });
+            this.effectLayers.forEach((o) => {
+                this.scene.addEffectLayer(o);
             });
         }
 
@@ -270,6 +281,9 @@ module BABYLON {
             this.textures.forEach((o) => {
                 this.scene.removeTexture(o);
             });
+            this.effectLayers.forEach((o) => {
+                this.scene.removeEffectLayer(o);
+            });
         }
 
         private _moveAssets<T>(sourceAssets: T[], targetAssets: T[], keepAssets: T[]): void {
@@ -314,6 +328,7 @@ module BABYLON {
             this._moveAssets(this.scene.mainSoundTrack.soundCollection, this.sounds, keepAssets.sounds);
             this._moveAssets(this.scene.transformNodes, this.transformNodes, keepAssets.transformNodes);
             this._moveAssets(this.scene.textures, this.textures, keepAssets.textures);
+            this._moveAssets(this.scene.effectLayers, this.effectLayers, keepAssets.effectLayers);
 
             this.removeAllFromScene();
         }

+ 53 - 10
src/babylon.scene.ts

@@ -2693,32 +2693,49 @@
                 var target = this._registeredForLateAnimationBindings.data[index];
 
                 for (var path in target._lateAnimationHolders) {
-                    var holder = target._lateAnimationHolders[path];       
+                    var holder = target._lateAnimationHolders[path];                     
+                    let originalValue = holder.animations[0].originalValue;      
                     
                     // Sanity check
-                    if (!holder.animations[0].originalValue.scaleAndAddToRef) {
+                    if (!originalValue.scaleAndAddToRef) {
                         continue;
                     }
 
+                    let matrixDecomposeMode = Animation.AllowMatrixDecomposeForInterpolation && originalValue.m; // ie. data is matrix
                     let normalizer = 1.0;
                     let finalValue: any;
 
                     if (holder.totalWeight < 1.0) {
-                        // We need to mix the original value in
-                        let originalValue = holder.animations[0].originalValue;                       
-
-                        finalValue = originalValue.scale(1.0 - holder.totalWeight)
+                        // We need to mix the original value in     
+                        if (matrixDecomposeMode) {
+                            finalValue = originalValue.clone();
+                        } else {            
+                            finalValue = originalValue.scale(1.0 - holder.totalWeight)
+                        }
                     } else {
                         // We need to normalize the weights
                         normalizer = holder.totalWeight;
                     }
 
                     for (var animIndex = 0; animIndex < holder.animations.length; animIndex++) {
-                        var runtimeAnimation = holder.animations[animIndex];    
+                        var runtimeAnimation = holder.animations[animIndex];   
+                        var scale = runtimeAnimation.weight / normalizer;
                         if (finalValue) {
-                            runtimeAnimation.currentValue.scaleAndAddToRef(runtimeAnimation.weight / normalizer, finalValue);
+                            if (matrixDecomposeMode) {
+                                Matrix.DecomposeLerpToRef(finalValue, runtimeAnimation.currentValue, scale, finalValue);
+                            } else {
+                                runtimeAnimation.currentValue.scaleAndAddToRef(scale, finalValue);
+                            }
                         } else {
-                            finalValue = runtimeAnimation.currentValue.scale(runtimeAnimation.weight / normalizer);
+                            if (scale !== 1) {
+                                if (matrixDecomposeMode) {
+                                    finalValue = runtimeAnimation.currentValue.clone();
+                                } else {
+                                    finalValue = runtimeAnimation.currentValue.scale(scale);
+                                }
+                            } else {
+                                finalValue = runtimeAnimation.currentValue;
+                            }
                         }
                     }
 
@@ -3075,6 +3092,21 @@
             return index;
         }
 
+        
+        /**
+         * Removes the given effect layer from this scene.
+         * @param toRemove defines the effect layer to remove
+         * @returns the index of the removed effect layer
+         */    
+        public removeEffectLayer(toRemove: EffectLayer): number {
+            var index = this.effectLayers.indexOf(toRemove);
+            if (index !== -1) {
+                this.effectLayers.splice(index, 1);
+            }
+
+            return index;
+        }
+
         /**
          * Removes the given texture from this scene.
          * @param toRemove The texture to remove
@@ -3198,6 +3230,14 @@
         }
 
         /**
+         * Adds the given effect layer to this scene
+         * @param newEffectLayer defines the effect layer to add
+         */     
+        public addEffectLayer(newEffectLayer: EffectLayer): void {
+            this.effectLayers.push(newEffectLayer);
+        }
+
+        /**
          * Adds the given action manager to this scene
          * @param newActionManager The action manager to add
          */   
@@ -4475,7 +4515,10 @@
                             }
 
                             //if this is an exit trigger, or no exit trigger exists, remove the id from the intersection in progress array.
-                            if (!sourceMesh.actionManager.hasSpecificTrigger(ActionManager.OnIntersectionExitTrigger) || action.trigger === ActionManager.OnIntersectionExitTrigger) {
+                            if (!sourceMesh.actionManager.hasSpecificTrigger(ActionManager.OnIntersectionExitTrigger, parameter => {
+                                var parameterMesh = parameter instanceof AbstractMesh ? parameter : parameter.mesh;
+                                return otherMesh === parameterMesh;
+                            }) || action.trigger === ActionManager.OnIntersectionExitTrigger) {
                                 sourceMesh._intersectionsInProgress.splice(currentIntersectionInProgress, 1);
                             }
                         }

BIN
tests/validation/ReferenceImages/enableDisablePostProcess.png


+ 12 - 1
tests/validation/validation.js

@@ -312,7 +312,18 @@ function runTest(index, done) {
 function init() {
     BABYLON.SceneLoader.ShowLoadingScreen = false;
     BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental = true;
-    BABYLON.DracoCompression.DecoderUrl = BABYLON.Tools.GetFolderPath(document.location.href) + "../../dist/preview%20release/draco_decoder.js";
+
+    // Draco configuration
+    var baseUrl = BABYLON.Tools.GetFolderPath(document.location.href);
+    BABYLON.DracoCompression.Configuration = {
+        decoder: {
+            url: baseUrl + "../../dist/preview%20release/draco_decoder.js"
+        },
+        decoderWasm: {
+            binaryUrl: baseUrl + "../../dist/preview%20release/draco_decoder.wasm",
+            wrapperUrl: baseUrl + "../../dist/preview%20release/draco_wasm_wrapper.js"
+        }
+    };
 
     canvas = document.createElement("canvas");
     canvas.className = "renderCanvas";