瀏覽代碼

Fix double pointer up problem

David Catuhe 6 年之前
父節點
當前提交
4f3f90d3ca

文件差異過大導致無法顯示
+ 8749 - 8717
Playground/babylon.d.txt


文件差異過大導致無法顯示
+ 8632 - 8602
dist/preview release/babylon.d.ts


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/babylon.js


+ 111 - 97
dist/preview release/babylon.max.js

@@ -12272,6 +12272,10 @@ var BABYLON;
              */
             this.onBeginFrameObservable = new BABYLON.Observable();
             /**
+             * If set, will be used to request the next animation frame for the render loop
+             */
+            this.customAnimationFrameRequester = null;
+            /**
              * Observable raised when the engine ends the current frame
              */
             this.onEndFrameObservable = new BABYLON.Observable();
@@ -13434,11 +13438,16 @@ var BABYLON;
             }
             if (this._activeRenderLoops.length > 0) {
                 // Register new frame
-                var requester = null;
-                if (this._vrDisplay && this._vrDisplay.isPresenting) {
-                    requester = this._vrDisplay;
+                if (this.customAnimationFrameRequester) {
+                    this.customAnimationFrameRequester.requestID = BABYLON.Tools.QueueNewFrame(this.customAnimationFrameRequester.renderFunction || this._bindedRenderFunction, this.customAnimationFrameRequester);
+                    this._frameHandler = this.customAnimationFrameRequester.requestID;
+                }
+                else if (this._vrDisplay && this._vrDisplay.isPresenting) {
+                    this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction, this._vrDisplay);
+                }
+                else {
+                    this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction);
                 }
-                this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction, requester);
             }
             else {
                 this._renderingQueueLaunched = false;
@@ -19208,7 +19217,7 @@ var BABYLON;
             this.minimum.copyFrom(min);
             this.maximum.copyFrom(max);
             var distance = BABYLON.Vector3.Distance(min, max);
-            BABYLON.Vector3.LerpToRef(min, max, 0.5, this.center);
+            max.addToRef(min, this.center).scaleInPlace(0.5);
             this.radius = distance * 0.5;
             this._update(worldMatrix || _identityMatrix);
         };
@@ -19219,8 +19228,8 @@ var BABYLON;
          */
         BoundingSphere.prototype.scale = function (factor) {
             var newRadius = this.radius * factor;
-            var tmpVectors = BABYLON.Tmp.Vector3;
-            var tempRadiusVector = tmpVectors[0].copyFromFloats(newRadius, newRadius, newRadius);
+            var tmpVectors = BoundingSphere.TmpVector3;
+            var tempRadiusVector = tmpVectors[0].setAll(newRadius);
             var min = this.center.subtractToRef(tempRadiusVector, tmpVectors[1]);
             var max = this.center.addToRef(tempRadiusVector, tmpVectors[2]);
             this.reConstruct(min, max);
@@ -19230,7 +19239,7 @@ var BABYLON;
         /** @hidden */
         BoundingSphere.prototype._update = function (world) {
             BABYLON.Vector3.TransformCoordinatesToRef(this.center, world, this.centerWorld);
-            var tempVector = BABYLON.Tmp.Vector3[0];
+            var tempVector = BoundingSphere.TmpVector3[0];
             BABYLON.Vector3.TransformNormalFromFloatsToRef(1.0, 1.0, 1.0, world, tempVector);
             this.radiusWorld = Math.max(Math.abs(tempVector.x), Math.abs(tempVector.y), Math.abs(tempVector.z)) * this.radius;
         };
@@ -19253,11 +19262,8 @@ var BABYLON;
          * @returns true if the point is inside the bounding sphere
          */
         BoundingSphere.prototype.intersectsPoint = function (point) {
-            var x = this.centerWorld.x - point.x;
-            var y = this.centerWorld.y - point.y;
-            var z = this.centerWorld.z - point.z;
-            var distance = Math.sqrt((x * x) + (y * y) + (z * z));
-            if (this.radiusWorld < distance) {
+            var squareDistance = BABYLON.Vector3.DistanceSquared(this.centerWorld, point);
+            if (this.radiusWorld * this.radiusWorld < squareDistance) {
                 return false;
             }
             return true;
@@ -19270,15 +19276,14 @@ var BABYLON;
          * @returns true if the speres intersect
          */
         BoundingSphere.Intersects = function (sphere0, sphere1) {
-            var x = sphere0.centerWorld.x - sphere1.centerWorld.x;
-            var y = sphere0.centerWorld.y - sphere1.centerWorld.y;
-            var z = sphere0.centerWorld.z - sphere1.centerWorld.z;
-            var distance = Math.sqrt((x * x) + (y * y) + (z * z));
-            if (sphere0.radiusWorld + sphere1.radiusWorld < distance) {
+            var squareDistance = BABYLON.Vector3.DistanceSquared(sphere0.centerWorld, sphere1.centerWorld);
+            var radiusSum = sphere0.radiusWorld + sphere1.radiusWorld;
+            if (radiusSum * radiusSum < squareDistance) {
                 return false;
             }
             return true;
         };
+        BoundingSphere.TmpVector3 = BABYLON.Tools.BuildArray(3, BABYLON.Vector3.Zero);
         return BoundingSphere;
     }());
     BABYLON.BoundingSphere = BoundingSphere;
@@ -19366,8 +19371,8 @@ var BABYLON;
             vectors[6].copyFromFloats(minX, maxY, maxZ);
             vectors[7].copyFromFloats(maxX, minY, maxZ);
             // OBB
-            this.maximum.addToRef(min, this.center).scaleInPlace(0.5);
-            this.maximum.subtractToRef(max, this.extendSize).scaleInPlace(0.5);
+            max.addToRef(min, this.center).scaleInPlace(0.5);
+            max.subtractToRef(max, this.extendSize).scaleInPlace(0.5);
             this._update(worldMatrix || this._worldMatrix || BABYLON.Matrix.Identity());
         };
         /**
@@ -19376,7 +19381,7 @@ var BABYLON;
          * @returns the current bounding box
          */
         BoundingBox.prototype.scale = function (factor) {
-            var tmpVectors = BABYLON.Tmp.Vector3;
+            var tmpVectors = BoundingBox.TmpVector3;
             var diff = this.maximum.subtractToRef(this.minimum, tmpVectors[0]);
             var len = diff.length();
             diff.normalizeFromLength(len);
@@ -19557,6 +19562,7 @@ var BABYLON;
             }
             return true;
         };
+        BoundingBox.TmpVector3 = BABYLON.Tools.BuildArray(3, BABYLON.Vector3.Zero);
         return BoundingBox;
     }());
     BABYLON.BoundingBox = BoundingBox;
@@ -19866,6 +19872,8 @@ var BABYLON;
             _this._pivotMatrix = BABYLON.Matrix.Identity();
             _this._postMultiplyPivotMatrix = false;
             _this._isWorldMatrixFrozen = false;
+            /** @hidden */
+            _this._indexInSceneTransformNodesArray = -1;
             /**
             * An event triggered after the world matrix is updated
             */
@@ -19937,8 +19945,8 @@ var BABYLON;
             set: function (quaternion) {
                 this._rotationQuaternion = quaternion;
                 //reset the rotation vector.
-                if (quaternion && this.rotation.length()) {
-                    this.rotation.copyFromFloats(0.0, 0.0, 0.0);
+                if (quaternion) {
+                    this.rotation.setAll(0.0);
                 }
             },
             enumerable: true,
@@ -20070,7 +20078,7 @@ var BABYLON;
         */
         TransformNode.prototype.setPivotMatrix = function (matrix, postMultiplyPivotMatrix) {
             if (postMultiplyPivotMatrix === void 0) { postMultiplyPivotMatrix = true; }
-            this._pivotMatrix = matrix.clone();
+            this._pivotMatrix.copyFrom(matrix);
             this._cache.pivotMatrixUpdated = true;
             this._postMultiplyPivotMatrix = postMultiplyPivotMatrix;
             if (this._postMultiplyPivotMatrix) {
@@ -20154,10 +20162,9 @@ var BABYLON;
                 absolutePositionZ = absolutePosition.z;
             }
             if (this.parent) {
-                var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
-                invertParentWorldMatrix.invert();
-                var worldPosition = new BABYLON.Vector3(absolutePositionX, absolutePositionY, absolutePositionZ);
-                this.position = BABYLON.Vector3.TransformCoordinates(worldPosition, invertParentWorldMatrix);
+                var invertParentWorldMatrix = BABYLON.Tmp.Matrix[0];
+                this.parent.getWorldMatrix().invertToRef(invertParentWorldMatrix);
+                BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(absolutePositionX, absolutePositionY, absolutePositionZ, invertParentWorldMatrix, this.position);
             }
             else {
                 this.position.x = absolutePositionX;
@@ -20182,8 +20189,8 @@ var BABYLON;
          */
         TransformNode.prototype.getPositionExpressedInLocalSpace = function () {
             this.computeWorldMatrix();
-            var invLocalWorldMatrix = this._localWorld.clone();
-            invLocalWorldMatrix.invert();
+            var invLocalWorldMatrix = BABYLON.Tmp.Matrix[0];
+            this._localWorld.invertToRef(invLocalWorldMatrix);
             return BABYLON.Vector3.TransformNormal(this.position, invLocalWorldMatrix);
         };
         /**
@@ -20320,52 +20327,33 @@ var BABYLON;
             if (!node && !this.parent) {
                 return this;
             }
+            var quatRotation = BABYLON.Tmp.Quaternion[0];
+            var position = BABYLON.Tmp.Vector3[0];
+            var scale = BABYLON.Tmp.Vector3[1];
             if (!node) {
-                var rotation = BABYLON.Tmp.Quaternion[0];
-                var position = BABYLON.Tmp.Vector3[0];
-                var scale = BABYLON.Tmp.Vector3[1];
                 if (this.parent && this.parent.computeWorldMatrix) {
                     this.parent.computeWorldMatrix(true);
                 }
                 this.computeWorldMatrix(true);
-                this.getWorldMatrix().decompose(scale, rotation, position);
-                if (this.rotationQuaternion) {
-                    this.rotationQuaternion.copyFrom(rotation);
-                }
-                else {
-                    rotation.toEulerAnglesToRef(this.rotation);
-                }
-                this.scaling.x = scale.x;
-                this.scaling.y = scale.y;
-                this.scaling.z = scale.z;
-                this.position.x = position.x;
-                this.position.y = position.y;
-                this.position.z = position.z;
+                this.getWorldMatrix().decompose(scale, quatRotation, position);
             }
             else {
-                var rotation = BABYLON.Tmp.Quaternion[0];
-                var position = BABYLON.Tmp.Vector3[0];
-                var scale = BABYLON.Tmp.Vector3[1];
                 var diffMatrix = BABYLON.Tmp.Matrix[0];
                 var invParentMatrix = BABYLON.Tmp.Matrix[1];
                 this.computeWorldMatrix(true);
                 node.computeWorldMatrix(true);
                 node.getWorldMatrix().invertToRef(invParentMatrix);
                 this.getWorldMatrix().multiplyToRef(invParentMatrix, diffMatrix);
-                diffMatrix.decompose(scale, rotation, position);
-                if (this.rotationQuaternion) {
-                    this.rotationQuaternion.copyFrom(rotation);
-                }
-                else {
-                    rotation.toEulerAnglesToRef(this.rotation);
-                }
-                this.position.x = position.x;
-                this.position.y = position.y;
-                this.position.z = position.z;
-                this.scaling.x = scale.x;
-                this.scaling.y = scale.y;
-                this.scaling.z = scale.z;
+                diffMatrix.decompose(scale, quatRotation, position);
             }
+            if (this.rotationQuaternion) {
+                this.rotationQuaternion.copyFrom(quatRotation);
+            }
+            else {
+                quatRotation.toEulerAnglesToRef(this.rotation);
+            }
+            this.scaling.copyFrom(scale);
+            this.position.copyFrom(position);
             this.parent = node;
             return this;
         };
@@ -20429,8 +20417,8 @@ var BABYLON;
         TransformNode.prototype.rotate = function (axis, amount, space) {
             axis.normalize();
             if (!this.rotationQuaternion) {
-                this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
-                this.rotation = BABYLON.Vector3.Zero();
+                this.rotationQuaternion = this.rotation.toQuaternion();
+                this.rotation.setAll(0);
             }
             var rotationQuaternion;
             if (!space || space === BABYLON.Space.LOCAL) {
@@ -20439,8 +20427,8 @@ var BABYLON;
             }
             else {
                 if (this.parent) {
-                    var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
-                    invertParentWorldMatrix.invert();
+                    var invertParentWorldMatrix = BABYLON.Tmp.Matrix[0];
+                    this.parent.getWorldMatrix().invertToRef(invertParentWorldMatrix);
                     axis = BABYLON.Vector3.TransformNormal(axis, invertParentWorldMatrix);
                 }
                 rotationQuaternion = BABYLON.Quaternion.RotationAxisToRef(axis, amount, TransformNode._rotationAxisCache);
@@ -20462,17 +20450,25 @@ var BABYLON;
             axis.normalize();
             if (!this.rotationQuaternion) {
                 this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
-                this.rotation.copyFromFloats(0, 0, 0);
-            }
-            point.subtractToRef(this.position, BABYLON.Tmp.Vector3[0]);
-            BABYLON.Matrix.TranslationToRef(BABYLON.Tmp.Vector3[0].x, BABYLON.Tmp.Vector3[0].y, BABYLON.Tmp.Vector3[0].z, BABYLON.Tmp.Matrix[0]);
-            BABYLON.Tmp.Matrix[0].invertToRef(BABYLON.Tmp.Matrix[2]);
-            BABYLON.Matrix.RotationAxisToRef(axis, amount, BABYLON.Tmp.Matrix[1]);
-            BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[1], BABYLON.Tmp.Matrix[2]);
-            BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[0], BABYLON.Tmp.Matrix[2]);
-            BABYLON.Tmp.Matrix[2].decompose(BABYLON.Tmp.Vector3[0], BABYLON.Tmp.Quaternion[0], BABYLON.Tmp.Vector3[1]);
-            this.position.addInPlace(BABYLON.Tmp.Vector3[1]);
-            BABYLON.Tmp.Quaternion[0].multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
+                this.rotation.setAll(0);
+            }
+            var tmpVector = BABYLON.Tmp.Vector3[0];
+            var finalScale = BABYLON.Tmp.Vector3[1];
+            var finalTranslation = BABYLON.Tmp.Vector3[2];
+            var finalRotation = BABYLON.Tmp.Quaternion[0];
+            var translationMatrix = BABYLON.Tmp.Matrix[0]; // T
+            var translationMatrixInv = BABYLON.Tmp.Matrix[1]; // T'
+            var rotationMatrix = BABYLON.Tmp.Matrix[2]; // R
+            var finalMatrix = BABYLON.Tmp.Matrix[3]; // T' x R x T
+            point.subtractToRef(this.position, tmpVector);
+            BABYLON.Matrix.TranslationToRef(tmpVector.x, tmpVector.y, tmpVector.z, translationMatrix); // T
+            BABYLON.Matrix.TranslationToRef(-tmpVector.x, -tmpVector.y, -tmpVector.z, translationMatrixInv); // T'
+            BABYLON.Matrix.RotationAxisToRef(axis, amount, rotationMatrix); // R
+            translationMatrixInv.multiplyToRef(rotationMatrix, finalMatrix); // T' x R
+            finalMatrix.multiplyToRef(translationMatrix, finalMatrix); // T' x R x T
+            finalMatrix.decompose(finalScale, finalRotation, finalTranslation);
+            this.position.addInPlace(finalTranslation);
+            finalRotation.multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
             return this;
         };
         /**
@@ -25204,6 +25200,9 @@ var BABYLON;
             this.geometries = new Array();
             /**
             * All of the tranform nodes added to this scene
+            * In the context a the Scene, it is not supposed to be modified manually.
+            * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
+            * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/how_to/transformnode
             */
             this.transformNodes = new Array();
@@ -27908,6 +27907,7 @@ var BABYLON;
          * @param newTransformNode defines the transform node to add
          */
         Scene.prototype.addTransformNode = function (newTransformNode) {
+            newTransformNode._indexInSceneTransformNodesArray = this.transformNodes.length;
             this.transformNodes.push(newTransformNode);
             this.onNewTransformNodeAddedObservable.notifyObservers(newTransformNode);
         };
@@ -27917,10 +27917,15 @@ var BABYLON;
          * @returns the index where the transform node was in the transform node list
          */
         Scene.prototype.removeTransformNode = function (toRemove) {
-            var index = this.transformNodes.indexOf(toRemove);
+            var index = toRemove._indexInSceneTransformNodesArray;
             if (index !== -1) {
-                // Remove from the scene if found
-                this.transformNodes.splice(index, 1);
+                if (index !== this.transformNodes.length - 1) {
+                    var lastNode = this.transformNodes[this.transformNodes.length - 1];
+                    this.transformNodes[index] = lastNode;
+                    lastNode._indexInSceneTransformNodesArray = index;
+                }
+                toRemove._indexInSceneTransformNodesArray = -1;
+                this.transformNodes.pop();
             }
             this.onTransformNodeRemovedObservable.notifyObservers(toRemove);
             return index;
@@ -33011,12 +33016,12 @@ var BABYLON;
             this.computeWorldMatrix();
             var mat = this.material || scene.defaultMaterial;
             if (mat) {
-                if (mat.storeEffectOnSubMeshes) {
+                if (mat._storeEffectOnSubMeshes) {
                     for (var _i = 0, _a = this.subMeshes; _i < _a.length; _i++) {
                         var subMesh = _a[_i];
                         var effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            if (effectiveMaterial.storeEffectOnSubMeshes) {
+                            if (effectiveMaterial._storeEffectOnSubMeshes) {
                                 if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
                                     return false;
                                 }
@@ -33693,7 +33698,7 @@ var BABYLON;
                 return this;
             }
             this._effectiveMaterial = material;
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 if (!this._effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
                     return this;
                 }
@@ -33710,7 +33715,7 @@ var BABYLON;
                 step.action(this, subMesh, batch);
             }
             var effect;
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 effect = subMesh.effect;
             }
             else {
@@ -33736,7 +33741,7 @@ var BABYLON;
                 this._bind(subMesh, effect, fillMode);
             }
             var world = this.getWorldMatrix();
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 this._effectiveMaterial.bindForSubMesh(world, this, subMesh);
             }
             else {
@@ -36378,9 +36383,9 @@ var BABYLON;
              */
             this.doNotSerialize = false;
             /**
-             * Specifies if the effect should be stored on sub meshes
+             * @hidden
              */
-            this.storeEffectOnSubMeshes = false;
+            this._storeEffectOnSubMeshes = false;
             /**
             * An event triggered when the material is disposed
             */
@@ -37066,7 +37071,7 @@ var BABYLON;
                 if (localOptions.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
-                if (_this.storeEffectOnSubMeshes) {
+                if (_this._storeEffectOnSubMeshes) {
                     if (_this.isReadyForSubMesh(mesh, subMesh)) {
                         if (onCompiled) {
                             onCompiled(_this);
@@ -37226,7 +37231,7 @@ var BABYLON;
                     mesh.material = null;
                     if (mesh.geometry) {
                         var geometry = (mesh.geometry);
-                        if (this.storeEffectOnSubMeshes) {
+                        if (this._storeEffectOnSubMeshes) {
                             for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
                                 var subMesh = _a[_i];
                                 geometry._releaseVertexArrayObject(subMesh._materialEffect);
@@ -37244,7 +37249,7 @@ var BABYLON;
             this._uniformBuffer.dispose();
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             if (forceDisposeEffect && this._effect) {
-                if (!this.storeEffectOnSubMeshes) {
+                if (!this._storeEffectOnSubMeshes) {
                     this._scene.getEngine()._releaseEffect(this._effect);
                 }
                 this._effect = null;
@@ -43224,7 +43229,7 @@ var BABYLON;
              * This is mostly used when shader parallel compilation is supported (true by default)
              */
             _this.allowShaderHotSwapping = true;
-            _this.storeEffectOnSubMeshes = true;
+            _this._storeEffectOnSubMeshes = true;
             return _this;
         }
         PushMaterial.prototype.getEffect = function () {
@@ -68345,13 +68350,22 @@ var BABYLON;
             var index = 0;
             var idx = 0;
             var tmpNormal = BABYLON.Tmp.Vector3[0];
-            var rotMatrix = BABYLON.Tmp.Matrix[0];
-            var invertedRotMatrix = BABYLON.Tmp.Matrix[1];
+            var quaternion = BABYLON.Tmp.Quaternion[0];
+            var invertedRotMatrix = BABYLON.Tmp.Matrix[0];
             for (var p = 0; p < this.particles.length; p++) {
                 var particle = this.particles[p];
                 var shape = particle._model._shape;
-                particle.getRotationMatrix(rotMatrix);
-                rotMatrix.invertToRef(invertedRotMatrix);
+                // computing the inverse of the rotation matrix from the quaternion
+                // is equivalent to computing the matrix of the inverse quaternion, i.e of the conjugate quaternion
+                if (particle.rotationQuaternion) {
+                    particle.rotationQuaternion.conjugateToRef(quaternion);
+                }
+                else {
+                    var rotation = particle.rotation;
+                    BABYLON.Quaternion.RotationYawPitchRollToRef(rotation.y, rotation.x, rotation.z, quaternion);
+                    quaternion.conjugateInPlace();
+                }
+                quaternion.toRotationMatrix(invertedRotMatrix);
                 for (var pt = 0; pt < shape.length; pt++) {
                     idx = index + pt * 3;
                     BABYLON.Vector3.TransformNormalFromFloatsToRef(this._normals32[idx], this._normals32[idx + 1], this._normals32[idx + 2], invertedRotMatrix, tmpNormal);
@@ -80200,7 +80214,7 @@ var BABYLON;
             var _this = _super.call(this, name, scene, true) || this;
             scene.multiMaterials.push(_this);
             _this.subMaterials = new Array();
-            _this.storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
+            _this._storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
             return _this;
         }
         Object.defineProperty(MultiMaterial.prototype, "subMaterials", {
@@ -80282,7 +80296,7 @@ var BABYLON;
             for (var index = 0; index < this.subMaterials.length; index++) {
                 var subMaterial = this.subMaterials[index];
                 if (subMaterial) {
-                    if (subMaterial.storeEffectOnSubMeshes) {
+                    if (subMaterial._storeEffectOnSubMeshes) {
                         if (!subMaterial.isReadyForSubMesh(mesh, subMesh, useInstances)) {
                             return false;
                         }

+ 111 - 97
dist/preview release/babylon.no-module.max.js

@@ -12239,6 +12239,10 @@ var BABYLON;
              */
             this.onBeginFrameObservable = new BABYLON.Observable();
             /**
+             * If set, will be used to request the next animation frame for the render loop
+             */
+            this.customAnimationFrameRequester = null;
+            /**
              * Observable raised when the engine ends the current frame
              */
             this.onEndFrameObservable = new BABYLON.Observable();
@@ -13401,11 +13405,16 @@ var BABYLON;
             }
             if (this._activeRenderLoops.length > 0) {
                 // Register new frame
-                var requester = null;
-                if (this._vrDisplay && this._vrDisplay.isPresenting) {
-                    requester = this._vrDisplay;
+                if (this.customAnimationFrameRequester) {
+                    this.customAnimationFrameRequester.requestID = BABYLON.Tools.QueueNewFrame(this.customAnimationFrameRequester.renderFunction || this._bindedRenderFunction, this.customAnimationFrameRequester);
+                    this._frameHandler = this.customAnimationFrameRequester.requestID;
+                }
+                else if (this._vrDisplay && this._vrDisplay.isPresenting) {
+                    this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction, this._vrDisplay);
+                }
+                else {
+                    this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction);
                 }
-                this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction, requester);
             }
             else {
                 this._renderingQueueLaunched = false;
@@ -19175,7 +19184,7 @@ var BABYLON;
             this.minimum.copyFrom(min);
             this.maximum.copyFrom(max);
             var distance = BABYLON.Vector3.Distance(min, max);
-            BABYLON.Vector3.LerpToRef(min, max, 0.5, this.center);
+            max.addToRef(min, this.center).scaleInPlace(0.5);
             this.radius = distance * 0.5;
             this._update(worldMatrix || _identityMatrix);
         };
@@ -19186,8 +19195,8 @@ var BABYLON;
          */
         BoundingSphere.prototype.scale = function (factor) {
             var newRadius = this.radius * factor;
-            var tmpVectors = BABYLON.Tmp.Vector3;
-            var tempRadiusVector = tmpVectors[0].copyFromFloats(newRadius, newRadius, newRadius);
+            var tmpVectors = BoundingSphere.TmpVector3;
+            var tempRadiusVector = tmpVectors[0].setAll(newRadius);
             var min = this.center.subtractToRef(tempRadiusVector, tmpVectors[1]);
             var max = this.center.addToRef(tempRadiusVector, tmpVectors[2]);
             this.reConstruct(min, max);
@@ -19197,7 +19206,7 @@ var BABYLON;
         /** @hidden */
         BoundingSphere.prototype._update = function (world) {
             BABYLON.Vector3.TransformCoordinatesToRef(this.center, world, this.centerWorld);
-            var tempVector = BABYLON.Tmp.Vector3[0];
+            var tempVector = BoundingSphere.TmpVector3[0];
             BABYLON.Vector3.TransformNormalFromFloatsToRef(1.0, 1.0, 1.0, world, tempVector);
             this.radiusWorld = Math.max(Math.abs(tempVector.x), Math.abs(tempVector.y), Math.abs(tempVector.z)) * this.radius;
         };
@@ -19220,11 +19229,8 @@ var BABYLON;
          * @returns true if the point is inside the bounding sphere
          */
         BoundingSphere.prototype.intersectsPoint = function (point) {
-            var x = this.centerWorld.x - point.x;
-            var y = this.centerWorld.y - point.y;
-            var z = this.centerWorld.z - point.z;
-            var distance = Math.sqrt((x * x) + (y * y) + (z * z));
-            if (this.radiusWorld < distance) {
+            var squareDistance = BABYLON.Vector3.DistanceSquared(this.centerWorld, point);
+            if (this.radiusWorld * this.radiusWorld < squareDistance) {
                 return false;
             }
             return true;
@@ -19237,15 +19243,14 @@ var BABYLON;
          * @returns true if the speres intersect
          */
         BoundingSphere.Intersects = function (sphere0, sphere1) {
-            var x = sphere0.centerWorld.x - sphere1.centerWorld.x;
-            var y = sphere0.centerWorld.y - sphere1.centerWorld.y;
-            var z = sphere0.centerWorld.z - sphere1.centerWorld.z;
-            var distance = Math.sqrt((x * x) + (y * y) + (z * z));
-            if (sphere0.radiusWorld + sphere1.radiusWorld < distance) {
+            var squareDistance = BABYLON.Vector3.DistanceSquared(sphere0.centerWorld, sphere1.centerWorld);
+            var radiusSum = sphere0.radiusWorld + sphere1.radiusWorld;
+            if (radiusSum * radiusSum < squareDistance) {
                 return false;
             }
             return true;
         };
+        BoundingSphere.TmpVector3 = BABYLON.Tools.BuildArray(3, BABYLON.Vector3.Zero);
         return BoundingSphere;
     }());
     BABYLON.BoundingSphere = BoundingSphere;
@@ -19333,8 +19338,8 @@ var BABYLON;
             vectors[6].copyFromFloats(minX, maxY, maxZ);
             vectors[7].copyFromFloats(maxX, minY, maxZ);
             // OBB
-            this.maximum.addToRef(min, this.center).scaleInPlace(0.5);
-            this.maximum.subtractToRef(max, this.extendSize).scaleInPlace(0.5);
+            max.addToRef(min, this.center).scaleInPlace(0.5);
+            max.subtractToRef(max, this.extendSize).scaleInPlace(0.5);
             this._update(worldMatrix || this._worldMatrix || BABYLON.Matrix.Identity());
         };
         /**
@@ -19343,7 +19348,7 @@ var BABYLON;
          * @returns the current bounding box
          */
         BoundingBox.prototype.scale = function (factor) {
-            var tmpVectors = BABYLON.Tmp.Vector3;
+            var tmpVectors = BoundingBox.TmpVector3;
             var diff = this.maximum.subtractToRef(this.minimum, tmpVectors[0]);
             var len = diff.length();
             diff.normalizeFromLength(len);
@@ -19524,6 +19529,7 @@ var BABYLON;
             }
             return true;
         };
+        BoundingBox.TmpVector3 = BABYLON.Tools.BuildArray(3, BABYLON.Vector3.Zero);
         return BoundingBox;
     }());
     BABYLON.BoundingBox = BoundingBox;
@@ -19833,6 +19839,8 @@ var BABYLON;
             _this._pivotMatrix = BABYLON.Matrix.Identity();
             _this._postMultiplyPivotMatrix = false;
             _this._isWorldMatrixFrozen = false;
+            /** @hidden */
+            _this._indexInSceneTransformNodesArray = -1;
             /**
             * An event triggered after the world matrix is updated
             */
@@ -19904,8 +19912,8 @@ var BABYLON;
             set: function (quaternion) {
                 this._rotationQuaternion = quaternion;
                 //reset the rotation vector.
-                if (quaternion && this.rotation.length()) {
-                    this.rotation.copyFromFloats(0.0, 0.0, 0.0);
+                if (quaternion) {
+                    this.rotation.setAll(0.0);
                 }
             },
             enumerable: true,
@@ -20037,7 +20045,7 @@ var BABYLON;
         */
         TransformNode.prototype.setPivotMatrix = function (matrix, postMultiplyPivotMatrix) {
             if (postMultiplyPivotMatrix === void 0) { postMultiplyPivotMatrix = true; }
-            this._pivotMatrix = matrix.clone();
+            this._pivotMatrix.copyFrom(matrix);
             this._cache.pivotMatrixUpdated = true;
             this._postMultiplyPivotMatrix = postMultiplyPivotMatrix;
             if (this._postMultiplyPivotMatrix) {
@@ -20121,10 +20129,9 @@ var BABYLON;
                 absolutePositionZ = absolutePosition.z;
             }
             if (this.parent) {
-                var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
-                invertParentWorldMatrix.invert();
-                var worldPosition = new BABYLON.Vector3(absolutePositionX, absolutePositionY, absolutePositionZ);
-                this.position = BABYLON.Vector3.TransformCoordinates(worldPosition, invertParentWorldMatrix);
+                var invertParentWorldMatrix = BABYLON.Tmp.Matrix[0];
+                this.parent.getWorldMatrix().invertToRef(invertParentWorldMatrix);
+                BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(absolutePositionX, absolutePositionY, absolutePositionZ, invertParentWorldMatrix, this.position);
             }
             else {
                 this.position.x = absolutePositionX;
@@ -20149,8 +20156,8 @@ var BABYLON;
          */
         TransformNode.prototype.getPositionExpressedInLocalSpace = function () {
             this.computeWorldMatrix();
-            var invLocalWorldMatrix = this._localWorld.clone();
-            invLocalWorldMatrix.invert();
+            var invLocalWorldMatrix = BABYLON.Tmp.Matrix[0];
+            this._localWorld.invertToRef(invLocalWorldMatrix);
             return BABYLON.Vector3.TransformNormal(this.position, invLocalWorldMatrix);
         };
         /**
@@ -20287,52 +20294,33 @@ var BABYLON;
             if (!node && !this.parent) {
                 return this;
             }
+            var quatRotation = BABYLON.Tmp.Quaternion[0];
+            var position = BABYLON.Tmp.Vector3[0];
+            var scale = BABYLON.Tmp.Vector3[1];
             if (!node) {
-                var rotation = BABYLON.Tmp.Quaternion[0];
-                var position = BABYLON.Tmp.Vector3[0];
-                var scale = BABYLON.Tmp.Vector3[1];
                 if (this.parent && this.parent.computeWorldMatrix) {
                     this.parent.computeWorldMatrix(true);
                 }
                 this.computeWorldMatrix(true);
-                this.getWorldMatrix().decompose(scale, rotation, position);
-                if (this.rotationQuaternion) {
-                    this.rotationQuaternion.copyFrom(rotation);
-                }
-                else {
-                    rotation.toEulerAnglesToRef(this.rotation);
-                }
-                this.scaling.x = scale.x;
-                this.scaling.y = scale.y;
-                this.scaling.z = scale.z;
-                this.position.x = position.x;
-                this.position.y = position.y;
-                this.position.z = position.z;
+                this.getWorldMatrix().decompose(scale, quatRotation, position);
             }
             else {
-                var rotation = BABYLON.Tmp.Quaternion[0];
-                var position = BABYLON.Tmp.Vector3[0];
-                var scale = BABYLON.Tmp.Vector3[1];
                 var diffMatrix = BABYLON.Tmp.Matrix[0];
                 var invParentMatrix = BABYLON.Tmp.Matrix[1];
                 this.computeWorldMatrix(true);
                 node.computeWorldMatrix(true);
                 node.getWorldMatrix().invertToRef(invParentMatrix);
                 this.getWorldMatrix().multiplyToRef(invParentMatrix, diffMatrix);
-                diffMatrix.decompose(scale, rotation, position);
-                if (this.rotationQuaternion) {
-                    this.rotationQuaternion.copyFrom(rotation);
-                }
-                else {
-                    rotation.toEulerAnglesToRef(this.rotation);
-                }
-                this.position.x = position.x;
-                this.position.y = position.y;
-                this.position.z = position.z;
-                this.scaling.x = scale.x;
-                this.scaling.y = scale.y;
-                this.scaling.z = scale.z;
+                diffMatrix.decompose(scale, quatRotation, position);
             }
+            if (this.rotationQuaternion) {
+                this.rotationQuaternion.copyFrom(quatRotation);
+            }
+            else {
+                quatRotation.toEulerAnglesToRef(this.rotation);
+            }
+            this.scaling.copyFrom(scale);
+            this.position.copyFrom(position);
             this.parent = node;
             return this;
         };
@@ -20396,8 +20384,8 @@ var BABYLON;
         TransformNode.prototype.rotate = function (axis, amount, space) {
             axis.normalize();
             if (!this.rotationQuaternion) {
-                this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
-                this.rotation = BABYLON.Vector3.Zero();
+                this.rotationQuaternion = this.rotation.toQuaternion();
+                this.rotation.setAll(0);
             }
             var rotationQuaternion;
             if (!space || space === BABYLON.Space.LOCAL) {
@@ -20406,8 +20394,8 @@ var BABYLON;
             }
             else {
                 if (this.parent) {
-                    var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
-                    invertParentWorldMatrix.invert();
+                    var invertParentWorldMatrix = BABYLON.Tmp.Matrix[0];
+                    this.parent.getWorldMatrix().invertToRef(invertParentWorldMatrix);
                     axis = BABYLON.Vector3.TransformNormal(axis, invertParentWorldMatrix);
                 }
                 rotationQuaternion = BABYLON.Quaternion.RotationAxisToRef(axis, amount, TransformNode._rotationAxisCache);
@@ -20429,17 +20417,25 @@ var BABYLON;
             axis.normalize();
             if (!this.rotationQuaternion) {
                 this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
-                this.rotation.copyFromFloats(0, 0, 0);
-            }
-            point.subtractToRef(this.position, BABYLON.Tmp.Vector3[0]);
-            BABYLON.Matrix.TranslationToRef(BABYLON.Tmp.Vector3[0].x, BABYLON.Tmp.Vector3[0].y, BABYLON.Tmp.Vector3[0].z, BABYLON.Tmp.Matrix[0]);
-            BABYLON.Tmp.Matrix[0].invertToRef(BABYLON.Tmp.Matrix[2]);
-            BABYLON.Matrix.RotationAxisToRef(axis, amount, BABYLON.Tmp.Matrix[1]);
-            BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[1], BABYLON.Tmp.Matrix[2]);
-            BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[0], BABYLON.Tmp.Matrix[2]);
-            BABYLON.Tmp.Matrix[2].decompose(BABYLON.Tmp.Vector3[0], BABYLON.Tmp.Quaternion[0], BABYLON.Tmp.Vector3[1]);
-            this.position.addInPlace(BABYLON.Tmp.Vector3[1]);
-            BABYLON.Tmp.Quaternion[0].multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
+                this.rotation.setAll(0);
+            }
+            var tmpVector = BABYLON.Tmp.Vector3[0];
+            var finalScale = BABYLON.Tmp.Vector3[1];
+            var finalTranslation = BABYLON.Tmp.Vector3[2];
+            var finalRotation = BABYLON.Tmp.Quaternion[0];
+            var translationMatrix = BABYLON.Tmp.Matrix[0]; // T
+            var translationMatrixInv = BABYLON.Tmp.Matrix[1]; // T'
+            var rotationMatrix = BABYLON.Tmp.Matrix[2]; // R
+            var finalMatrix = BABYLON.Tmp.Matrix[3]; // T' x R x T
+            point.subtractToRef(this.position, tmpVector);
+            BABYLON.Matrix.TranslationToRef(tmpVector.x, tmpVector.y, tmpVector.z, translationMatrix); // T
+            BABYLON.Matrix.TranslationToRef(-tmpVector.x, -tmpVector.y, -tmpVector.z, translationMatrixInv); // T'
+            BABYLON.Matrix.RotationAxisToRef(axis, amount, rotationMatrix); // R
+            translationMatrixInv.multiplyToRef(rotationMatrix, finalMatrix); // T' x R
+            finalMatrix.multiplyToRef(translationMatrix, finalMatrix); // T' x R x T
+            finalMatrix.decompose(finalScale, finalRotation, finalTranslation);
+            this.position.addInPlace(finalTranslation);
+            finalRotation.multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
             return this;
         };
         /**
@@ -25171,6 +25167,9 @@ var BABYLON;
             this.geometries = new Array();
             /**
             * All of the tranform nodes added to this scene
+            * In the context a the Scene, it is not supposed to be modified manually.
+            * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
+            * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/how_to/transformnode
             */
             this.transformNodes = new Array();
@@ -27875,6 +27874,7 @@ var BABYLON;
          * @param newTransformNode defines the transform node to add
          */
         Scene.prototype.addTransformNode = function (newTransformNode) {
+            newTransformNode._indexInSceneTransformNodesArray = this.transformNodes.length;
             this.transformNodes.push(newTransformNode);
             this.onNewTransformNodeAddedObservable.notifyObservers(newTransformNode);
         };
@@ -27884,10 +27884,15 @@ var BABYLON;
          * @returns the index where the transform node was in the transform node list
          */
         Scene.prototype.removeTransformNode = function (toRemove) {
-            var index = this.transformNodes.indexOf(toRemove);
+            var index = toRemove._indexInSceneTransformNodesArray;
             if (index !== -1) {
-                // Remove from the scene if found
-                this.transformNodes.splice(index, 1);
+                if (index !== this.transformNodes.length - 1) {
+                    var lastNode = this.transformNodes[this.transformNodes.length - 1];
+                    this.transformNodes[index] = lastNode;
+                    lastNode._indexInSceneTransformNodesArray = index;
+                }
+                toRemove._indexInSceneTransformNodesArray = -1;
+                this.transformNodes.pop();
             }
             this.onTransformNodeRemovedObservable.notifyObservers(toRemove);
             return index;
@@ -32978,12 +32983,12 @@ var BABYLON;
             this.computeWorldMatrix();
             var mat = this.material || scene.defaultMaterial;
             if (mat) {
-                if (mat.storeEffectOnSubMeshes) {
+                if (mat._storeEffectOnSubMeshes) {
                     for (var _i = 0, _a = this.subMeshes; _i < _a.length; _i++) {
                         var subMesh = _a[_i];
                         var effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            if (effectiveMaterial.storeEffectOnSubMeshes) {
+                            if (effectiveMaterial._storeEffectOnSubMeshes) {
                                 if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
                                     return false;
                                 }
@@ -33660,7 +33665,7 @@ var BABYLON;
                 return this;
             }
             this._effectiveMaterial = material;
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 if (!this._effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
                     return this;
                 }
@@ -33677,7 +33682,7 @@ var BABYLON;
                 step.action(this, subMesh, batch);
             }
             var effect;
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 effect = subMesh.effect;
             }
             else {
@@ -33703,7 +33708,7 @@ var BABYLON;
                 this._bind(subMesh, effect, fillMode);
             }
             var world = this.getWorldMatrix();
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 this._effectiveMaterial.bindForSubMesh(world, this, subMesh);
             }
             else {
@@ -36345,9 +36350,9 @@ var BABYLON;
              */
             this.doNotSerialize = false;
             /**
-             * Specifies if the effect should be stored on sub meshes
+             * @hidden
              */
-            this.storeEffectOnSubMeshes = false;
+            this._storeEffectOnSubMeshes = false;
             /**
             * An event triggered when the material is disposed
             */
@@ -37033,7 +37038,7 @@ var BABYLON;
                 if (localOptions.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
-                if (_this.storeEffectOnSubMeshes) {
+                if (_this._storeEffectOnSubMeshes) {
                     if (_this.isReadyForSubMesh(mesh, subMesh)) {
                         if (onCompiled) {
                             onCompiled(_this);
@@ -37193,7 +37198,7 @@ var BABYLON;
                     mesh.material = null;
                     if (mesh.geometry) {
                         var geometry = (mesh.geometry);
-                        if (this.storeEffectOnSubMeshes) {
+                        if (this._storeEffectOnSubMeshes) {
                             for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
                                 var subMesh = _a[_i];
                                 geometry._releaseVertexArrayObject(subMesh._materialEffect);
@@ -37211,7 +37216,7 @@ var BABYLON;
             this._uniformBuffer.dispose();
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             if (forceDisposeEffect && this._effect) {
-                if (!this.storeEffectOnSubMeshes) {
+                if (!this._storeEffectOnSubMeshes) {
                     this._scene.getEngine()._releaseEffect(this._effect);
                 }
                 this._effect = null;
@@ -43191,7 +43196,7 @@ var BABYLON;
              * This is mostly used when shader parallel compilation is supported (true by default)
              */
             _this.allowShaderHotSwapping = true;
-            _this.storeEffectOnSubMeshes = true;
+            _this._storeEffectOnSubMeshes = true;
             return _this;
         }
         PushMaterial.prototype.getEffect = function () {
@@ -68312,13 +68317,22 @@ var BABYLON;
             var index = 0;
             var idx = 0;
             var tmpNormal = BABYLON.Tmp.Vector3[0];
-            var rotMatrix = BABYLON.Tmp.Matrix[0];
-            var invertedRotMatrix = BABYLON.Tmp.Matrix[1];
+            var quaternion = BABYLON.Tmp.Quaternion[0];
+            var invertedRotMatrix = BABYLON.Tmp.Matrix[0];
             for (var p = 0; p < this.particles.length; p++) {
                 var particle = this.particles[p];
                 var shape = particle._model._shape;
-                particle.getRotationMatrix(rotMatrix);
-                rotMatrix.invertToRef(invertedRotMatrix);
+                // computing the inverse of the rotation matrix from the quaternion
+                // is equivalent to computing the matrix of the inverse quaternion, i.e of the conjugate quaternion
+                if (particle.rotationQuaternion) {
+                    particle.rotationQuaternion.conjugateToRef(quaternion);
+                }
+                else {
+                    var rotation = particle.rotation;
+                    BABYLON.Quaternion.RotationYawPitchRollToRef(rotation.y, rotation.x, rotation.z, quaternion);
+                    quaternion.conjugateInPlace();
+                }
+                quaternion.toRotationMatrix(invertedRotMatrix);
                 for (var pt = 0; pt < shape.length; pt++) {
                     idx = index + pt * 3;
                     BABYLON.Vector3.TransformNormalFromFloatsToRef(this._normals32[idx], this._normals32[idx + 1], this._normals32[idx + 2], invertedRotMatrix, tmpNormal);
@@ -80167,7 +80181,7 @@ var BABYLON;
             var _this = _super.call(this, name, scene, true) || this;
             scene.multiMaterials.push(_this);
             _this.subMaterials = new Array();
-            _this.storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
+            _this._storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
             return _this;
         }
         Object.defineProperty(MultiMaterial.prototype, "subMaterials", {
@@ -80249,7 +80263,7 @@ var BABYLON;
             for (var index = 0; index < this.subMaterials.length; index++) {
                 var subMaterial = this.subMaterials[index];
                 if (subMaterial) {
-                    if (subMaterial.storeEffectOnSubMeshes) {
+                    if (subMaterial._storeEffectOnSubMeshes) {
                         if (!subMaterial.isReadyForSubMesh(mesh, subMesh, useInstances)) {
                             return false;
                         }

文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/babylon.worker.js


+ 111 - 97
dist/preview release/es6.js

@@ -12239,6 +12239,10 @@ var BABYLON;
              */
             this.onBeginFrameObservable = new BABYLON.Observable();
             /**
+             * If set, will be used to request the next animation frame for the render loop
+             */
+            this.customAnimationFrameRequester = null;
+            /**
              * Observable raised when the engine ends the current frame
              */
             this.onEndFrameObservable = new BABYLON.Observable();
@@ -13401,11 +13405,16 @@ var BABYLON;
             }
             if (this._activeRenderLoops.length > 0) {
                 // Register new frame
-                var requester = null;
-                if (this._vrDisplay && this._vrDisplay.isPresenting) {
-                    requester = this._vrDisplay;
+                if (this.customAnimationFrameRequester) {
+                    this.customAnimationFrameRequester.requestID = BABYLON.Tools.QueueNewFrame(this.customAnimationFrameRequester.renderFunction || this._bindedRenderFunction, this.customAnimationFrameRequester);
+                    this._frameHandler = this.customAnimationFrameRequester.requestID;
+                }
+                else if (this._vrDisplay && this._vrDisplay.isPresenting) {
+                    this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction, this._vrDisplay);
+                }
+                else {
+                    this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction);
                 }
-                this._frameHandler = BABYLON.Tools.QueueNewFrame(this._bindedRenderFunction, requester);
             }
             else {
                 this._renderingQueueLaunched = false;
@@ -19175,7 +19184,7 @@ var BABYLON;
             this.minimum.copyFrom(min);
             this.maximum.copyFrom(max);
             var distance = BABYLON.Vector3.Distance(min, max);
-            BABYLON.Vector3.LerpToRef(min, max, 0.5, this.center);
+            max.addToRef(min, this.center).scaleInPlace(0.5);
             this.radius = distance * 0.5;
             this._update(worldMatrix || _identityMatrix);
         };
@@ -19186,8 +19195,8 @@ var BABYLON;
          */
         BoundingSphere.prototype.scale = function (factor) {
             var newRadius = this.radius * factor;
-            var tmpVectors = BABYLON.Tmp.Vector3;
-            var tempRadiusVector = tmpVectors[0].copyFromFloats(newRadius, newRadius, newRadius);
+            var tmpVectors = BoundingSphere.TmpVector3;
+            var tempRadiusVector = tmpVectors[0].setAll(newRadius);
             var min = this.center.subtractToRef(tempRadiusVector, tmpVectors[1]);
             var max = this.center.addToRef(tempRadiusVector, tmpVectors[2]);
             this.reConstruct(min, max);
@@ -19197,7 +19206,7 @@ var BABYLON;
         /** @hidden */
         BoundingSphere.prototype._update = function (world) {
             BABYLON.Vector3.TransformCoordinatesToRef(this.center, world, this.centerWorld);
-            var tempVector = BABYLON.Tmp.Vector3[0];
+            var tempVector = BoundingSphere.TmpVector3[0];
             BABYLON.Vector3.TransformNormalFromFloatsToRef(1.0, 1.0, 1.0, world, tempVector);
             this.radiusWorld = Math.max(Math.abs(tempVector.x), Math.abs(tempVector.y), Math.abs(tempVector.z)) * this.radius;
         };
@@ -19220,11 +19229,8 @@ var BABYLON;
          * @returns true if the point is inside the bounding sphere
          */
         BoundingSphere.prototype.intersectsPoint = function (point) {
-            var x = this.centerWorld.x - point.x;
-            var y = this.centerWorld.y - point.y;
-            var z = this.centerWorld.z - point.z;
-            var distance = Math.sqrt((x * x) + (y * y) + (z * z));
-            if (this.radiusWorld < distance) {
+            var squareDistance = BABYLON.Vector3.DistanceSquared(this.centerWorld, point);
+            if (this.radiusWorld * this.radiusWorld < squareDistance) {
                 return false;
             }
             return true;
@@ -19237,15 +19243,14 @@ var BABYLON;
          * @returns true if the speres intersect
          */
         BoundingSphere.Intersects = function (sphere0, sphere1) {
-            var x = sphere0.centerWorld.x - sphere1.centerWorld.x;
-            var y = sphere0.centerWorld.y - sphere1.centerWorld.y;
-            var z = sphere0.centerWorld.z - sphere1.centerWorld.z;
-            var distance = Math.sqrt((x * x) + (y * y) + (z * z));
-            if (sphere0.radiusWorld + sphere1.radiusWorld < distance) {
+            var squareDistance = BABYLON.Vector3.DistanceSquared(sphere0.centerWorld, sphere1.centerWorld);
+            var radiusSum = sphere0.radiusWorld + sphere1.radiusWorld;
+            if (radiusSum * radiusSum < squareDistance) {
                 return false;
             }
             return true;
         };
+        BoundingSphere.TmpVector3 = BABYLON.Tools.BuildArray(3, BABYLON.Vector3.Zero);
         return BoundingSphere;
     }());
     BABYLON.BoundingSphere = BoundingSphere;
@@ -19333,8 +19338,8 @@ var BABYLON;
             vectors[6].copyFromFloats(minX, maxY, maxZ);
             vectors[7].copyFromFloats(maxX, minY, maxZ);
             // OBB
-            this.maximum.addToRef(min, this.center).scaleInPlace(0.5);
-            this.maximum.subtractToRef(max, this.extendSize).scaleInPlace(0.5);
+            max.addToRef(min, this.center).scaleInPlace(0.5);
+            max.subtractToRef(max, this.extendSize).scaleInPlace(0.5);
             this._update(worldMatrix || this._worldMatrix || BABYLON.Matrix.Identity());
         };
         /**
@@ -19343,7 +19348,7 @@ var BABYLON;
          * @returns the current bounding box
          */
         BoundingBox.prototype.scale = function (factor) {
-            var tmpVectors = BABYLON.Tmp.Vector3;
+            var tmpVectors = BoundingBox.TmpVector3;
             var diff = this.maximum.subtractToRef(this.minimum, tmpVectors[0]);
             var len = diff.length();
             diff.normalizeFromLength(len);
@@ -19524,6 +19529,7 @@ var BABYLON;
             }
             return true;
         };
+        BoundingBox.TmpVector3 = BABYLON.Tools.BuildArray(3, BABYLON.Vector3.Zero);
         return BoundingBox;
     }());
     BABYLON.BoundingBox = BoundingBox;
@@ -19833,6 +19839,8 @@ var BABYLON;
             _this._pivotMatrix = BABYLON.Matrix.Identity();
             _this._postMultiplyPivotMatrix = false;
             _this._isWorldMatrixFrozen = false;
+            /** @hidden */
+            _this._indexInSceneTransformNodesArray = -1;
             /**
             * An event triggered after the world matrix is updated
             */
@@ -19904,8 +19912,8 @@ var BABYLON;
             set: function (quaternion) {
                 this._rotationQuaternion = quaternion;
                 //reset the rotation vector.
-                if (quaternion && this.rotation.length()) {
-                    this.rotation.copyFromFloats(0.0, 0.0, 0.0);
+                if (quaternion) {
+                    this.rotation.setAll(0.0);
                 }
             },
             enumerable: true,
@@ -20037,7 +20045,7 @@ var BABYLON;
         */
         TransformNode.prototype.setPivotMatrix = function (matrix, postMultiplyPivotMatrix) {
             if (postMultiplyPivotMatrix === void 0) { postMultiplyPivotMatrix = true; }
-            this._pivotMatrix = matrix.clone();
+            this._pivotMatrix.copyFrom(matrix);
             this._cache.pivotMatrixUpdated = true;
             this._postMultiplyPivotMatrix = postMultiplyPivotMatrix;
             if (this._postMultiplyPivotMatrix) {
@@ -20121,10 +20129,9 @@ var BABYLON;
                 absolutePositionZ = absolutePosition.z;
             }
             if (this.parent) {
-                var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
-                invertParentWorldMatrix.invert();
-                var worldPosition = new BABYLON.Vector3(absolutePositionX, absolutePositionY, absolutePositionZ);
-                this.position = BABYLON.Vector3.TransformCoordinates(worldPosition, invertParentWorldMatrix);
+                var invertParentWorldMatrix = BABYLON.Tmp.Matrix[0];
+                this.parent.getWorldMatrix().invertToRef(invertParentWorldMatrix);
+                BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(absolutePositionX, absolutePositionY, absolutePositionZ, invertParentWorldMatrix, this.position);
             }
             else {
                 this.position.x = absolutePositionX;
@@ -20149,8 +20156,8 @@ var BABYLON;
          */
         TransformNode.prototype.getPositionExpressedInLocalSpace = function () {
             this.computeWorldMatrix();
-            var invLocalWorldMatrix = this._localWorld.clone();
-            invLocalWorldMatrix.invert();
+            var invLocalWorldMatrix = BABYLON.Tmp.Matrix[0];
+            this._localWorld.invertToRef(invLocalWorldMatrix);
             return BABYLON.Vector3.TransformNormal(this.position, invLocalWorldMatrix);
         };
         /**
@@ -20287,52 +20294,33 @@ var BABYLON;
             if (!node && !this.parent) {
                 return this;
             }
+            var quatRotation = BABYLON.Tmp.Quaternion[0];
+            var position = BABYLON.Tmp.Vector3[0];
+            var scale = BABYLON.Tmp.Vector3[1];
             if (!node) {
-                var rotation = BABYLON.Tmp.Quaternion[0];
-                var position = BABYLON.Tmp.Vector3[0];
-                var scale = BABYLON.Tmp.Vector3[1];
                 if (this.parent && this.parent.computeWorldMatrix) {
                     this.parent.computeWorldMatrix(true);
                 }
                 this.computeWorldMatrix(true);
-                this.getWorldMatrix().decompose(scale, rotation, position);
-                if (this.rotationQuaternion) {
-                    this.rotationQuaternion.copyFrom(rotation);
-                }
-                else {
-                    rotation.toEulerAnglesToRef(this.rotation);
-                }
-                this.scaling.x = scale.x;
-                this.scaling.y = scale.y;
-                this.scaling.z = scale.z;
-                this.position.x = position.x;
-                this.position.y = position.y;
-                this.position.z = position.z;
+                this.getWorldMatrix().decompose(scale, quatRotation, position);
             }
             else {
-                var rotation = BABYLON.Tmp.Quaternion[0];
-                var position = BABYLON.Tmp.Vector3[0];
-                var scale = BABYLON.Tmp.Vector3[1];
                 var diffMatrix = BABYLON.Tmp.Matrix[0];
                 var invParentMatrix = BABYLON.Tmp.Matrix[1];
                 this.computeWorldMatrix(true);
                 node.computeWorldMatrix(true);
                 node.getWorldMatrix().invertToRef(invParentMatrix);
                 this.getWorldMatrix().multiplyToRef(invParentMatrix, diffMatrix);
-                diffMatrix.decompose(scale, rotation, position);
-                if (this.rotationQuaternion) {
-                    this.rotationQuaternion.copyFrom(rotation);
-                }
-                else {
-                    rotation.toEulerAnglesToRef(this.rotation);
-                }
-                this.position.x = position.x;
-                this.position.y = position.y;
-                this.position.z = position.z;
-                this.scaling.x = scale.x;
-                this.scaling.y = scale.y;
-                this.scaling.z = scale.z;
+                diffMatrix.decompose(scale, quatRotation, position);
             }
+            if (this.rotationQuaternion) {
+                this.rotationQuaternion.copyFrom(quatRotation);
+            }
+            else {
+                quatRotation.toEulerAnglesToRef(this.rotation);
+            }
+            this.scaling.copyFrom(scale);
+            this.position.copyFrom(position);
             this.parent = node;
             return this;
         };
@@ -20396,8 +20384,8 @@ var BABYLON;
         TransformNode.prototype.rotate = function (axis, amount, space) {
             axis.normalize();
             if (!this.rotationQuaternion) {
-                this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
-                this.rotation = BABYLON.Vector3.Zero();
+                this.rotationQuaternion = this.rotation.toQuaternion();
+                this.rotation.setAll(0);
             }
             var rotationQuaternion;
             if (!space || space === BABYLON.Space.LOCAL) {
@@ -20406,8 +20394,8 @@ var BABYLON;
             }
             else {
                 if (this.parent) {
-                    var invertParentWorldMatrix = this.parent.getWorldMatrix().clone();
-                    invertParentWorldMatrix.invert();
+                    var invertParentWorldMatrix = BABYLON.Tmp.Matrix[0];
+                    this.parent.getWorldMatrix().invertToRef(invertParentWorldMatrix);
                     axis = BABYLON.Vector3.TransformNormal(axis, invertParentWorldMatrix);
                 }
                 rotationQuaternion = BABYLON.Quaternion.RotationAxisToRef(axis, amount, TransformNode._rotationAxisCache);
@@ -20429,17 +20417,25 @@ var BABYLON;
             axis.normalize();
             if (!this.rotationQuaternion) {
                 this.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
-                this.rotation.copyFromFloats(0, 0, 0);
-            }
-            point.subtractToRef(this.position, BABYLON.Tmp.Vector3[0]);
-            BABYLON.Matrix.TranslationToRef(BABYLON.Tmp.Vector3[0].x, BABYLON.Tmp.Vector3[0].y, BABYLON.Tmp.Vector3[0].z, BABYLON.Tmp.Matrix[0]);
-            BABYLON.Tmp.Matrix[0].invertToRef(BABYLON.Tmp.Matrix[2]);
-            BABYLON.Matrix.RotationAxisToRef(axis, amount, BABYLON.Tmp.Matrix[1]);
-            BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[1], BABYLON.Tmp.Matrix[2]);
-            BABYLON.Tmp.Matrix[2].multiplyToRef(BABYLON.Tmp.Matrix[0], BABYLON.Tmp.Matrix[2]);
-            BABYLON.Tmp.Matrix[2].decompose(BABYLON.Tmp.Vector3[0], BABYLON.Tmp.Quaternion[0], BABYLON.Tmp.Vector3[1]);
-            this.position.addInPlace(BABYLON.Tmp.Vector3[1]);
-            BABYLON.Tmp.Quaternion[0].multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
+                this.rotation.setAll(0);
+            }
+            var tmpVector = BABYLON.Tmp.Vector3[0];
+            var finalScale = BABYLON.Tmp.Vector3[1];
+            var finalTranslation = BABYLON.Tmp.Vector3[2];
+            var finalRotation = BABYLON.Tmp.Quaternion[0];
+            var translationMatrix = BABYLON.Tmp.Matrix[0]; // T
+            var translationMatrixInv = BABYLON.Tmp.Matrix[1]; // T'
+            var rotationMatrix = BABYLON.Tmp.Matrix[2]; // R
+            var finalMatrix = BABYLON.Tmp.Matrix[3]; // T' x R x T
+            point.subtractToRef(this.position, tmpVector);
+            BABYLON.Matrix.TranslationToRef(tmpVector.x, tmpVector.y, tmpVector.z, translationMatrix); // T
+            BABYLON.Matrix.TranslationToRef(-tmpVector.x, -tmpVector.y, -tmpVector.z, translationMatrixInv); // T'
+            BABYLON.Matrix.RotationAxisToRef(axis, amount, rotationMatrix); // R
+            translationMatrixInv.multiplyToRef(rotationMatrix, finalMatrix); // T' x R
+            finalMatrix.multiplyToRef(translationMatrix, finalMatrix); // T' x R x T
+            finalMatrix.decompose(finalScale, finalRotation, finalTranslation);
+            this.position.addInPlace(finalTranslation);
+            finalRotation.multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
             return this;
         };
         /**
@@ -25171,6 +25167,9 @@ var BABYLON;
             this.geometries = new Array();
             /**
             * All of the tranform nodes added to this scene
+            * In the context a the Scene, it is not supposed to be modified manually.
+            * Any addition or removal should be done using the addTransformNode and removeTransformNode Scene methods.
+            * Note also that the order of the TransformNode wihin the array is not significant and might change.
             * @see http://doc.babylonjs.com/how_to/transformnode
             */
             this.transformNodes = new Array();
@@ -27875,6 +27874,7 @@ var BABYLON;
          * @param newTransformNode defines the transform node to add
          */
         Scene.prototype.addTransformNode = function (newTransformNode) {
+            newTransformNode._indexInSceneTransformNodesArray = this.transformNodes.length;
             this.transformNodes.push(newTransformNode);
             this.onNewTransformNodeAddedObservable.notifyObservers(newTransformNode);
         };
@@ -27884,10 +27884,15 @@ var BABYLON;
          * @returns the index where the transform node was in the transform node list
          */
         Scene.prototype.removeTransformNode = function (toRemove) {
-            var index = this.transformNodes.indexOf(toRemove);
+            var index = toRemove._indexInSceneTransformNodesArray;
             if (index !== -1) {
-                // Remove from the scene if found
-                this.transformNodes.splice(index, 1);
+                if (index !== this.transformNodes.length - 1) {
+                    var lastNode = this.transformNodes[this.transformNodes.length - 1];
+                    this.transformNodes[index] = lastNode;
+                    lastNode._indexInSceneTransformNodesArray = index;
+                }
+                toRemove._indexInSceneTransformNodesArray = -1;
+                this.transformNodes.pop();
             }
             this.onTransformNodeRemovedObservable.notifyObservers(toRemove);
             return index;
@@ -32978,12 +32983,12 @@ var BABYLON;
             this.computeWorldMatrix();
             var mat = this.material || scene.defaultMaterial;
             if (mat) {
-                if (mat.storeEffectOnSubMeshes) {
+                if (mat._storeEffectOnSubMeshes) {
                     for (var _i = 0, _a = this.subMeshes; _i < _a.length; _i++) {
                         var subMesh = _a[_i];
                         var effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            if (effectiveMaterial.storeEffectOnSubMeshes) {
+                            if (effectiveMaterial._storeEffectOnSubMeshes) {
                                 if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
                                     return false;
                                 }
@@ -33660,7 +33665,7 @@ var BABYLON;
                 return this;
             }
             this._effectiveMaterial = material;
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 if (!this._effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
                     return this;
                 }
@@ -33677,7 +33682,7 @@ var BABYLON;
                 step.action(this, subMesh, batch);
             }
             var effect;
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 effect = subMesh.effect;
             }
             else {
@@ -33703,7 +33708,7 @@ var BABYLON;
                 this._bind(subMesh, effect, fillMode);
             }
             var world = this.getWorldMatrix();
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 this._effectiveMaterial.bindForSubMesh(world, this, subMesh);
             }
             else {
@@ -36345,9 +36350,9 @@ var BABYLON;
              */
             this.doNotSerialize = false;
             /**
-             * Specifies if the effect should be stored on sub meshes
+             * @hidden
              */
-            this.storeEffectOnSubMeshes = false;
+            this._storeEffectOnSubMeshes = false;
             /**
             * An event triggered when the material is disposed
             */
@@ -37033,7 +37038,7 @@ var BABYLON;
                 if (localOptions.clipPlane) {
                     scene.clipPlane = new BABYLON.Plane(0, 0, 0, 1);
                 }
-                if (_this.storeEffectOnSubMeshes) {
+                if (_this._storeEffectOnSubMeshes) {
                     if (_this.isReadyForSubMesh(mesh, subMesh)) {
                         if (onCompiled) {
                             onCompiled(_this);
@@ -37193,7 +37198,7 @@ var BABYLON;
                     mesh.material = null;
                     if (mesh.geometry) {
                         var geometry = (mesh.geometry);
-                        if (this.storeEffectOnSubMeshes) {
+                        if (this._storeEffectOnSubMeshes) {
                             for (var _i = 0, _a = mesh.subMeshes; _i < _a.length; _i++) {
                                 var subMesh = _a[_i];
                                 geometry._releaseVertexArrayObject(subMesh._materialEffect);
@@ -37211,7 +37216,7 @@ var BABYLON;
             this._uniformBuffer.dispose();
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             if (forceDisposeEffect && this._effect) {
-                if (!this.storeEffectOnSubMeshes) {
+                if (!this._storeEffectOnSubMeshes) {
                     this._scene.getEngine()._releaseEffect(this._effect);
                 }
                 this._effect = null;
@@ -43191,7 +43196,7 @@ var BABYLON;
              * This is mostly used when shader parallel compilation is supported (true by default)
              */
             _this.allowShaderHotSwapping = true;
-            _this.storeEffectOnSubMeshes = true;
+            _this._storeEffectOnSubMeshes = true;
             return _this;
         }
         PushMaterial.prototype.getEffect = function () {
@@ -68312,13 +68317,22 @@ var BABYLON;
             var index = 0;
             var idx = 0;
             var tmpNormal = BABYLON.Tmp.Vector3[0];
-            var rotMatrix = BABYLON.Tmp.Matrix[0];
-            var invertedRotMatrix = BABYLON.Tmp.Matrix[1];
+            var quaternion = BABYLON.Tmp.Quaternion[0];
+            var invertedRotMatrix = BABYLON.Tmp.Matrix[0];
             for (var p = 0; p < this.particles.length; p++) {
                 var particle = this.particles[p];
                 var shape = particle._model._shape;
-                particle.getRotationMatrix(rotMatrix);
-                rotMatrix.invertToRef(invertedRotMatrix);
+                // computing the inverse of the rotation matrix from the quaternion
+                // is equivalent to computing the matrix of the inverse quaternion, i.e of the conjugate quaternion
+                if (particle.rotationQuaternion) {
+                    particle.rotationQuaternion.conjugateToRef(quaternion);
+                }
+                else {
+                    var rotation = particle.rotation;
+                    BABYLON.Quaternion.RotationYawPitchRollToRef(rotation.y, rotation.x, rotation.z, quaternion);
+                    quaternion.conjugateInPlace();
+                }
+                quaternion.toRotationMatrix(invertedRotMatrix);
                 for (var pt = 0; pt < shape.length; pt++) {
                     idx = index + pt * 3;
                     BABYLON.Vector3.TransformNormalFromFloatsToRef(this._normals32[idx], this._normals32[idx + 1], this._normals32[idx + 2], invertedRotMatrix, tmpNormal);
@@ -80167,7 +80181,7 @@ var BABYLON;
             var _this = _super.call(this, name, scene, true) || this;
             scene.multiMaterials.push(_this);
             _this.subMaterials = new Array();
-            _this.storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
+            _this._storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
             return _this;
         }
         Object.defineProperty(MultiMaterial.prototype, "subMaterials", {
@@ -80249,7 +80263,7 @@ var BABYLON;
             for (var index = 0; index < this.subMaterials.length; index++) {
                 var subMaterial = this.subMaterials[index];
                 if (subMaterial) {
-                    if (subMaterial.storeEffectOnSubMeshes) {
+                    if (subMaterial._storeEffectOnSubMeshes) {
                         if (!subMaterial.isReadyForSubMesh(mesh, subMesh, useInstances)) {
                             return false;
                         }

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

@@ -849,6 +849,8 @@ declare module BABYLON.GUI {
             isPointerBlocker: boolean;
             /** Gets or sets a boolean indicating if the control can be focusable */
             isFocusInvisible: boolean;
+            /** Gets or sets a boolean indicating if the children are clipped to the current control bounds */
+            clipChildren: boolean;
             /** Gets or sets a value indicating the offset to apply on X axis to render the shadow */
             shadowOffsetX: number;
             /** Gets or sets a value indicating the offset to apply on Y axis to render the shadow */

文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/gui/babylon.gui.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


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

@@ -952,6 +952,8 @@ declare module 'babylonjs-gui/2D/controls/control' {
             isPointerBlocker: boolean;
             /** Gets or sets a boolean indicating if the control can be focusable */
             isFocusInvisible: boolean;
+            /** Gets or sets a boolean indicating if the children are clipped to the current control bounds */
+            clipChildren: boolean;
             /** Gets or sets a value indicating the offset to apply on X axis to render the shadow */
             shadowOffsetX: number;
             /** Gets or sets a value indicating the offset to apply on Y axis to render the shadow */
@@ -3676,6 +3678,8 @@ declare module BABYLON.GUI {
             isPointerBlocker: boolean;
             /** Gets or sets a boolean indicating if the control can be focusable */
             isFocusInvisible: boolean;
+            /** Gets or sets a boolean indicating if the children are clipped to the current control bounds */
+            clipChildren: boolean;
             /** Gets or sets a value indicating the offset to apply on X axis to render the shadow */
             shadowOffsetX: number;
             /** Gets or sets a value indicating the offset to apply on Y axis to render the shadow */

文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js.map


+ 459 - 0
dist/preview release/viewer/babylon.viewer.d.ts

@@ -1728,6 +1728,465 @@ declare module BabylonViewer {
     }
 }
 declare module BabylonViewer {
+    export interface ICameraConfiguration {
+        position?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+        rotation?: {
+            x: number;
+            y: number;
+            z: number;
+            w: number;
+        };
+        fov?: number;
+        fovMode?: number;
+        minZ?: number;
+        maxZ?: number;
+        inertia?: number;
+        exposure?: number;
+        pinchPrecision?: number;
+        behaviors?: {
+            [name: string]: boolean | number | ICameraBehaviorConfiguration;
+        };
+        disableCameraControl?: boolean;
+        disableCtrlForPanning?: boolean;
+        disableAutoFocus?: boolean;
+        [propName: string]: any;
+    }
+    export interface ICameraBehaviorConfiguration {
+        type: number;
+        [propName: string]: any;
+    }
+}
+declare module BabylonViewer {
+    /**
+        * The Color Grading Configuration groups the different settings used to define the color grading used in the viewer.
+        */
+    export interface IColorGradingConfiguration {
+            /**
+                * Transform data string, encoded as determined by transformDataFormat.
+                */
+            transformData: string;
+            /**
+                * The encoding format of TransformData (currently only raw-base16 is supported).
+                */
+            transformDataFormat: string;
+            /**
+                * The weight of the transform
+                */
+            transformWeight: number;
+            /**
+                * Color curve colorFilterHueGlobal value
+                */
+            colorFilterHueGlobal: number;
+            /**
+                * Color curve colorFilterHueShadows value
+                */
+            colorFilterHueShadows: number;
+            /**
+                * Color curve colorFilterHueMidtones value
+                */
+            colorFilterHueMidtones: number;
+            /**
+                * Color curve colorFilterHueHighlights value
+                */
+            colorFilterHueHighlights: number;
+            /**
+                * Color curve colorFilterDensityGlobal value
+                */
+            colorFilterDensityGlobal: number;
+            /**
+                * Color curve colorFilterDensityShadows value
+                */
+            colorFilterDensityShadows: number;
+            /**
+                * Color curve colorFilterDensityMidtones value
+                */
+            colorFilterDensityMidtones: number;
+            /**
+                * Color curve colorFilterDensityHighlights value
+                */
+            colorFilterDensityHighlights: number;
+            /**
+                * Color curve saturationGlobal value
+                */
+            saturationGlobal: number;
+            /**
+                * Color curve saturationShadows value
+                */
+            saturationShadows: number;
+            /**
+                * Color curve saturationMidtones value
+                */
+            saturationMidtones: number;
+            /**
+                * Color curve saturationHighlights value
+                */
+            saturationHighlights: number;
+            /**
+                * Color curve exposureGlobal value
+                */
+            exposureGlobal: number;
+            /**
+                * Color curve exposureShadows value
+                */
+            exposureShadows: number;
+            /**
+                * Color curve exposureMidtones value
+                */
+            exposureMidtones: number;
+            /**
+                * Color curve exposureHighlights value
+                */
+            exposureHighlights: number;
+    }
+}
+declare module BabylonViewer {
+    export interface IDefaultRenderingPipelineConfiguration {
+        sharpenEnabled?: boolean;
+        bloomEnabled?: boolean;
+        bloomThreshold?: number;
+        depthOfFieldEnabled?: boolean;
+        depthOfFieldBlurLevel?: BABYLON.DepthOfFieldEffectBlurLevel;
+        fxaaEnabled?: boolean;
+        imageProcessingEnabled?: boolean;
+        defaultPipelineTextureType?: number;
+        bloomScale?: number;
+        chromaticAberrationEnabled?: boolean;
+        grainEnabled?: boolean;
+        bloomKernel?: number;
+        hardwareScaleLevel?: number;
+        bloomWeight?: number;
+        hdr?: boolean;
+        samples?: number;
+        glowLayerEnabled?: boolean;
+    }
+}
+declare module BabylonViewer {
+    export interface IGroundConfiguration {
+        size?: number;
+        receiveShadows?: boolean;
+        shadowLevel?: number;
+        shadowOnly?: boolean;
+        mirror?: boolean | {
+            sizeRatio?: number;
+            blurKernel?: number;
+            amount?: number;
+            fresnelWeight?: number;
+            fallOffDistance?: number;
+            textureType?: number;
+        };
+        texture?: string;
+        color?: {
+            r: number;
+            g: number;
+            b: number;
+        };
+        opacity?: number;
+        material?: {
+            [propName: string]: any;
+        };
+    }
+}
+declare module BabylonViewer {
+    export interface IImageProcessingConfiguration {
+        colorGradingEnabled?: boolean;
+        colorCurvesEnabled?: boolean;
+        colorCurves?: {
+            globalHue?: number;
+            globalDensity?: number;
+            globalSaturation?: number;
+            globalExposure?: number;
+            highlightsHue?: number;
+            highlightsDensity?: number;
+            highlightsSaturation?: number;
+            highlightsExposure?: number;
+            midtonesHue?: number;
+            midtonesDensity?: number;
+            midtonesSaturation?: number;
+            midtonesExposure?: number;
+            shadowsHue?: number;
+            shadowsDensity?: number;
+            shadowsSaturation?: number;
+            shadowsExposure?: number;
+        };
+        colorGradingWithGreenDepth?: boolean;
+        colorGradingBGR?: boolean;
+        exposure?: number;
+        toneMappingEnabled?: boolean;
+        contrast?: number;
+        vignetteEnabled?: boolean;
+        vignetteStretch?: number;
+        vignetteCentreX?: number;
+        vignetteCentreY?: number;
+        vignetteWeight?: number;
+        vignetteColor?: {
+            r: number;
+            g: number;
+            b: number;
+            a?: number;
+        };
+        vignetteCameraFov?: number;
+        vignetteBlendMode?: number;
+        vignetteM?: boolean;
+        applyByPostProcess?: boolean;
+        isEnabled?: boolean;
+    }
+}
+declare module BabylonViewer {
+    export interface ILightConfiguration {
+        type: number;
+        name?: string;
+        disabled?: boolean;
+        position?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+        target?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+        direction?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+        diffuse?: {
+            r: number;
+            g: number;
+            b: number;
+        };
+        specular?: {
+            r: number;
+            g: number;
+            b: number;
+        };
+        intensity?: number;
+        intensityMode?: number;
+        radius?: number;
+        shadownEnabled?: boolean;
+        shadowConfig?: {
+            useBlurExponentialShadowMap?: boolean;
+            useBlurCloseExponentialShadowMap?: boolean;
+            useKernelBlur?: boolean;
+            blurKernel?: number;
+            blurScale?: number;
+            minZ?: number;
+            maxZ?: number;
+            frustumSize?: number;
+            angleScale?: number;
+            frustumEdgeFalloff?: number;
+            [propName: string]: any;
+        };
+        spotAngle?: number;
+        shadowFieldOfView?: number;
+        shadowBufferSize?: number;
+        shadowFrustumSize?: number;
+        shadowMinZ?: number;
+        shadowMaxZ?: number;
+        [propName: string]: any;
+        behaviors?: {
+            [name: string]: number | {
+                type: number;
+                [propName: string]: any;
+            };
+        };
+    }
+}
+declare module BabylonViewer {
+    export interface IObserversConfiguration {
+        onEngineInit?: string;
+        onSceneInit?: string;
+        onModelLoaded?: string;
+    }
+}
+declare module BabylonViewer {
+    export interface ISceneConfiguration {
+            debug?: boolean;
+            clearColor?: {
+                    r: number;
+                    g: number;
+                    b: number;
+                    a: number;
+            };
+            /** Deprecated, use environmentMap.mainColor instead. */
+            mainColor?: {
+                    r?: number;
+                    g?: number;
+                    b?: number;
+            };
+            imageProcessingConfiguration?: IImageProcessingConfiguration;
+            environmentTexture?: string;
+            colorGrading?: IColorGradingConfiguration;
+            environmentRotationY?: number;
+            /**
+                * Deprecated, please use default rendering pipeline
+                */
+            glow?: boolean | BABYLON.IGlowLayerOptions;
+            disableHdr?: boolean;
+            renderInBackground?: boolean;
+            disableCameraControl?: boolean;
+            animationPropertiesOverride?: {
+                    [propName: string]: any;
+            };
+            defaultMaterial?: {
+                    materialType: "standard" | "pbr";
+                    [propName: string]: any;
+            };
+            flags?: {
+                    shadowsEnabled?: boolean;
+                    particlesEnabled?: boolean;
+                    collisionsEnabled?: boolean;
+                    lightsEnabled?: boolean;
+                    texturesEnabled?: boolean;
+                    lensFlaresEnabled?: boolean;
+                    proceduralTexturesEnabled?: boolean;
+                    renderTargetsEnabled?: boolean;
+                    spritesEnabled?: boolean;
+                    skeletonsEnabled?: boolean;
+                    audioEnabled?: boolean;
+            };
+            assetsRootURL?: string;
+    }
+}
+declare module BabylonViewer {
+    export interface ISceneOptimizerConfiguration {
+        targetFrameRate?: number;
+        trackerDuration?: number;
+        autoGeneratePriorities?: boolean;
+        improvementMode?: boolean;
+        degradation?: string;
+        types?: {
+            texture?: ISceneOptimizerParameters;
+            hardwareScaling?: ISceneOptimizerParameters;
+            shadow?: ISceneOptimizerParameters;
+            postProcess?: ISceneOptimizerParameters;
+            lensFlare?: ISceneOptimizerParameters;
+            particles?: ISceneOptimizerParameters;
+            renderTarget?: ISceneOptimizerParameters;
+            mergeMeshes?: ISceneOptimizerParameters;
+        };
+        custom?: string;
+    }
+    export interface ISceneOptimizerParameters {
+        priority?: number;
+        maximumSize?: number;
+        step?: number;
+    }
+}
+declare module BabylonViewer {
+    export interface ISkyboxConfiguration {
+        cubeTexture?: {
+            noMipMap?: boolean;
+            gammaSpace?: boolean;
+            url?: string | Array<string>;
+        };
+        color?: {
+            r: number;
+            g: number;
+            b: number;
+        };
+        pbr?: boolean;
+        scale?: number;
+        blur?: number;
+        material?: {
+            imageProcessingConfiguration?: IImageProcessingConfiguration;
+            [propName: string]: any;
+        };
+        infiniteDistance?: boolean;
+    }
+}
+declare module BabylonViewer {
+    /**
+        * A single template configuration object
+        */
+    export interface ITemplateConfiguration {
+            /**
+                * can be either the id of the template's html element or a URL.
+                * See - http://doc.babylonjs.com/extensions/the_templating_system#location-vs-html
+                */
+            location?: string;
+            /**
+                * If no location is provided you can provide here the raw html of this template.
+                * See http://doc.babylonjs.com/extensions/the_templating_system#location-vs-html
+                */
+            html?: string;
+            id?: string;
+            /**
+                * Parameters that will be delivered to the template and will render it accordingly.
+                */
+            params?: {
+                    [key: string]: string | number | boolean | object;
+            };
+            /**
+                * Events to attach to this template.
+                * event name is the key. the value can either be a boolean (attach to the parent element)
+                * or a map of html id elements.
+                *
+                * See - http://doc.babylonjs.com/extensions/the_templating_system#event-binding
+                */
+            events?: {
+                    pointerdown?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerup?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointermove?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerover?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerout?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerenter?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerleave?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointercancel?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    click?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    dragstart?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    drop?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    [key: string]: boolean | {
+                            [id: string]: boolean;
+                    } | undefined;
+            };
+    }
+}
+declare module BabylonViewer {
+    export interface IVRConfiguration {
+        disabled?: boolean;
+        objectScaleFactor?: number;
+        disableInteractions?: boolean;
+        disableTeleportation?: boolean;
+        overrideFloorMeshName?: string;
+        vrOptions?: BABYLON.VRExperienceHelperOptions;
+        modelHeightCorrection?: number | boolean;
+        rotateUsingControllers?: boolean;
+        cameraPosition?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+    }
+}
+declare module BabylonViewer {
     /**
         * Spherical polynomial coefficients (counter part to spherical harmonic coefficients used in shader irradiance calculation)
         * @ignoreChildren

文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


文件差異過大導致無法顯示
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


+ 492 - 1
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -1663,7 +1663,21 @@ declare module 'babylonjs-viewer/loader/plugins' {
 }
 
 declare module 'babylonjs-viewer/configuration/interfaces' {
-    
+    export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/defaultRenderingPipelineConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/groundConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/imageProcessingConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/lightConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/modelAnimationConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/modelConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/observersConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/sceneConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/sceneOptimizerConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/skyboxConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/templateConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/vrConfiguration';
+    export * from 'babylonjs-viewer/configuration/interfaces/environmentMapConfiguration';
 }
 
 declare module 'babylonjs-viewer/configuration/interfaces/environmentMapConfiguration' {
@@ -1857,6 +1871,483 @@ declare module 'babylonjs-viewer/loader/plugins/extendedMaterialLoaderPlugin' {
     }
 }
 
+declare module 'babylonjs-viewer/configuration/interfaces/cameraConfiguration' {
+    export interface ICameraConfiguration {
+        position?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+        rotation?: {
+            x: number;
+            y: number;
+            z: number;
+            w: number;
+        };
+        fov?: number;
+        fovMode?: number;
+        minZ?: number;
+        maxZ?: number;
+        inertia?: number;
+        exposure?: number;
+        pinchPrecision?: number;
+        behaviors?: {
+            [name: string]: boolean | number | ICameraBehaviorConfiguration;
+        };
+        disableCameraControl?: boolean;
+        disableCtrlForPanning?: boolean;
+        disableAutoFocus?: boolean;
+        [propName: string]: any;
+    }
+    export interface ICameraBehaviorConfiguration {
+        type: number;
+        [propName: string]: any;
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration' {
+    /**
+        * The Color Grading Configuration groups the different settings used to define the color grading used in the viewer.
+        */
+    export interface IColorGradingConfiguration {
+            /**
+                * Transform data string, encoded as determined by transformDataFormat.
+                */
+            transformData: string;
+            /**
+                * The encoding format of TransformData (currently only raw-base16 is supported).
+                */
+            transformDataFormat: string;
+            /**
+                * The weight of the transform
+                */
+            transformWeight: number;
+            /**
+                * Color curve colorFilterHueGlobal value
+                */
+            colorFilterHueGlobal: number;
+            /**
+                * Color curve colorFilterHueShadows value
+                */
+            colorFilterHueShadows: number;
+            /**
+                * Color curve colorFilterHueMidtones value
+                */
+            colorFilterHueMidtones: number;
+            /**
+                * Color curve colorFilterHueHighlights value
+                */
+            colorFilterHueHighlights: number;
+            /**
+                * Color curve colorFilterDensityGlobal value
+                */
+            colorFilterDensityGlobal: number;
+            /**
+                * Color curve colorFilterDensityShadows value
+                */
+            colorFilterDensityShadows: number;
+            /**
+                * Color curve colorFilterDensityMidtones value
+                */
+            colorFilterDensityMidtones: number;
+            /**
+                * Color curve colorFilterDensityHighlights value
+                */
+            colorFilterDensityHighlights: number;
+            /**
+                * Color curve saturationGlobal value
+                */
+            saturationGlobal: number;
+            /**
+                * Color curve saturationShadows value
+                */
+            saturationShadows: number;
+            /**
+                * Color curve saturationMidtones value
+                */
+            saturationMidtones: number;
+            /**
+                * Color curve saturationHighlights value
+                */
+            saturationHighlights: number;
+            /**
+                * Color curve exposureGlobal value
+                */
+            exposureGlobal: number;
+            /**
+                * Color curve exposureShadows value
+                */
+            exposureShadows: number;
+            /**
+                * Color curve exposureMidtones value
+                */
+            exposureMidtones: number;
+            /**
+                * Color curve exposureHighlights value
+                */
+            exposureHighlights: number;
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/defaultRenderingPipelineConfiguration' {
+    import { DepthOfFieldEffectBlurLevel } from 'babylonjs';
+    export interface IDefaultRenderingPipelineConfiguration {
+        sharpenEnabled?: boolean;
+        bloomEnabled?: boolean;
+        bloomThreshold?: number;
+        depthOfFieldEnabled?: boolean;
+        depthOfFieldBlurLevel?: DepthOfFieldEffectBlurLevel;
+        fxaaEnabled?: boolean;
+        imageProcessingEnabled?: boolean;
+        defaultPipelineTextureType?: number;
+        bloomScale?: number;
+        chromaticAberrationEnabled?: boolean;
+        grainEnabled?: boolean;
+        bloomKernel?: number;
+        hardwareScaleLevel?: number;
+        bloomWeight?: number;
+        hdr?: boolean;
+        samples?: number;
+        glowLayerEnabled?: boolean;
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/groundConfiguration' {
+    export interface IGroundConfiguration {
+        size?: number;
+        receiveShadows?: boolean;
+        shadowLevel?: number;
+        shadowOnly?: boolean;
+        mirror?: boolean | {
+            sizeRatio?: number;
+            blurKernel?: number;
+            amount?: number;
+            fresnelWeight?: number;
+            fallOffDistance?: number;
+            textureType?: number;
+        };
+        texture?: string;
+        color?: {
+            r: number;
+            g: number;
+            b: number;
+        };
+        opacity?: number;
+        material?: {
+            [propName: string]: any;
+        };
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/imageProcessingConfiguration' {
+    export interface IImageProcessingConfiguration {
+        colorGradingEnabled?: boolean;
+        colorCurvesEnabled?: boolean;
+        colorCurves?: {
+            globalHue?: number;
+            globalDensity?: number;
+            globalSaturation?: number;
+            globalExposure?: number;
+            highlightsHue?: number;
+            highlightsDensity?: number;
+            highlightsSaturation?: number;
+            highlightsExposure?: number;
+            midtonesHue?: number;
+            midtonesDensity?: number;
+            midtonesSaturation?: number;
+            midtonesExposure?: number;
+            shadowsHue?: number;
+            shadowsDensity?: number;
+            shadowsSaturation?: number;
+            shadowsExposure?: number;
+        };
+        colorGradingWithGreenDepth?: boolean;
+        colorGradingBGR?: boolean;
+        exposure?: number;
+        toneMappingEnabled?: boolean;
+        contrast?: number;
+        vignetteEnabled?: boolean;
+        vignetteStretch?: number;
+        vignetteCentreX?: number;
+        vignetteCentreY?: number;
+        vignetteWeight?: number;
+        vignetteColor?: {
+            r: number;
+            g: number;
+            b: number;
+            a?: number;
+        };
+        vignetteCameraFov?: number;
+        vignetteBlendMode?: number;
+        vignetteM?: boolean;
+        applyByPostProcess?: boolean;
+        isEnabled?: boolean;
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/lightConfiguration' {
+    export interface ILightConfiguration {
+        type: number;
+        name?: string;
+        disabled?: boolean;
+        position?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+        target?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+        direction?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+        diffuse?: {
+            r: number;
+            g: number;
+            b: number;
+        };
+        specular?: {
+            r: number;
+            g: number;
+            b: number;
+        };
+        intensity?: number;
+        intensityMode?: number;
+        radius?: number;
+        shadownEnabled?: boolean;
+        shadowConfig?: {
+            useBlurExponentialShadowMap?: boolean;
+            useBlurCloseExponentialShadowMap?: boolean;
+            useKernelBlur?: boolean;
+            blurKernel?: number;
+            blurScale?: number;
+            minZ?: number;
+            maxZ?: number;
+            frustumSize?: number;
+            angleScale?: number;
+            frustumEdgeFalloff?: number;
+            [propName: string]: any;
+        };
+        spotAngle?: number;
+        shadowFieldOfView?: number;
+        shadowBufferSize?: number;
+        shadowFrustumSize?: number;
+        shadowMinZ?: number;
+        shadowMaxZ?: number;
+        [propName: string]: any;
+        behaviors?: {
+            [name: string]: number | {
+                type: number;
+                [propName: string]: any;
+            };
+        };
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/observersConfiguration' {
+    export interface IObserversConfiguration {
+        onEngineInit?: string;
+        onSceneInit?: string;
+        onModelLoaded?: string;
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/sceneConfiguration' {
+    import { IImageProcessingConfiguration } from "babylonjs-viewer/configuration/interfaces/imageProcessingConfiguration";
+    import { IColorGradingConfiguration } from "babylonjs-viewer/configuration/interfaces/colorGradingConfiguration";
+    import { IGlowLayerOptions } from "babylonjs";
+    export interface ISceneConfiguration {
+            debug?: boolean;
+            clearColor?: {
+                    r: number;
+                    g: number;
+                    b: number;
+                    a: number;
+            };
+            /** Deprecated, use environmentMap.mainColor instead. */
+            mainColor?: {
+                    r?: number;
+                    g?: number;
+                    b?: number;
+            };
+            imageProcessingConfiguration?: IImageProcessingConfiguration;
+            environmentTexture?: string;
+            colorGrading?: IColorGradingConfiguration;
+            environmentRotationY?: number;
+            /**
+                * Deprecated, please use default rendering pipeline
+                */
+            glow?: boolean | IGlowLayerOptions;
+            disableHdr?: boolean;
+            renderInBackground?: boolean;
+            disableCameraControl?: boolean;
+            animationPropertiesOverride?: {
+                    [propName: string]: any;
+            };
+            defaultMaterial?: {
+                    materialType: "standard" | "pbr";
+                    [propName: string]: any;
+            };
+            flags?: {
+                    shadowsEnabled?: boolean;
+                    particlesEnabled?: boolean;
+                    collisionsEnabled?: boolean;
+                    lightsEnabled?: boolean;
+                    texturesEnabled?: boolean;
+                    lensFlaresEnabled?: boolean;
+                    proceduralTexturesEnabled?: boolean;
+                    renderTargetsEnabled?: boolean;
+                    spritesEnabled?: boolean;
+                    skeletonsEnabled?: boolean;
+                    audioEnabled?: boolean;
+            };
+            assetsRootURL?: string;
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/sceneOptimizerConfiguration' {
+    export interface ISceneOptimizerConfiguration {
+        targetFrameRate?: number;
+        trackerDuration?: number;
+        autoGeneratePriorities?: boolean;
+        improvementMode?: boolean;
+        degradation?: string;
+        types?: {
+            texture?: ISceneOptimizerParameters;
+            hardwareScaling?: ISceneOptimizerParameters;
+            shadow?: ISceneOptimizerParameters;
+            postProcess?: ISceneOptimizerParameters;
+            lensFlare?: ISceneOptimizerParameters;
+            particles?: ISceneOptimizerParameters;
+            renderTarget?: ISceneOptimizerParameters;
+            mergeMeshes?: ISceneOptimizerParameters;
+        };
+        custom?: string;
+    }
+    export interface ISceneOptimizerParameters {
+        priority?: number;
+        maximumSize?: number;
+        step?: number;
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/skyboxConfiguration' {
+    import { IImageProcessingConfiguration } from "babylonjs-viewer/configuration/interfaces/imageProcessingConfiguration";
+    export interface ISkyboxConfiguration {
+        cubeTexture?: {
+            noMipMap?: boolean;
+            gammaSpace?: boolean;
+            url?: string | Array<string>;
+        };
+        color?: {
+            r: number;
+            g: number;
+            b: number;
+        };
+        pbr?: boolean;
+        scale?: number;
+        blur?: number;
+        material?: {
+            imageProcessingConfiguration?: IImageProcessingConfiguration;
+            [propName: string]: any;
+        };
+        infiniteDistance?: boolean;
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/templateConfiguration' {
+    /**
+        * A single template configuration object
+        */
+    export interface ITemplateConfiguration {
+            /**
+                * can be either the id of the template's html element or a URL.
+                * See - http://doc.babylonjs.com/extensions/the_templating_system#location-vs-html
+                */
+            location?: string;
+            /**
+                * If no location is provided you can provide here the raw html of this template.
+                * See http://doc.babylonjs.com/extensions/the_templating_system#location-vs-html
+                */
+            html?: string;
+            id?: string;
+            /**
+                * Parameters that will be delivered to the template and will render it accordingly.
+                */
+            params?: {
+                    [key: string]: string | number | boolean | object;
+            };
+            /**
+                * Events to attach to this template.
+                * event name is the key. the value can either be a boolean (attach to the parent element)
+                * or a map of html id elements.
+                *
+                * See - http://doc.babylonjs.com/extensions/the_templating_system#event-binding
+                */
+            events?: {
+                    pointerdown?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerup?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointermove?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerover?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerout?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerenter?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointerleave?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    pointercancel?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    click?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    dragstart?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    drop?: boolean | {
+                            [id: string]: boolean;
+                    };
+                    [key: string]: boolean | {
+                            [id: string]: boolean;
+                    } | undefined;
+            };
+    }
+}
+
+declare module 'babylonjs-viewer/configuration/interfaces/vrConfiguration' {
+    import { VRExperienceHelperOptions } from "babylonjs";
+    export interface IVRConfiguration {
+        disabled?: boolean;
+        objectScaleFactor?: number;
+        disableInteractions?: boolean;
+        disableTeleportation?: boolean;
+        overrideFloorMeshName?: string;
+        vrOptions?: VRExperienceHelperOptions;
+        modelHeightCorrection?: number | boolean;
+        rotateUsingControllers?: boolean;
+        cameraPosition?: {
+            x: number;
+            y: number;
+            z: number;
+        };
+    }
+}
+
 declare module 'babylonjs-viewer/labs/environmentSerializer' {
     import { Vector3 } from "babylonjs";
     import { TextureCube } from 'babylonjs-viewer/labs/texture';

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

@@ -18,9 +18,9 @@
 - Added utility function `Tools.BuildArray` for array initialisation ([barroij](https://github.com/barroij))
 - Introduced a new `IOfflineSupport` interface to hide IndexedDB ([Deltakosh](https://github.com/deltakosh))
 - `PBRMaterial` and `StandardMaterial` now use hot swapping feature for shaders. This means they can keep using a previous shader while a new one is being compiled ([Deltakosh](https://github.com/deltakosh))
-- Performance oriented changes ([barroij](https://github.com/barroij))
-  - prevent avoidable matrix inversion or square root computation.
-  - enable a removal in O(1) from the `transformNodes`array of the Scene.
+- Performance oriented updates ([barroij](https://github.com/barroij))
+  - Prevent avoidable matrix inversion or square root computation
+  - Enable a removal in O(1) from the `transformNodes`array of the Scene
 
 ### glTF Loader
 

+ 6 - 6
src/Materials/babylon.material.ts

@@ -467,7 +467,7 @@ module BABYLON {
          * Gets a boolean indicating that current material needs to register RTT
          */
         public get hasRenderTargetTextures(): boolean {
-          return false;
+            return false;
         }
 
         /**
@@ -476,9 +476,9 @@ module BABYLON {
         public doNotSerialize = false;
 
         /**
-         * Specifies if the effect should be stored on sub meshes
+         * @hidden
          */
-        public storeEffectOnSubMeshes = false;
+        public _storeEffectOnSubMeshes = false;
 
         /**
          * Stores the animations for the material
@@ -1100,7 +1100,7 @@ module BABYLON {
                     scene.clipPlane = new Plane(0, 0, 0, 1);
                 }
 
-                if (this.storeEffectOnSubMeshes) {
+                if (this._storeEffectOnSubMeshes) {
                     if (this.isReadyForSubMesh(mesh, subMesh)) {
                         if (onCompiled) {
                             onCompiled(this);
@@ -1282,7 +1282,7 @@ module BABYLON {
                     if ((<Mesh>mesh).geometry) {
                         var geometry = <Geometry>((<Mesh>mesh).geometry);
 
-                        if (this.storeEffectOnSubMeshes) {
+                        if (this._storeEffectOnSubMeshes) {
                             for (var subMesh of mesh.subMeshes) {
                                 geometry._releaseVertexArrayObject(subMesh._materialEffect);
                                 if (forceDisposeEffect && subMesh._materialEffect) {
@@ -1300,7 +1300,7 @@ module BABYLON {
 
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             if (forceDisposeEffect && this._effect) {
-                if (!this.storeEffectOnSubMeshes) {
+                if (!this._storeEffectOnSubMeshes) {
                     this._scene.getEngine()._releaseEffect(this._effect);
                 }
 

+ 2 - 2
src/Materials/babylon.multiMaterial.ts

@@ -35,7 +35,7 @@ module BABYLON {
 
             this.subMaterials = new Array<Material>();
 
-            this.storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
+            this._storeEffectOnSubMeshes = true; // multimaterial is considered like a push material
         }
 
         private _hookArray(array: Nullable<Material>[]): void {
@@ -105,7 +105,7 @@ module BABYLON {
             for (var index = 0; index < this.subMaterials.length; index++) {
                 var subMaterial = this.subMaterials[index];
                 if (subMaterial) {
-                    if (subMaterial.storeEffectOnSubMeshes) {
+                    if (subMaterial._storeEffectOnSubMeshes) {
                         if (!subMaterial.isReadyForSubMesh(mesh, subMesh, useInstances)) {
                             return false;
                         }

+ 1 - 1
src/Materials/babylon.pushMaterial.ts

@@ -18,7 +18,7 @@ module BABYLON {
 
         constructor(name: string, scene: Scene) {
             super(name, scene);
-            this.storeEffectOnSubMeshes = true;
+            this._storeEffectOnSubMeshes = true;
         }
 
         public getEffect(): Effect {

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

@@ -759,11 +759,11 @@ module BABYLON {
 
             let mat = this.material || scene.defaultMaterial;
             if (mat) {
-                if (mat.storeEffectOnSubMeshes) {
+                if (mat._storeEffectOnSubMeshes) {
                     for (var subMesh of this.subMeshes) {
                         let effectiveMaterial = subMesh.getMaterial();
                         if (effectiveMaterial) {
-                            if (effectiveMaterial.storeEffectOnSubMeshes) {
+                            if (effectiveMaterial._storeEffectOnSubMeshes) {
                                 if (!effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
                                     return false;
                                 }
@@ -1533,7 +1533,7 @@ module BABYLON {
 
             this._effectiveMaterial = material;
 
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 if (!this._effectiveMaterial.isReadyForSubMesh(this, subMesh, hardwareInstancedRendering)) {
                     return this;
                 }
@@ -1551,7 +1551,7 @@ module BABYLON {
             }
 
             var effect: Nullable<Effect>;
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 effect = subMesh.effect;
             } else {
                 effect = this._effectiveMaterial.getEffect();
@@ -1584,7 +1584,7 @@ module BABYLON {
 
             var world = this.getWorldMatrix();
 
-            if (this._effectiveMaterial.storeEffectOnSubMeshes) {
+            if (this._effectiveMaterial._storeEffectOnSubMeshes) {
                 this._effectiveMaterial.bindForSubMesh(world, this, subMesh);
             } else {
                 this._effectiveMaterial.bind(world, this);

+ 3 - 2
src/babylon.scene.ts

@@ -1960,9 +1960,10 @@ module BABYLON {
                             }
                         }
                     }
+                } else {
+                    clickInfo.ignore = true;
+                    cb(clickInfo, this._currentPickResult);
                 }
-                clickInfo.ignore = true;
-                cb(clickInfo, this._currentPickResult);
             };
 
             this._onPointerMove = (evt: PointerEvent) => {

+ 1 - 1
src/babylon.sceneComponent.ts

@@ -138,7 +138,7 @@ module BABYLON {
     /**
      * Strong typing of a Active Mesh related stage step action
      */
-    export type ActiveMeshStageAction =  (sourceMesh: AbstractMesh, mesh: AbstractMesh) => void;
+    export type ActiveMeshStageAction = (sourceMesh: AbstractMesh, mesh: AbstractMesh) => void;
 
     /**
      * Strong typing of a Camera related stage step action

+ 2 - 2
tests/validation/validation.js

@@ -7,7 +7,7 @@ var config;
 var justOnce;
 
 var threshold = 25;
-var errorCountThreshold = 400;
+var errorRatio = 2.5;
 
 // Overload the random to make it deterministic
 var seed = 100000,
@@ -52,7 +52,7 @@ function compare(renderData, referenceCanvas) {
         console.log("Pixel difference: " + differencesCount + " pixels.");
     }
 
-    return differencesCount > errorCountThreshold;
+    return (differencesCount * 100) / (width * height) > errorRatio;
 }
 
 function getRenderData(canvas, engine) {