Browse Source

merged with upstream

Benjamin Guignabert 8 years ago
parent
commit
832018118f
71 changed files with 3638 additions and 2530 deletions
  1. 8 0
      Tools/Gulp/gulpfile.js
  2. 2 1
      Tools/Gulp/package.json
  3. 1 1
      Tools/Gulp/profiling.html
  4. 28 28
      dist/preview release/babylon.core.js
  5. 1009 856
      dist/preview release/babylon.d.ts
  6. 39 39
      dist/preview release/babylon.js
  7. 543 223
      dist/preview release/babylon.max.js
  8. 1009 856
      dist/preview release/babylon.module.d.ts
  9. 38 38
      dist/preview release/babylon.noworker.js
  10. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.js
  11. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.min.js
  12. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.js
  13. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.min.js
  14. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.js
  15. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js
  16. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.js
  17. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.min.js
  18. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.js
  19. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js
  20. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  21. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  22. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js
  23. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  24. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.js
  25. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js
  26. 1 1
      dist/preview release/materialsLibrary/babylon.skyMaterial.js
  27. 1 1
      dist/preview release/materialsLibrary/babylon.skyMaterial.min.js
  28. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  29. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  30. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js
  31. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js
  32. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  33. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  34. 49 94
      localDev/src/index.js
  35. 1 1
      materialsLibrary/src/fire/babylon.fireMaterial.ts
  36. 1 1
      materialsLibrary/src/fur/babylon.furMaterial.ts
  37. 1 1
      materialsLibrary/src/gradient/babylon.gradientMaterial.ts
  38. 1 1
      materialsLibrary/src/grid/babylon.gridmaterial.ts
  39. 1 1
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  40. 1 1
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  41. 1 1
      materialsLibrary/src/shadowOnly/babylon.shadowOnlyMaterial.ts
  42. 1 1
      materialsLibrary/src/simple/babylon.simpleMaterial.ts
  43. 1 1
      materialsLibrary/src/sky/babylon.skyMaterial.ts
  44. 1 1
      materialsLibrary/src/terrain/babylon.terrainMaterial.ts
  45. 1 1
      materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts
  46. 1 1
      materialsLibrary/src/water/babylon.waterMaterial.ts
  47. BIN
      sandbox/Assets/BtnCamera.png
  48. 3 0
      sandbox/index-local.html
  49. 8 8
      sandbox/index.css
  50. 3 0
      sandbox/index.html
  51. 50 0
      sandbox/index.js
  52. 79 25
      src/Cameras/VR/babylon.webVRCamera.ts
  53. 2 0
      src/Cameras/babylon.camera.ts
  54. 7 0
      src/Loading/Plugins/babylon.babylonFileLoader.ts
  55. 6 15
      src/Materials/babylon.effect.ts
  56. 3 0
      src/Materials/babylon.material.ts
  57. 4 1
      src/Materials/babylon.materialHelper.ts
  58. 162 121
      src/Materials/babylon.pbrMaterial.ts
  59. 78 26
      src/Math/babylon.math.ts
  60. 87 1
      src/Mesh/babylon.abstractMesh.ts
  61. 77 0
      src/Mesh/babylon.instancedMesh.ts
  62. 12 1
      src/Mesh/babylon.mesh.ts
  63. 14 2
      src/Morph/babylon.morphTarget.ts
  64. 15 0
      src/Morph/babylon.morphTargetManager.ts
  65. 0 1
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  66. 14 1
      src/Physics/babylon.physicsImpostor.ts
  67. 189 154
      src/Shaders/pbr.fragment.fx
  68. 18 1
      src/Shaders/pbr.vertex.fx
  69. 10 0
      src/Tools/babylon.sceneSerializer.ts
  70. 1 0
      src/babylon.mixins.ts
  71. 34 1
      src/babylon.scene.ts

+ 8 - 0
Tools/Gulp/gulpfile.js

@@ -26,6 +26,8 @@ var zip = require('gulp-zip');
 var config = require("./config.json");
 var customConfig = require("./custom.config.json");
 
+var del = require('del');
+
 var debug = require('gulp-debug');
 var includeShadersStream;
 var shadersStream;
@@ -393,3 +395,9 @@ gulp.task("zip-blender" , function() {
     .pipe(zip('Blender2Babylon-5.2.zip'))
     .pipe(gulp.dest('../../Exporters/Blender'));
 });
+
+gulp.task('clean-JS-MAP', function () {
+	  return del([
+		  '../../src/**/*.js.map','../../src/**/*.js'
+	  ], {force: true});
+	});

+ 2 - 1
Tools/Gulp/package.json

@@ -32,7 +32,8 @@
     "style-loader": "^0.13.1",
     "exports-loader": "^0.6.3",
     "imports-loader": "^0.7.0",
-    "gulp-zip": "~3.2.0"
+    "gulp-zip": "~3.2.0",
+    "del": "2.2.2"
   },
   "scripts": {
     "install": "npm --prefix ../../Playground/ install ../../Playground/ && gulp typescript-compile && gulp typescript-libraries && gulp deployLocalDev"

+ 1 - 1
Tools/Gulp/profiling.html

@@ -75,7 +75,7 @@ On this page:
                         	var name = fileNames[i].match(reg)[0].substring(8);  // remove the babylon.
                         	files[i] = [false, fileNames[i], name];
                         }
-						appendSecondarySearches("math.js", "mathtools|color3|color4|vector2|vector3|vector4|size|quaternion|matrix|plane|viewport|frustum|bezierCurve"); // got tired
+						appendSecondarySearches("math.js", "mathtools|color3|color4|vector2|vector3|vector4|size|quaternion|matrix|plane|viewport|frustum|space|axis|bezierCurve|orientation|angle|arc2|path2|path3d|curve3|sphericalHarmonics|mathTmp");
 
 						// force stuff to always be added
 						appendSecondarySearches("decorators.js", "engine"); //needed for Serialize

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


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


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


File diff suppressed because it is too large
+ 543 - 223
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 1009 - 856
dist/preview release/babylon.module.d.ts


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


+ 1 - 1
dist/preview release/materialsLibrary/babylon.fireMaterial.js

@@ -68,7 +68,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.fireMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.furMaterial.js

@@ -108,7 +108,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.furMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.gradientMaterial.js

@@ -112,7 +112,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.gridMaterial.js

@@ -85,7 +85,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gridMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.lavaMaterial.js

@@ -109,7 +109,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.normalMaterial.js

@@ -104,7 +104,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.normalMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js

@@ -62,7 +62,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.simpleMaterial.js

@@ -71,7 +71,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.skyMaterial.js

@@ -71,7 +71,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.skyMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.terrainMaterial.js

@@ -74,7 +74,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js

@@ -77,7 +77,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js


+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.js

@@ -187,7 +187,7 @@ var BABYLON;
             }
             var defines = subMesh._materialDefines;
             var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


+ 49 - 94
localDev/src/index.js

@@ -1,19 +1,14 @@
-/// <reference path="../../dist/preview release/babylon.d.ts"/>
 
-var scramble = function(data) {
-    for (index = 0; index < data.length; index ++) {
-        data[index] += 0.1 * Math.random();
-    }
-}
 
-// Playground like creation of the scene
-var createScene = function () {
+var globals = {};
 
+var createScene = function()
+{
     // This creates a basic Babylon Scene object (non-mesh)
     var scene = new BABYLON.Scene(engine);
 
     // This creates and positions a free camera (non-mesh)
-    var camera = new BABYLON.ArcRotateCamera("camera1", 1.14, 1.13, 10, BABYLON.Vector3.Zero(), scene);
+    var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -5), scene);
 
     // This targets the camera to scene origin
     camera.setTarget(BABYLON.Vector3.Zero());
@@ -27,91 +22,51 @@ var createScene = function () {
     // Default intensity is 1. Let's dim the light a small amount
     light.intensity = 0.7;
 
-    // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
-    var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
-
-    var sphere2 = BABYLON.Mesh.CreateSphere("sphere2", 16, 2, scene);
-    sphere2.setEnabled(false);
-    sphere2.updateMeshPositions(scramble);
-
-    var sphere3 = BABYLON.Mesh.CreateSphere("sphere3", 16, 2, scene);
-    sphere3.setEnabled(false);
-
-    sphere3.scaling = new BABYLON.Vector3(2.1, 3.5, 1.0);
-    sphere3.bakeCurrentTransformIntoVertices();
-
-    var sphere4 = BABYLON.Mesh.CreateSphere("sphere4", 16, 2, scene);
-    sphere4.setEnabled(false);
-    sphere4.updateMeshPositions(scramble);
-
-    var sphere5 = BABYLON.Mesh.CreateSphere("sphere5", 16, 2, scene);
-    sphere5.setEnabled(false);
-
-    sphere5.scaling = new BABYLON.Vector3(1.0, 0.1, 1.0);
-    sphere5.bakeCurrentTransformIntoVertices();    
-
-    var manager = new BABYLON.MorphTargetManager();
-    sphere.morphTargetManager = manager;
-
-    var target0 = BABYLON.MorphTarget.FromMesh(sphere2, "sphere2", 0.25);
-    manager.addTarget(target0);
-
-    var target1 = BABYLON.MorphTarget.FromMesh(sphere3, "sphere3", 0.25);
-    manager.addTarget(target1);
-
-    var target2 = BABYLON.MorphTarget.FromMesh(sphere4, "sphere4", 0.25);
-    manager.addTarget(target2);   
-
-    var target3 = BABYLON.MorphTarget.FromMesh(sphere5, "sphere5", 0.25);
-    manager.addTarget(target3);       
-
-    var gui = new dat.GUI();
-    var options = {
-	    influence0: 0.25,
-        influence1: 0.25,
-        influence2: 0.25,
-        influence3: 0.25,
-    }
-
-    gui.add(options, "influence0", 0, 1).onChange(function(value) {
-		target0.influence = value;
-    });
-
-    gui.add(options, "influence1", 0, 1).onChange(function(value) {
-		target1.influence = value;
-    });
-
-    gui.add(options, "influence2", 0, 1).onChange(function(value) {
-		target2.influence = value;
-    });  
-
-    gui.add(options, "influence3", 0, 1).onChange(function(value) {
-		target3.influence = value;
-    });        
-
-    var button = { switch:function(){
-         if (sphere.morphTargetManager) {
-             sphere.morphTargetManager = null;
-         } else {
-             sphere.morphTargetManager = manager;
-         }
-    }};
-
-    gui.add(button,'switch');
-
-    var disposeButton = { dispose:function(){
-         sphere.dispose();
-    }};
-
-    gui.add(disposeButton,'dispose');
-
-    var removeButton = { removeLast:function(){
-         manager.removeTarget(target3);   
-    }};
-
-    gui.add(removeButton,'removeLast');
-
+    var material0 = new BABYLON.StandardMaterial("mat0", scene);
+    material0.diffuseColor = new BABYLON.Color3(1, 0, 0);
+    //material0.bumpTexture = new BABYLON.Texture("normalMap.jpg", scene);
+   
+    var material1 = new BABYLON.StandardMaterial("mat1", scene);
+    material1.diffuseColor = new BABYLON.Color3(0, 0, 1);
+    
+    var material2 = new BABYLON.StandardMaterial("mat2", scene);
+    material2.emissiveColor = new BABYLON.Color3(0.4, 0, 0.4);
+
+    var multimat = new BABYLON.MultiMaterial("multi", scene);
+    multimat.subMaterials.push(material0);
+    multimat.subMaterials.push(material1);
+    multimat.subMaterials.push(material2);
+
+    globals.multimat = multimat;
+
+    var sphere = BABYLON.Mesh.CreateSphere("Sphere0", 16, 3, scene);
+    sphere.material = multimat;
+
+    sphere.subMeshes = [];
+    var verticesCount = sphere.getTotalVertices();
+
+    sphere.subMeshes.push(new BABYLON.SubMesh(0, 0, verticesCount, 0, 900, sphere));
+    sphere.subMeshes.push(new BABYLON.SubMesh(1, 0, verticesCount, 900, 900, sphere));
+    sphere.subMeshes.push(new BABYLON.SubMesh(2, 0, verticesCount, 1800, 2088, sphere));
+
+  //  material0.diffuseTexture = new BABYLON.Texture("textures/misc.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE); 
+
+    scene.actionManager = new BABYLON.ActionManager(scene);
+    scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyUpTrigger, function (evt) {
+        if (evt.sourceEvent.key == "t")
+        {
+          //  globals.multimat.subMaterials[0].diffuseColor = new BABYLON.Color3(1, 1, 1);
+            globals.multimat.subMaterials[0].diffuseTexture = new BABYLON.Texture("/assets/textures/amiga.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
+        }
+        else if (evt.sourceEvent.key == "m")
+        {
+            var material0 = new BABYLON.StandardMaterial("mat0", scene);
+          //  material0.diffuseColor = new BABYLON.Color3(0, 1, 0);
+            material0.diffuseTexture = new BABYLON.Texture("/assets/textures/amiga.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
+
+            globals.multimat.subMaterials[0] = material0; 
+        }
+    }));
 
     return scene;
-
 };

+ 1 - 1
materialsLibrary/src/fire/babylon.fireMaterial.ts

@@ -78,7 +78,7 @@ module BABYLON {
             var defines = <FireMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/fur/babylon.furMaterial.ts

@@ -144,7 +144,7 @@ module BABYLON {
             var defines = <FurMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/gradient/babylon.gradientMaterial.ts

@@ -121,7 +121,7 @@ module BABYLON {
             var defines = <GradientMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/grid/babylon.gridmaterial.ts

@@ -88,7 +88,7 @@ module BABYLON {
             var defines = <GridMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/lava/babylon.lavaMaterial.ts

@@ -129,7 +129,7 @@ module BABYLON {
             var defines = <LavaMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -109,7 +109,7 @@ module BABYLON {
             var defines = <NormalMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/shadowOnly/babylon.shadowOnlyMaterial.ts

@@ -54,7 +54,7 @@ module BABYLON {
             var defines = <ShadowOnlyMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/simple/babylon.simpleMaterial.ts

@@ -76,7 +76,7 @@ module BABYLON {
             var defines = <SimpleMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/sky/babylon.skyMaterial.ts

@@ -82,7 +82,7 @@ module BABYLON {
             var defines = <SkyMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/terrain/babylon.terrainMaterial.ts

@@ -114,7 +114,7 @@ module BABYLON {
             var defines = <TerrainMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts

@@ -118,7 +118,7 @@ module BABYLON {
             var defines = <TriPlanarMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

+ 1 - 1
materialsLibrary/src/water/babylon.waterMaterial.ts

@@ -226,7 +226,7 @@ module BABYLON {
             var defines = <WaterMaterialDefines>subMesh._materialDefines;
             var scene = this.getScene();
 
-            if (!this.checkReadyOnEveryCall) {
+            if (!this.checkReadyOnEveryCall && subMesh.effect) {
                 if (this._renderId === scene.getRenderId()) {
                     return true;
                 }

BIN
sandbox/Assets/BtnCamera.png


+ 3 - 0
sandbox/index-local.html

@@ -36,6 +36,9 @@
                 <li id="btnFullscreen">
                     <img src="./Assets/BtnFullscreen.png" alt="Switch the scene to full screen" title="Switch the scene to full screen" />
                 </li>
+                <li id="btnCamera">
+                    <img src="./Assets/BtnCamera.png" alt="Toggle the camera" title="Toggle the camera" />
+                </li>
                 <li id="btnPerf">
                     <img src="./Assets/BtnPerf.png" alt="Display inspector" title="Display inspector" />
                 </li>

+ 8 - 8
sandbox/index.css

@@ -62,6 +62,7 @@ a {
 }
 
 .help {
+    display: none;
     position: absolute;
     background-color: #988DB5;
     right: 0;
@@ -80,9 +81,11 @@ a {
     .help.shown {
         transform: translateX(-100px);
         -webkit-transform: translateX(-100px);
+        display: inline;
     }
 
  .help2 {
+    display: none;
     position: absolute;
     background-color: #988DB5;
     right: 0;
@@ -101,6 +104,7 @@ a {
     .help2.shown {
         transform: translateX(0px);
         -webkit-transform: translateX(0px);
+        display: inline;
     }
 
 #helpArrow {
@@ -173,12 +177,11 @@ a {
     position: relative;
     text-align: right;    
     -moz-opacity:0 ;
-    filter:alpha(opacity: 0);
     opacity: 0;
     z-index: 2;
     width:100%;
     height:100%;
-    
+    filter:alpha(opacity=0);
 }
 
 #logo {
@@ -188,10 +191,7 @@ a {
     background-position: center;
 }
 
-#btnFullscreen {
-}
-
-#btnFullscreen {
+#btnFullscreen , #btnCamera {
     margin-top: 10px;
     margin-right: 25px;
 }
@@ -253,12 +253,12 @@ li {
     -webkit-transform: translateX(120%);
 }
 
-#btnFullscreen, #btnPerf, #btnFiles {
+#btnFullscreen, #btnCamera, #btnPerf, #btnFiles {
      -webkit-transition: -webkit-transform 0.15s ease-in-out;
      transition: transform 0.15s ease-in-out;
 }
 
-#btnFullscreen:hover, #btnPerf:hover, #btnFiles:hover {
+#btnFullscreen:hover, #btnCamera:hover, #btnPerf:hover, #btnFiles:hover {
     -webkit-transform: scale(0.9);
     transform: scale(0.9);
 }

+ 3 - 0
sandbox/index.html

@@ -32,6 +32,9 @@
                 <li id="btnFullscreen">
                     <img src="./Assets/BtnFullscreen.png" alt="Switch the scene to full screen" title="Switch the scene to full screen" />
                 </li>
+                <li id="btnCamera">
+                    <img src="./Assets/BtnCamera.png" alt="Toggle the camera" title="Toggle the camera" />
+                </li>
                 <li id="btnPerf">
                     <img src="./Assets/BtnPerf.png" alt="Display debug & performance layer" title="Display debug & performance layer" />
                 </li>

+ 50 - 0
sandbox/index.js

@@ -17,6 +17,9 @@ if (BABYLON.Engine.isSupported()) {
     var currentHelpCounter;
     var currentScene;
     var enableDebugLayer = false;
+    var enableArcRotateCamera = false;
+    var arcRotateCamera;
+    var defaultCamera;
 
     currentHelpCounter = localStorage.getItem("helpcounter");
 
@@ -68,6 +71,19 @@ if (BABYLON.Engine.isSupported()) {
                 currentScene.activeCamera.keysRight.push(69); // E
                 currentScene.activeCamera.keysRight.push(68); // D
             }
+            defaultCamera = currentScene.activeCamera;
+            var worldExtends = currentScene.getWorldExtends();
+            var worldCenter = worldExtends.min.add(worldExtends.max.subtract(worldExtends.min).scale(0.5));
+            arcRotateCamera = new BABYLON.ArcRotateCamera("arcRotateCamera", 0, 0, 10, BABYLON.Vector3.Zero(), currentScene);
+            arcRotateCamera.setPosition(new BABYLON.Vector3(worldCenter.x, worldCenter.y, worldExtends.min.z - (worldExtends.max.z - worldExtends.min.z)));
+            arcRotateCamera.setTarget(worldCenter);
+            arcRotateCamera.wheelPrecision = 100.0;
+            arcRotateCamera.minZ = 0.1;
+            arcRotateCamera.maxZ = 1000;
+            if(enableArcRotateCamera){
+                currentScene.activeCamera = arcRotateCamera;
+                currentScene.activeCamera.attachControl(canvas);
+            }
         }
     };
 
@@ -81,6 +97,26 @@ if (BABYLON.Engine.isSupported()) {
         }
     });
     htmlInput.addEventListener('change', function (event) {
+        var filestoLoad;
+            // Handling data transfer via drag'n'drop
+            if (event && event.dataTransfer && event.dataTransfer.files) {
+                filesToLoad = event.dataTransfer.files;
+            }
+            // Handling files from input files
+            if (event && event.target && event.target.files) {
+                filesToLoad = event.target.files;
+            }
+            if (filesToLoad && filesToLoad.length > 0) {
+            enableArcRotateCamera= false;
+            for (var i = 0; i < filesToLoad.length; i++) {
+                    var extension = filesToLoad[i].name.split('.').pop();
+                    if (extension === "gltf" || extension === "glb")
+                    {       
+                         enableArcRotateCamera= true;
+                         break;
+                    }
+                }
+            }
         filesInput.loadFiles(event);
     }, false);
     btnFullScreen.addEventListener('click', function () {
@@ -98,6 +134,20 @@ if (BABYLON.Engine.isSupported()) {
             }
         }
     }, false);
+    btnCamera.addEventListener('click', function () {
+        if (currentScene) {
+            if (!enableArcRotateCamera) {
+                currentScene.activeCamera = arcRotateCamera;
+                currentScene.activeCamera.attachControl(canvas);
+                enableArcRotateCamera = true;
+            }
+            else {
+                currentScene.activeCamera = defaultCamera;
+                currentScene.activeCamera.attachControl(canvas);
+                enableArcRotateCamera = false;
+            }
+        }
+    }, false);
 
     // The help tips will be displayed only 5 times
     if (currentHelpCounter < 5) {

+ 79 - 25
src/Cameras/VR/babylon.webVRCamera.ts

@@ -42,6 +42,7 @@ module BABYLON {
         public _vrDevice = null;
         public rawPose: DevicePose = null;
         private _vrEnabled = false;
+        private _specsVersion: number = 1.1;
         private _attached: boolean = false;
 
         private _oldSize: BABYLON.Size;
@@ -98,7 +99,15 @@ module BABYLON {
             if (!this.getEngine().vrDisplaysPromise) {
                 Tools.Error("WebVR is not enabled on your browser");
             } else {
-                this._frameData = new VRFrameData();
+                //check specs version
+                if (!window.VRFrameData) {
+                    this._specsVersion = 1.0;
+                    this._frameData = {
+                    };
+                } else {
+                    this._frameData = new VRFrameData();
+                }
+
                 this.getEngine().vrDisplaysPromise.then((devices) => {
                     if (devices.length > 0) {
                         this._vrEnabled = true;
@@ -121,7 +130,7 @@ module BABYLON {
                         }
 
                         //reset the rig parameters.
-                        this.setCameraRigMode(Camera.RIG_MODE_WEBVR, { parentCamera: this, vrDisplay: this._vrDevice, frameData: this._frameData });
+                        this.setCameraRigMode(Camera.RIG_MODE_WEBVR, { parentCamera: this, vrDisplay: this._vrDevice, frameData: this._frameData, specs: this._specsVersion });
 
                         if (this._attached) {
                             this.getEngine().enableVR(this._vrDevice)
@@ -170,9 +179,17 @@ module BABYLON {
         }
 
         public _checkInputs(): void {
-            if (this._vrEnabled && this._vrDevice.getFrameData(this._frameData)) {
-                var currentPose = this._frameData.pose;
-                this.updateFromDevice(currentPose);
+            if (this._vrEnabled) {
+                if (this._specsVersion === 1.1) {
+                    this._vrDevice.getFrameData(this._frameData);
+                } else {
+                    //backwards comp
+                    let pose = this._vrDevice.getPose();
+                    this._frameData.pose = pose;
+                    // calculate view and projection matrix
+                }
+
+                this.updateFromDevice(this._frameData.pose);
             }
 
             super._checkInputs();
@@ -251,16 +268,52 @@ module BABYLON {
          * 'this' is the left or right camera (and NOT (!!!) the WebVRFreeCamera instance)
          */
         protected _getWebVRViewMatrix(): Matrix {
-            var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
+            //WebVR 1.0
+            if (this._cameraRigParams["specs"] === 1.0) {
+                this._updateCameraRotationMatrix();
 
-            Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
+                Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
 
-            if (!this.getScene().useRightHandedSystem) {
-                [2, 6, 8, 9, 14].forEach((num) => {
-                    this._webvrViewMatrix.m[num] *= -1;
-                });
+                // Computing target and final matrix
+                this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
+
+                if (this.getScene().useRightHandedSystem) {
+                    Matrix.LookAtRHToRef(this.position, this._currentTarget, this.upVector, this._webvrViewMatrix);
+                } else {
+                    Matrix.LookAtLHToRef(this.position, this._currentTarget, this.upVector, this._webvrViewMatrix);
+                }
+
+                //now move the eye in the right direction
+                var eyeParams = this._cameraRigParams["eyeParameters"];
+                let offset = eyeParams.offset;
+                // it will actually always be 0, but just in case
+                if (this.getScene().useRightHandedSystem) {
+                    offset[2] *= -1;
+                }
+                Matrix.TranslationToRef(-offset[0], offset[1], -offset[2], Tmp.Matrix[0]);
+
+                this._webvrViewMatrix.multiplyToRef(Tmp.Matrix[0], this._webvrViewMatrix);
+
+            } else /* WebVR 1.1 */ {
+                var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
+
+                Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
+
+                if (!this.getScene().useRightHandedSystem) {
+                    [2, 6, 8, 9, 14].forEach((num) => {
+                        this._webvrViewMatrix.m[num] *= -1;
+                    });
+                }
+
+                // update the camera rotation matrix
+                this._webvrViewMatrix.getRotationMatrixToRef(this._cameraRotationMatrix);
+                Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
+
+                // Computing target and final matrix
+                this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
             }
 
+
             let parentCamera: WebVRFreeCamera = this._cameraRigParams["parentCamera"];
 
             // should the view matrix be updated with scale and position offset?
@@ -276,25 +329,26 @@ module BABYLON {
                 this._webvrViewMatrix.invert();
             }
 
-            // update the camera rotation matrix
-            this._webvrViewMatrix.getRotationMatrixToRef(this._cameraRotationMatrix);
-            Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
-
-            // Computing target and final matrix
-            this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
             return this._webvrViewMatrix;
         }
 
         protected _getWebVRProjectionMatrix(): Matrix {
-            var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
-            Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
-
-            //babylon compatible matrix
-            if (!this.getScene().useRightHandedSystem) {
-                [8, 9, 10, 11].forEach((num) => {
-                    this._projectionMatrix.m[num] *= -1;
-                });
+            if (this._cameraRigParams["specs"] === 1.0) {
+                var eyeParams = this._cameraRigParams["eyeParameters"];
+                // deprecated!!
+                Matrix.PerspectiveFovWebVRToRef(eyeParams.fieldOfView, 0.1, 1000, this._projectionMatrix, this.getScene().useRightHandedSystem);
+            } else /*WebVR 1.1*/ {
+                var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
+                Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
+
+                //babylon compatible matrix
+                if (!this.getScene().useRightHandedSystem) {
+                    [8, 9, 10, 11].forEach((num) => {
+                        this._projectionMatrix.m[num] *= -1;
+                    });
+                }
             }
+
             return this._projectionMatrix;
         }
 

+ 2 - 0
src/Cameras/babylon.camera.ts

@@ -613,6 +613,7 @@
                         //Left eye
                         this._rigCameras[0].viewport = new Viewport(0, 0, 0.5, 1.0);
                         this._rigCameras[0].setCameraRigParameter("left", true);
+                        this._rigCameras[0].setCameraRigParameter("specs", rigParams.specs);
                         this._rigCameras[0].setCameraRigParameter("eyeParameters", leftEye);
                         this._rigCameras[0].setCameraRigParameter("frameData", rigParams.frameData);
                         this._rigCameras[0].setCameraRigParameter("parentCamera", rigParams.parentCamera);
@@ -624,6 +625,7 @@
                         //Right eye
                         this._rigCameras[1].viewport = new Viewport(0.5, 0, 0.5, 1.0);
                         this._rigCameras[1].setCameraRigParameter('eyeParameters', rightEye);
+                        this._rigCameras[1].setCameraRigParameter("specs", rigParams.specs);
                         this._rigCameras[1].setCameraRigParameter("frameData", rigParams.frameData);
                         this._rigCameras[1].setCameraRigParameter("parentCamera", rigParams.parentCamera);
                         this._rigCameras[1]._cameraRigParams.vrWorkMatrix = new Matrix();

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

@@ -309,6 +309,13 @@
                         log += "\n\t\t" + mmat.toString(fullDetails);
                     }
                 }
+
+                // Morph targets
+                if (parsedData.morphTargetManagers) {
+                    for (var managerData of parsedData.morphTargetManagers) {
+                        var parsedManager = MorphTargetManager.Parse(managerData, scene);
+                    }
+                }
     
                 // Skeletons
                 if (parsedData.skeletons) {

+ 6 - 15
src/Materials/babylon.effect.ts

@@ -490,24 +490,15 @@
         }
 
         public _cacheMatrix(uniformName: string, matrix: Matrix): boolean {
-            var changed = false;
-            var cache: Matrix = this._valueCache[uniformName];
-            if (!cache || !(cache instanceof Matrix)) {
-                changed = true;
-                cache = new Matrix();
+            var cache = this._valueCache[uniformName];
+            var flag = matrix.updateFlag;
+            if (cache !== undefined && cache === flag) {
+                return false;
             }
 
-            var tm = cache.m;
-            var om = matrix.m;
-            for (var index = 0; index < 16; index++) {
-                if (tm[index] !== om[index]) {
-                    tm[index] = om[index];
-                    changed = true;
-                }
-            }
+            this._valueCache[uniformName] = flag;
 
-            this._valueCache[uniformName] = cache;
-            return changed;
+            return true;
         }
 
         public _cacheFloat2(uniformName: string, x: number, y: number): boolean {

+ 3 - 0
src/Materials/babylon.material.ts

@@ -10,6 +10,9 @@
         public _areFresnelDirty = true;
         public _areMiscDirty = true;    
 
+        public _normals = false;
+        public _uvs = false;
+
         public _needNormals = false;
         public _needUVs = false;
 

+ 4 - 1
src/Materials/babylon.materialHelper.ts

@@ -33,10 +33,13 @@
         }
 
         public static PrepareDefinesForAttributes(mesh: AbstractMesh, defines: MaterialDefines, useVertexColor: boolean, useBones: boolean, useMorphTargets = false): void {
-            if (!defines._areAttributesDirty) {
+            if (!defines._areAttributesDirty && defines._needNormals === defines._normals && defines._needUVs === defines._uvs) {
                 return;
             }               
 
+            defines._normals = defines._needNormals;
+            defines._uvs = defines._needUVs;
+            
             defines["NORMAL"] = (defines._needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind));
 
             if (defines._needNormals && mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {

+ 162 - 121
src/Materials/babylon.pbrMaterial.ts

@@ -69,9 +69,12 @@
         public SHADOWFULLFLOAT = false;
 
         public METALLICWORKFLOW = false;
-        public METALLICROUGHNESSMAP = false;
-        public METALLICROUGHNESSGSTOREINALPHA = false;
-        public METALLICROUGHNESSGSTOREINGREEN = false;
+        public METALLICMAP = false;
+        public ROUGHNESSSTOREINMETALMAPALPHA = false;
+        public ROUGHNESSSTOREINMETALMAPGREEN = false;
+        public METALLNESSSTOREINMETALMAPBLUE = false;
+        public AOSTOREINMETALMAPRED = false;
+        public MICROSURFACEMAP = false;
 
         public MORPHTARGETS = false;
         public MORPHTARGETS_NORMAL = false;
@@ -210,7 +213,7 @@
          * This as to be use with the overloadedReflectivityIntensity parameter.
          */
         @serializeAsColor3()
-        public overloadedReflectivity: Color3 = new BABYLON.Color3(0.3, 0.3, 0.3);
+        public overloadedReflectivity: Color3 = new BABYLON.Color3(0.0, 0.0, 0.0);
         
         /**
          * Debug Control indicating how much the overloaded reflectivity color is used against the default one.
@@ -314,6 +317,13 @@
         @serialize()
         public roughness: number;
 
+        /**
+         * Used to enable roughness/glossiness fetch from a separate chanel depending on the current mode.
+         * Gray Scale represents roughness in metallic mode and glossiness in specular mode.
+         */
+        @serializeAsTexture()
+        public microSurfaceTexture: BaseTexture;
+
         @serializeAsTexture()
         public bumpTexture: BaseTexture;
 
@@ -339,7 +349,7 @@
         public reflectivityColor = new Color3(1, 1, 1);
 
         @serializeAsColor3("reflection")
-        public reflectionColor = new Color3(0.5, 0.5, 0.5);
+        public reflectionColor = new Color3(0.0, 0.0, 0.0);
 
         @serializeAsColor3("emissive")
         public emissiveColor = new Color3(0, 0, 0);
@@ -421,6 +431,18 @@
          */
         @serialize()
         public useRoughnessFromMetallicTextureGreen = false;
+
+        /**
+         * Specifies if the metallic texture contains the metallness information in its blue channel.
+         */
+        @serialize()
+        public useMetallnessFromMetallicTextureBlue = false;
+
+        /**
+         * Specifies if the metallic texture contains the ambient occlusion information in its red channel.
+         */
+        @serialize()
+        public useAmbientOcclusionFromMetallicTextureRed = false;
         
         /**
          * In case the reflectivity map does not contain the microsurface information in its alpha channel,
@@ -642,13 +664,12 @@
 
             var scene = this.getScene();
             var engine = scene.getEngine();
-            var needNormals = false;
             var needUVs = false;
 
             this._defines.reset();
 
             if (scene.lightsEnabled && !this.disableLighting) {
-                needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, true, this.maxSimultaneousLights) || needNormals;
+                MaterialHelper.PrepareDefinesForLights(scene, mesh, this._defines, true, this.maxSimultaneousLights);
             }
 
             if (!this.checkReadyOnEveryCall) {
@@ -667,85 +688,83 @@
                 if (this.albedoTexture && StandardMaterial.DiffuseTextureEnabled) {
                     if (!this.albedoTexture.isReady()) {
                         return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.ALBEDO = true;
                     }
+
+                    needUVs = true;
+                    this._defines.ALBEDO = true;
                 }
 
                 if (this.ambientTexture && StandardMaterial.AmbientTextureEnabled) {
                     if (!this.ambientTexture.isReady()) {
                         return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.AMBIENT = true;
                     }
+                    
+                    needUVs = true;
+                    this._defines.AMBIENT = true;
                 }
 
                 if (this.opacityTexture && StandardMaterial.OpacityTextureEnabled) {
                     if (!this.opacityTexture.isReady()) {
                         return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.OPACITY = true;
+                    }
+                    
+                    needUVs = true;
+                    this._defines.OPACITY = true;
 
-                        if (this.opacityTexture.getAlphaFromRGB) {
-                            this._defines.OPACITYRGB = true;
-                        }
+                    if (this.opacityTexture.getAlphaFromRGB) {
+                        this._defines.OPACITYRGB = true;
                     }
                 }
 
                 if (this.reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
                     if (!this.reflectionTexture.isReady()) {
                         return false;
-                    } else {
-                        needNormals = true;
-                        this._defines.REFLECTION = true;
+                    }
+                    
+                    this._defines.REFLECTION = true;
 
-                        if (this.reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE) {
-                            this._defines.INVERTCUBICMAP = true;
-                        }
+                    if (this.reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE) {
+                        this._defines.INVERTCUBICMAP = true;
+                    }
 
-                        this._defines.REFLECTIONMAP_3D = this.reflectionTexture.isCube;
-
-                        switch (this.reflectionTexture.coordinatesMode) {
-                            case Texture.CUBIC_MODE:
-                            case Texture.INVCUBIC_MODE:
-                                this._defines.REFLECTIONMAP_CUBIC = true;
-                                break;
-                            case Texture.EXPLICIT_MODE:
-                                this._defines.REFLECTIONMAP_EXPLICIT = true;
-                                break;
-                            case Texture.PLANAR_MODE:
-                                this._defines.REFLECTIONMAP_PLANAR = true;
-                                break;
-                            case Texture.PROJECTION_MODE:
-                                this._defines.REFLECTIONMAP_PROJECTION = true;
-                                break;
-                            case Texture.SKYBOX_MODE:
-                                this._defines.REFLECTIONMAP_SKYBOX = true;
-                                break;
-                            case Texture.SPHERICAL_MODE:
-                                this._defines.REFLECTIONMAP_SPHERICAL = true;
-                                break;
-                            case Texture.EQUIRECTANGULAR_MODE:
-                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
-                                break;
-                            case Texture.FIXED_EQUIRECTANGULAR_MODE:
-                                this._defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
-                                break;
-                            case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE:
-                                this._defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true;
-                                break;                                
-                        }
+                    this._defines.REFLECTIONMAP_3D = this.reflectionTexture.isCube;
+
+                    switch (this.reflectionTexture.coordinatesMode) {
+                        case Texture.CUBIC_MODE:
+                        case Texture.INVCUBIC_MODE:
+                            this._defines.REFLECTIONMAP_CUBIC = true;
+                            break;
+                        case Texture.EXPLICIT_MODE:
+                            this._defines.REFLECTIONMAP_EXPLICIT = true;
+                            break;
+                        case Texture.PLANAR_MODE:
+                            this._defines.REFLECTIONMAP_PLANAR = true;
+                            break;
+                        case Texture.PROJECTION_MODE:
+                            this._defines.REFLECTIONMAP_PROJECTION = true;
+                            break;
+                        case Texture.SKYBOX_MODE:
+                            this._defines.REFLECTIONMAP_SKYBOX = true;
+                            break;
+                        case Texture.SPHERICAL_MODE:
+                            this._defines.REFLECTIONMAP_SPHERICAL = true;
+                            break;
+                        case Texture.EQUIRECTANGULAR_MODE:
+                            this._defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
+                            break;
+                        case Texture.FIXED_EQUIRECTANGULAR_MODE:
+                            this._defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
+                            break;
+                        case Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE:
+                            this._defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true;
+                            break;                                
+                    }
 
-                        if (this.reflectionTexture instanceof HDRCubeTexture && (<HDRCubeTexture>this.reflectionTexture)) {
-                            this._defines.USESPHERICALFROMREFLECTIONMAP = true;
-                            needNormals = true;
+                    if (this.reflectionTexture instanceof HDRCubeTexture && (<HDRCubeTexture>this.reflectionTexture)) {
+                        this._defines.USESPHERICALFROMREFLECTIONMAP = true;
 
-                            if ((<HDRCubeTexture>this.reflectionTexture).isPMREM) {
-                                this._defines.USEPMREMREFLECTION = true;
-                            }
+                        if ((<HDRCubeTexture>this.reflectionTexture).isPMREM) {
+                            this._defines.USEPMREMREFLECTION = true;
                         }
                     }
                 }
@@ -753,92 +772,103 @@
                 if (this.lightmapTexture && StandardMaterial.LightmapTextureEnabled) {
                     if (!this.lightmapTexture.isReady()) {
                         return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.LIGHTMAP = true;
-                        this._defines.USELIGHTMAPASSHADOWMAP = this.useLightmapAsShadowmap;
                     }
+
+                    needUVs = true;
+                    this._defines.LIGHTMAP = true;
+                    this._defines.USELIGHTMAPASSHADOWMAP = this.useLightmapAsShadowmap;
                 }
 
                 if (this.emissiveTexture && StandardMaterial.EmissiveTextureEnabled) {
                     if (!this.emissiveTexture.isReady()) {
                         return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.EMISSIVE = true;
                     }
+
+                    needUVs = true;
+                    this._defines.EMISSIVE = true;
                 }
 
                 if (StandardMaterial.SpecularTextureEnabled) {
                     if (this.metallicTexture) {
                         if (!this.metallicTexture.isReady()) {
                             return false;
-                        } else {
-                            needUVs = true;
-                            this._defines.METALLICWORKFLOW = true;
-                            this._defines.METALLICROUGHNESSMAP = true;
-                            this._defines.METALLICROUGHNESSGSTOREINALPHA = this.useRoughnessFromMetallicTextureAlpha;
-                            this._defines.METALLICROUGHNESSGSTOREINGREEN = !this.useRoughnessFromMetallicTextureAlpha && this.useRoughnessFromMetallicTextureGreen;
                         }
+
+                        needUVs = true;
+                        this._defines.METALLICWORKFLOW = true;
+                        this._defines.METALLICMAP = true;
+                        this._defines.ROUGHNESSSTOREINMETALMAPALPHA = this.useRoughnessFromMetallicTextureAlpha;
+                        this._defines.ROUGHNESSSTOREINMETALMAPGREEN = !this.useRoughnessFromMetallicTextureAlpha && this.useRoughnessFromMetallicTextureGreen;                            
+                        this._defines.METALLNESSSTOREINMETALMAPBLUE = this.useMetallnessFromMetallicTextureBlue;                            
+                        this._defines.AOSTOREINMETALMAPRED = this.useAmbientOcclusionFromMetallicTextureRed;
                     }
                     else if (this.reflectivityTexture) {
                         if (!this.reflectivityTexture.isReady()) {
                             return false;
-                        } else {
-                            needUVs = true;
-                            this._defines.REFLECTIVITY = true;
-                            this._defines.MICROSURFACEFROMREFLECTIVITYMAP = this.useMicroSurfaceFromReflectivityMapAlpha;
-                            this._defines.MICROSURFACEAUTOMATIC = this.useAutoMicroSurfaceFromReflectivityMap;
                         }
+
+                        needUVs = true;
+                        this._defines.REFLECTIVITY = true;
+                        this._defines.MICROSURFACEFROMREFLECTIVITYMAP = this.useMicroSurfaceFromReflectivityMapAlpha;
+                        this._defines.MICROSURFACEAUTOMATIC = this.useAutoMicroSurfaceFromReflectivityMap;
+                    }
+
+                    if (this.microSurfaceTexture) {
+                        if (!this.microSurfaceTexture.isReady()) {
+                            return false;
+                        }
+
+                        needUVs = true;
+                        this._defines.MICROSURFACEMAP = true;
                     }
                 }
 
                 if (scene.getEngine().getCaps().standardDerivatives && this.bumpTexture && StandardMaterial.BumpTextureEnabled && !this.disableBumpMap) {
                     if (!this.bumpTexture.isReady()) {
                         return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.BUMP = true;
-
-                        if (this.useParallax && this.albedoTexture && StandardMaterial.DiffuseTextureEnabled) {
-                            this._defines.PARALLAX = true;
-                            if (this.useParallaxOcclusion) {
-                                this._defines.PARALLAXOCCLUSION = true;
-                            }
-                        }
+                    }
+                    
+                    needUVs = true;
+                    this._defines.BUMP = true;
 
-                        if (this.invertNormalMapX) {
-                            this._defines.INVERTNORMALMAPX = true;
+                    if (this.useParallax && this.albedoTexture && StandardMaterial.DiffuseTextureEnabled) {
+                        this._defines.PARALLAX = true;
+                        if (this.useParallaxOcclusion) {
+                            this._defines.PARALLAXOCCLUSION = true;
                         }
+                    }
 
-                        if (this.invertNormalMapY) {
-                            this._defines.INVERTNORMALMAPY = true;
-                        }
+                    if (this.invertNormalMapX) {
+                        this._defines.INVERTNORMALMAPX = true;
+                    }
 
-                        if (scene._mirroredCameraPosition) {
-                            this._defines.INVERTNORMALMAPX = !this._defines.INVERTNORMALMAPX;
-                            this._defines.INVERTNORMALMAPY = !this._defines.INVERTNORMALMAPY;
-                        }
+                    if (this.invertNormalMapY) {
+                        this._defines.INVERTNORMALMAPY = true;
                     }
+
+                    if (scene._mirroredCameraPosition) {
+                        this._defines.INVERTNORMALMAPX = !this._defines.INVERTNORMALMAPX;
+                        this._defines.INVERTNORMALMAPY = !this._defines.INVERTNORMALMAPY;
+                    }                        
                 }
 
                 if (this.refractionTexture && StandardMaterial.RefractionTextureEnabled) {
                     if (!this.refractionTexture.isReady()) {
                         return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.REFRACTION = true;
-                        this._defines.REFRACTIONMAP_3D = this.refractionTexture.isCube;
+                    }
+                    
+                    needUVs = true;
+                    this._defines.REFRACTION = true;
+                    this._defines.REFRACTIONMAP_3D = this.refractionTexture.isCube;
 
-                        if (this.linkRefractionWithTransparency) {
-                            this._defines.LINKREFRACTIONTOTRANSPARENCY = true;
-                        }
-                        if (this.refractionTexture instanceof HDRCubeTexture) {
-                            this._defines.REFRACTIONMAPINLINEARSPACE = true;
+                    if (this.linkRefractionWithTransparency) {
+                        this._defines.LINKREFRACTIONTOTRANSPARENCY = true;
+                    }
+                    if (this.refractionTexture instanceof HDRCubeTexture) {
+                        this._defines.REFRACTIONMAPINLINEARSPACE = true;
 
-                            if ((<HDRCubeTexture>this.refractionTexture).isPMREM) {
-                                this._defines.USEPMREMREFRACTION = true;
-                            }
+                        if ((<HDRCubeTexture>this.refractionTexture).isPMREM) {
+                            this._defines.USEPMREMREFRACTION = true;
                         }
                     }
                 }
@@ -846,9 +876,9 @@
                 if (this.cameraColorGradingTexture && StandardMaterial.ColorGradingTextureEnabled) {
                     if (!this.cameraColorGradingTexture.isReady()) {
                         return false;
-                    } else {
-                        this._defines.CAMERACOLORGRADING = true;
                     }
+                    
+                    this._defines.CAMERACOLORGRADING = true;
                 }
 
                 if (!this.backFaceCulling && this.twoSidedLighting) {
@@ -930,7 +960,6 @@
                         this._defines.EMISSIVEFRESNEL = true;
                     }
 
-                    needNormals = true;
                     this._defines.FRESNEL = true;
                 }
             }
@@ -953,7 +982,12 @@
 
             // Attribs
             if (mesh) {
-                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                if (!mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                    mesh.createNormals(true);
+                    Tools.Warn("PBRMaterial: Normals have been created for the mesh: " + mesh.name);
+                }
+
+                if (mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                     this._defines.NORMAL = true;
                     if (mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
                         this._defines.TANGENT = true;
@@ -1094,9 +1128,9 @@
                 
                 var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vAmbientColor", "vAlbedoColor", "vReflectivityColor", "vEmissiveColor", "vReflectionColor",
                         "vFogInfos", "vFogColor", "pointSize",
-                        "vAlbedoInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vReflectivityInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos",
+                        "vAlbedoInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vReflectivityInfos", "vMicroSurfaceSamplerInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos",
                         "mBones",
-                        "vClipPlane", "albedoMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "reflectivityMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
+                        "vClipPlane", "albedoMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "reflectivityMatrix", "microSurfaceSamplerMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
                         "depthValues",
                         "opacityParts", "emissiveLeftColor", "emissiveRightColor",
                         "vLightingIntensity", "vOverloadedShadowIntensity", "vOverloadedIntensity", "vOverloadedAlbedo", "vOverloadedReflection", "vOverloadedReflectivity", "vOverloadedEmissive", "vOverloadedMicroSurface",
@@ -1108,7 +1142,7 @@
                         "vCameraInfos"
                 ];
 
-                var samplers = ["albedoSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "reflectivitySampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"];
+                var samplers = ["albedoSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "reflectivitySampler", "microSurfaceSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"];
                 
                 ColorCurves.PrepareUniforms(uniforms); 
                 ColorGradingTexture.PrepareUniformsAndSamplers(uniforms, samplers); 
@@ -1257,15 +1291,22 @@
                         if (this.metallicTexture) {
                             this._effect.setTexture("reflectivitySampler", this.metallicTexture);
 
-                            this._effect.setFloat2("vReflectivityInfos", this.metallicTexture.coordinatesIndex, this.metallicTexture.level);
+                            this._effect.setFloat3("vReflectivityInfos", this.metallicTexture.coordinatesIndex, this.reflectivityTexture.level, this.ambientTextureStrength);
                             this._effect.setMatrix("reflectivityMatrix", this.metallicTexture.getTextureMatrix());
                         }
                         else if (this.reflectivityTexture) {
                             this._effect.setTexture("reflectivitySampler", this.reflectivityTexture);
 
-                            this._effect.setFloat2("vReflectivityInfos", this.reflectivityTexture.coordinatesIndex, this.reflectivityTexture.level);
+                            this._effect.setFloat3("vReflectivityInfos", this.reflectivityTexture.coordinatesIndex, this.reflectivityTexture.level, 1.0);
                             this._effect.setMatrix("reflectivityMatrix", this.reflectivityTexture.getTextureMatrix());
                         }
+
+                        if (this.microSurfaceTexture) {
+                            this._effect.setTexture("microSurfaceSampler", this.microSurfaceTexture);
+
+                            this._effect.setFloat2("vMicroSurfaceSamplerInfos", this.microSurfaceTexture.coordinatesIndex, this.microSurfaceTexture.level);
+                            this._effect.setMatrix("microSurfaceSamplerMatrix", this.microSurfaceTexture.getTextureMatrix());
+                        }
                     }
 
                     if (this.bumpTexture && this._myScene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled && !this.disableBumpMap) {

+ 78 - 26
src/Math/babylon.math.ts

@@ -516,7 +516,7 @@
          * Returns the updated Color4.  
          */
         public set(r: number, g: number, b: number, a: number): Color4 {
-            return this.copyFromFloats(r, g, b,a);
+            return this.copyFromFloats(r, g, b, a);
         }
         /**
          * Returns a string containing the hexadecimal Color4 code.  
@@ -2144,7 +2144,7 @@
         /**
          * Returns a new Vector4 set from the starting index of the passed array.  
          */
-        public static FromArray(array: number[]  | Float32Array, offset?: number): Vector4 {
+        public static FromArray(array: number[] | Float32Array, offset?: number): Vector4 {
             if (!offset) {
                 offset = 0;
             }
@@ -2328,7 +2328,7 @@
          */
         public set(width: number, height: number): Size {
             return this.copyFromFloats(width, height);
-        }        
+        }
         /**
          * Returns a new Size set with the multiplication result of the current Size and the passed floats.  
          */
@@ -2465,7 +2465,7 @@
          */
         public set(x: number, y: number, z: number, w: number): Quaternion {
             return this.copyFromFloats(x, y, z, w);
-        }        
+        }
         /**
          * Returns a new Quaternion as the addition result of the passed one and the current Quaternion.  
          */
@@ -2631,6 +2631,8 @@
             result.m[13] = 0;
             result.m[14] = 0;
             result.m[15] = 1.0;
+
+            result._markAsUpdated();
             return this;
         }
         /**
@@ -2864,9 +2866,19 @@
         private static _xAxis: Vector3 = Vector3.Zero();
         private static _yAxis: Vector3 = Vector3.Zero();
         private static _zAxis: Vector3 = Vector3.Zero();
+        private static _updateFlagSeed = 0;
 
+        public updateFlag: number;
         public m: Float32Array = new Float32Array(16);
 
+        public _markAsUpdated() {
+            this.updateFlag = Matrix._updateFlagSeed++;
+        }
+
+        public constructor() {
+            this._markAsUpdated();
+        }
+
         // Properties
         /**
          * Boolean : True is the matrix is the identity matrix
@@ -2929,6 +2941,7 @@
                 this.m[index] = 0.0;
             }
 
+            this._markAsUpdated();
             return this;
         }
         /**
@@ -2947,6 +2960,7 @@
             for (var index = 0; index < 16; index++) {
                 result.m[index] = this.m[index] + other.m[index];
             }
+            result._markAsUpdated();
             return this;
         }
         /**
@@ -2957,6 +2971,7 @@
             for (var index = 0; index < 16; index++) {
                 this.m[index] += other.m[index];
             }
+            this._markAsUpdated();
             return this;
         }
         /**
@@ -3021,6 +3036,7 @@
             other.m[11] = -(((l1 * l35) - (l2 * l37)) + (l4 * l39)) * l27;
             other.m[15] = (((l1 * l36) - (l2 * l38)) + (l3 * l39)) * l27;
 
+            other._markAsUpdated();
             return this;
         }
         /**
@@ -3031,6 +3047,8 @@
             this.m[12] = x;
             this.m[13] = y;
             this.m[14] = z;
+
+            this._markAsUpdated();
             return this;
         }
         /**
@@ -3041,6 +3059,8 @@
             this.m[12] = vector3.x;
             this.m[13] = vector3.y;
             this.m[14] = vector3.z;
+
+            this._markAsUpdated();
             return this;
         }
         /**
@@ -3085,6 +3105,8 @@
             for (var index = 0; index < 16; index++) {
                 this.m[index] = other.m[index];
             }
+
+            this._markAsUpdated();
             return this;
         }
         /**
@@ -3102,6 +3124,8 @@
          */
         public multiplyToRef(other: Matrix, result: Matrix): Matrix {
             this.multiplyToArray(other, result.m, 0);
+
+            result._markAsUpdated();
             return this;
         }
         /**
@@ -3161,7 +3185,6 @@
             result[offset + 13] = tm12 * om1 + tm13 * om5 + tm14 * om9 + tm15 * om13;
             result[offset + 14] = tm12 * om2 + tm13 * om6 + tm14 * om10 + tm15 * om14;
             result[offset + 15] = tm12 * om3 + tm13 * om7 + tm14 * om11 + tm15 * om15;
-
             return this;
         }
         /**
@@ -3265,6 +3288,7 @@
                 m[4] / sy, m[5] / sy, m[6] / sy, 0,
                 m[8] / sz, m[9] / sz, m[10] / sz, 0,
                 0, 0, 0, 1, result);
+
             return this;
         }
 
@@ -3288,6 +3312,7 @@
             for (var index = 0; index < 16; index++) {
                 result.m[index] = array[index + offset];
             }
+            result._markAsUpdated();
         }
         /**
          * Sets the passed "result" matrix from the starting index of the passed Float32Array by multiplying each element by the float "scale".  
@@ -3296,6 +3321,8 @@
             for (var index = 0; index < 16; index++) {
                 result.m[index] = array[index + offset] * scale;
             }
+
+            result._markAsUpdated();
         }
         /**
          * Sets the passed matrix "result" with the 16 passed floats.  
@@ -3321,6 +3348,8 @@
             result.m[13] = initialM42;
             result.m[14] = initialM43;
             result.m[15] = initialM44;
+
+            result._markAsUpdated();
         }
         /**
          * Returns the index-th row of the current matrix as a new Vector4.  
@@ -3345,6 +3374,9 @@
             this.m[i + 1] = row.y;
             this.m[i + 2] = row.z;
             this.m[i + 3] = row.w;
+
+            this._markAsUpdated();
+
             return this;
         }
 
@@ -3361,6 +3393,8 @@
             this.m[i + 1] = y;
             this.m[i + 2] = z;
             this.m[i + 3] = w;
+
+            this._markAsUpdated();
             return this;
         }
         /**
@@ -3484,6 +3518,8 @@
             result.m[12] = 0.0;
             result.m[13] = 0.0;
             result.m[14] = 0.0;
+
+            result._markAsUpdated();
         }
         /**
          * Returns a new rotation matrix for "angle" radians around the Y axis.  
@@ -3518,6 +3554,8 @@
             result.m[12] = 0.0;
             result.m[13] = 0.0;
             result.m[14] = 0.0;
+
+            result._markAsUpdated();
         }
         /**
          * Returns a new rotation matrix for "angle" radians around the Z axis.  
@@ -3552,6 +3590,8 @@
             result.m[12] = 0.0;
             result.m[13] = 0.0;
             result.m[14] = 0.0;
+
+            result._markAsUpdated();
         }
         /**
          * Returns a new rotation matrix for "angle" radians around the passed axis.  
@@ -3587,6 +3627,8 @@
             result.m[11] = 0.0;
 
             result.m[15] = 1.0;
+
+            result._markAsUpdated();
         }
         /**
          * Returns a new Matrix as a rotation matrix from the Euler angles (y, x, z). 
@@ -3631,6 +3673,8 @@
             result.m[13] = 0.0;
             result.m[14] = 0.0;
             result.m[15] = 1.0;
+
+            result._markAsUpdated();
         }
         /**
          * Returns a new Matrix as a translation matrix from the passed floats (x, y, z). 
@@ -3657,6 +3701,7 @@
             for (var index = 0; index < 16; index++) {
                 result.m[index] = startValue.m[index] * (1.0 - gradient) + endValue.m[index] * gradient;
             }
+            result._markAsUpdated();
             return result;
         }
 
@@ -3949,14 +3994,16 @@
             result.m[1] = result.m[2] = result.m[3] = result.m[4] = 0.0;
             result.m[5] = yScale;
             result.m[6] = result.m[7] = 0.0;
-            result.m[8] = ((leftTan - rightTan) * xScale * 0.5) * rightHandedFactor;
-            result.m[9] = -((upTan - downTan) * yScale * 0.5) * rightHandedFactor;
-            result.m[10] = -(znear + zfar) / (zfar - znear) * rightHandedFactor;
-            // result.m[10] = -zfar / (znear - zfar);
+            result.m[8] = ((leftTan - rightTan) * xScale * 0.5)// * rightHandedFactor;
+            result.m[9] = -((upTan - downTan) * yScale * 0.5)// * rightHandedFactor;
+            //result.m[10] = -(znear + zfar) / (zfar - znear) * rightHandedFactor;
+            result.m[10] = -zfar / (znear - zfar);
             result.m[11] = 1.0 * rightHandedFactor;
             result.m[12] = result.m[13] = result.m[15] = 0.0;
             result.m[14] = -(2.0 * zfar * znear) / (zfar - znear);
             // result.m[14] = (znear * zfar) / (znear - zfar);
+
+            result._markAsUpdated();
         }
 
         /**
@@ -4062,37 +4109,40 @@
             result.m[13] = temp2 * plane.d;
             result.m[14] = temp3 * plane.d;
             result.m[15] = 1.0;
+
+            result._markAsUpdated();
         }
 
         /**
          * Sets the passed matrix "mat" as a rotation matrix composed from the 3 passed  left handed axis.  
          */
-        public static FromXYZAxesToRef(xaxis: Vector3, yaxis: Vector3, zaxis: Vector3, mat: Matrix) {
+        public static FromXYZAxesToRef(xaxis: Vector3, yaxis: Vector3, zaxis: Vector3, result: Matrix) {
 
-            mat.m[0] = xaxis.x;
-            mat.m[1] = xaxis.y;
-            mat.m[2] = xaxis.z;
+            result.m[0] = xaxis.x;
+            result.m[1] = xaxis.y;
+            result.m[2] = xaxis.z;
 
-            mat.m[3] = 0.0;
+            result.m[3] = 0.0;
 
-            mat.m[4] = yaxis.x;
-            mat.m[5] = yaxis.y;
-            mat.m[6] = yaxis.z;
+            result.m[4] = yaxis.x;
+            result.m[5] = yaxis.y;
+            result.m[6] = yaxis.z;
 
-            mat.m[7] = 0.0;
+            result.m[7] = 0.0;
 
-            mat.m[8] = zaxis.x;
-            mat.m[9] = zaxis.y;
-            mat.m[10] = zaxis.z;
+            result.m[8] = zaxis.x;
+            result.m[9] = zaxis.y;
+            result.m[10] = zaxis.z;
 
-            mat.m[11] = 0.0;
+            result.m[11] = 0.0;
 
-            mat.m[12] = 0.0;
-            mat.m[13] = 0.0;
-            mat.m[14] = 0.0;
+            result.m[12] = 0.0;
+            result.m[13] = 0.0;
+            result.m[14] = 0.0;
 
-            mat.m[15] = 1.0;
+            result.m[15] = 1.0;
 
+            result._markAsUpdated();
         }
 
         /**
@@ -4128,6 +4178,8 @@
             result.m[14] = 0.0;
 
             result.m[15] = 1.0;
+
+            result._markAsUpdated();
         }
     }
 

+ 87 - 1
src/Mesh/babylon.abstractMesh.ts

@@ -1,5 +1,5 @@
 module BABYLON {
-    export class AbstractMesh extends Node implements IDisposable, ICullable {
+    export class AbstractMesh extends Node implements IDisposable, ICullable, IGetSetVerticesData {
         // Statics
         private static _BILLBOARDMODE_NONE = 0;
         private static _BILLBOARDMODE_X = 1;
@@ -579,6 +579,73 @@
         public getVerticesData(kind: string): number[] | Float32Array {
             return null;
         }
+        /**
+         * Sets the vertex data of the mesh geometry for the requested `kind`.
+         * If the mesh has no geometry, a new Geometry object is set to the mesh and then passed this vertex data.  
+         * The `data` are either a numeric array either a Float32Array. 
+         * The parameter `updatable` is passed as is to the underlying Geometry object constructor (if initianilly none) or updater. 
+         * The parameter `stride` is an optional positive integer, it is usually automatically deducted from the `kind` (3 for positions or normals, 2 for UV, etc).  
+         * Note that a new underlying VertexBuffer object is created each call. 
+         * If the `kind` is the `PositionKind`, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed. 
+         *
+         * Possible `kind` values :
+         * - BABYLON.VertexBuffer.PositionKind
+         * - BABYLON.VertexBuffer.UVKind
+         * - BABYLON.VertexBuffer.UV2Kind
+         * - BABYLON.VertexBuffer.UV3Kind
+         * - BABYLON.VertexBuffer.UV4Kind
+         * - BABYLON.VertexBuffer.UV5Kind
+         * - BABYLON.VertexBuffer.UV6Kind
+         * - BABYLON.VertexBuffer.ColorKind
+         * - BABYLON.VertexBuffer.MatricesIndicesKind
+         * - BABYLON.VertexBuffer.MatricesIndicesExtraKind
+         * - BABYLON.VertexBuffer.MatricesWeightsKind
+         * - BABYLON.VertexBuffer.MatricesWeightsExtraKind  
+         * 
+         * Returns the Mesh.  
+         */
+        public setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean, stride?: number): Mesh {
+            return null;
+        }
+
+        /**
+         * Updates the existing vertex data of the mesh geometry for the requested `kind`.
+         * If the mesh has no geometry, it is simply returned as it is.  
+         * The `data` are either a numeric array either a Float32Array. 
+         * No new underlying VertexBuffer object is created. 
+         * If the `kind` is the `PositionKind` and if `updateExtends` is true, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.  
+         * If the parameter `makeItUnique` is true, a new global geometry is created from this positions and is set to the mesh.
+         *
+         * Possible `kind` values :
+         * - BABYLON.VertexBuffer.PositionKind
+         * - BABYLON.VertexBuffer.UVKind
+         * - BABYLON.VertexBuffer.UV2Kind
+         * - BABYLON.VertexBuffer.UV3Kind
+         * - BABYLON.VertexBuffer.UV4Kind
+         * - BABYLON.VertexBuffer.UV5Kind
+         * - BABYLON.VertexBuffer.UV6Kind
+         * - BABYLON.VertexBuffer.ColorKind
+         * - BABYLON.VertexBuffer.MatricesIndicesKind
+         * - BABYLON.VertexBuffer.MatricesIndicesExtraKind
+         * - BABYLON.VertexBuffer.MatricesWeightsKind
+         * - BABYLON.VertexBuffer.MatricesWeightsExtraKind
+         * 
+         * Returns the Mesh.  
+         */
+        public updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): Mesh {
+            return null;
+        }
+
+        /**
+         * Sets the mesh indices.  
+         * Expects an array populated with integers or a typed array (Int32Array, Uint32Array, Uint16Array).
+         * If the mesh has no geometry, a new Geometry object is created and set to the mesh. 
+         * This method creates a new index buffer each call.  
+         * Returns the Mesh.  
+         */
+        public setIndices(indices: IndicesArray, totalVertices?: number): Mesh {
+            return null;
+        }
 
         /** Returns false by default, used by the class Mesh.  
          *  Returns a boolean
@@ -2102,6 +2169,25 @@
                 this._facetParameters = null;
             }
             return this;
+        }
+
+        /**
+         * Creates new normals data for the mesh.
+         * @param updatable.
+         */
+        public createNormals(updatable: boolean) {
+            var positions = this.getVerticesData(VertexBuffer.PositionKind);
+            var indices = this.getIndices();
+            var normals: number[] | Float32Array;
+            
+            if (this.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                normals = this.getVerticesData(VertexBuffer.NormalKind);
+            } else {
+                normals = [];
+            }
+            
+            VertexData.ComputeNormals(positions, indices, normals);
+            this.setVerticesData(VertexBuffer.NormalKind, normals, updatable);
         } 
 
     }

+ 77 - 0
src/Mesh/babylon.instancedMesh.ts

@@ -77,6 +77,83 @@
         }
 
         /**
+         * Sets the vertex data of the mesh geometry for the requested `kind`.
+         * If the mesh has no geometry, a new Geometry object is set to the mesh and then passed this vertex data.  
+         * The `data` are either a numeric array either a Float32Array. 
+         * The parameter `updatable` is passed as is to the underlying Geometry object constructor (if initianilly none) or updater. 
+         * The parameter `stride` is an optional positive integer, it is usually automatically deducted from the `kind` (3 for positions or normals, 2 for UV, etc).  
+         * Note that a new underlying VertexBuffer object is created each call. 
+         * If the `kind` is the `PositionKind`, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed. 
+         *
+         * Possible `kind` values :
+         * - BABYLON.VertexBuffer.PositionKind
+         * - BABYLON.VertexBuffer.UVKind
+         * - BABYLON.VertexBuffer.UV2Kind
+         * - BABYLON.VertexBuffer.UV3Kind
+         * - BABYLON.VertexBuffer.UV4Kind
+         * - BABYLON.VertexBuffer.UV5Kind
+         * - BABYLON.VertexBuffer.UV6Kind
+         * - BABYLON.VertexBuffer.ColorKind
+         * - BABYLON.VertexBuffer.MatricesIndicesKind
+         * - BABYLON.VertexBuffer.MatricesIndicesExtraKind
+         * - BABYLON.VertexBuffer.MatricesWeightsKind
+         * - BABYLON.VertexBuffer.MatricesWeightsExtraKind  
+         * 
+         * Returns the Mesh.  
+         */
+        public setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean, stride?: number): Mesh {
+            if (this.sourceMesh) {
+               this.sourceMesh.setVerticesData(kind, data, updatable, stride);
+            }
+            return this.sourceMesh;
+        }
+
+        /**
+         * Updates the existing vertex data of the mesh geometry for the requested `kind`.
+         * If the mesh has no geometry, it is simply returned as it is.  
+         * The `data` are either a numeric array either a Float32Array. 
+         * No new underlying VertexBuffer object is created. 
+         * If the `kind` is the `PositionKind` and if `updateExtends` is true, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.  
+         * If the parameter `makeItUnique` is true, a new global geometry is created from this positions and is set to the mesh.
+         *
+         * Possible `kind` values :
+         * - BABYLON.VertexBuffer.PositionKind
+         * - BABYLON.VertexBuffer.UVKind
+         * - BABYLON.VertexBuffer.UV2Kind
+         * - BABYLON.VertexBuffer.UV3Kind
+         * - BABYLON.VertexBuffer.UV4Kind
+         * - BABYLON.VertexBuffer.UV5Kind
+         * - BABYLON.VertexBuffer.UV6Kind
+         * - BABYLON.VertexBuffer.ColorKind
+         * - BABYLON.VertexBuffer.MatricesIndicesKind
+         * - BABYLON.VertexBuffer.MatricesIndicesExtraKind
+         * - BABYLON.VertexBuffer.MatricesWeightsKind
+         * - BABYLON.VertexBuffer.MatricesWeightsExtraKind
+         * 
+         * Returns the Mesh.  
+         */
+        public updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): Mesh {
+            if (this.sourceMesh) {
+               this.sourceMesh.updateVerticesData(kind, data, updateExtends, makeItUnique);
+            }
+            return this.sourceMesh;
+        }
+
+        /**
+         * Sets the mesh indices.  
+         * Expects an array populated with integers or a typed array (Int32Array, Uint32Array, Uint16Array).
+         * If the mesh has no geometry, a new Geometry object is created and set to the mesh. 
+         * This method creates a new index buffer each call.  
+         * Returns the Mesh.  
+         */
+        public setIndices(indices: IndicesArray, totalVertices?: number): Mesh {
+            if (this.sourceMesh) {
+               this.sourceMesh.setIndices(indices, totalVertices);
+            }
+            return this.sourceMesh;
+        }
+
+        /**
          * Boolean : True if the mesh owns the requested kind of data.
          */
         public isVerticesDataPresent(kind: string): boolean {

+ 12 - 1
src/Mesh/babylon.mesh.ts

@@ -803,7 +803,6 @@
             return this;
         }
 
-
         /**
          * Creates a un-shared specific occurence of the geometry for the mesh.  
          * Returns the Mesh.  
@@ -1928,6 +1927,11 @@
                 this.material = null;
             }
 
+            // Morph targets
+            if (this.morphTargetManager) {
+                serializationObject.morphTargetManagerId = this.morphTargetManager.uniqueId;
+            }
+
             // Skeleton
             if (this.skeleton) {
                 serializationObject.skeletonId = this.skeleton.id;
@@ -1969,6 +1973,8 @@
                 serializationInstance.ranges = instance.serializeAnimationRanges();
             }
 
+            // 
+
             // Animations
             Animation.AppendSerializedAnimations(this, serializationObject);
             serializationObject.ranges = this.serializeAnimationRanges();
@@ -2200,6 +2206,11 @@
                 mesh.material = null;
             }
 
+            // Morph targets
+            if (parsedMesh.morphTargetManagerId > -1) {
+                mesh.morphTargetManager = scene.getMorphTargetManagerById(parsedMesh.morphTargetManagerId);
+            }
+
             // Skeleton
             if (parsedMesh.skeletonId > -1) {
                 mesh.skeleton = scene.getLastSkeletonByID(parsedMesh.skeletonId);

+ 14 - 2
src/Morph/babylon.morphTarget.ts

@@ -57,15 +57,27 @@ module BABYLON {
             serializationObject.name = this.name;
             serializationObject.influence = this.influence;
 
-            serializationObject.positions = this.getPositions();
+            serializationObject.positions = Array.prototype.slice.call(this.getPositions());
             if (this.hasNormals) {
-                serializationObject.normals = this.getNormals();
+                serializationObject.normals = Array.prototype.slice.call(this.getNormals());
             }
 
             return serializationObject;
         }
 
         // Statics
+        public static Parse(serializationObject: any): MorphTarget {
+            var result = new MorphTarget(serializationObject.name , serializationObject.influence);
+
+            result.setPositions(serializationObject.positions);
+
+            if (serializationObject.normals) {
+                result.setNormals(serializationObject.normals);
+            }
+
+            return result;
+        }
+
         public static FromMesh(mesh: AbstractMesh, name?: string, influence?: number): MorphTarget {
             if (!name) {
                 name = mesh.name;

+ 15 - 0
src/Morph/babylon.morphTargetManager.ts

@@ -16,6 +16,8 @@ module BABYLON {
 
             this._scene = scene;
 
+            this._scene.morphTargetManagers.push(this);
+
             this._uniqueId = scene.getUniqueId();
         }
 
@@ -118,5 +120,18 @@ module BABYLON {
                 }
             }
         }
+
+        // Statics
+        public static Parse(serializationObject: any, scene: Scene): MorphTargetManager {
+            var result = new MorphTargetManager(scene);
+
+            result._uniqueId = serializationObject.id;
+
+            for (var targetData of serializationObject.targets) {
+                result.addTarget(MorphTarget.Parse(targetData));
+            }
+
+            return result;
+        }
     }
 }

+ 0 - 1
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -338,7 +338,6 @@
             object.computeWorldMatrix && object.computeWorldMatrix(true);
             // The delta between the mesh position and the mesh bounding box center
             var center = impostor.getObjectCenter();
-            var extendSize = impostor.getObjectExtendSize();
             this._tmpDeltaPosition.copyFrom(object.position.subtract(center));
             this._tmpPosition.copyFrom(center);
             var quaternion = object.rotationQuaternion;

+ 14 - 1
src/Physics/babylon.physicsImpostor.ts

@@ -15,6 +15,7 @@ module BABYLON {
         parent?: any;
         getBoundingInfo?(): BoundingInfo;
         computeWorldMatrix?(force: boolean): void;
+        getWorldMatrix?(): Matrix;
         getChildMeshes?(): Array<AbstractMesh>;
         getVerticesData?(kind: string): Array<number> | Float32Array;
         getIndices?(): IndicesArray;
@@ -25,6 +26,8 @@ module BABYLON {
 
         public static DEFAULT_OBJECT_SIZE: Vector3 = new BABYLON.Vector3(1, 1, 1);
 
+        public static IDENTITY_QUATERNION = Quaternion.Identity();
+
         private _physicsEngine: PhysicsEngine;
         //The native cannon/oimo/energy physics body object.
         private _physicsBody: any;
@@ -168,8 +171,18 @@ module BABYLON {
 
         public getObjectExtendSize(): Vector3 {
             if (this.object.getBoundingInfo) {
+                let q = this.object.rotationQuaternion;
+                //reset rotation
+                this.object.rotationQuaternion = PhysicsImpostor.IDENTITY_QUATERNION;
+                //calculate the world matrix with no rotation
+                this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
+                let size = this.object.getBoundingInfo().boundingBox.extendSizeWorld.scale(2)
+                //bring back the rotation
+                this.object.rotationQuaternion = q;
+                //calculate the world matrix with the new rotation
                 this.object.computeWorldMatrix && this.object.computeWorldMatrix(true);
-                return this.object.getBoundingInfo().boundingBox.extendSizeWorld.scale(2).multiply(this.object.scaling)
+
+                return size;
             } else {
                 return PhysicsImpostor.DEFAULT_OBJECT_SIZE;
             }

+ 189 - 154
src/Shaders/pbr.fragment.fx

@@ -89,10 +89,16 @@ uniform sampler2D lightmapSampler;
 
 #if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
 varying vec2 vReflectivityUV;
-uniform vec2 vReflectivityInfos;
+uniform vec3 vReflectivityInfos;
 uniform sampler2D reflectivitySampler;
 #endif
 
+#ifdef MICROSURFACEMAP
+varying vec2 vMicroSurfaceSamplerUV;
+uniform vec2 vMicroSurfaceSamplerInfos;
+uniform sampler2D microSurfaceSampler;
+#endif
+
 // Fresnel
 #include<fresnelFunction>
 
@@ -208,16 +214,16 @@ void main(void) {
 	surfaceAlbedo = texture2D(albedoSampler, vAlbedoUV + uvOffset);
 	surfaceAlbedo = vec4(toLinearSpace(surfaceAlbedo.rgb), surfaceAlbedo.a);
 
-#ifndef LINKREFRACTIONTOTRANSPARENCY
-#ifdef ALPHATEST
-	if (surfaceAlbedo.a < 0.4)
-		discard;
-#endif
-#endif
+	#ifndef LINKREFRACTIONTOTRANSPARENCY
+		#ifdef ALPHATEST
+			if (surfaceAlbedo.a < 0.4)
+				discard;
+		#endif
+	#endif
 
-#ifdef ALPHAFROMALBEDO
-	alpha *= surfaceAlbedo.a;
-#endif
+	#ifdef ALPHAFROMALBEDO
+		alpha *= surfaceAlbedo.a;
+	#endif
 
 	surfaceAlbedo.rgb *= vAlbedoInfos.y;
 #else
@@ -235,67 +241,85 @@ void main(void) {
 #endif
 
 	// Ambient color
-	vec3 ambientColor = vec3(1., 1., 1.);
+	vec3 ambientOcclusionColor = vec3(1., 1., 1.);
 
 #ifdef AMBIENT
-	ambientColor = texture2D(ambientSampler, vAmbientUV + uvOffset).rgb * vAmbientInfos.y;
-	ambientColor = vec3(1., 1., 1.) - ((vec3(1., 1., 1.) - ambientColor) * vAmbientInfos.z);
+	vec3 ambientOcclusionColorMap = texture2D(ambientSampler, vAmbientUV + uvOffset).rgb * vAmbientInfos.y;
+	ambientOcclusionColor = mix(ambientOcclusionColor, ambientOcclusionColorMap, vAmbientInfos.z);
 
-#ifdef OVERLOADEDVALUES
-	ambientColor.rgb = mix(ambientColor.rgb, vOverloadedAmbient, vOverloadedIntensity.x);
-#endif
+	#ifdef OVERLOADEDVALUES
+		ambientOcclusionColor.rgb = mix(ambientOcclusionColor.rgb, vOverloadedAmbient, vOverloadedIntensity.x);
+	#endif
 #endif
 
 	// Reflectivity map
 	float microSurface = vReflectivityColor.a;
 	vec3 surfaceReflectivityColor = vReflectivityColor.rgb;
 
-#ifdef OVERLOADEDVALUES
-	surfaceReflectivityColor.rgb = mix(surfaceReflectivityColor.rgb, vOverloadedReflectivity, vOverloadedIntensity.z);
-#endif
-
 #ifdef REFLECTIVITY
 	vec4 surfaceReflectivityColorMap = texture2D(reflectivitySampler, vReflectivityUV + uvOffset);
 	surfaceReflectivityColor = surfaceReflectivityColorMap.rgb;
 	surfaceReflectivityColor = toLinearSpace(surfaceReflectivityColor);
+	surfaceReflectivityColor *= vReflectivityInfos.y;
 
 	#ifdef OVERLOADEDVALUES
 		surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
 	#endif
 
 	#ifdef MICROSURFACEFROMREFLECTIVITYMAP
-		microSurface = surfaceReflectivityColorMap.a;
+		microSurface = surfaceReflectivityColorMap.a * vReflectivityInfos.z;
 	#else
 		#ifdef MICROSURFACEAUTOMATIC
 			microSurface = computeDefaultMicroSurface(microSurface, surfaceReflectivityColor);
 		#endif
 	#endif
+#else
+	#ifdef OVERLOADEDVALUES
+		surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
+	#endif
 #endif
 
 #ifdef METALLICWORKFLOW
 	vec2 metallicRoughness = surfaceReflectivityColor.rg;
 
-	#ifdef METALLICROUGHNESSMAP
+	#ifdef METALLICMAP
 		vec4 surfaceMetallicColorMap = texture2D(reflectivitySampler, vReflectivityUV + uvOffset);
 
-		// No gamma space from the metallic map in metallic workflow.
-		metallicRoughness.r *= surfaceMetallicColorMap.r;
-		#ifdef METALLICROUGHNESSGSTOREINALPHA
+		#ifdef AOSTOREINMETALMAPRED			
+			vec3 aoStoreInMetalMap = vec3(surfaceMetallicColorMap.r, surfaceMetallicColorMap.r, surfaceMetallicColorMap.r);
+			ambientOcclusionColor = mix(ambientOcclusionColor, aoStoreInMetalMap, vReflectivityInfos.z);
+		#endif
+
+		#ifdef METALLNESSSTOREINMETALMAPBLUE
+			metallicRoughness.r *= surfaceMetallicColorMap.b;
+		#else
+			metallicRoughness.r *= surfaceMetallicColorMap.r;
+		#endif
+
+		#ifdef ROUGHNESSSTOREINMETALMAPALPHA
 			metallicRoughness.g *= surfaceMetallicColorMap.a;
 		#else
-			#ifdef METALLICROUGHNESSGSTOREINGREEN
+			#ifdef ROUGHNESSSTOREINMETALMAPGREEN
 				metallicRoughness.g *= surfaceMetallicColorMap.g;
 			#endif
 		#endif
 	#endif
 
+	#ifdef MICROSURFACEMAP
+		vec4 microSurfaceTexel = texture2D(microSurfaceSampler, vMicroSurfaceSamplerUV + uvOffset) * vMicroSurfaceSamplerInfos.y;
+		metallicRoughness.g *= microSurfaceTexel.r;
+	#endif
+
+	// Compute microsurface form roughness.
+	microSurface = 1.0 - metallicRoughness.g;
+
 	// Diffuse is used as the base of the reflectivity.
 	vec3 baseColor = surfaceAlbedo.rgb;
 
 	// Drop the surface diffuse by the 1.0 - metalness.
 	surfaceAlbedo.rgb *= (1.0 - metallicRoughness.r);
 	
-	// Default specular reflectance at normal incidence.
+	// Default specular reflectance at normal incidence aka F0.
 	// 4% corresponds to index of refraction (IOR) of 1.50, approximately equal to glass.
 	const vec3 DefaultSpecularReflectanceDielectric = vec3(0.04, 0.04, 0.04);
 
@@ -305,8 +329,11 @@ void main(void) {
 	#ifdef OVERLOADEDVALUES
 		surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
 	#endif
-
-	microSurface = 1.0 - metallicRoughness.g;
+#else
+	#ifdef MICROSURFACEMAP
+		vec4 microSurfaceTexel = texture2D(microSurfaceSampler, vMicroSurfaceSamplerUV + uvOffset) * vMicroSurfaceSamplerInfos.y;
+		microSurface = microSurfaceTexel.r;
+	#endif
 #endif
 
 #ifdef OVERLOADEDVALUES
@@ -360,13 +387,12 @@ void main(void) {
 #ifdef OPACITY
 	vec4 opacityMap = texture2D(opacitySampler, vOpacityUV + uvOffset);
 
-#ifdef OPACITYRGB
-	opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11);
-	alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;
-#else
-	alpha *= opacityMap.a * vOpacityInfos.y;
-#endif
-
+	#ifdef OPACITYRGB
+		opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11);
+		alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;
+	#else
+		alpha *= opacityMap.a * vOpacityInfos.y;
+	#endif
 #endif
 
 #ifdef VERTEXALPHA
@@ -390,59 +416,59 @@ void main(void) {
 #ifdef REFRACTION
 	vec3 refractionVector = refract(-viewDirectionW, normalW, vRefractionInfos.y);
 
-#ifdef LODBASEDMICROSFURACE
-#ifdef USEPMREMREFRACTION
-	float lodRefraction = getMipMapIndexFromAverageSlopeWithPMREM(vMicrosurfaceTextureLods.y, alphaG);
-#else
-	float lodRefraction = getMipMapIndexFromAverageSlope(vMicrosurfaceTextureLods.y, alphaG);
-#endif
-#else
-	float biasRefraction = (vMicrosurfaceTextureLods.y + 2.) * (1.0 - microSurface);
-#endif
+	#ifdef LODBASEDMICROSFURACE
+		#ifdef USEPMREMREFRACTION
+			float lodRefraction = getMipMapIndexFromAverageSlopeWithPMREM(vMicrosurfaceTextureLods.y, alphaG);
+		#else
+			float lodRefraction = getMipMapIndexFromAverageSlope(vMicrosurfaceTextureLods.y, alphaG);
+		#endif
+	#else
+		float biasRefraction = (vMicrosurfaceTextureLods.y + 2.) * (1.0 - microSurface);
+	#endif
 
-#ifdef REFRACTIONMAP_3D
-	refractionVector.y = refractionVector.y * vRefractionInfos.w;
+	#ifdef REFRACTIONMAP_3D
+		refractionVector.y = refractionVector.y * vRefractionInfos.w;
 
-	if (dot(refractionVector, viewDirectionW) < 1.0)
-	{
-#ifdef LODBASEDMICROSFURACE
-#ifdef USEPMREMREFRACTION
-		// Empiric Threshold
-		if ((vMicrosurfaceTextureLods.y - lodRefraction) > 4.0)
+		if (dot(refractionVector, viewDirectionW) < 1.0)
 		{
-			// Bend to not reach edges.
-			float scaleRefraction = 1. - exp2(lodRefraction) / exp2(vMicrosurfaceTextureLods.y); // CubemapSize is the size of the base mipmap
-			float maxRefraction = max(max(abs(refractionVector.x), abs(refractionVector.y)), abs(refractionVector.z));
-			if (abs(refractionVector.x) != maxRefraction) refractionVector.x *= scaleRefraction;
-			if (abs(refractionVector.y) != maxRefraction) refractionVector.y *= scaleRefraction;
-			if (abs(refractionVector.z) != maxRefraction) refractionVector.z *= scaleRefraction;
-		}
-#endif
+		#ifdef LODBASEDMICROSFURACE
+			#ifdef USEPMREMREFRACTION
+					// Empiric Threshold
+					if ((vMicrosurfaceTextureLods.y - lodRefraction) > 4.0)
+					{
+						// Bend to not reach edges.
+						float scaleRefraction = 1. - exp2(lodRefraction) / exp2(vMicrosurfaceTextureLods.y); // CubemapSize is the size of the base mipmap
+						float maxRefraction = max(max(abs(refractionVector.x), abs(refractionVector.y)), abs(refractionVector.z));
+						if (abs(refractionVector.x) != maxRefraction) refractionVector.x *= scaleRefraction;
+						if (abs(refractionVector.y) != maxRefraction) refractionVector.y *= scaleRefraction;
+						if (abs(refractionVector.z) != maxRefraction) refractionVector.z *= scaleRefraction;
+					}
+			#endif
 
-		surfaceRefractionColor = textureCubeLodEXT(refractionCubeSampler, refractionVector, lodRefraction).rgb * vRefractionInfos.x;
-#else
-		surfaceRefractionColor = textureCube(refractionCubeSampler, refractionVector, biasRefraction).rgb * vRefractionInfos.x;
-#endif
-	}
+				surfaceRefractionColor = textureCubeLodEXT(refractionCubeSampler, refractionVector, lodRefraction).rgb * vRefractionInfos.x;
+		#else
+				surfaceRefractionColor = textureCube(refractionCubeSampler, refractionVector, biasRefraction).rgb * vRefractionInfos.x;
+		#endif
+		}
 
-#ifndef REFRACTIONMAPINLINEARSPACE
-	surfaceRefractionColor = toLinearSpace(surfaceRefractionColor.rgb);
-#endif
-#else
-	vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0)));
+		#ifndef REFRACTIONMAPINLINEARSPACE
+			surfaceRefractionColor = toLinearSpace(surfaceRefractionColor.rgb);
+		#endif
+	#else
+		vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0)));
 
-	vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z;
+		vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z;
 
-	refractionCoords.y = 1.0 - refractionCoords.y;
+		refractionCoords.y = 1.0 - refractionCoords.y;
 
-#ifdef LODBASEDMICROSFURACE
-	surfaceRefractionColor = texture2DLodEXT(refraction2DSampler, refractionCoords, lodRefraction).rgb * vRefractionInfos.x;
-#else
-	surfaceRefractionColor = texture2D(refraction2DSampler, refractionCoords, biasRefraction).rgb * vRefractionInfos.x;
-#endif    
+		#ifdef LODBASEDMICROSFURACE
+			surfaceRefractionColor = texture2DLodEXT(refraction2DSampler, refractionCoords, lodRefraction).rgb * vRefractionInfos.x;
+		#else
+			surfaceRefractionColor = texture2D(refraction2DSampler, refractionCoords, biasRefraction).rgb * vRefractionInfos.x;
+		#endif    
 
-	surfaceRefractionColor = toLinearSpace(surfaceRefractionColor.rgb);
-#endif
+		surfaceRefractionColor = toLinearSpace(surfaceRefractionColor.rgb);
+	#endif
 #endif
 
 	// Reflection
@@ -452,68 +478,68 @@ void main(void) {
 #ifdef REFLECTION
 	vec3 vReflectionUVW = computeReflectionCoords(vec4(vPositionW, 1.0), normalW);
 
-#ifdef LODBASEDMICROSFURACE
-#ifdef USEPMREMREFLECTION
-	float lodReflection = getMipMapIndexFromAverageSlopeWithPMREM(vMicrosurfaceTextureLods.x, alphaG);
-#else
-	float lodReflection = getMipMapIndexFromAverageSlope(vMicrosurfaceTextureLods.x, alphaG);
-#endif
-#else
-	float biasReflection = (vMicrosurfaceTextureLods.x + 2.) * (1.0 - microSurface);
-#endif
+	#ifdef LODBASEDMICROSFURACE
+		#ifdef USEPMREMREFLECTION
+			float lodReflection = getMipMapIndexFromAverageSlopeWithPMREM(vMicrosurfaceTextureLods.x, alphaG);
+		#else
+			float lodReflection = getMipMapIndexFromAverageSlope(vMicrosurfaceTextureLods.x, alphaG);
+		#endif
+	#else
+		float biasReflection = (vMicrosurfaceTextureLods.x + 2.) * (1.0 - microSurface);
+	#endif
 
-#ifdef REFLECTIONMAP_3D
+	#ifdef REFLECTIONMAP_3D
+
+		#ifdef LODBASEDMICROSFURACE
+			#ifdef USEPMREMREFLECTION
+				// Empiric Threshold
+				if ((vMicrosurfaceTextureLods.y - lodReflection) > 4.0)
+				{
+					// Bend to not reach edges.
+					float scaleReflection = 1. - exp2(lodReflection) / exp2(vMicrosurfaceTextureLods.x); // CubemapSize is the size of the base mipmap
+					float maxReflection = max(max(abs(vReflectionUVW.x), abs(vReflectionUVW.y)), abs(vReflectionUVW.z));
+					if (abs(vReflectionUVW.x) != maxReflection) vReflectionUVW.x *= scaleReflection;
+					if (abs(vReflectionUVW.y) != maxReflection) vReflectionUVW.y *= scaleReflection;
+					if (abs(vReflectionUVW.z) != maxReflection) vReflectionUVW.z *= scaleReflection;
+				}
+			#endif
 
-#ifdef LODBASEDMICROSFURACE
-#ifdef USEPMREMREFLECTION
-	// Empiric Threshold
-	if ((vMicrosurfaceTextureLods.y - lodReflection) > 4.0)
-	{
-		// Bend to not reach edges.
-		float scaleReflection = 1. - exp2(lodReflection) / exp2(vMicrosurfaceTextureLods.x); // CubemapSize is the size of the base mipmap
-		float maxReflection = max(max(abs(vReflectionUVW.x), abs(vReflectionUVW.y)), abs(vReflectionUVW.z));
-		if (abs(vReflectionUVW.x) != maxReflection) vReflectionUVW.x *= scaleReflection;
-		if (abs(vReflectionUVW.y) != maxReflection) vReflectionUVW.y *= scaleReflection;
-		if (abs(vReflectionUVW.z) != maxReflection) vReflectionUVW.z *= scaleReflection;
-	}
-#endif
-
-	environmentRadiance = textureCubeLodEXT(reflectionCubeSampler, vReflectionUVW, lodReflection).rgb * vReflectionInfos.x;
-#else
-	environmentRadiance = textureCube(reflectionCubeSampler, vReflectionUVW, biasReflection).rgb * vReflectionInfos.x;
-#endif
+			environmentRadiance = textureCubeLodEXT(reflectionCubeSampler, vReflectionUVW, lodReflection).rgb * vReflectionInfos.x;
+		#else
+			environmentRadiance = textureCube(reflectionCubeSampler, vReflectionUVW, biasReflection).rgb * vReflectionInfos.x;
+		#endif
 
-#ifdef USESPHERICALFROMREFLECTIONMAP
-#ifndef REFLECTIONMAP_SKYBOX
-	vec3 normalEnvironmentSpace = (reflectionMatrix * vec4(normalW, 1)).xyz;
-	environmentIrradiance = EnvironmentIrradiance(normalEnvironmentSpace);
-#endif
-#else
-	environmentRadiance = toLinearSpace(environmentRadiance.rgb);
+		#ifdef USESPHERICALFROMREFLECTIONMAP
+			#ifndef REFLECTIONMAP_SKYBOX
+				vec3 normalEnvironmentSpace = (reflectionMatrix * vec4(normalW, 1)).xyz;
+				environmentIrradiance = EnvironmentIrradiance(normalEnvironmentSpace);
+			#endif
+		#else
+			environmentRadiance = toLinearSpace(environmentRadiance.rgb);
 
-	environmentIrradiance = textureCube(reflectionCubeSampler, normalW, 20.).rgb * vReflectionInfos.x;
-	environmentIrradiance = toLinearSpace(environmentIrradiance.rgb);
-	environmentIrradiance *= 0.2; // Hack in case of no hdr cube map use for environment.
-#endif
-#else
-	vec2 coords = vReflectionUVW.xy;
+			environmentIrradiance = textureCube(reflectionCubeSampler, normalW, 20.).rgb * vReflectionInfos.x;
+			environmentIrradiance = toLinearSpace(environmentIrradiance.rgb);
+			environmentIrradiance *= 0.2; // Hack in case of no hdr cube map use for environment.
+		#endif
+	#else
+		vec2 coords = vReflectionUVW.xy;
 
-#ifdef REFLECTIONMAP_PROJECTION
-	coords /= vReflectionUVW.z;
-#endif
+		#ifdef REFLECTIONMAP_PROJECTION
+			coords /= vReflectionUVW.z;
+		#endif
 
-	coords.y = 1.0 - coords.y;
-#ifdef LODBASEDMICROSFURACE
-	environmentRadiance = texture2DLodEXT(reflection2DSampler, coords, lodReflection).rgb * vReflectionInfos.x;
-#else
-	environmentRadiance = texture2D(reflection2DSampler, coords, biasReflection).rgb * vReflectionInfos.x;
-#endif
+		coords.y = 1.0 - coords.y;
+		#ifdef LODBASEDMICROSFURACE
+			environmentRadiance = texture2DLodEXT(reflection2DSampler, coords, lodReflection).rgb * vReflectionInfos.x;
+		#else
+			environmentRadiance = texture2D(reflection2DSampler, coords, biasReflection).rgb * vReflectionInfos.x;
+		#endif
 
-	environmentRadiance = toLinearSpace(environmentRadiance.rgb);
+		environmentRadiance = toLinearSpace(environmentRadiance.rgb);
 
-	environmentIrradiance = texture2D(reflection2DSampler, coords, 20.).rgb * vReflectionInfos.x;
-	environmentIrradiance = toLinearSpace(environmentIrradiance.rgb);
-#endif
+		environmentIrradiance = texture2D(reflection2DSampler, coords, 20.).rgb * vReflectionInfos.x;
+		environmentIrradiance = toLinearSpace(environmentIrradiance.rgb);
+	#endif
 #endif
 
 #ifdef OVERLOADEDVALUES
@@ -591,31 +617,40 @@ void main(void) {
 
 	// Composition
 #ifdef EMISSIVEASILLUMINATION
-	vec3 finalDiffuse = max(lightDiffuseContribution * surfaceAlbedoContribution + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
+	vec3 finalDiffuse = lightDiffuseContribution * surfaceAlbedoContribution;
 
-#ifdef OVERLOADEDSHADOWVALUES
-	shadowedOnlyLightDiffuseContribution = max(shadowedOnlyLightDiffuseContribution * surfaceAlbedoContribution + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
-#endif
+	#ifdef OVERLOADEDSHADOWVALUES
+		shadowedOnlyLightDiffuseContribution = shadowedOnlyLightDiffuseContribution * surfaceAlbedoContribution;
+	#endif
 #else
-#ifdef LINKEMISSIVEWITHALBEDO
-	vec3 finalDiffuse = max((lightDiffuseContribution + surfaceEmissiveColor) * surfaceAlbedoContribution + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
+	#ifdef LINKEMISSIVEWITHALBEDO
+		vec3 finalDiffuse = (lightDiffuseContribution + surfaceEmissiveColor) * surfaceAlbedoContribution;
 
-#ifdef OVERLOADEDSHADOWVALUES
-	shadowedOnlyLightDiffuseContribution = max((shadowedOnlyLightDiffuseContribution + surfaceEmissiveColor) * surfaceAlbedoContribution + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
-#endif
-#else
-	vec3 finalDiffuse = max(lightDiffuseContribution * surfaceAlbedoContribution + surfaceEmissiveColor + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
+		#ifdef OVERLOADEDSHADOWVALUES
+			shadowedOnlyLightDiffuseContribution = (shadowedOnlyLightDiffuseContribution + surfaceEmissiveColor) * surfaceAlbedoContribution;
+		#endif
+	#else
+		vec3 finalDiffuse = lightDiffuseContribution * surfaceAlbedoContribution + surfaceEmissiveColor;
 
-#ifdef OVERLOADEDSHADOWVALUES
-	shadowedOnlyLightDiffuseContribution = max(shadowedOnlyLightDiffuseContribution * surfaceAlbedoContribution + surfaceEmissiveColor + vAmbientColor, 0.0) * surfaceAlbedo.rgb;
-#endif
-#endif
+		#ifdef OVERLOADEDSHADOWVALUES
+			shadowedOnlyLightDiffuseContribution = shadowedOnlyLightDiffuseContribution * surfaceAlbedoContribution + surfaceEmissiveColor;
+		#endif
+	#endif
 #endif
 
+finalDiffuse.rgb += vAmbientColor;
+finalDiffuse *= surfaceAlbedo.rgb;
+finalDiffuse = max(finalDiffuse, 0.0);
+
 #ifdef OVERLOADEDSHADOWVALUES
+	shadowedOnlyLightDiffuseContribution += vAmbientColor;
+	shadowedOnlyLightDiffuseContribution *= surfaceAlbedo.rgb;
+	shadowedOnlyLightDiffuseContribution = max(shadowedOnlyLightDiffuseContribution, 0.0);
 	finalDiffuse = mix(finalDiffuse, shadowedOnlyLightDiffuseContribution, (1.0 - vOverloadedShadowIntensity.y));
 #endif
 
+finalDiffuse = (finalDiffuse * vLightingIntensity.x + surfaceAlbedo.rgb * environmentIrradiance) * ambientOcclusionColor;
+
 #ifdef SPECULARTERM
 	vec3 finalSpecular = lightSpecularContribution * surfaceReflectivityColor;
 	#ifdef SPECULAROVERALPHA
@@ -629,12 +664,12 @@ void main(void) {
 	alpha = clamp(alpha + getLuminance(environmentRadiance), 0., 1.);
 #endif
 
-	// Composition
-	// Reflection already includes the environment intensity.
+// Composition
+// Reflection already includes the environment intensity.
+vec4 finalColor = vec4(finalDiffuse + finalSpecular * vLightingIntensity.x + environmentRadiance + refractance, alpha);
+
 #ifdef EMISSIVEASILLUMINATION
-	vec4 finalColor = vec4(finalDiffuse * ambientColor * vLightingIntensity.x + surfaceAlbedo.rgb * environmentIrradiance + finalSpecular * vLightingIntensity.x + environmentRadiance + surfaceEmissiveColor * vLightingIntensity.y + refractance, alpha);
-#else
-	vec4 finalColor = vec4(finalDiffuse * ambientColor * vLightingIntensity.x + surfaceAlbedo.rgb * environmentIrradiance + finalSpecular * vLightingIntensity.x + environmentRadiance + refractance, alpha);
+	finalColor.rgb += (surfaceEmissiveColor * vLightingIntensity.y);
 #endif
 
 #ifdef LIGHTMAP

+ 18 - 1
src/Shaders/pbr.vertex.fx

@@ -58,10 +58,16 @@ uniform mat4 lightmapMatrix;
 
 #if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
 varying vec2 vReflectivityUV;
-uniform vec2 vReflectivityInfos;
+uniform vec3 vReflectivityInfos;
 uniform mat4 reflectivityMatrix;
 #endif
 
+#ifdef MICROSURFACEMAP
+varying vec2 vMicroSurfaceSamplerUV;
+uniform vec2 vMicroSurfaceSamplerInfos;
+uniform mat4 microSurfaceSamplerMatrix;
+#endif
+
 #ifdef BUMP
 varying vec2 vBumpUV;
 uniform vec3 vBumpInfos;
@@ -203,6 +209,17 @@ void main(void) {
     }
 #endif
 
+#ifdef MICROSURFACEMAP
+    if (vMicroSurfaceSamplerInfos.x == 0.)
+    {
+        vMicroSurfaceSamplerUV = vec2(microSurfaceSamplerMatrix * vec4(uv, 1.0, 0.0));
+    }
+    else
+    {
+        vMicroSurfaceSamplerUV = vec2(microSurfaceSamplerMatrix * vec4(uv2, 1.0, 0.0));
+    }
+#endif
+
 #ifdef BUMP
     if (vBumpInfos.x == 0.)
     {

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

@@ -148,6 +148,16 @@
                 serializationObject.metadata = scene.metadata;
             }
 
+            // Morph targets
+            serializationObject.morphTargetManagers = [];
+            for (var abstractMesh of scene.meshes) {
+                var manager = (<Mesh>abstractMesh).morphTargetManager;
+                
+                if (manager) {
+                    serializationObject.morphTargetManagers.push(manager.serialize());
+                }
+            }            
+
             // Lights
             serializationObject.lights = [];
             var index: number;

+ 1 - 0
src/babylon.mixins.ts

@@ -25,6 +25,7 @@ interface Window {
     Float32Array: Float32ArrayConstructor;
     mozURL: any;
     msURL: any;
+    VRFrameData: any; // WebVR, from specs 1.1
 }
 
 interface WebGLVertexArrayObject {

+ 34 - 1
src/babylon.scene.ts

@@ -566,6 +566,9 @@
 
         public skeletons = new Array<Skeleton>();
 
+        // Morph targets
+        public morphTargetManagers = new Array<MorphTargetManager>();
+
         // Lens flares
         public lensFlaresEnabled = true;
         public lensFlareSystems = new Array<LensFlareSystem>();
@@ -653,6 +656,9 @@
         private _executeWhenReadyTimeoutId = -1;
         private _intermediateRendering = false;
 
+        private _viewUpdateFlag = -1;
+        private _projectionUpdateFlag = -1;
+
         public _toBeDisposed = new SmartArray<IDisposable>(256);
         private _pendingData = [];//ANY
 
@@ -1660,6 +1666,12 @@
         }
 
         public setTransformMatrix(view: Matrix, projection: Matrix): void {
+            if (this._viewUpdateFlag === view.updateFlag && this._projectionUpdateFlag === projection.updateFlag) {
+                return;
+            }
+
+            this._viewUpdateFlag = view.updateFlag;
+            this._projectionUpdateFlag = projection.updateFlag;
             this._viewMatrix = view;
             this._projectionMatrix = projection;
 
@@ -1714,13 +1726,23 @@
         public removeSkeleton(toRemove: Skeleton): number {
             var index = this.skeletons.indexOf(toRemove);
             if (index !== -1) {
-                // Remove from the scene if mesh found 
+                // Remove from the scene if found 
                 this.skeletons.splice(index, 1);
             }
 
             return index;
         }
 
+        public removeMorphTargetManager(toRemove: MorphTargetManager): number {
+            var index = this.morphTargetManagers.indexOf(toRemove);
+            if (index !== -1) {
+                // Remove from the scene if found 
+                this.morphTargetManagers.splice(index, 1);
+            }
+
+            return index;
+        }
+
         public removeLight(toRemove: Light): number {
             var index = this.lights.indexOf(toRemove);
             if (index !== -1) {
@@ -2245,6 +2267,16 @@
             return null;
         }
 
+        public getMorphTargetManagerById(id: number): MorphTargetManager {
+            for (var index = 0; index < this.morphTargetManagers.length; index++) {
+                if (this.morphTargetManagers[index].uniqueId === id) {
+                    return this.morphTargetManagers[index];
+                }
+            }
+
+            return null;
+        }
+
         public isActiveMesh(mesh: Mesh): boolean {
             return (this._activeMeshes.indexOf(mesh) !== -1);
         }
@@ -3044,6 +3076,7 @@
             this.afterRender = null;
 
             this.skeletons = [];
+            this.morphTargetManagers = [];
 
             this._boundingBoxRenderer.dispose();