Ver código fonte

Merge remote-tracking branch 'upstream/master' into draco-updates

Gary Hsu 7 anos atrás
pai
commit
ffed167fd2
56 arquivos alterados com 31409 adições e 45301 exclusões
  1. 15730 30139
      Playground/babylon.d.txt
  2. 13521 13502
      dist/preview release/babylon.d.ts
  3. 56 56
      dist/preview release/babylon.js
  4. 379 228
      dist/preview release/babylon.max.js
  5. 379 228
      dist/preview release/babylon.no-module.max.js
  6. 57 57
      dist/preview release/babylon.worker.js
  7. 379 228
      dist/preview release/es6.js
  8. 4 0
      dist/preview release/gui/babylon.gui.d.ts
  9. 18 0
      dist/preview release/gui/babylon.gui.js
  10. 4 4
      dist/preview release/gui/babylon.gui.min.js
  11. 4 0
      dist/preview release/gui/babylon.gui.module.d.ts
  12. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  13. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  14. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  15. 0 7
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  16. 4 57
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  17. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  18. 0 7
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  19. 4 57
      dist/preview release/loaders/babylon.glTFFileLoader.js
  20. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  21. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  22. 0 7
      dist/preview release/loaders/babylonjs.loaders.d.ts
  23. 4 57
      dist/preview release/loaders/babylonjs.loaders.js
  24. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  25. 0 7
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  26. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  27. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  28. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  29. 3 3
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  30. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  31. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  32. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  33. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  34. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  35. 2 30
      dist/preview release/typedocValidationBaseline.json
  36. 64 64
      dist/preview release/viewer/babylon.viewer.js
  37. 383 285
      dist/preview release/viewer/babylon.viewer.max.js
  38. 18 0
      gui/src/advancedDynamicTexture.ts
  39. 4 0
      gui/src/controls/container.ts
  40. 42 57
      materialsLibrary/test/addbackground.js
  41. 2 1
      sandbox/index.html
  42. 1 1
      src/Animations/babylon.animatable.ts
  43. 2 1
      src/Animations/babylon.runtimeAnimation.ts
  44. 0 4
      src/Bones/babylon.bone.ts
  45. 2 2
      src/Bones/babylon.boneIKController.ts
  46. 49 80
      src/Engine/babylon.engine.ts
  47. 24 11
      src/Helpers/babylon.environmentHelper.ts
  48. 128 43
      src/Materials/Background/babylon.backgroundMaterial.ts
  49. 3 1
      src/Materials/Textures/babylon.mirrorTexture.ts
  50. 16 1
      src/Math/babylon.math.ts
  51. 3 2
      src/Shaders/ShadersInclude/backgroundFragmentDeclaration.fx
  52. 1 2
      src/Shaders/ShadersInclude/backgroundUboDeclaration.fx
  53. 7 3
      src/Shaders/background.fragment.fx
  54. 81 30
      src/babylon.scene.ts
  55. BIN
      tests/validation/ReferenceImages/gltf1CesiumMan.png
  56. 5 13
      tests/validation/config.json

Diferenças do arquivo suprimidas por serem muito extensas
+ 15730 - 30139
Playground/babylon.d.txt


Diferenças do arquivo suprimidas por serem muito extensas
+ 13521 - 13502
dist/preview release/babylon.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 56 - 56
dist/preview release/babylon.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 379 - 228
dist/preview release/babylon.max.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 379 - 228
dist/preview release/babylon.no-module.max.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 57 - 57
dist/preview release/babylon.worker.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 379 - 228
dist/preview release/es6.js


+ 4 - 0
dist/preview release/gui/babylon.gui.d.ts

@@ -58,6 +58,10 @@ declare module BABYLON.GUI {
         private _checkUpdate(camera);
         private _render();
         private _doPicking(x, y, type, pointerId, buttonIndex);
+        _cleanControlAfterRemovalFromList(list: {
+            [pointerId: number]: Control;
+        }, control: Control): void;
+        _cleanControlAfterRemoval(control: Control): void;
         attach(): void;
         attachToMesh(mesh: AbstractMesh, supportPointerMove?: boolean): void;
         moveFocusToControl(control: IFocusableControl): void;

+ 18 - 0
dist/preview release/gui/babylon.gui.js

@@ -391,6 +391,21 @@ var BABYLON;
                 }
                 this._manageFocus();
             };
+            AdvancedDynamicTexture.prototype._cleanControlAfterRemovalFromList = function (list, control) {
+                for (var pointerId in list) {
+                    if (!list.hasOwnProperty(pointerId)) {
+                        continue;
+                    }
+                    var lastControlOver = list[pointerId];
+                    if (lastControlOver === control) {
+                        delete list[pointerId];
+                    }
+                }
+            };
+            AdvancedDynamicTexture.prototype._cleanControlAfterRemoval = function (control) {
+                this._cleanControlAfterRemovalFromList(this._lastControlDown, control);
+                this._cleanControlAfterRemovalFromList(this._lastControlOver, control);
+            };
             AdvancedDynamicTexture.prototype.attach = function () {
                 var _this = this;
                 var scene = this.getScene();
@@ -2083,6 +2098,9 @@ var BABYLON;
                     control.parent = null;
                 }
                 control.linkWithMesh(null);
+                if (this._host) {
+                    this._host._cleanControlAfterRemoval(control);
+                }
                 this._markAsDirty();
                 return this;
             };

Diferenças do arquivo suprimidas por serem muito extensas
+ 4 - 4
dist/preview release/gui/babylon.gui.min.js


+ 4 - 0
dist/preview release/gui/babylon.gui.module.d.ts

@@ -63,6 +63,10 @@ declare module BABYLON.GUI {
         private _checkUpdate(camera);
         private _render();
         private _doPicking(x, y, type, pointerId, buttonIndex);
+        _cleanControlAfterRemovalFromList(list: {
+            [pointerId: number]: Control;
+        }, control: Control): void;
+        _cleanControlAfterRemoval(control: Control): void;
         attach(): void;
         attachToMesh(mesh: AbstractMesh, supportPointerMove?: boolean): void;
         moveFocusToControl(control: IFocusableControl): void;

Diferenças do arquivo suprimidas por serem muito extensas
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 0 - 7
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -191,13 +191,6 @@ declare module BABYLON.GLTF2 {
     class ArrayItem {
         static Assign(values?: IArrayItem[]): void;
     }
-    class AnimationMultiTarget {
-        subTargets: any[];
-        position: Vector3;
-        rotationQuaternion: Quaternion;
-        scaling: Vector3;
-        influence: number;
-    }
 }
 
 

+ 4 - 57
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -491,53 +491,6 @@ var BABYLON;
             return ArrayItem;
         }());
         GLTF2.ArrayItem = ArrayItem;
-        var AnimationMultiTarget = /** @class */ (function () {
-            function AnimationMultiTarget() {
-                this.subTargets = new Array();
-            }
-            Object.defineProperty(AnimationMultiTarget.prototype, "position", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.position = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "rotationQuaternion", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.rotationQuaternion = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "scaling", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.scaling = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "influence", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.influence = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            return AnimationMultiTarget;
-        }());
-        GLTF2.AnimationMultiTarget = AnimationMultiTarget;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
@@ -1339,12 +1292,11 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            var multiTarget = new GLTF2.AnimationMultiTarget();
+                            var morphTargets = new Array();
                             _this._forEachPrimitive(targetNode, function (babylonMesh) {
-                                var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
-                                multiTarget.subTargets.push(morphTarget);
+                                morphTargets.push(babylonMesh.morphTargetManager.getTarget(targetIndex));
                             });
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, multiTarget);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTargets);
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -1355,12 +1307,7 @@ var BABYLON;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
                         if (targetNode._babylonAnimationTargets) {
-                            var multiTarget = new GLTF2.AnimationMultiTarget();
-                            for (var _i = 0, _a = targetNode._babylonAnimationTargets; _i < _a.length; _i++) {
-                                var target = _a[_i];
-                                multiTarget.subTargets.push(target);
-                            }
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, multiTarget);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonAnimationTargets);
                         }
                     }
                 });

Diferenças do arquivo suprimidas por serem muito extensas
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 0 - 7
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -747,13 +747,6 @@ declare module BABYLON.GLTF2 {
     class ArrayItem {
         static Assign(values?: IArrayItem[]): void;
     }
-    class AnimationMultiTarget {
-        subTargets: any[];
-        position: Vector3;
-        rotationQuaternion: Quaternion;
-        scaling: Vector3;
-        influence: number;
-    }
 }
 
 

+ 4 - 57
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2689,53 +2689,6 @@ var BABYLON;
             return ArrayItem;
         }());
         GLTF2.ArrayItem = ArrayItem;
-        var AnimationMultiTarget = /** @class */ (function () {
-            function AnimationMultiTarget() {
-                this.subTargets = new Array();
-            }
-            Object.defineProperty(AnimationMultiTarget.prototype, "position", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.position = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "rotationQuaternion", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.rotationQuaternion = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "scaling", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.scaling = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "influence", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.influence = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            return AnimationMultiTarget;
-        }());
-        GLTF2.AnimationMultiTarget = AnimationMultiTarget;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
@@ -3537,12 +3490,11 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            var multiTarget = new GLTF2.AnimationMultiTarget();
+                            var morphTargets = new Array();
                             _this._forEachPrimitive(targetNode, function (babylonMesh) {
-                                var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
-                                multiTarget.subTargets.push(morphTarget);
+                                morphTargets.push(babylonMesh.morphTargetManager.getTarget(targetIndex));
                             });
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, multiTarget);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTargets);
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -3553,12 +3505,7 @@ var BABYLON;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
                         if (targetNode._babylonAnimationTargets) {
-                            var multiTarget = new GLTF2.AnimationMultiTarget();
-                            for (var _i = 0, _a = targetNode._babylonAnimationTargets; _i < _a.length; _i++) {
-                                var target = _a[_i];
-                                multiTarget.subTargets.push(target);
-                            }
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, multiTarget);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonAnimationTargets);
                         }
                     }
                 });

Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 0 - 7
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -842,13 +842,6 @@ declare module BABYLON.GLTF2 {
     class ArrayItem {
         static Assign(values?: IArrayItem[]): void;
     }
-    class AnimationMultiTarget {
-        subTargets: any[];
-        position: Vector3;
-        rotationQuaternion: Quaternion;
-        scaling: Vector3;
-        influence: number;
-    }
 }
 
 

+ 4 - 57
dist/preview release/loaders/babylonjs.loaders.js

@@ -3668,53 +3668,6 @@ var BABYLON;
             return ArrayItem;
         }());
         GLTF2.ArrayItem = ArrayItem;
-        var AnimationMultiTarget = /** @class */ (function () {
-            function AnimationMultiTarget() {
-                this.subTargets = new Array();
-            }
-            Object.defineProperty(AnimationMultiTarget.prototype, "position", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.position = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "rotationQuaternion", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.rotationQuaternion = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "scaling", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.scaling = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            Object.defineProperty(AnimationMultiTarget.prototype, "influence", {
-                set: function (value) {
-                    for (var _i = 0, _a = this.subTargets; _i < _a.length; _i++) {
-                        var subTarget = _a[_i];
-                        subTarget.influence = value;
-                    }
-                },
-                enumerable: true,
-                configurable: true
-            });
-            return AnimationMultiTarget;
-        }());
-        GLTF2.AnimationMultiTarget = AnimationMultiTarget;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
@@ -4516,12 +4469,11 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            var multiTarget = new GLTF2.AnimationMultiTarget();
+                            var morphTargets = new Array();
                             _this._forEachPrimitive(targetNode, function (babylonMesh) {
-                                var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
-                                multiTarget.subTargets.push(morphTarget);
+                                morphTargets.push(babylonMesh.morphTargetManager.getTarget(targetIndex));
                             });
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, multiTarget);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTargets);
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -4532,12 +4484,7 @@ var BABYLON;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
                         if (targetNode._babylonAnimationTargets) {
-                            var multiTarget = new GLTF2.AnimationMultiTarget();
-                            for (var _i = 0, _a = targetNode._babylonAnimationTargets; _i < _a.length; _i++) {
-                                var target = _a[_i];
-                                multiTarget.subTargets.push(target);
-                            }
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, multiTarget);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonAnimationTargets);
                         }
                     }
                 });

Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


+ 0 - 7
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -849,13 +849,6 @@ declare module BABYLON.GLTF2 {
     class ArrayItem {
         static Assign(values?: IArrayItem[]): void;
     }
-    class AnimationMultiTarget {
-        subTargets: any[];
-        position: Vector3;
-        rotationQuaternion: Quaternion;
-        scaling: Vector3;
-        influence: number;
-    }
 }
 
 

Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 3 - 3
dist/preview release/materialsLibrary/babylonjs.materials.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


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

@@ -1,7 +1,7 @@
 {
-  "errors": 5347,
+  "errors": 5236,
   "babylon.typedoc.json": {
-    "errors": 5347,
+    "errors": 5236,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {
@@ -2168,11 +2168,6 @@
       }
     },
     "Animation": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
       "Constructor": {
         "new Animation": {
           "Comments": {
@@ -4705,15 +4700,6 @@
             }
           }
         },
-        "setScale": {
-          "Parameter": {
-            "y": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "updateMatrix": {
           "Comments": {
             "MissingText": true
@@ -26633,20 +26619,6 @@
               }
             }
           }
-        },
-        "updateDirectly": {
-          "Parameter": {
-            "data": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "offset": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
         }
       }
     },

Diferenças do arquivo suprimidas por serem muito extensas
+ 64 - 64
dist/preview release/viewer/babylon.viewer.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 383 - 285
dist/preview release/viewer/babylon.viewer.max.js


+ 18 - 0
gui/src/advancedDynamicTexture.ts

@@ -419,6 +419,24 @@ module BABYLON.GUI {
             this._manageFocus();
         }
 
+        public _cleanControlAfterRemovalFromList(list: {[pointerId:number]:Control}, control:Control) {
+            for (var pointerId in list) {
+                if (!list.hasOwnProperty(pointerId)) {
+                    continue;
+                }
+
+                var lastControlOver = list[pointerId];
+                if (lastControlOver === control) {
+                    delete list[pointerId];
+                }
+            }
+        }
+
+        public _cleanControlAfterRemoval(control: Control) {
+            this._cleanControlAfterRemovalFromList(this._lastControlDown, control);
+            this._cleanControlAfterRemovalFromList(this._lastControlOver, control);
+        }
+
         public attach(): void {
             var scene = this.getScene();
             if (!scene) {

+ 4 - 0
gui/src/controls/container.ts

@@ -120,6 +120,10 @@ module BABYLON.GUI {
 
             control.linkWithMesh(null);
 
+            if (this._host) {
+                this._host._cleanControlAfterRemoval(control);
+            }
+
             this._markAsDirty();
             return this;
         }

+ 42 - 57
materialsLibrary/test/addbackground.js

@@ -26,10 +26,19 @@ window.prepareBackgroundMaterial = function() {
 	mirror.mirrorPlane = new BABYLON.Plane(0, -1.0, 0, 0.0);
 	mirror.adaptiveBlurKernel = 64;
 	
+	var perceptualColor = new BABYLON.Color3(1, 1, 1);
+	var primaryColor = new BABYLON.Color3(1, 1, 1);
+
 	registerRangeUI("background", "primaryColorR", 0, 1, function(value) {
 		mirror.clearColor.r = value;
 		back.primaryColor.r = value;
 		backSky.primaryColor.r = value;
+		if (back.perceptualColor) {
+			back.perceptualColor.r = value;
+			backSky.perceptualColor.r = value;
+		}
+		perceptualColor.r = value;
+		primaryColor.r = value;
 	}, function() {
 		return back.primaryColor.r;
 	});
@@ -38,6 +47,12 @@ window.prepareBackgroundMaterial = function() {
 		mirror.clearColor.g = value;
 		back.primaryColor.g = value;
 		backSky.primaryColor.g = value;
+		if (back.perceptualColor) {
+			back.perceptualColor.g = value;
+			backSky.perceptualColor.g = value;
+		}
+		perceptualColor.g = value;
+		primaryColor.g = value;
 	}, function() {
 		return back.primaryColor.g;
 	});
@@ -46,71 +61,28 @@ window.prepareBackgroundMaterial = function() {
 		mirror.clearColor.b = value;
 		back.primaryColor.b = value;
 		backSky.primaryColor.b = value;
+		if (back.perceptualColor) {
+			back.perceptualColor.b = value;
+			backSky.perceptualColor.b = value;
+		}
+		perceptualColor.b = value;
+		primaryColor.b = value;
 	}, function() {
 		return back.primaryColor.b;
 	});
 
-	registerRangeUI("background", "primaryLevel", 0, 30, function(value) {
-		back.primaryLevel = value;
-		backSky.primaryLevel = value;
-	}, function() {
-		return back.primaryLevel;
-	});
-
-	registerRangeUI("background", "secondaryColorR", 0, 1, function(value) {
-		back.secondaryColor.r = value;
-		backSky.secondaryColor.r = value;
-	}, function() {
-		return back.secondaryColor.r;
-	});
-
-	registerRangeUI("background", "secondaryColorG", 0, 1, function(value) {
-		back.secondaryColor.g = value;
-		backSky.secondaryColor.g = value;
-	}, function() {
-		return back.secondaryColor.g;
-	});
-
-	registerRangeUI("background", "secondaryColorB", 0, 1, function(value) {
-		back.secondaryColor.b = value;
-		backSky.secondaryColor.b = value;
-	}, function() {
-		return back.secondaryColor.b;
-	});
-
-	registerRangeUI("background", "secondaryLevel", 0, 30, function(value) {
-		back.secondaryLevel = value;
-		backSky.secondaryLevel = value;
-	}, function() {
-		return back.secondaryLevel;
-	});
-
-	registerRangeUI("background", "tertiaryColorR", 0, 1, function(value) {
-		back.tertiaryColor.r = value;
-		backSky.tertiaryColor.r = value;
+	registerRangeUI("background", "primaryColorShadowLevel", 0, 1, function(value) {
+		back.primaryColorShadowLevel = value;
+		backSky.primaryColorShadowLevel = value;
 	}, function() {
-		return back.tertiaryColor.r;
+		return back.primaryColorShadowLevel;
 	});
 
-	registerRangeUI("background", "tertiaryColorG", 0, 1, function(value) {
-		back.tertiaryColor.g = value;
-		backSky.tertiaryColor.g = value;
+	registerRangeUI("background", "primaryColorHighlightLevel", 0, 1, function(value) {
+		back.primaryColorHighlightLevel = value;		
+		backSky.primaryColorHighlightLevel = value;
 	}, function() {
-		return back.tertiaryColor.g;
-	});
-
-	registerRangeUI("background", "tertiaryColorB", 0, 1, function(value) {
-		back.tertiaryColor.b = value;
-		backSky.tertiaryColor.b = value;
-	}, function() {
-		return back.tertiaryColor.b;
-	});
-
-	registerRangeUI("background", "tertiaryLevel", 0, 30, function(value) {
-		back.tertiaryLevel = value;		
-		backSky.tertiaryLevel = value;
-	}, function() {
-		return back.tertiaryLevel;
+		return back.primaryColorHighlightLevel;
 	});
 
 	registerRangeUI("background", "reflectionBlur", 0, 1, function(value) {
@@ -148,6 +120,19 @@ window.prepareBackgroundMaterial = function() {
 		back.useRGBColor = !back.useRGBColor;
 	});
 
+	registerButtonUI("background", "TogglePerceptualColor", function() {
+		if (back.perceptualColor) {
+			back.perceptualColor = null;
+			backSky.perceptualColor = null;
+			back.primaryColor = primaryColor.clone();
+			backSky.primaryColor = primaryColor.clone();
+		}
+		else {
+			back.perceptualColor = perceptualColor.clone();
+			backSky.perceptualColor = perceptualColor.clone();
+		}
+	});
+
 	registerButtonUI("background", "ToggleSkyRGB", function() {
 		backSky.useRGBColor = !backSky.useRGBColor;
 	});

+ 2 - 1
sandbox/index.html

@@ -22,6 +22,7 @@
     <meta name="msapplication-TileImage" content="http://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
     <meta name="msapplication-config" content="http://www.babylonjs.com/img/favicon/browserconfig.xml">
     <meta name="theme-color" content="#ffffff">
+    <meta name="keywords" content="3D, Babylon.js, webgl, gltf, viewer">
 
     <link href="index.css" rel="stylesheet" />
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
@@ -44,7 +45,7 @@
         <img id="helpArrow" src="./Assets/FlecheTuto.png" />
     </div>
     <div id="help02" class="help2">
-        <span class="helpText">Or directly drag'n'drop your files in the browser</span>
+        <span class="helpText">Or directly drag'n'drop your files (in .babylon, .gltf, .glb, .obj format) in the browser</span>
     </div>
     <div id="footer" class="footer">
         <div class="footerLeft">

+ 1 - 1
src/Animations/babylon.animatable.ts

@@ -65,12 +65,12 @@
 
 
         constructor(scene: Scene, public target: any, public fromFrame: number = 0, public toFrame: number = 100, public loopAnimation: boolean = false, speedRatio: number = 1.0, public onAnimationEnd?: Nullable<() => void>, animations?: any) {
+            this._scene = scene;
             if (animations) {
                 this.appendAnimations(target, animations);
             }
 
             this._speedRatio = speedRatio;
-            this._scene = scene;
             scene._activeAnimatables.push(this);
         }
 

+ 2 - 1
src/Animations/babylon.runtimeAnimation.ts

@@ -15,7 +15,8 @@
         private _scene: Scene;
 
         private _currentValue: any;
-        private _workValue: any;
+        /** @ignore */
+        public _workValue: any;
         private _activeTarget: any;
         private _targetPath: string = "";
         private _weight = 1.0;

+ 0 - 4
src/Bones/babylon.bone.ts

@@ -678,9 +678,7 @@
          * @returns the additional scale of the bone
          */
         public getAdditionalScale(): Vector3 {
-
             return this._scaleVector.clone();
-
         }
 
         /**
@@ -688,9 +686,7 @@
          * @param result The vector3 to copy the additional scale to
          */
         public getAdditionalScaleToRef(result: Vector3): void {
-
             result.copyFrom(this._scaleVector);
-
         }
 
         /**

+ 2 - 2
src/Bones/babylon.boneIKController.ts

@@ -83,8 +83,8 @@ module BABYLON {
             
             if (this._bone1.length) {
 
-                var boneScale1 = this._bone1.getScale();
-                var boneScale2 = this._bone2.getScale();
+                var boneScale1 = this._bone1.getAdditionalScale();
+                var boneScale2 = this._bone2.getAdditionalScale();
                 
                 this._bone1Length = this._bone1.length * boneScale1.y * this.mesh.scaling.y;
                 this._bone2Length = this._bone2.length * boneScale2.y * this.mesh.scaling.y;

+ 49 - 80
src/Engine/babylon.engine.ts

@@ -1013,7 +1013,7 @@
         private _internalTexturesCache = new Array<InternalTexture>();
         /** @ignore */
         protected _activeChannel = 0;
-        private _currentTextureChannel = -1;
+        private _currentTextureChannel = -1;    
         /** @ignore */
         protected _boundTexturesCache: { [key: string]: Nullable<InternalTexture> } = {};
         /** @ignore */
@@ -1662,13 +1662,16 @@
          */
         public resetTextureCache() {
             for (var key in this._boundTexturesCache) {
+                if (!this._boundTexturesCache.hasOwnProperty(key)) {
+                    continue;
+                }
                 let boundTexture = this._boundTexturesCache[key];
                 if (boundTexture) {
                     this._removeDesignatedSlot(boundTexture);
                 }
                 this._boundTexturesCache[key] = null;
-            }
-
+            }       
+            
             if (!this.disableTextureBindingOptimization) {
                 this._nextFreeTextureSlots = [];
                 for (let slot = 0; slot < this._maxSimultaneousTextures; slot++) {
@@ -4457,22 +4460,16 @@
             var filters = getSamplingParameters(samplingMode, texture.generateMipMaps, this._gl);
 
             if (texture.isCube) {
-                this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, texture, true);
-
-                this._gl.texParameteri(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_MAG_FILTER, filters.mag);
-                this._gl.texParameteri(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_MIN_FILTER, filters.min);
+                this._setTextureParameterInteger(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_MAG_FILTER, filters.mag, texture);
+                this._setTextureParameterInteger(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_MIN_FILTER, filters.min);
                 this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
             } else if (texture.is3D) {
-                this._bindTextureDirectly(this._gl.TEXTURE_3D, texture, true);
-
-                this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
-                this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_MIN_FILTER, filters.min);
+                this._setTextureParameterInteger(this._gl.TEXTURE_3D, this._gl.TEXTURE_MAG_FILTER, filters.mag, texture);
+                this._setTextureParameterInteger(this._gl.TEXTURE_3D, this._gl.TEXTURE_MIN_FILTER, filters.min);
                 this._bindTextureDirectly(this._gl.TEXTURE_3D, null);
             } else {
-                this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-
-                this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
-                this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
+                this._setTextureParameterInteger(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag, texture);
+                this._setTextureParameterInteger(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
                 this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
             }
 
@@ -6217,7 +6214,7 @@
         }
 
         /** @ignore */
-        protected _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>, forTextureDataUpdate = false): void {
+        protected _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>, forTextureDataUpdate = false, force = false): void {
             if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
                 this._activeChannel = texture._designatedSlot;
             }
@@ -6225,7 +6222,7 @@
             let currentTextureBound = this._boundTexturesCache[this._activeChannel];
             let isTextureForRendering = texture && texture._initialSlot > -1;
 
-            if (currentTextureBound !== texture) {
+            if (currentTextureBound !== texture || force) {
                 if (currentTextureBound) {
                     this._removeDesignatedSlot(currentTextureBound);
                 }
@@ -6353,6 +6350,18 @@
             uniform._currentState = destination;
         }
 
+        private _getTextureWrapMode(mode: number): number {
+            switch(mode) {
+                case Texture.WRAP_ADDRESSMODE:
+                    return this._gl.REPEAT;
+                case Texture.CLAMP_ADDRESSMODE:
+                    return this._gl.CLAMP_TO_EDGE;
+                case Texture.MIRROR_ADDRESSMODE:
+                    return this._gl.MIRRORED_REPEAT;
+            }
+            return this._gl.REPEAT;
+        }
+
         private _setTexture(channel: number, texture: Nullable<BaseTexture>, isPartOfTextureArray = false, depthStencilTexture = false): boolean {
             // Not ready?
             if (!texture) {
@@ -6403,6 +6412,7 @@
                 if (!isPartOfTextureArray) {
                     this._bindSamplerUniformToChannel(internalTexture._initialSlot, channel);
                 }
+                
                 needToBind = false;
             }
 
@@ -6415,48 +6425,17 @@
 
                 if (internalTexture && internalTexture._cachedWrapU !== texture.wrapU) {
                     internalTexture._cachedWrapU = texture.wrapU;
-
-                    switch (texture.wrapU) {
-                        case Texture.WRAP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_S, this._gl.REPEAT);
-                            break;
-                        case Texture.CLAMP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_S, this._gl.CLAMP_TO_EDGE);
-                            break;
-                        case Texture.MIRROR_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_S, this._gl.MIRRORED_REPEAT);
-                            break;
-                    }
+                    this._setTextureParameterInteger(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_S, this._getTextureWrapMode(texture.wrapU), internalTexture);
                 }
 
                 if (internalTexture && internalTexture._cachedWrapV !== texture.wrapV) {
                     internalTexture._cachedWrapV = texture.wrapV;
-                    switch (texture.wrapV) {
-                        case Texture.WRAP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_T, this._gl.REPEAT);
-                            break;
-                        case Texture.CLAMP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_T, this._gl.CLAMP_TO_EDGE);
-                            break;
-                        case Texture.MIRROR_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_T, this._gl.MIRRORED_REPEAT);
-                            break;
-                    }
+                    this._setTextureParameterInteger(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_T, this._getTextureWrapMode(texture.wrapV), internalTexture);
                 }
 
                 if (internalTexture && internalTexture._cachedWrapR !== texture.wrapR) {
                     internalTexture._cachedWrapR = texture.wrapR;
-                    switch (texture.wrapR) {
-                        case Texture.WRAP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_R, this._gl.REPEAT);
-                            break;
-                        case Texture.CLAMP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_R, this._gl.CLAMP_TO_EDGE);
-                            break;
-                        case Texture.MIRROR_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_R, this._gl.MIRRORED_REPEAT);
-                            break;
-                    }
+                    this._setTextureParameterInteger(this._gl.TEXTURE_3D, this._gl.TEXTURE_WRAP_R, this._getTextureWrapMode(texture.wrapR), internalTexture);
                 }
 
                 this._setAnisotropicLevel(this._gl.TEXTURE_3D, texture);
@@ -6464,14 +6443,14 @@
             else if (internalTexture && internalTexture.isCube) {
                 if (needToBind) {
                     this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, internalTexture, isPartOfTextureArray);
-                }
+                }                
 
                 if (internalTexture._cachedCoordinatesMode !== texture.coordinatesMode) {
                     internalTexture._cachedCoordinatesMode = texture.coordinatesMode;
                     // CUBIC_MODE and SKYBOX_MODE both require CLAMP_TO_EDGE.  All other modes use REPEAT.
                     var textureWrapMode = (texture.coordinatesMode !== Texture.CUBIC_MODE && texture.coordinatesMode !== Texture.SKYBOX_MODE) ? this._gl.REPEAT : this._gl.CLAMP_TO_EDGE;
-                    this._gl.texParameteri(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_WRAP_S, textureWrapMode);
-                    this._gl.texParameteri(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_WRAP_T, textureWrapMode);
+                    this._setTextureParameterInteger(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_WRAP_S, textureWrapMode, internalTexture);
+                    this._setTextureParameterInteger(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_WRAP_T, textureWrapMode);
                 }
 
                 this._setAnisotropicLevel(this._gl.TEXTURE_CUBE_MAP, texture);
@@ -6482,33 +6461,12 @@
 
                 if (internalTexture && internalTexture._cachedWrapU !== texture.wrapU) {
                     internalTexture._cachedWrapU = texture.wrapU;
-
-                    switch (texture.wrapU) {
-                        case Texture.WRAP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.REPEAT);
-                            break;
-                        case Texture.CLAMP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.CLAMP_TO_EDGE);
-                            break;
-                        case Texture.MIRROR_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.MIRRORED_REPEAT);
-                            break;
-                    }
+                    this._setTextureParameterInteger(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._getTextureWrapMode(texture.wrapU), internalTexture);
                 }
 
                 if (internalTexture && internalTexture._cachedWrapV !== texture.wrapV) {
                     internalTexture._cachedWrapV = texture.wrapV;
-                    switch (texture.wrapV) {
-                        case Texture.WRAP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_T, this._gl.REPEAT);
-                            break;
-                        case Texture.CLAMP_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_T, this._gl.CLAMP_TO_EDGE);
-                            break;
-                        case Texture.MIRROR_ADDRESSMODE:
-                            this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_T, this._gl.MIRRORED_REPEAT);
-                            break;
-                    }
+                    this._setTextureParameterInteger(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_T, this._getTextureWrapMode(texture.wrapV), internalTexture);
                 }
 
                 this._setAnisotropicLevel(this._gl.TEXTURE_2D, texture);
@@ -6542,7 +6500,7 @@
         }
 
         /** @ignore */
-        public _setAnisotropicLevel(key: number, texture: BaseTexture) {
+        public _setAnisotropicLevel(target: number, texture: BaseTexture) {
             var internalTexture = texture.getInternalTexture();
 
             if (!internalTexture) {
@@ -6552,7 +6510,6 @@
             var anisotropicFilterExtension = this._caps.textureAnisotropicFilterExtension;
             var value = texture.anisotropicFilteringLevel;
 
-
             if (internalTexture.samplingMode !== Texture.LINEAR_LINEAR_MIPNEAREST
                 && internalTexture.samplingMode !== Texture.LINEAR_LINEAR_MIPLINEAR
                 && internalTexture.samplingMode !== Texture.LINEAR_LINEAR) {
@@ -6560,11 +6517,23 @@
             }
 
             if (anisotropicFilterExtension && internalTexture._cachedAnisotropicFilteringLevel !== value) {
-                this._gl.texParameterf(key, anisotropicFilterExtension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(value, this._caps.maxAnisotropy));
+                this._setTextureParameterFloat(target, anisotropicFilterExtension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(value, this._caps.maxAnisotropy), internalTexture);
                 internalTexture._cachedAnisotropicFilteringLevel = value;
             }
         }
 
+        private _setTextureParameterFloat(target: number, parameter: number, value: number, texture: InternalTexture): void {
+            this._bindTextureDirectly(target, texture, true, true);
+            this._gl.texParameterf(target, parameter, value);
+        }
+
+        private _setTextureParameterInteger(target: number, parameter: number, value: number, texture?: InternalTexture) {
+            if (texture) {
+                this._bindTextureDirectly(target, texture, true, true);
+            }
+            this._gl.texParameteri(target, parameter, value);
+        }
+
         /**
          * Reads pixels from the current frame buffer. Please note that this function can be slow
          * @param x defines the x coordinate of the rectangle where pixels must be read

+ 24 - 11
src/Helpers/babylon.environmentHelper.ts

@@ -395,19 +395,38 @@ module BABYLON {
 
         /**
          * Sets the primary color of all the available elements.
-         * @param color 
+         * @param color the main color to affect to the ground and the background
+         * @param perceptual Specifies wether the chosen color has been set as intented to be seen e.g. in gamma space not accounting for exposure and tone mapping
          */
-        public setMainColor(color: Color3): void {
+        public setMainColor(color: Color3, perceptual = false): void {
             if (this.groundMaterial) {
-                this.groundMaterial.primaryColor = color;
+                if (perceptual) {
+                    this.groundMaterial.perceptualColor = color;
+                }
+                else {
+                    this.groundMaterial.primaryColor = color;
+                }
             }
 
             if (this.skyboxMaterial) {
-                this.skyboxMaterial.primaryColor = color;
+                if (perceptual) {
+                    this.skyboxMaterial.perceptualColor = color;
+                }
+                else {
+                    this.skyboxMaterial.primaryColor = color;
+                }
             }
 
             if (this.groundMirror) {
-                this.groundMirror.clearColor = new Color4(color.r, color.g, color.b, 1.0);
+                if (perceptual && this.groundMaterial) {
+                    this.groundMirror.clearColor = new Color4(this.groundMaterial.primaryColor.r, 
+                        this.groundMaterial.primaryColor.g, 
+                        this.groundMaterial.primaryColor.b, 
+                        1.0);
+                }
+                else {
+                    this.groundMirror.clearColor = new Color4(color.r, color.g, color.b, 1.0);
+                }
             }
         }
 
@@ -535,10 +554,7 @@ module BABYLON {
             this._groundMaterial.alpha = this._options.groundOpacity;
             this._groundMaterial.alphaMode = Engine.ALPHA_PREMULTIPLIED_PORTERDUFF;
             this._groundMaterial.shadowLevel = this._options.groundShadowLevel;
-            this._groundMaterial.primaryLevel = 1;
             this._groundMaterial.primaryColor = this._options.groundColor;
-            this._groundMaterial.secondaryLevel = 0;
-            this._groundMaterial.tertiaryLevel = 0;
             this._groundMaterial.useRGBColor = false;
             this._groundMaterial.enableNoise = true;
 
@@ -645,10 +661,7 @@ module BABYLON {
                 this._skyboxMaterial = new BackgroundMaterial("BackgroundSkyboxMaterial", this._scene);
             }
             this._skyboxMaterial.useRGBColor = false;
-            this._skyboxMaterial.primaryLevel = 1;
             this._skyboxMaterial.primaryColor = this._options.skyboxColor;
-            this._skyboxMaterial.secondaryLevel = 0;
-            this._skyboxMaterial.tertiaryLevel = 0;
             this._skyboxMaterial.enableNoise = true;
 
             this._skybox.material = this._skyboxMaterial;

+ 128 - 43
src/Materials/Background/babylon.backgroundMaterial.ts

@@ -60,6 +60,12 @@
         public USERGBCOLOR = false;
 
         /**
+         * True if highlight and shadow levels have been specified. It can help ensuring the main perceived color
+         * stays aligned with the desired configuration.
+         */
+        public USEHIGHLIGHTANDSHADOWCOLORS = false;
+
+        /**
          * True to add noise in order to reduce the banding effect.
          */
         public NOISE = false;
@@ -143,49 +149,60 @@
         @serializeAsColor3()
         protected _primaryColor: Color3;
         /**
-         * Key light Color (multiply against the R channel of the environement texture)
+         * Key light Color (multiply against the environement texture)
          */
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
         public primaryColor = Color3.White();
-
-        @serialize()
-        protected _primaryLevel: float;
-        /**
-         * Key light Level (allowing HDR output of the background)
-         */
-        @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public primaryLevel: float = 1;
+        
         @serializeAsColor3()
-        protected _secondaryColor: Color3;
+        protected _perceptualColor: Nullable<Color3>;
         /**
-         * Secondary light Color (multiply against the G channel of the environement texture)
+         * Key light Color in "perceptual value" meaning the color you would like to see on screen.
+         * This acts as a helper to set the primary color to a more "human friendly" value.
+         * Conversion to linear space as well as exposure and tone mapping correction will be applied to keep the
+         * output color as close as possible from the chosen value.
+         * (This does not account for contrast color grading and color curves as they are considered post effect and not directly
+         * part of lighting setup.)
          */
-        @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public secondaryColor = Color3.Gray();
+        public get perceptualColor(): Nullable<Color3> {
+            return this._perceptualColor;
+        }
+        public set perceptualColor(value: Nullable<Color3>) {
+            this._perceptualColor = value;
+            this._computePrimaryColorFromPerceptualColor();
+            this._markAllSubMeshesAsLightsDirty();
+        }
 
         @serialize()
-        protected _secondaryLevel: float;
-        /**
-         * Secondary light Level (allowing HDR output of the background)
-         */
-        @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public secondaryLevel: float = 1;
-
-        @serializeAsColor3()
-        protected _tertiaryColor: Color3;
+        protected _primaryColorShadowLevel: float = 0;
         /**
-         * Tertiary light Color (multiply against the B channel of the environement texture)
+         * Defines the level of the shadows (dark area of the reflection map) in order to help scaling the colors.
+         * The color opposite to the primary color is used at the level chosen to define what the black area would look.
          */
-        @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public tertiaryColor = Color3.Black();
+        public get primaryColorShadowLevel(): float {
+            return this._primaryColorShadowLevel;
+        }
+        public set primaryColorShadowLevel(value: float) {
+            this._primaryColorShadowLevel = value;
+            this._computePrimaryColors();
+            this._markAllSubMeshesAsLightsDirty();
+        }
 
         @serialize()
-        protected _tertiaryLevel: float;
+        protected _primaryColorHighlightLevel: float = 0;
         /**
-         * Tertiary light Level (allowing HDR output of the background)
+         * Defines the level of the highliights (highlight area of the reflection map) in order to help scaling the colors.
+         * The primary color is used at the level chosen to define what the white area would look.
          */
         @expandToProperty("_markAllSubMeshesAsLightsDirty")
-        public tertiaryLevel: float = 1;
+        public get primaryColorHighlightLevel(): float {
+            return this._primaryColorHighlightLevel;
+        }
+        public set primaryColorHighlightLevel(value: float) {
+            this._primaryColorHighlightLevel = value;
+            this._computePrimaryColors();
+            this._markAllSubMeshesAsLightsDirty();
+        }
 
         @serializeAsTexture()
         protected _reflectionTexture: Nullable<BaseTexture>;
@@ -225,15 +242,6 @@
         public shadowLights: Nullable<IShadowLight[]> = null;
 
         @serialize()
-        protected _shadowBlurScale: int;
-        /**
-         * For the lights having a blurred shadow generator, this can add a second blur pass in order to reach
-         * soft lighting on the background.
-         */
-        @expandToProperty("_markAllSubMeshesAsTexturesDirty")
-        public shadowBlurScale: int = 1;
-
-        @serialize()
         protected _shadowLevel: float;
         /**
          * Helps adjusting the shadow to a softer level if required.
@@ -400,6 +408,7 @@
 
             // Attaches observer.
             this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(conf => {
+                this._computePrimaryColorFromPerceptualColor();
                 this._markAllSubMeshesAsImageProcessingDirty();
             });
         }
@@ -534,6 +543,9 @@
         // Temp values kept as cache in the material.
         private _renderTargets = new SmartArray<RenderTargetTexture>(16);
         private _reflectionControls = Vector4.Zero();
+        private _white = Color3.White();
+        private _primaryShadowColor = Color3.Black();
+        private _primaryHighlightColor = Color3.Black();
 
         /**
          * Instantiates a Background Material in the given scene
@@ -723,6 +735,10 @@
                 defines.NOISE = this._enableNoise;
             }
 
+            if (defines._areLightsDirty) {
+                defines.USEHIGHLIGHTANDSHADOWCOLORS = !this._useRGBColor && (this._primaryColorShadowLevel !== 0 || this._primaryColorHighlightLevel !== 0);
+            }
+
             if (defines._areImageProcessingDirty) {
                 if (!this._imageProcessingConfiguration.isReady()) {
                     return false;
@@ -790,7 +806,7 @@
                     "vFogInfos", "vFogColor", "pointSize",
                     "vClipPlane", "mBones",
 
-                    "vPrimaryColor", "vSecondaryColor", "vTertiaryColor",
+                    "vPrimaryColor", "vPrimaryColorShadow",
                     "vReflectionInfos", "reflectionMatrix", "vReflectionMicrosurfaceInfos", "fFovMultiplier",
 
                     "shadowLevel", "alpha",
@@ -849,13 +865,78 @@
         }
 
         /**
+         * Tone Mapping calibration (should match image processing tone mapping calibration value).
+         */
+        private static readonly _tonemappingCalibration = 1.590579;
+
+        /**
+         * Compute the primary color according to the chosen perceptual color.
+         */
+        private _computePrimaryColorFromPerceptualColor(): void {
+            if (!this._perceptualColor) {
+                return;
+            }
+
+            this._primaryColor.copyFrom(this._perceptualColor);
+
+            // Revert gamma space.
+            this._primaryColor.toLinearSpaceToRef(this._primaryColor);
+
+            // Revert image processing configuration.
+            if (this._imageProcessingConfiguration) {
+                // Revert tone mapping.
+                if (this._imageProcessingConfiguration.toneMappingEnabled) {
+                    // shader reference.
+                    // tonemapped.rgb = 1.0 - exp2(-tonemappingCalibration * color.rgb);
+                    // providing
+                    // log2(1.0 - tonemapped.rgb) / -tonemappingCalibration = color.rgb;
+
+                    // 1.0 - tonemapped.rgb
+                    this._white.subtractToRef(this._primaryColor, this._primaryColor);
+
+                    // log2(1.0 - tonemapped.rgb)
+                    this._primaryColor.r = Scalar.Log2(this._primaryColor.r);
+                    this._primaryColor.g = Scalar.Log2(this._primaryColor.g);
+                    this._primaryColor.b = Scalar.Log2(this._primaryColor.b);
+                    
+                    // log2(1.0 - tonemapped.rgb) / -tonemappingCalibration
+                    this._primaryColor.scaleToRef(-1 / BackgroundMaterial._tonemappingCalibration, this._primaryColor);
+                }
+
+                // Revert Exposure.
+                this._primaryColor.scaleToRef(1 / this._imageProcessingConfiguration.exposure, this._primaryColor);
+            }
+
+            this._computePrimaryColors();
+        }
+
+        /**
+         * Compute the highlights and shadow colors according to their chosen levels.
+         */
+        private _computePrimaryColors(): void {
+            if (this._primaryColorShadowLevel === 0 && this._primaryColorHighlightLevel === 0) {
+                return;
+            }
+
+            // Find the highlight color based on the configuration.
+            this._primaryColor.scaleToRef(this._primaryColorShadowLevel, this._primaryShadowColor);
+            this._primaryColor.subtractToRef(this._primaryShadowColor, this._primaryShadowColor);
+            this._primaryShadowColor.clampToRef(0, 1, this._primaryShadowColor);
+
+            // Find the shadow color based on the configuration.
+            this._white.subtractToRef(this._primaryColor, this._primaryHighlightColor);
+            this._primaryHighlightColor.scaleToRef(this._primaryColorHighlightLevel, this._primaryHighlightColor);
+            this._primaryColor.addToRef(this._primaryHighlightColor, this._primaryHighlightColor);
+            this._primaryHighlightColor.clampToRef(0, 1, this._primaryHighlightColor);
+        }
+
+        /**
          * Build the uniform buffer used in the material.
          */
         public buildUniformLayout(): void {
             // Order is important !
             this._uniformBuffer.addUniform("vPrimaryColor", 4);
-            this._uniformBuffer.addUniform("vSecondaryColor", 4);
-            this._uniformBuffer.addUniform("vTertiaryColor", 4);
+            this._uniformBuffer.addUniform("vPrimaryColorShadow", 4);
             this._uniformBuffer.addUniform("vDiffuseInfos", 2);
             this._uniformBuffer.addUniform("vReflectionInfos", 2);
             this._uniformBuffer.addUniform("diffuseMatrix", 16);
@@ -956,9 +1037,13 @@
                         this._uniformBuffer.updateFloat("pointSize", this.pointSize);
                     }
 
-                    this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryColor, this._primaryLevel);
-                    this._uniformBuffer.updateColor4("vSecondaryColor", this._secondaryColor, this._secondaryLevel);
-                    this._uniformBuffer.updateColor4("vTertiaryColor", this._tertiaryColor, this._tertiaryLevel);
+                    if (defines.USEHIGHLIGHTANDSHADOWCOLORS) {
+                        this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryHighlightColor, 1.0);
+                        this._uniformBuffer.updateColor4("vPrimaryColorShadow", this._primaryShadowColor, 1.0);
+                    }
+                    else {
+                        this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryColor, 1.0);
+                    }
                 }
 
                 this._uniformBuffer.updateFloat("fFovMultiplier", this._fovMultiplier);

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

@@ -94,7 +94,9 @@
             this.ignoreCameraViewport = true;
             
             this._updateGammaSpace();
-            this._imageProcessingConfigChangeObserver = scene.imageProcessingConfiguration.onUpdateParameters.add(this._updateGammaSpace)
+            this._imageProcessingConfigChangeObserver = scene.imageProcessingConfiguration.onUpdateParameters.add(() => {
+                this._updateGammaSpace
+            });
 
             this.onBeforeRenderObservable.add(() => {
                 Matrix.ReflectionToRef(this.mirrorPlane, this._mirrorMatrix);

+ 16 - 1
src/Math/babylon.math.ts

@@ -3223,6 +3223,7 @@
         public subtract(other: Quaternion): Quaternion {
             return new Quaternion(this.x - other.x, this.y - other.y, this.z - other.z, this.w - other.w);
         }
+
         /**
          * Multiplies the current quaternion by a scale factor
          * @param value defines the scale factor
@@ -3244,7 +3245,21 @@
             result.z = this.z * scale;
             result.w = this.w * scale;
             return this;
-        }         
+        }    
+        
+        /**
+         * Multiplies in place the current quaternion by a scale factor
+         * @param value defines the scale factor
+         * @returns the current modified quaternion
+         */
+        public scaleInPlace(value: number): Quaternion {
+            this.x *= value;
+            this.y *= value;
+            this.z *= value;
+            this.w *= value;
+            
+            return this;
+        }
 
         /**
          * Scale the current quaternion values by a factor and add the result to a given quaternion  

+ 3 - 2
src/Shaders/ShadersInclude/backgroundFragmentDeclaration.fx

@@ -1,6 +1,7 @@
     uniform vec4 vPrimaryColor;
-    uniform vec4 vSecondaryColor;
-    uniform vec4 vTertiaryColor;
+#ifdef USEHIGHLIGHTANDSHADOWCOLORS
+    uniform vec4 vPrimaryColorShadow;
+#endif
     uniform float shadowLevel;
     uniform float alpha;
 

+ 1 - 2
src/Shaders/ShadersInclude/backgroundUboDeclaration.fx

@@ -3,8 +3,7 @@ layout(std140, column_major) uniform;
 uniform Material
 {
 	uniform vec4 vPrimaryColor;
-	uniform vec4 vSecondaryColor;
-	uniform vec4 vTertiaryColor;
+	uniform vec4 vPrimaryColorShadow;
 	uniform vec2 vDiffuseInfos;
 	uniform vec2 vReflectionInfos;
 	uniform mat4 diffuseMatrix;

+ 7 - 3
src/Shaders/background.fragment.fx

@@ -229,9 +229,13 @@ float finalAlpha = alpha;
 #ifdef USERGBCOLOR
     vec3 finalColor = colorBase;
 #else
-    vec3 finalColor = colorBase.r * vPrimaryColor.rgb * vPrimaryColor.a;
-    finalColor += colorBase.g * vSecondaryColor.rgb * vSecondaryColor.a;
-    finalColor += colorBase.b * vTertiaryColor.rgb * vTertiaryColor.a;
+    #ifdef USEHIGHLIGHTANDSHADOWCOLORS
+        vec3 mainColor = mix(vPrimaryColorShadow.rgb, vPrimaryColor.rgb, colorBase);
+    #else
+        vec3 mainColor = vPrimaryColor.rgb;
+    #endif
+
+    vec3 finalColor = colorBase * mainColor;
 #endif
 
 // ___________________________ FRESNELS _______________________________________

+ 81 - 30
src/babylon.scene.ts

@@ -2685,6 +2685,54 @@
             target._lateAnimationHolders[runtimeAnimation.targetPath].totalWeight += runtimeAnimation.weight;
         }
 
+        private _processLateAnimationBindingsForMatrices(holder: {
+            totalWeight: number,
+            animations: RuntimeAnimation[]
+        }, originalValue: Matrix): any {
+            let normalizer = 1.0;
+            let finalPosition = Tmp.Vector3[0];
+            let finalScaling = Tmp.Vector3[1];
+            let finalQuaternion = Tmp.Quaternion[0];
+            let startIndex = 0;            
+            let originalAnimation = holder.animations[0];
+
+            var scale = 1;
+            if (holder.totalWeight < 1.0) {
+                // We need to mix the original value in                     
+                originalValue.decompose(finalScaling, finalQuaternion, finalPosition);
+                scale = 1.0 - holder.totalWeight;
+            } else {
+                startIndex = 1;            
+                // We need to normalize the weights
+                normalizer = holder.totalWeight;
+                originalAnimation.currentValue.decompose(finalScaling, finalQuaternion, finalPosition);
+                scale = originalAnimation.weight / normalizer;
+                if (scale == 1) {
+                    return originalAnimation.currentValue;
+                }
+            }
+
+            finalScaling.scaleInPlace(scale);
+            finalPosition.scaleInPlace(scale);
+            finalQuaternion.scaleInPlace(scale);
+
+            for (var animIndex = startIndex; animIndex < holder.animations.length; animIndex++) {
+                var runtimeAnimation = holder.animations[animIndex];   
+                var scale = runtimeAnimation.weight / normalizer;
+                let currentPosition = Tmp.Vector3[2];
+                let currentScaling = Tmp.Vector3[3];
+                let currentQuaternion = Tmp.Quaternion[1];
+
+                runtimeAnimation.currentValue.decompose(currentScaling, currentQuaternion, currentPosition);
+                currentScaling.scaleAndAddToRef(scale, finalScaling);
+                currentQuaternion.scaleAndAddToRef(scale, finalQuaternion);
+                currentPosition.scaleAndAddToRef(scale, finalPosition);
+            }  
+            
+            Matrix.ComposeToRef(finalScaling, finalQuaternion, finalPosition, originalAnimation._workValue);
+            return originalAnimation._workValue;
+        }
+
         private _processLateAnimationBindings(): void {
             if (!this._registeredForLateAnimationBindings.length) {
                 return;
@@ -2694,52 +2742,55 @@
 
                 for (var path in target._lateAnimationHolders) {
                     var holder = target._lateAnimationHolders[path];                     
-                    let originalValue = holder.animations[0].originalValue;      
+                    let originalAnimation = holder.animations[0];
+                    let originalValue = originalAnimation.originalValue;
+                    let finalTarget = originalAnimation.target;   
                     
-                    // Sanity check
-                    if (!originalValue.scaleAndAddToRef) {
-                        continue;
-                    }
-
                     let matrixDecomposeMode = Animation.AllowMatrixDecomposeForInterpolation && originalValue.m; // ie. data is matrix
-                    let normalizer = 1.0;
-                    let finalValue: any;
 
-                    if (holder.totalWeight < 1.0) {
-                        // We need to mix the original value in     
-                        if (matrixDecomposeMode) {
-                            finalValue = originalValue.clone();
-                        } else {            
-                            finalValue = originalValue.scale(1.0 - holder.totalWeight)
-                        }
+                    let finalValue: any;
+                    if (matrixDecomposeMode) {
+                        finalValue = this._processLateAnimationBindingsForMatrices(holder, originalValue);
                     } else {
-                        // We need to normalize the weights
-                        normalizer = holder.totalWeight;
-                    }
+                        let startIndex = 0;
+                        let normalizer = 1.0;
 
-                    for (var animIndex = 0; animIndex < holder.animations.length; animIndex++) {
-                        var runtimeAnimation = holder.animations[animIndex];   
-                        var scale = runtimeAnimation.weight / normalizer;
-                        if (finalValue) {
-                            if (matrixDecomposeMode) {
-                                Matrix.DecomposeLerpToRef(finalValue, runtimeAnimation.currentValue, scale, finalValue);
+                        if (holder.totalWeight < 1.0) {
+                            // We need to mix the original value in     
+                            if (originalValue.scale) {
+                                finalValue = originalValue.scale(1.0 - holder.totalWeight);
                             } else {
-                                runtimeAnimation.currentValue.scaleAndAddToRef(scale, finalValue);
+                                finalValue = originalValue * (1.0 - holder.totalWeight);
                             }
                         } else {
+                            // We need to normalize the weights
+                            normalizer = holder.totalWeight;
+                            let scale = originalAnimation.weight / normalizer;
                             if (scale !== 1) {
-                                if (matrixDecomposeMode) {
-                                    finalValue = runtimeAnimation.currentValue.clone();
+                                if (originalAnimation.currentValue.scale) {
+                                    finalValue = originalAnimation.currentValue.scale(scale);
                                 } else {
-                                    finalValue = runtimeAnimation.currentValue.scale(scale);
+                                    finalValue = originalAnimation.currentValue * scale;
                                 }
                             } else {
-                                finalValue = runtimeAnimation.currentValue;
+                                finalValue = originalAnimation.currentValue;
+                            }
+
+                            startIndex = 1;
+                        }
+
+                        for (var animIndex = startIndex; animIndex < holder.animations.length; animIndex++) {
+                            var runtimeAnimation = holder.animations[animIndex];   
+                            var scale = runtimeAnimation.weight / normalizer;
+                            if (runtimeAnimation.currentValue.scaleAndAddToRef) {
+                                runtimeAnimation.currentValue.scaleAndAddToRef(scale, finalValue);
+                            } else {
+                                finalValue += runtimeAnimation.currentValue * scale;
                             }
                         }
                     }
 
-                    runtimeAnimation.target[path] = finalValue;
+                    finalTarget[path] = finalValue;
                 }
 
                 target._lateAnimationHolders = {};

BIN
tests/validation/ReferenceImages/gltf1CesiumMan.png


+ 5 - 13
tests/validation/config.json

@@ -279,14 +279,6 @@
       "referenceImage": "gltfTextureSampler.png"
     },
     {
-      "title": "GLTF 1.0 Skin Animation Test",
-      "renderCount": 20,
-      "scriptToRun": "/Demos/GLTF1CesiumMan/index.js",
-      "functionToCall": "createScene",
-      "referenceImage": "gltf1CesiumMan.png",
-      "excludeFromAutomaticTesting": true
-    },
-    {
       "title": "GLTF Buggy with Draco Mesh Compression",
       "playgroundId": "#JNW207#1",
       "referenceImage": "gltfBuggyDraco.png"
@@ -385,6 +377,11 @@
       "referenceImage": "pbr.png"
     },
     {
+      "title": "Texture cache",
+      "playgroundId": "#20OAV9#133",
+      "referenceImage": "texture cache.png"
+    },
+    {
       "title": "MultiSample render targets",
       "renderCount": 20,
       "playgroundId": "#12MKMN#0",
@@ -455,11 +452,6 @@
       "title": "Local cubemaps",
       "playgroundId": "#RNASML#4",
       "referenceImage": "local cubemaps.png"
-    },
-    {
-      "title": "Texture cache",
-      "playgroundId": "#20OAV9#133",
-      "referenceImage": "texture cache.png"
     }
   ]
 }