فهرست منبع

Nightly + particles pre-warming

David Catuhe 7 سال پیش
والد
کامیت
95efda3eb6

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 11605 - 11605
Playground/babylon.d.txt


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 13119 - 13114
dist/preview release/babylon.d.ts


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7 - 7
dist/preview release/babylon.js


+ 78 - 31
dist/preview release/babylon.max.js

@@ -55345,6 +55345,10 @@ var BABYLON;
              * If using a spritesheet (isAnimationSheetEnabled), defines the sprite cell height to use
              */
             this.spriteCellHeight = 0;
+            /** Gets or sets a value indicating how many cycles (or frames) must be executed before first rendering (this value has to be set before starting the system). Default is 0 */
+            this.preWarmCycles = 0;
+            /** Gets or sets a value indicating the time step multiplier to use in pre-warm mode (default is 1) */
+            this.preWarmStepOffset = 1;
             /**
             * An event triggered when the system is disposed
             */
@@ -55734,6 +55738,11 @@ var BABYLON;
             if (this.subEmitters && this.subEmitters.length != 0) {
                 this.activeSubSystems = new Array();
             }
+            if (this.preWarmCycles) {
+                for (var index = 0; index < this.preWarmCycles; index++) {
+                    this.animate(true);
+                }
+            }
         };
         /**
          * Stops the particle system.
@@ -55913,19 +55922,23 @@ var BABYLON;
         };
         /**
          * Animates the particle system for the current frame by emitting new particles and or animating the living ones.
+         * @param preWarmOnly will prevent the system from updating the vertex buffer (default is false)
          */
-        ParticleSystem.prototype.animate = function () {
+        ParticleSystem.prototype.animate = function (preWarmOnly) {
+            if (preWarmOnly === void 0) { preWarmOnly = false; }
             if (!this._started)
                 return;
-            var effect = this._getEffect();
-            // Check
-            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
-                return;
-            if (this._currentRenderId === this._scene.getRenderId()) {
-                return;
+            if (!preWarmOnly) {
+                var effect = this._getEffect();
+                // Check
+                if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
+                    return;
+                if (this._currentRenderId === this._scene.getRenderId()) {
+                    return;
+                }
+                this._currentRenderId = this._scene.getRenderId();
             }
-            this._currentRenderId = this._scene.getRenderId();
-            this._scaledUpdateSpeed = this.updateSpeed * this._scene.getAnimationRatio();
+            this._scaledUpdateSpeed = this.updateSpeed * (preWarmOnly ? this.preWarmStepOffset : this._scene.getAnimationRatio());
             // determine the number of particles we need to create
             var newParticles;
             if (this.manualEmitCount > -1) {
@@ -55963,15 +55976,17 @@ var BABYLON;
                     }
                 }
             }
-            // Update VBO
-            var offset = 0;
-            for (var index = 0; index < this._particles.length; index++) {
-                var particle = this._particles[index];
-                this._appendParticleVertices(offset, particle);
-                offset += this._useInstancing ? 1 : 4;
-            }
-            if (this._vertexBuffer) {
-                this._vertexBuffer.update(this._vertexData);
+            if (!preWarmOnly) {
+                // Update VBO
+                var offset = 0;
+                for (var index = 0; index < this._particles.length; index++) {
+                    var particle = this._particles[index];
+                    this._appendParticleVertices(offset, particle);
+                    offset += this._useInstancing ? 1 : 4;
+                }
+                if (this._vertexBuffer) {
+                    this._vertexBuffer.update(this._vertexData);
+                }
             }
             if (this.manualEmitCount === 0 && this.disposeOnStop) {
                 this.stop();
@@ -61924,7 +61939,7 @@ var BABYLON;
         /**
         * Create a sound and attach it to a scene
         * @param name Name of your sound
-        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer
+        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer, it also works with MediaStreams
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
         * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel, streaming
         */
@@ -61999,15 +62014,32 @@ var BABYLON;
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 if (urlOrArrayBuffer) {
                     try {
-                        if (typeof (urlOrArrayBuffer) === "string")
+                        if (typeof (urlOrArrayBuffer) === "string") {
                             this._urlType = "String";
-                        if (Array.isArray(urlOrArrayBuffer))
-                            this._urlType = "Array";
-                        if (urlOrArrayBuffer instanceof ArrayBuffer)
+                        }
+                        else if (urlOrArrayBuffer instanceof ArrayBuffer) {
                             this._urlType = "ArrayBuffer";
+                        }
+                        else if (urlOrArrayBuffer instanceof MediaStream) {
+                            this._urlType = "MediaStream";
+                        }
+                        else if (Array.isArray(urlOrArrayBuffer)) {
+                            this._urlType = "Array";
+                        }
                         var urls = [];
                         var codecSupportedFound = false;
                         switch (this._urlType) {
+                            case "MediaStream":
+                                this._streaming = true;
+                                this._isReadyToPlay = true;
+                                this._streamingSource = BABYLON.Engine.audioEngine.audioContext.createMediaStreamSource(urlOrArrayBuffer);
+                                if (this.autoplay) {
+                                    this.play();
+                                }
+                                if (this._readyToPlayCallback) {
+                                    this._readyToPlayCallback();
+                                }
+                                break;
                             case "ArrayBuffer":
                                 if (urlOrArrayBuffer.byteLength > 0) {
                                     codecSupportedFound = true;
@@ -62143,6 +62175,9 @@ var BABYLON;
                     this._htmlAudioElement.src = "";
                     document.body.removeChild(this._htmlAudioElement);
                 }
+                if (this._streamingSource) {
+                    this._streamingSource.disconnect();
+                }
                 if (this._connectedMesh && this._registerFunc) {
                     this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
                     this._connectedMesh = null;
@@ -62185,7 +62220,7 @@ var BABYLON;
                 this._playbackRate = options.playbackRate || this._playbackRate;
                 this._updateSpatialParameters();
                 if (this.isPlaying) {
-                    if (this._streaming) {
+                    if (this._streaming && this._htmlAudioElement) {
                         this._htmlAudioElement.playbackRate = this._playbackRate;
                     }
                     else {
@@ -62336,7 +62371,9 @@ var BABYLON;
                         }
                         this._streamingSource.disconnect();
                         this._streamingSource.connect(this._inputAudioNode);
-                        this._htmlAudioElement.play();
+                        if (this._htmlAudioElement) {
+                            this._htmlAudioElement.play();
+                        }
                     }
                     else {
                         this._soundSource = BABYLON.Engine.audioEngine.audioContext.createBufferSource();
@@ -62371,10 +62408,15 @@ var BABYLON;
         Sound.prototype.stop = function (time) {
             if (this.isPlaying) {
                 if (this._streaming) {
-                    this._htmlAudioElement.pause();
-                    // Test needed for Firefox or it will generate an Invalid State Error
-                    if (this._htmlAudioElement.currentTime > 0) {
-                        this._htmlAudioElement.currentTime = 0;
+                    if (this._htmlAudioElement) {
+                        this._htmlAudioElement.pause();
+                        // Test needed for Firefox or it will generate an Invalid State Error
+                        if (this._htmlAudioElement.currentTime > 0) {
+                            this._htmlAudioElement.currentTime = 0;
+                        }
+                    }
+                    else {
+                        this._streamingSource.disconnect();
                     }
                 }
                 else if (BABYLON.Engine.audioEngine.audioContext && this._soundSource) {
@@ -62392,7 +62434,12 @@ var BABYLON;
             if (this.isPlaying) {
                 this.isPaused = true;
                 if (this._streaming) {
-                    this._htmlAudioElement.pause();
+                    if (this._htmlAudioElement) {
+                        this._htmlAudioElement.pause();
+                    }
+                    else {
+                        this._streamingSource.disconnect();
+                    }
                 }
                 else if (BABYLON.Engine.audioEngine.audioContext) {
                     this.stop(0);
@@ -62416,7 +62463,7 @@ var BABYLON;
         Sound.prototype.setPlaybackRate = function (newPlaybackRate) {
             this._playbackRate = newPlaybackRate;
             if (this.isPlaying) {
-                if (this._streaming) {
+                if (this._streaming && this._htmlAudioElement) {
                     this._htmlAudioElement.playbackRate = this._playbackRate;
                 }
                 else if (this._soundSource) {

+ 78 - 31
dist/preview release/babylon.no-module.max.js

@@ -55312,6 +55312,10 @@ var BABYLON;
              * If using a spritesheet (isAnimationSheetEnabled), defines the sprite cell height to use
              */
             this.spriteCellHeight = 0;
+            /** Gets or sets a value indicating how many cycles (or frames) must be executed before first rendering (this value has to be set before starting the system). Default is 0 */
+            this.preWarmCycles = 0;
+            /** Gets or sets a value indicating the time step multiplier to use in pre-warm mode (default is 1) */
+            this.preWarmStepOffset = 1;
             /**
             * An event triggered when the system is disposed
             */
@@ -55701,6 +55705,11 @@ var BABYLON;
             if (this.subEmitters && this.subEmitters.length != 0) {
                 this.activeSubSystems = new Array();
             }
+            if (this.preWarmCycles) {
+                for (var index = 0; index < this.preWarmCycles; index++) {
+                    this.animate(true);
+                }
+            }
         };
         /**
          * Stops the particle system.
@@ -55880,19 +55889,23 @@ var BABYLON;
         };
         /**
          * Animates the particle system for the current frame by emitting new particles and or animating the living ones.
+         * @param preWarmOnly will prevent the system from updating the vertex buffer (default is false)
          */
-        ParticleSystem.prototype.animate = function () {
+        ParticleSystem.prototype.animate = function (preWarmOnly) {
+            if (preWarmOnly === void 0) { preWarmOnly = false; }
             if (!this._started)
                 return;
-            var effect = this._getEffect();
-            // Check
-            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
-                return;
-            if (this._currentRenderId === this._scene.getRenderId()) {
-                return;
+            if (!preWarmOnly) {
+                var effect = this._getEffect();
+                // Check
+                if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
+                    return;
+                if (this._currentRenderId === this._scene.getRenderId()) {
+                    return;
+                }
+                this._currentRenderId = this._scene.getRenderId();
             }
-            this._currentRenderId = this._scene.getRenderId();
-            this._scaledUpdateSpeed = this.updateSpeed * this._scene.getAnimationRatio();
+            this._scaledUpdateSpeed = this.updateSpeed * (preWarmOnly ? this.preWarmStepOffset : this._scene.getAnimationRatio());
             // determine the number of particles we need to create
             var newParticles;
             if (this.manualEmitCount > -1) {
@@ -55930,15 +55943,17 @@ var BABYLON;
                     }
                 }
             }
-            // Update VBO
-            var offset = 0;
-            for (var index = 0; index < this._particles.length; index++) {
-                var particle = this._particles[index];
-                this._appendParticleVertices(offset, particle);
-                offset += this._useInstancing ? 1 : 4;
-            }
-            if (this._vertexBuffer) {
-                this._vertexBuffer.update(this._vertexData);
+            if (!preWarmOnly) {
+                // Update VBO
+                var offset = 0;
+                for (var index = 0; index < this._particles.length; index++) {
+                    var particle = this._particles[index];
+                    this._appendParticleVertices(offset, particle);
+                    offset += this._useInstancing ? 1 : 4;
+                }
+                if (this._vertexBuffer) {
+                    this._vertexBuffer.update(this._vertexData);
+                }
             }
             if (this.manualEmitCount === 0 && this.disposeOnStop) {
                 this.stop();
@@ -61891,7 +61906,7 @@ var BABYLON;
         /**
         * Create a sound and attach it to a scene
         * @param name Name of your sound
-        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer
+        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer, it also works with MediaStreams
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
         * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel, streaming
         */
@@ -61966,15 +61981,32 @@ var BABYLON;
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 if (urlOrArrayBuffer) {
                     try {
-                        if (typeof (urlOrArrayBuffer) === "string")
+                        if (typeof (urlOrArrayBuffer) === "string") {
                             this._urlType = "String";
-                        if (Array.isArray(urlOrArrayBuffer))
-                            this._urlType = "Array";
-                        if (urlOrArrayBuffer instanceof ArrayBuffer)
+                        }
+                        else if (urlOrArrayBuffer instanceof ArrayBuffer) {
                             this._urlType = "ArrayBuffer";
+                        }
+                        else if (urlOrArrayBuffer instanceof MediaStream) {
+                            this._urlType = "MediaStream";
+                        }
+                        else if (Array.isArray(urlOrArrayBuffer)) {
+                            this._urlType = "Array";
+                        }
                         var urls = [];
                         var codecSupportedFound = false;
                         switch (this._urlType) {
+                            case "MediaStream":
+                                this._streaming = true;
+                                this._isReadyToPlay = true;
+                                this._streamingSource = BABYLON.Engine.audioEngine.audioContext.createMediaStreamSource(urlOrArrayBuffer);
+                                if (this.autoplay) {
+                                    this.play();
+                                }
+                                if (this._readyToPlayCallback) {
+                                    this._readyToPlayCallback();
+                                }
+                                break;
                             case "ArrayBuffer":
                                 if (urlOrArrayBuffer.byteLength > 0) {
                                     codecSupportedFound = true;
@@ -62110,6 +62142,9 @@ var BABYLON;
                     this._htmlAudioElement.src = "";
                     document.body.removeChild(this._htmlAudioElement);
                 }
+                if (this._streamingSource) {
+                    this._streamingSource.disconnect();
+                }
                 if (this._connectedMesh && this._registerFunc) {
                     this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
                     this._connectedMesh = null;
@@ -62152,7 +62187,7 @@ var BABYLON;
                 this._playbackRate = options.playbackRate || this._playbackRate;
                 this._updateSpatialParameters();
                 if (this.isPlaying) {
-                    if (this._streaming) {
+                    if (this._streaming && this._htmlAudioElement) {
                         this._htmlAudioElement.playbackRate = this._playbackRate;
                     }
                     else {
@@ -62303,7 +62338,9 @@ var BABYLON;
                         }
                         this._streamingSource.disconnect();
                         this._streamingSource.connect(this._inputAudioNode);
-                        this._htmlAudioElement.play();
+                        if (this._htmlAudioElement) {
+                            this._htmlAudioElement.play();
+                        }
                     }
                     else {
                         this._soundSource = BABYLON.Engine.audioEngine.audioContext.createBufferSource();
@@ -62338,10 +62375,15 @@ var BABYLON;
         Sound.prototype.stop = function (time) {
             if (this.isPlaying) {
                 if (this._streaming) {
-                    this._htmlAudioElement.pause();
-                    // Test needed for Firefox or it will generate an Invalid State Error
-                    if (this._htmlAudioElement.currentTime > 0) {
-                        this._htmlAudioElement.currentTime = 0;
+                    if (this._htmlAudioElement) {
+                        this._htmlAudioElement.pause();
+                        // Test needed for Firefox or it will generate an Invalid State Error
+                        if (this._htmlAudioElement.currentTime > 0) {
+                            this._htmlAudioElement.currentTime = 0;
+                        }
+                    }
+                    else {
+                        this._streamingSource.disconnect();
                     }
                 }
                 else if (BABYLON.Engine.audioEngine.audioContext && this._soundSource) {
@@ -62359,7 +62401,12 @@ var BABYLON;
             if (this.isPlaying) {
                 this.isPaused = true;
                 if (this._streaming) {
-                    this._htmlAudioElement.pause();
+                    if (this._htmlAudioElement) {
+                        this._htmlAudioElement.pause();
+                    }
+                    else {
+                        this._streamingSource.disconnect();
+                    }
                 }
                 else if (BABYLON.Engine.audioEngine.audioContext) {
                     this.stop(0);
@@ -62383,7 +62430,7 @@ var BABYLON;
         Sound.prototype.setPlaybackRate = function (newPlaybackRate) {
             this._playbackRate = newPlaybackRate;
             if (this.isPlaying) {
-                if (this._streaming) {
+                if (this._streaming && this._htmlAudioElement) {
                     this._htmlAudioElement.playbackRate = this._playbackRate;
                 }
                 else if (this._soundSource) {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 17 - 17
dist/preview release/babylon.worker.js


+ 78 - 31
dist/preview release/es6.js

@@ -55312,6 +55312,10 @@ var BABYLON;
              * If using a spritesheet (isAnimationSheetEnabled), defines the sprite cell height to use
              */
             this.spriteCellHeight = 0;
+            /** Gets or sets a value indicating how many cycles (or frames) must be executed before first rendering (this value has to be set before starting the system). Default is 0 */
+            this.preWarmCycles = 0;
+            /** Gets or sets a value indicating the time step multiplier to use in pre-warm mode (default is 1) */
+            this.preWarmStepOffset = 1;
             /**
             * An event triggered when the system is disposed
             */
@@ -55701,6 +55705,11 @@ var BABYLON;
             if (this.subEmitters && this.subEmitters.length != 0) {
                 this.activeSubSystems = new Array();
             }
+            if (this.preWarmCycles) {
+                for (var index = 0; index < this.preWarmCycles; index++) {
+                    this.animate(true);
+                }
+            }
         };
         /**
          * Stops the particle system.
@@ -55880,19 +55889,23 @@ var BABYLON;
         };
         /**
          * Animates the particle system for the current frame by emitting new particles and or animating the living ones.
+         * @param preWarmOnly will prevent the system from updating the vertex buffer (default is false)
          */
-        ParticleSystem.prototype.animate = function () {
+        ParticleSystem.prototype.animate = function (preWarmOnly) {
+            if (preWarmOnly === void 0) { preWarmOnly = false; }
             if (!this._started)
                 return;
-            var effect = this._getEffect();
-            // Check
-            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
-                return;
-            if (this._currentRenderId === this._scene.getRenderId()) {
-                return;
+            if (!preWarmOnly) {
+                var effect = this._getEffect();
+                // Check
+                if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
+                    return;
+                if (this._currentRenderId === this._scene.getRenderId()) {
+                    return;
+                }
+                this._currentRenderId = this._scene.getRenderId();
             }
-            this._currentRenderId = this._scene.getRenderId();
-            this._scaledUpdateSpeed = this.updateSpeed * this._scene.getAnimationRatio();
+            this._scaledUpdateSpeed = this.updateSpeed * (preWarmOnly ? this.preWarmStepOffset : this._scene.getAnimationRatio());
             // determine the number of particles we need to create
             var newParticles;
             if (this.manualEmitCount > -1) {
@@ -55930,15 +55943,17 @@ var BABYLON;
                     }
                 }
             }
-            // Update VBO
-            var offset = 0;
-            for (var index = 0; index < this._particles.length; index++) {
-                var particle = this._particles[index];
-                this._appendParticleVertices(offset, particle);
-                offset += this._useInstancing ? 1 : 4;
-            }
-            if (this._vertexBuffer) {
-                this._vertexBuffer.update(this._vertexData);
+            if (!preWarmOnly) {
+                // Update VBO
+                var offset = 0;
+                for (var index = 0; index < this._particles.length; index++) {
+                    var particle = this._particles[index];
+                    this._appendParticleVertices(offset, particle);
+                    offset += this._useInstancing ? 1 : 4;
+                }
+                if (this._vertexBuffer) {
+                    this._vertexBuffer.update(this._vertexData);
+                }
             }
             if (this.manualEmitCount === 0 && this.disposeOnStop) {
                 this.stop();
@@ -61891,7 +61906,7 @@ var BABYLON;
         /**
         * Create a sound and attach it to a scene
         * @param name Name of your sound
-        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer
+        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer, it also works with MediaStreams
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
         * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel, streaming
         */
@@ -61966,15 +61981,32 @@ var BABYLON;
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 if (urlOrArrayBuffer) {
                     try {
-                        if (typeof (urlOrArrayBuffer) === "string")
+                        if (typeof (urlOrArrayBuffer) === "string") {
                             this._urlType = "String";
-                        if (Array.isArray(urlOrArrayBuffer))
-                            this._urlType = "Array";
-                        if (urlOrArrayBuffer instanceof ArrayBuffer)
+                        }
+                        else if (urlOrArrayBuffer instanceof ArrayBuffer) {
                             this._urlType = "ArrayBuffer";
+                        }
+                        else if (urlOrArrayBuffer instanceof MediaStream) {
+                            this._urlType = "MediaStream";
+                        }
+                        else if (Array.isArray(urlOrArrayBuffer)) {
+                            this._urlType = "Array";
+                        }
                         var urls = [];
                         var codecSupportedFound = false;
                         switch (this._urlType) {
+                            case "MediaStream":
+                                this._streaming = true;
+                                this._isReadyToPlay = true;
+                                this._streamingSource = BABYLON.Engine.audioEngine.audioContext.createMediaStreamSource(urlOrArrayBuffer);
+                                if (this.autoplay) {
+                                    this.play();
+                                }
+                                if (this._readyToPlayCallback) {
+                                    this._readyToPlayCallback();
+                                }
+                                break;
                             case "ArrayBuffer":
                                 if (urlOrArrayBuffer.byteLength > 0) {
                                     codecSupportedFound = true;
@@ -62110,6 +62142,9 @@ var BABYLON;
                     this._htmlAudioElement.src = "";
                     document.body.removeChild(this._htmlAudioElement);
                 }
+                if (this._streamingSource) {
+                    this._streamingSource.disconnect();
+                }
                 if (this._connectedMesh && this._registerFunc) {
                     this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
                     this._connectedMesh = null;
@@ -62152,7 +62187,7 @@ var BABYLON;
                 this._playbackRate = options.playbackRate || this._playbackRate;
                 this._updateSpatialParameters();
                 if (this.isPlaying) {
-                    if (this._streaming) {
+                    if (this._streaming && this._htmlAudioElement) {
                         this._htmlAudioElement.playbackRate = this._playbackRate;
                     }
                     else {
@@ -62303,7 +62338,9 @@ var BABYLON;
                         }
                         this._streamingSource.disconnect();
                         this._streamingSource.connect(this._inputAudioNode);
-                        this._htmlAudioElement.play();
+                        if (this._htmlAudioElement) {
+                            this._htmlAudioElement.play();
+                        }
                     }
                     else {
                         this._soundSource = BABYLON.Engine.audioEngine.audioContext.createBufferSource();
@@ -62338,10 +62375,15 @@ var BABYLON;
         Sound.prototype.stop = function (time) {
             if (this.isPlaying) {
                 if (this._streaming) {
-                    this._htmlAudioElement.pause();
-                    // Test needed for Firefox or it will generate an Invalid State Error
-                    if (this._htmlAudioElement.currentTime > 0) {
-                        this._htmlAudioElement.currentTime = 0;
+                    if (this._htmlAudioElement) {
+                        this._htmlAudioElement.pause();
+                        // Test needed for Firefox or it will generate an Invalid State Error
+                        if (this._htmlAudioElement.currentTime > 0) {
+                            this._htmlAudioElement.currentTime = 0;
+                        }
+                    }
+                    else {
+                        this._streamingSource.disconnect();
                     }
                 }
                 else if (BABYLON.Engine.audioEngine.audioContext && this._soundSource) {
@@ -62359,7 +62401,12 @@ var BABYLON;
             if (this.isPlaying) {
                 this.isPaused = true;
                 if (this._streaming) {
-                    this._htmlAudioElement.pause();
+                    if (this._htmlAudioElement) {
+                        this._htmlAudioElement.pause();
+                    }
+                    else {
+                        this._streamingSource.disconnect();
+                    }
                 }
                 else if (BABYLON.Engine.audioEngine.audioContext) {
                     this.stop(0);
@@ -62383,7 +62430,7 @@ var BABYLON;
         Sound.prototype.setPlaybackRate = function (newPlaybackRate) {
             this._playbackRate = newPlaybackRate;
             if (this.isPlaying) {
-                if (this._streaming) {
+                if (this._streaming && this._htmlAudioElement) {
                     this._htmlAudioElement.playbackRate = this._playbackRate;
                 }
                 else if (this._soundSource) {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7 - 7
dist/preview release/viewer/babylon.viewer.js


+ 78 - 31
dist/preview release/viewer/babylon.viewer.max.js

@@ -55433,6 +55433,10 @@ var BABYLON;
              * If using a spritesheet (isAnimationSheetEnabled), defines the sprite cell height to use
              */
             this.spriteCellHeight = 0;
+            /** Gets or sets a value indicating how many cycles (or frames) must be executed before first rendering (this value has to be set before starting the system). Default is 0 */
+            this.preWarmCycles = 0;
+            /** Gets or sets a value indicating the time step multiplier to use in pre-warm mode (default is 1) */
+            this.preWarmStepOffset = 1;
             /**
             * An event triggered when the system is disposed
             */
@@ -55822,6 +55826,11 @@ var BABYLON;
             if (this.subEmitters && this.subEmitters.length != 0) {
                 this.activeSubSystems = new Array();
             }
+            if (this.preWarmCycles) {
+                for (var index = 0; index < this.preWarmCycles; index++) {
+                    this.animate(true);
+                }
+            }
         };
         /**
          * Stops the particle system.
@@ -56001,19 +56010,23 @@ var BABYLON;
         };
         /**
          * Animates the particle system for the current frame by emitting new particles and or animating the living ones.
+         * @param preWarmOnly will prevent the system from updating the vertex buffer (default is false)
          */
-        ParticleSystem.prototype.animate = function () {
+        ParticleSystem.prototype.animate = function (preWarmOnly) {
+            if (preWarmOnly === void 0) { preWarmOnly = false; }
             if (!this._started)
                 return;
-            var effect = this._getEffect();
-            // Check
-            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
-                return;
-            if (this._currentRenderId === this._scene.getRenderId()) {
-                return;
+            if (!preWarmOnly) {
+                var effect = this._getEffect();
+                // Check
+                if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
+                    return;
+                if (this._currentRenderId === this._scene.getRenderId()) {
+                    return;
+                }
+                this._currentRenderId = this._scene.getRenderId();
             }
-            this._currentRenderId = this._scene.getRenderId();
-            this._scaledUpdateSpeed = this.updateSpeed * this._scene.getAnimationRatio();
+            this._scaledUpdateSpeed = this.updateSpeed * (preWarmOnly ? this.preWarmStepOffset : this._scene.getAnimationRatio());
             // determine the number of particles we need to create
             var newParticles;
             if (this.manualEmitCount > -1) {
@@ -56051,15 +56064,17 @@ var BABYLON;
                     }
                 }
             }
-            // Update VBO
-            var offset = 0;
-            for (var index = 0; index < this._particles.length; index++) {
-                var particle = this._particles[index];
-                this._appendParticleVertices(offset, particle);
-                offset += this._useInstancing ? 1 : 4;
-            }
-            if (this._vertexBuffer) {
-                this._vertexBuffer.update(this._vertexData);
+            if (!preWarmOnly) {
+                // Update VBO
+                var offset = 0;
+                for (var index = 0; index < this._particles.length; index++) {
+                    var particle = this._particles[index];
+                    this._appendParticleVertices(offset, particle);
+                    offset += this._useInstancing ? 1 : 4;
+                }
+                if (this._vertexBuffer) {
+                    this._vertexBuffer.update(this._vertexData);
+                }
             }
             if (this.manualEmitCount === 0 && this.disposeOnStop) {
                 this.stop();
@@ -62012,7 +62027,7 @@ var BABYLON;
         /**
         * Create a sound and attach it to a scene
         * @param name Name of your sound
-        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer
+        * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer, it also works with MediaStreams
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
         * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel, streaming
         */
@@ -62087,15 +62102,32 @@ var BABYLON;
                 // if no parameter is passed, you need to call setAudioBuffer yourself to prepare the sound
                 if (urlOrArrayBuffer) {
                     try {
-                        if (typeof (urlOrArrayBuffer) === "string")
+                        if (typeof (urlOrArrayBuffer) === "string") {
                             this._urlType = "String";
-                        if (Array.isArray(urlOrArrayBuffer))
-                            this._urlType = "Array";
-                        if (urlOrArrayBuffer instanceof ArrayBuffer)
+                        }
+                        else if (urlOrArrayBuffer instanceof ArrayBuffer) {
                             this._urlType = "ArrayBuffer";
+                        }
+                        else if (urlOrArrayBuffer instanceof MediaStream) {
+                            this._urlType = "MediaStream";
+                        }
+                        else if (Array.isArray(urlOrArrayBuffer)) {
+                            this._urlType = "Array";
+                        }
                         var urls = [];
                         var codecSupportedFound = false;
                         switch (this._urlType) {
+                            case "MediaStream":
+                                this._streaming = true;
+                                this._isReadyToPlay = true;
+                                this._streamingSource = BABYLON.Engine.audioEngine.audioContext.createMediaStreamSource(urlOrArrayBuffer);
+                                if (this.autoplay) {
+                                    this.play();
+                                }
+                                if (this._readyToPlayCallback) {
+                                    this._readyToPlayCallback();
+                                }
+                                break;
                             case "ArrayBuffer":
                                 if (urlOrArrayBuffer.byteLength > 0) {
                                     codecSupportedFound = true;
@@ -62231,6 +62263,9 @@ var BABYLON;
                     this._htmlAudioElement.src = "";
                     document.body.removeChild(this._htmlAudioElement);
                 }
+                if (this._streamingSource) {
+                    this._streamingSource.disconnect();
+                }
                 if (this._connectedMesh && this._registerFunc) {
                     this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
                     this._connectedMesh = null;
@@ -62273,7 +62308,7 @@ var BABYLON;
                 this._playbackRate = options.playbackRate || this._playbackRate;
                 this._updateSpatialParameters();
                 if (this.isPlaying) {
-                    if (this._streaming) {
+                    if (this._streaming && this._htmlAudioElement) {
                         this._htmlAudioElement.playbackRate = this._playbackRate;
                     }
                     else {
@@ -62424,7 +62459,9 @@ var BABYLON;
                         }
                         this._streamingSource.disconnect();
                         this._streamingSource.connect(this._inputAudioNode);
-                        this._htmlAudioElement.play();
+                        if (this._htmlAudioElement) {
+                            this._htmlAudioElement.play();
+                        }
                     }
                     else {
                         this._soundSource = BABYLON.Engine.audioEngine.audioContext.createBufferSource();
@@ -62459,10 +62496,15 @@ var BABYLON;
         Sound.prototype.stop = function (time) {
             if (this.isPlaying) {
                 if (this._streaming) {
-                    this._htmlAudioElement.pause();
-                    // Test needed for Firefox or it will generate an Invalid State Error
-                    if (this._htmlAudioElement.currentTime > 0) {
-                        this._htmlAudioElement.currentTime = 0;
+                    if (this._htmlAudioElement) {
+                        this._htmlAudioElement.pause();
+                        // Test needed for Firefox or it will generate an Invalid State Error
+                        if (this._htmlAudioElement.currentTime > 0) {
+                            this._htmlAudioElement.currentTime = 0;
+                        }
+                    }
+                    else {
+                        this._streamingSource.disconnect();
                     }
                 }
                 else if (BABYLON.Engine.audioEngine.audioContext && this._soundSource) {
@@ -62480,7 +62522,12 @@ var BABYLON;
             if (this.isPlaying) {
                 this.isPaused = true;
                 if (this._streaming) {
-                    this._htmlAudioElement.pause();
+                    if (this._htmlAudioElement) {
+                        this._htmlAudioElement.pause();
+                    }
+                    else {
+                        this._streamingSource.disconnect();
+                    }
                 }
                 else if (BABYLON.Engine.audioEngine.audioContext) {
                     this.stop(0);
@@ -62504,7 +62551,7 @@ var BABYLON;
         Sound.prototype.setPlaybackRate = function (newPlaybackRate) {
             this._playbackRate = newPlaybackRate;
             if (this.isPlaying) {
-                if (this._streaming) {
+                if (this._streaming && this._htmlAudioElement) {
                     this._htmlAudioElement.playbackRate = this._playbackRate;
                 }
                 else if (this._soundSource) {

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

@@ -16,6 +16,7 @@
   - Added support for `radiusRange` for sphere emitter. [Doc](http://doc.babylonjs.com/babylon101/particles#sphere-emitter)
   - Added support for `ParticleSystem.BLENDMODE_ADD` alpha mode. [Doc](http://doc.babylonjs.com/babylon101/particles#particle-blending)
   - Added support for color gradients. [Doc](http://doc.babylonjs.com/babylon101/particles#particle-colors)
+  - Added support for pre-warming. [Doc](http://doc.babylonjs.com/babylon101/particles#pre-warming)
 
 ## Updates
 

+ 35 - 19
src/Particles/babylon.particleSystem.ts

@@ -315,6 +315,12 @@
          */
         public spriteCellHeight = 0;
 
+        /** Gets or sets a value indicating how many cycles (or frames) must be executed before first rendering (this value has to be set before starting the system). Default is 0 */
+        public preWarmCycles = 0;
+
+        /** Gets or sets a value indicating the time step multiplier to use in pre-warm mode (default is 1) */
+        public preWarmStepOffset = 1;
+
         /**
         * An event triggered when the system is disposed
         */
@@ -668,6 +674,12 @@
             if (this.subEmitters && this.subEmitters.length != 0) {
                 this.activeSubSystems = new Array<ParticleSystem>();
             }
+
+            if (this.preWarmCycles) {
+                for (var index = 0; index < this.preWarmCycles; index++) {
+                    this.animate(true);
+                }
+            }
         }
 
         /**
@@ -928,24 +940,26 @@
 
         /**
          * Animates the particle system for the current frame by emitting new particles and or animating the living ones.
+         * @param preWarmOnly will prevent the system from updating the vertex buffer (default is false)
          */
-        public animate(): void {
+        public animate(preWarmOnly = false): void {
             if (!this._started)
                 return;
 
-            var effect = this._getEffect();
+            if (!preWarmOnly) {
+                var effect = this._getEffect();
 
-            // Check
-            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
-                return;
+                // Check
+                if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady())
+                    return;
 
-            if (this._currentRenderId === this._scene.getRenderId()) {
-                return;
+                if (this._currentRenderId === this._scene.getRenderId()) {
+                    return;
+                }
+                this._currentRenderId = this._scene.getRenderId();
             }
 
-            this._currentRenderId = this._scene.getRenderId();
-
-            this._scaledUpdateSpeed = this.updateSpeed * this._scene.getAnimationRatio();
+            this._scaledUpdateSpeed = this.updateSpeed * (preWarmOnly ? this.preWarmStepOffset : this._scene.getAnimationRatio());
 
             // determine the number of particles we need to create
             var newParticles;
@@ -989,16 +1003,18 @@
                 }
             }
 
-            // Update VBO
-            var offset = 0;
-            for (var index = 0; index < this._particles.length; index++) {
-                var particle = this._particles[index];
-                this._appendParticleVertices(offset, particle);                
-                offset += this._useInstancing ? 1 : 4;
-            }
+            if (!preWarmOnly) {
+                // Update VBO
+                var offset = 0;
+                for (var index = 0; index < this._particles.length; index++) {
+                    var particle = this._particles[index];
+                    this._appendParticleVertices(offset, particle);                
+                    offset += this._useInstancing ? 1 : 4;
+                }
 
-            if (this._vertexBuffer) {
-                this._vertexBuffer.update(this._vertexData);
+                if (this._vertexBuffer) {
+                    this._vertexBuffer.update(this._vertexData);
+                }
             }
 
             if (this.manualEmitCount === 0 && this.disposeOnStop) {