Browse Source

Merge remote-tracking branch 'refs/remotes/BabylonJS/master' into ParticleAnimation

# Conflicts:
#	dist/preview release/babylon.d.ts
#	dist/preview release/babylon.js
#	dist/preview release/babylon.module.d.ts
#	dist/preview release/babylon.worker.js
DESKTOP-QJU4N0L\mityh 8 years ago
parent
commit
1b0fa69194
26 changed files with 11848 additions and 11776 deletions
  1. 45 30
      dist/preview release/babylon.max.js
  2. 5688 5676
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  3. 45 45
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  4. 45 30
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  5. 5688 5676
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  6. 3 3
      dist/preview release/gui/babylon.gui.min.js
  7. 263 263
      dist/preview release/inspector/babylon.inspector.bundle.js
  8. 6 0
      dist/preview release/inspector/babylon.inspector.js
  9. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  10. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  11. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  12. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  13. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  14. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  15. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  16. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  17. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  18. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  19. 6 0
      inspector/src/tabs/StatsTab.ts
  20. 2 0
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  21. 2 1
      src/Lights/Shadows/babylon.shadowGenerator.ts
  22. 1 1
      src/Materials/Textures/babylon.renderTargetTexture.ts
  23. 3 31
      src/Mesh/babylon.abstractMesh.ts
  24. 2 2
      src/PostProcess/babylon.postProcessManager.ts
  25. 2 1
      src/Sprites/babylon.sprite.ts
  26. 33 3
      src/babylon.scene.ts

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

@@ -13955,30 +13955,11 @@ var BABYLON;
                 child.position.z = position.z;
             }
             else {
-                var rotation = BABYLON.Tmp.Quaternion[0];
                 var position = BABYLON.Tmp.Vector3[0];
-                var scale = BABYLON.Tmp.Vector3[1];
                 var m1 = BABYLON.Tmp.Matrix[0];
-                var m2 = BABYLON.Tmp.Matrix[1];
-                parent.getWorldMatrix().decompose(scale, rotation, position);
-                rotation.toRotationMatrix(m1);
-                m2.setTranslation(position);
-                m2.multiplyToRef(m1, m1);
-                var invParentMatrix = BABYLON.Matrix.Invert(m1);
-                var m = child.getWorldMatrix().multiply(invParentMatrix);
-                m.decompose(scale, rotation, position);
-                if (child.rotationQuaternion) {
-                    child.rotationQuaternion.copyFrom(rotation);
-                }
-                else {
-                    rotation.toEulerAnglesToRef(child.rotation);
-                }
-                invParentMatrix = BABYLON.Matrix.Invert(parent.getWorldMatrix());
-                var m = child.getWorldMatrix().multiply(invParentMatrix);
-                m.decompose(scale, rotation, position);
-                child.position.x = position.x;
-                child.position.y = position.y;
-                child.position.z = position.z;
+                parent.getWorldMatrix().invertToRef(m1);
+                BABYLON.Vector3.TransformCoordinatesToRef(child.position, m1, position);
+                child.position.copyFrom(position);
             }
             child.parent = parent;
             return this;
@@ -16715,6 +16696,7 @@ var BABYLON;
             this._totalVertices = new BABYLON.PerfCounter();
             this._activeIndices = new BABYLON.PerfCounter();
             this._activeParticles = new BABYLON.PerfCounter();
+            this._interFrameDuration = new BABYLON.PerfCounter();
             this._lastFrameDuration = new BABYLON.PerfCounter();
             this._evaluateActiveMeshesDuration = new BABYLON.PerfCounter();
             this._renderTargetsDuration = new BABYLON.PerfCounter();
@@ -16741,6 +16723,7 @@ var BABYLON;
             this._transformMatrix = BABYLON.Matrix.Zero();
             this.requireLightSorting = false;
             this._uniqueIdCounter = 0;
+            this._activeMeshesFrozen = false;
             this._engine = engine || BABYLON.Engine.LastCreatedEngine;
             this._engine.scenes.push(this);
             this._uid = null;
@@ -17197,6 +17180,16 @@ var BABYLON;
             configurable: true
         });
         // Stats
+        Scene.prototype.getInterFramePerfCounter = function () {
+            return this._interFrameDuration.current;
+        };
+        Object.defineProperty(Scene.prototype, "interFramePerfCounter", {
+            get: function () {
+                return this._interFrameDuration;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Scene.prototype.getLastFrameDuration = function () {
             return this._lastFrameDuration.current;
         };
@@ -18622,7 +18615,25 @@ var BABYLON;
         Scene.prototype._isInIntermediateRendering = function () {
             return this._intermediateRendering;
         };
+        /**
+         * Use this function to stop evaluating active meshes. The current list will be keep alive between frames
+         */
+        Scene.prototype.freezeActiveMeshes = function () {
+            this._evaluateActiveMeshes();
+            this._activeMeshesFrozen = true;
+            return this;
+        };
+        /**
+         * Use this function to restart evaluating active meshes on every frame
+         */
+        Scene.prototype.unfreezeActiveMeshes = function () {
+            this._activeMeshesFrozen = false;
+            return this;
+        };
         Scene.prototype._evaluateActiveMeshes = function () {
+            if (this._activeMeshesFrozen && this._activeMeshes.length) {
+                return;
+            }
             this.activeCamera._activeMeshes.reset();
             this._activeMeshes.reset();
             this._renderingManager.reset();
@@ -18931,6 +18942,7 @@ var BABYLON;
             if (this.isDisposed) {
                 return;
             }
+            this._interFrameDuration.endMonitoring();
             this._lastFrameDuration.beginMonitoring();
             this._particlesDuration.fetchNewFrame();
             this._spritesDuration.fetchNewFrame();
@@ -18979,9 +18991,6 @@ var BABYLON;
                     this.onAfterStepObservable.notifyObservers(this);
                     this._currentStepId++;
                     if ((internalSteps > 1) && (this._currentInternalStep != internalSteps - 1)) {
-                        // Q: can this be optimized by putting some code in the afterStep callback?
-                        // I had to put this code here, otherwise mesh attached to bones of another mesh skeleton,
-                        // would return incorrect positions for internal stepIds (non-rendered steps)
                         this._evaluateActiveMeshes();
                     }
                 }
@@ -19108,6 +19117,7 @@ var BABYLON;
                 this.dumpNextRenderTargets = false;
             }
             BABYLON.Tools.EndPerformanceCounter("Scene rendering");
+            this._interFrameDuration.beginMonitoring();
             this._lastFrameDuration.endMonitoring();
             this._totalMeshesCounter.addCount(this.meshes.length, true);
             this._totalLightsCounter.addCount(this.lights.length, true);
@@ -30157,7 +30167,8 @@ var BABYLON;
             engine.setDepthBuffer(true);
             engine.setDepthWrite(true);
         };
-        PostProcessManager.prototype._finalizeFrame = function (doNotPresent, targetTexture, faceIndex, postProcesses) {
+        PostProcessManager.prototype._finalizeFrame = function (doNotPresent, targetTexture, faceIndex, postProcesses, forceFullscreenViewport) {
+            if (forceFullscreenViewport === void 0) { forceFullscreenViewport = false; }
             postProcesses = postProcesses || this._scene.activeCamera._postProcesses;
             if (postProcesses.length === 0 || !this._scene.postProcessesEnabled) {
                 return;
@@ -30169,7 +30180,7 @@ var BABYLON;
                 }
                 else {
                     if (targetTexture) {
-                        engine.bindFramebuffer(targetTexture, faceIndex);
+                        engine.bindFramebuffer(targetTexture, faceIndex, null, null, forceFullscreenViewport);
                     }
                     else {
                         engine.restoreDefaultFramebuffer();
@@ -39837,11 +39848,12 @@ var BABYLON;
             if (this._time > this._delay) {
                 this._time = this._time % this._delay;
                 this.cellIndex += this._direction;
-                if (this.cellIndex === this._toIndex) {
+                if (this.cellIndex > this._toIndex) {
                     if (this._loopAnimation) {
                         this.cellIndex = this._fromIndex;
                     }
                     else {
+                        this.cellIndex = this._toIndex;
                         this._animationStarted = false;
                         if (this._onAnimationEnd) {
                             this._onAnimationEnd();
@@ -46463,7 +46475,7 @@ var BABYLON;
             // Render
             this._renderingManager.render(this.customRenderFunction, currentRenderList, this.renderParticles, this.renderSprites);
             if (this._postProcessManager) {
-                this._postProcessManager._finalizeFrame(false, this._texture, faceIndex, this._postProcesses);
+                this._postProcessManager._finalizeFrame(false, this._texture, faceIndex, this._postProcesses, this.ignoreCameraViewport);
             }
             else if (useCameraPostProcess) {
                 scene.postProcessManager._finalizeFrame(false, this._texture, faceIndex);
@@ -47964,6 +47976,7 @@ var BABYLON;
             this._shadowMap.anisotropicFilteringLevel = 1;
             this._shadowMap.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE);
             this._shadowMap.renderParticles = false;
+            this._shadowMap.ignoreCameraViewport = true;
             // Record Face Index before render.
             this._shadowMap.onBeforeRenderObservable.add(function (faceIndex) {
                 _this._currentFaceIndex = faceIndex;
@@ -47978,7 +47991,7 @@ var BABYLON;
                 if (!_this._blurPostProcesses) {
                     _this._initializeBlurRTTAndPostProcesses();
                 }
-                _this._scene.postProcessManager.directRender(_this._blurPostProcesses, _this.getShadowMapForRendering().getInternalTexture());
+                _this._scene.postProcessManager.directRender(_this._blurPostProcesses, _this.getShadowMapForRendering().getInternalTexture(), true);
             });
             // Clear according to the chosen filter.
             this._shadowMap.onClearObservable.add(function (engine) {
@@ -66978,6 +66991,8 @@ var BABYLON;
                 if (scene.activeCamera.rotation) {
                     newCamera.rotation = scene.activeCamera.rotation.clone();
                 }
+                newCamera.minZ = this._scene.activeCamera.minZ;
+                newCamera.maxZ = this._scene.activeCamera.maxZ;
                 this._scene.activeCamera = newCamera;
             }
             this._position = this._scene.activeCamera.position;

File diff suppressed because it is too large
+ 5688 - 5676
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


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


+ 45 - 30
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -13955,30 +13955,11 @@ var BABYLON;
                 child.position.z = position.z;
             }
             else {
-                var rotation = BABYLON.Tmp.Quaternion[0];
                 var position = BABYLON.Tmp.Vector3[0];
-                var scale = BABYLON.Tmp.Vector3[1];
                 var m1 = BABYLON.Tmp.Matrix[0];
-                var m2 = BABYLON.Tmp.Matrix[1];
-                parent.getWorldMatrix().decompose(scale, rotation, position);
-                rotation.toRotationMatrix(m1);
-                m2.setTranslation(position);
-                m2.multiplyToRef(m1, m1);
-                var invParentMatrix = BABYLON.Matrix.Invert(m1);
-                var m = child.getWorldMatrix().multiply(invParentMatrix);
-                m.decompose(scale, rotation, position);
-                if (child.rotationQuaternion) {
-                    child.rotationQuaternion.copyFrom(rotation);
-                }
-                else {
-                    rotation.toEulerAnglesToRef(child.rotation);
-                }
-                invParentMatrix = BABYLON.Matrix.Invert(parent.getWorldMatrix());
-                var m = child.getWorldMatrix().multiply(invParentMatrix);
-                m.decompose(scale, rotation, position);
-                child.position.x = position.x;
-                child.position.y = position.y;
-                child.position.z = position.z;
+                parent.getWorldMatrix().invertToRef(m1);
+                BABYLON.Vector3.TransformCoordinatesToRef(child.position, m1, position);
+                child.position.copyFrom(position);
             }
             child.parent = parent;
             return this;
@@ -16715,6 +16696,7 @@ var BABYLON;
             this._totalVertices = new BABYLON.PerfCounter();
             this._activeIndices = new BABYLON.PerfCounter();
             this._activeParticles = new BABYLON.PerfCounter();
+            this._interFrameDuration = new BABYLON.PerfCounter();
             this._lastFrameDuration = new BABYLON.PerfCounter();
             this._evaluateActiveMeshesDuration = new BABYLON.PerfCounter();
             this._renderTargetsDuration = new BABYLON.PerfCounter();
@@ -16741,6 +16723,7 @@ var BABYLON;
             this._transformMatrix = BABYLON.Matrix.Zero();
             this.requireLightSorting = false;
             this._uniqueIdCounter = 0;
+            this._activeMeshesFrozen = false;
             this._engine = engine || BABYLON.Engine.LastCreatedEngine;
             this._engine.scenes.push(this);
             this._uid = null;
@@ -17197,6 +17180,16 @@ var BABYLON;
             configurable: true
         });
         // Stats
+        Scene.prototype.getInterFramePerfCounter = function () {
+            return this._interFrameDuration.current;
+        };
+        Object.defineProperty(Scene.prototype, "interFramePerfCounter", {
+            get: function () {
+                return this._interFrameDuration;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Scene.prototype.getLastFrameDuration = function () {
             return this._lastFrameDuration.current;
         };
@@ -18622,7 +18615,25 @@ var BABYLON;
         Scene.prototype._isInIntermediateRendering = function () {
             return this._intermediateRendering;
         };
+        /**
+         * Use this function to stop evaluating active meshes. The current list will be keep alive between frames
+         */
+        Scene.prototype.freezeActiveMeshes = function () {
+            this._evaluateActiveMeshes();
+            this._activeMeshesFrozen = true;
+            return this;
+        };
+        /**
+         * Use this function to restart evaluating active meshes on every frame
+         */
+        Scene.prototype.unfreezeActiveMeshes = function () {
+            this._activeMeshesFrozen = false;
+            return this;
+        };
         Scene.prototype._evaluateActiveMeshes = function () {
+            if (this._activeMeshesFrozen && this._activeMeshes.length) {
+                return;
+            }
             this.activeCamera._activeMeshes.reset();
             this._activeMeshes.reset();
             this._renderingManager.reset();
@@ -18931,6 +18942,7 @@ var BABYLON;
             if (this.isDisposed) {
                 return;
             }
+            this._interFrameDuration.endMonitoring();
             this._lastFrameDuration.beginMonitoring();
             this._particlesDuration.fetchNewFrame();
             this._spritesDuration.fetchNewFrame();
@@ -18979,9 +18991,6 @@ var BABYLON;
                     this.onAfterStepObservable.notifyObservers(this);
                     this._currentStepId++;
                     if ((internalSteps > 1) && (this._currentInternalStep != internalSteps - 1)) {
-                        // Q: can this be optimized by putting some code in the afterStep callback?
-                        // I had to put this code here, otherwise mesh attached to bones of another mesh skeleton,
-                        // would return incorrect positions for internal stepIds (non-rendered steps)
                         this._evaluateActiveMeshes();
                     }
                 }
@@ -19108,6 +19117,7 @@ var BABYLON;
                 this.dumpNextRenderTargets = false;
             }
             BABYLON.Tools.EndPerformanceCounter("Scene rendering");
+            this._interFrameDuration.beginMonitoring();
             this._lastFrameDuration.endMonitoring();
             this._totalMeshesCounter.addCount(this.meshes.length, true);
             this._totalLightsCounter.addCount(this.lights.length, true);
@@ -30157,7 +30167,8 @@ var BABYLON;
             engine.setDepthBuffer(true);
             engine.setDepthWrite(true);
         };
-        PostProcessManager.prototype._finalizeFrame = function (doNotPresent, targetTexture, faceIndex, postProcesses) {
+        PostProcessManager.prototype._finalizeFrame = function (doNotPresent, targetTexture, faceIndex, postProcesses, forceFullscreenViewport) {
+            if (forceFullscreenViewport === void 0) { forceFullscreenViewport = false; }
             postProcesses = postProcesses || this._scene.activeCamera._postProcesses;
             if (postProcesses.length === 0 || !this._scene.postProcessesEnabled) {
                 return;
@@ -30169,7 +30180,7 @@ var BABYLON;
                 }
                 else {
                     if (targetTexture) {
-                        engine.bindFramebuffer(targetTexture, faceIndex);
+                        engine.bindFramebuffer(targetTexture, faceIndex, null, null, forceFullscreenViewport);
                     }
                     else {
                         engine.restoreDefaultFramebuffer();
@@ -39837,11 +39848,12 @@ var BABYLON;
             if (this._time > this._delay) {
                 this._time = this._time % this._delay;
                 this.cellIndex += this._direction;
-                if (this.cellIndex === this._toIndex) {
+                if (this.cellIndex > this._toIndex) {
                     if (this._loopAnimation) {
                         this.cellIndex = this._fromIndex;
                     }
                     else {
+                        this.cellIndex = this._toIndex;
                         this._animationStarted = false;
                         if (this._onAnimationEnd) {
                             this._onAnimationEnd();
@@ -46287,7 +46299,7 @@ var BABYLON;
             // Render
             this._renderingManager.render(this.customRenderFunction, currentRenderList, this.renderParticles, this.renderSprites);
             if (this._postProcessManager) {
-                this._postProcessManager._finalizeFrame(false, this._texture, faceIndex, this._postProcesses);
+                this._postProcessManager._finalizeFrame(false, this._texture, faceIndex, this._postProcesses, this.ignoreCameraViewport);
             }
             else if (useCameraPostProcess) {
                 scene.postProcessManager._finalizeFrame(false, this._texture, faceIndex);
@@ -47788,6 +47800,7 @@ var BABYLON;
             this._shadowMap.anisotropicFilteringLevel = 1;
             this._shadowMap.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE);
             this._shadowMap.renderParticles = false;
+            this._shadowMap.ignoreCameraViewport = true;
             // Record Face Index before render.
             this._shadowMap.onBeforeRenderObservable.add(function (faceIndex) {
                 _this._currentFaceIndex = faceIndex;
@@ -47802,7 +47815,7 @@ var BABYLON;
                 if (!_this._blurPostProcesses) {
                     _this._initializeBlurRTTAndPostProcesses();
                 }
-                _this._scene.postProcessManager.directRender(_this._blurPostProcesses, _this.getShadowMapForRendering().getInternalTexture());
+                _this._scene.postProcessManager.directRender(_this._blurPostProcesses, _this.getShadowMapForRendering().getInternalTexture(), true);
             });
             // Clear according to the chosen filter.
             this._shadowMap.onClearObservable.add(function (engine) {
@@ -66802,6 +66815,8 @@ var BABYLON;
                 if (scene.activeCamera.rotation) {
                     newCamera.rotation = scene.activeCamera.rotation.clone();
                 }
+                newCamera.minZ = this._scene.activeCamera.minZ;
+                newCamera.maxZ = this._scene.activeCamera.maxZ;
                 this._scene.activeCamera = newCamera;
             }
             this._position = this._scene.activeCamera.position;

File diff suppressed because it is too large
+ 5688 - 5676
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


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


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


+ 6 - 0
dist/preview release/inspector/babylon.inspector.js

@@ -3780,6 +3780,12 @@ var INSPECTOR;
                     elem: elemValue,
                     updateFct: function () { return BABYLON.Tools.Format(_this._scene.getLastFrameDuration()); }
                 });
+                elemLabel = _this._createStatLabel("Inter-frame", _this._panel);
+                elemValue = INSPECTOR.Helpers.CreateDiv('stat-value', _this._panel);
+                _this._updatableProperties.push({
+                    elem: elemValue,
+                    updateFct: function () { return BABYLON.Tools.Format(_this._scene.getInterFramePerfCounter()); }
+                });
                 elemLabel = _this._createStatLabel("Potential FPS", _this._panel);
                 elemValue = INSPECTOR.Helpers.CreateDiv('stat-value', _this._panel);
                 _this._updatableProperties.push({

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


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


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


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


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


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


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


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


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


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


+ 6 - 0
inspector/src/tabs/StatsTab.ts

@@ -157,6 +157,12 @@ module INSPECTOR {
                     elem:elemValue, 
                     updateFct:() => { return BABYLON.Tools.Format(this._scene.getLastFrameDuration())}
                 });
+                elemLabel = this._createStatLabel("Inter-frame", this._panel);
+                elemValue = Helpers.CreateDiv('stat-value', this._panel);
+                this._updatableProperties.push({ 
+                    elem:elemValue, 
+                    updateFct:() => { return BABYLON.Tools.Format(this._scene.getInterFramePerfCounter())}
+                });                
                 elemLabel = this._createStatLabel("Potential FPS", this._panel);
                 elemValue = Helpers.CreateDiv('stat-value', this._panel);
                 this._updatableProperties.push({ 

+ 2 - 0
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -18,6 +18,8 @@ module BABYLON {
                 if ((<FreeCamera>scene.activeCamera).rotation) {
                     newCamera.rotation = (<FreeCamera>scene.activeCamera).rotation.clone();
                 }
+                newCamera.minZ = this._scene.activeCamera.minZ;
+                newCamera.maxZ = this._scene.activeCamera.maxZ;
                 this._scene.activeCamera = newCamera;
             }
             this._position = this._scene.activeCamera.position;

+ 2 - 1
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -367,6 +367,7 @@
             this._shadowMap.anisotropicFilteringLevel = 1;
             this._shadowMap.updateSamplingMode(Texture.BILINEAR_SAMPLINGMODE);
             this._shadowMap.renderParticles = false;
+            this._shadowMap.ignoreCameraViewport = true;
 
             // Record Face Index before render.
             this._shadowMap.onBeforeRenderObservable.add((faceIndex: number) => {
@@ -386,7 +387,7 @@
                     this._initializeBlurRTTAndPostProcesses();
                 }
 
-                this._scene.postProcessManager.directRender(this._blurPostProcesses, this.getShadowMapForRendering().getInternalTexture());
+                this._scene.postProcessManager.directRender(this._blurPostProcesses, this.getShadowMapForRendering().getInternalTexture(), true);
             });
 
             // Clear according to the chosen filter.

+ 1 - 1
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -424,7 +424,7 @@
             this._renderingManager.render(this.customRenderFunction, currentRenderList, this.renderParticles, this.renderSprites);
 
             if (this._postProcessManager) {
-                this._postProcessManager._finalizeFrame(false, this._texture, faceIndex, this._postProcesses);
+                this._postProcessManager._finalizeFrame(false, this._texture, faceIndex, this._postProcesses, this.ignoreCameraViewport);
             }
             else if (useCameraPostProcess) {
                 scene.postProcessManager._finalizeFrame(false, this._texture, faceIndex);

+ 3 - 31
src/Mesh/babylon.abstractMesh.ts

@@ -1995,41 +1995,13 @@
 
             } else {
 
-                var rotation = Tmp.Quaternion[0];
                 var position = Tmp.Vector3[0];
-                var scale = Tmp.Vector3[1];
                 var m1 = Tmp.Matrix[0];
-                var m2 = Tmp.Matrix[1];
-
-                parent.getWorldMatrix().decompose(scale, rotation, position);
-
-                rotation.toRotationMatrix(m1);
-                m2.setTranslation(position);
-
-                m2.multiplyToRef(m1, m1);
-
-                var invParentMatrix = Matrix.Invert(m1);
-
-                var m = child.getWorldMatrix().multiply(invParentMatrix);
-
-                m.decompose(scale, rotation, position);
-
-                if (child.rotationQuaternion) {
-                    child.rotationQuaternion.copyFrom(rotation);
-                } else {
-                    rotation.toEulerAnglesToRef(child.rotation);
-                }
-
-                invParentMatrix = Matrix.Invert(parent.getWorldMatrix());
 
-                var m = child.getWorldMatrix().multiply(invParentMatrix);
-
-                m.decompose(scale, rotation, position);
-
-                child.position.x = position.x;
-                child.position.y = position.y;
-                child.position.z = position.z;
+                parent.getWorldMatrix().invertToRef(m1);
+                Vector3.TransformCoordinatesToRef(child.position, m1, position);
 
+                child.position.copyFrom(position);
             }
             child.parent = parent;
             return this;

+ 2 - 2
src/PostProcess/babylon.postProcessManager.ts

@@ -95,7 +95,7 @@
             engine.setDepthWrite(true);
         }
 
-        public _finalizeFrame(doNotPresent?: boolean, targetTexture?: InternalTexture, faceIndex?: number, postProcesses?: PostProcess[]): void {
+        public _finalizeFrame(doNotPresent?: boolean, targetTexture?: InternalTexture, faceIndex?: number, postProcesses?: PostProcess[], forceFullscreenViewport = false): void {
             postProcesses = postProcesses || this._scene.activeCamera._postProcesses;
             if (postProcesses.length === 0 || !this._scene.postProcessesEnabled) {
                 return;
@@ -107,7 +107,7 @@
                     postProcesses[index + 1].activate(this._scene.activeCamera, targetTexture);
                 } else {
                     if (targetTexture) {
-                        engine.bindFramebuffer(targetTexture, faceIndex);
+                        engine.bindFramebuffer(targetTexture, faceIndex, null, null, forceFullscreenViewport);
                     } else {
                         engine.restoreDefaultFramebuffer();
                     }

+ 2 - 1
src/Sprites/babylon.sprite.ts

@@ -68,10 +68,11 @@
             if (this._time > this._delay) {
                 this._time = this._time % this._delay;
                 this.cellIndex += this._direction;
-                if (this.cellIndex === this._toIndex) {
+                if (this.cellIndex > this._toIndex) {
                     if (this._loopAnimation) {
                         this.cellIndex = this._fromIndex;
                     } else {
+                        this.cellIndex = this._toIndex;
                         this._animationStarted = false;
                         if (this._onAnimationEnd) {
                             this._onAnimationEnd();

+ 33 - 3
src/babylon.scene.ts

@@ -706,6 +706,7 @@
         private _totalVertices = new PerfCounter();
         public _activeIndices = new PerfCounter();
         public _activeParticles = new PerfCounter();
+        private _interFrameDuration = new PerfCounter();
         private _lastFrameDuration = new PerfCounter();
         private _evaluateActiveMeshesDuration = new PerfCounter();
         private _renderTargetsDuration = new PerfCounter();
@@ -943,6 +944,14 @@
         }
 
         // Stats
+        public getInterFramePerfCounter(): number {
+            return this._interFrameDuration.current;
+        }
+
+        public get interFramePerfCounter(): PerfCounter {
+            return this._interFrameDuration;
+        }
+
         public getLastFrameDuration(): number {
             return this._lastFrameDuration.current;
         }
@@ -2597,8 +2606,30 @@
         public _isInIntermediateRendering(): boolean {
             return this._intermediateRendering
         }
+        
+        private _activeMeshesFrozen = false;
+
+        /**
+         * Use this function to stop evaluating active meshes. The current list will be keep alive between frames
+         */
+        public freezeActiveMeshes(): Scene {
+            this._evaluateActiveMeshes();
+            this._activeMeshesFrozen = true;
+            return this;
+        }
+        
+        /**
+         * Use this function to restart evaluating active meshes on every frame
+         */
+        public unfreezeActiveMeshes() {
+            this._activeMeshesFrozen = false;
+            return this;
+        }
 
         private _evaluateActiveMeshes(): void {
+            if (this._activeMeshesFrozen && this._activeMeshes.length) {
+                return;
+            }
             this.activeCamera._activeMeshes.reset();
             this._activeMeshes.reset();
             this._renderingManager.reset();
@@ -2984,6 +3015,7 @@
                 return;
             }
 
+            this._interFrameDuration.endMonitoring();
             this._lastFrameDuration.beginMonitoring();
             this._particlesDuration.fetchNewFrame();
             this._spritesDuration.fetchNewFrame();
@@ -3046,9 +3078,6 @@
                 this._currentStepId++;
 
                 if((internalSteps > 1) && (this._currentInternalStep != internalSteps - 1)) {
-                    // Q: can this be optimized by putting some code in the afterStep callback?
-                    // I had to put this code here, otherwise mesh attached to bones of another mesh skeleton,
-                    // would return incorrect positions for internal stepIds (non-rendered steps)
                     this._evaluateActiveMeshes();
                 }
               }
@@ -3202,6 +3231,7 @@
             }
 
             Tools.EndPerformanceCounter("Scene rendering");
+            this._interFrameDuration.beginMonitoring();           
             this._lastFrameDuration.endMonitoring();
             this._totalMeshesCounter.addCount(this.meshes.length, true);
             this._totalLightsCounter.addCount(this.lights.length, true);