瀏覽代碼

Merge pull request #3773 from bghgary/draco-web-workers

Update Draco compression to use web workers
David Catuhe 7 年之前
父節點
當前提交
a7df11d381

+ 1 - 1
Playground/debug.html

@@ -37,7 +37,7 @@
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
     <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
+    <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
     <script src="https://preview.babylonjs.com/babylon.max.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 1 - 1
Playground/frame.html

@@ -26,7 +26,7 @@
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
     <!-- Babylon.js -->
     <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
+    <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 1 - 1
Playground/full.html

@@ -26,7 +26,7 @@
         <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
         <!-- Babylon.js -->
         <script src="https://preview.babylonjs.com/cannon.js"></script>
-        <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
+        <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 1 - 1
Playground/index-local.html

@@ -17,7 +17,7 @@
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
     <script src="../dist/preview%20release/cannon.js"></script>
-    <script src="../dist/preview%20release/draco_decoder.js"></script>
+    <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="../dist/preview%20release/Oimo.js"></script>
     <script src="../tools/DevLoader/BabylonLoader.js"></script>
 

+ 1 - 1
Playground/index.html

@@ -37,7 +37,7 @@
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
     <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
+    <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 1 - 1
Playground/indexStable.html

@@ -37,7 +37,7 @@
     <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
     <!-- Babylon.js -->
     <script src="https://cdn.babylonjs.com/cannon.js"></script>
-    <script src="https://cdn.babylonjs.com/draco_decoder.js"></script>
+    <script src="https://cdn.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="https://cdn.babylonjs.com/Oimo.js"></script>
     <script src="https://cdn.babylonjs.com/babylon.js"></script>
     <script src="https://cdn.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 1 - 1
Playground/zipContent/index.html

@@ -9,7 +9,7 @@
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
         <script src="https://preview.babylonjs.com/cannon.js"></script>
-        <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
+        <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
         <script src="https://preview.babylonjs.com/oimo.js"></script>
         
         <style>

+ 1 - 0
Tools/Gulp/config.json

@@ -186,6 +186,7 @@
                 "../../src/Tools/babylon.smartArray.js",
                 "../../src/Tools/babylon.tools.js",
                 "../../src/Tools/babylon.promise.js",
+                "../../src/Tools/babylon.workerPool.js",
                 "../../src/States/babylon.alphaCullingState.js",
                 "../../src/States/babylon.depthCullingState.js",
                 "../../src/States/babylon.stencilState.js",

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

@@ -1,92 +1,93 @@
-# 3.2.0
-
-## Major updates
-
-- Support for [GPU particles](https://doc.babylonjs.com/babylon101/particles#gpu-particles) ([deltakosh](https://github.com/deltakosh))
-- Improved building process: We now run a full visual validation test for each pull request. Furthermore, code comments and what's new updates are now mandatory ([sebavan](https://github.com/sebavan))
-- Introduced texture binding atlas. This optimization allows the engine to reuse texture bindings instead of rebinding textures when they are not on constant sampler indexes ([deltakosh](https://github.com/deltakosh))
-- New [AnimationGroup class](http://doc.babylonjs.com/how_to/group) to control simultaneously multiple animations with different targets ([deltakosh](https://github.com/deltakosh))
-- `WebVRCamera` now supports GearVR ([brianzinn](https://github.com/brianzinn))
-- New glTF [serializer](https://github.com/BabylonJS/Babylon.js/tree/master/serializers/src/glTF/2.0). You can now export glTF or glb files directly from a Babylon scene ([kcoley](https://github.com/kcoley))
-- Babylon.js now uses Promises in addition to callbacks. We created several `xxxAsync` functions all over the framework (`SceneLoader.AppendAsync` for instance, which returns a Promise). A polyfill is also integrated to support older browsers ([deltakosh](https://github.com/deltakosh))
-- Introduced [Projection Texture on SpotLight](http://doc.babylonjs.com/babylon101/lights#projection-texture) ([lostink](https://github.com/lostink))
-- Introduced support for [local cubemaps](http://doc.babylonjs.com/how_to/reflect#using-local-cubemap-mode) ([deltakosh](https://github.com/deltakosh))
-- Added [VideoDome](http://doc.babylonjs.com/how_to/360videodome) class to easily support 360 videos ([DavidHGillen](https://github.com/DavidHGillen))
-- Added [GlowLayer](https://doc.babylonjs.com/how_to/glow_layer) to easily support glow from emissive materials ([sebavan](https://github.com/sebavan))
-
-## Updates
-
-- Tons of functions and classes received the code comments they deserved (All the community)
-- Added `particleSystem.reset()` to clear a particle system ([deltakosh](https://github.com/deltakosh))
-- Added support for all RGBA orders (BGR, RGB, etc..) for the DDS loader ([deltakosh](https://github.com/deltakosh))
-- Improved [SceneOptimizer](http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer) to provide better adaptability ([deltakosh](https://github.com/deltakosh))
-- Improved `scene.isReady()` function which now takes in account shadows and LOD ([deltakosh](https://github.com/deltakosh))
-- New watcher configuration for VSCode. Now the task only compiles changed files ([sebavan](https://github.com/sebavan))
-- Added new draw modes to engine (points, lines, linesloop, linestrip, trianglestrip, trianglefan) ([benaadams](https://github.com/benaadams))
-- Added GUI Textblock.lineSpacing setter and getter to configure vertical space between lines in pixels or percentage values when working with text wrapping ([carloslanderas](https://github.com/carloslanderas))
-- VRHelper now has onSelectedMeshUnselected observable that will notify observers when the current selected mesh gets unselected
-  ([carloslanderas](https://github.com/carloslanderas))
-- VRHelper now has onBeforeCameraTeleport and onAfterCameraTeleport observables that will be notified before and after camera teleportation is triggered.
-  ([carloslanderas](https://github.com/carloslanderas))
-- VRHelper now has the public property teleportationEnabled to enable / disable camera teleportation.
-   ([carloslanderas](https://github.com/carloslanderas))
-- VRHelper now exposes onNewMeshPicked observable that will notify a PickingInfo object after meshSelectionPredicate evaluation
-   ([carloslanderas](https://github.com/carloslanderas))
-- `AssetsManager` will now clear its `tasks` lsit from all successfully loaded tasks ([deltakosh](https://github.com/deltakosh))
-- Added documentation to WebVRCamera and VRExperienceHelper ([trevordev](https://github.com/trevordev))
-- Introduced `isStroke` on `HighlightLayerOptions` which makes the highlight solid ([PixelsCommander](https://github.com/pixelscommander))
-- (Viewer) There is now an option to paste payload instead of a URL for configuration ([RaananW](https://github.com/RaananW))
-- (Viewer) Models can be loaded async using JavaScript ([RaananW](https://github.com/RaananW))
-- VRHelper will notify now onSelectedMeshUnselected observable to subscribers when the applied ray selection predicate does not produce a hit and a mesh compliant with the meshSelectionPredicate was previously selected
-   ([carloslanderas](https://github.com/carloslanderas))
-- (Viewer) initScene and initEngine can now be extended. onProgress during model loading is implemented as observable. ([RaananW](https://github.com/RaananW))
-- glTF loader now supports the KHR_lights extension ([MiiBond](https://github.com/MiiBond))
-- Added depth of field effect to the default pipeline ([trevordev](https://github.com/trevordev))
-- The observable can now notify observers using promise-based callback chain. ([RaananW](https://github.com/RaananW))
-- Added base64 helper functions to `Tools` ([bghgary](https://github.com/bghgary))
-- Added `createDefaultCamera` and `createDefaultLight` functions to `Scene` ([bghgary](https://github.com/bghgary))
-- Gulp process now supports multiple outputs when using webpack. ([RaananW](https://github.com/RaananW))
-- (Viewer) Scene Optimizer intergrated in viewer. ([RaananW](https://github.com/RaananW))
-- (Viewer) The viewer supports custom shaders in the configuration. ([RaananW](https://github.com/RaananW))
-- Documented PostProcessRenderEffect, DefaultRenderingPipeline, BlurPostProcess, DepthOfFieldEffect, PostProcess, PostProcessManager, Effect classes ([trevordev](https://github.com/trevordev))
-- SPS internal storage of each solid particle rotation matrix ([jbousquie](https://github.com/jbousquie)) 
-- SPS particle parenting feature ([jbousquie](https://github.com/jbousquie))
-- (Viewer) Introducing the viewer labs - testing new features. ([RaananW](https://github.com/RaananW))
-- AssetContainer Class and loading methods ([trevordev](https://github.com/trevordev))
-- KeepAssets class and AssetContainer.moveAllFromScene ([HoloLite](http://www.html5gamedevs.com/profile/28694-hololite/) [trevordev](https://github.com/trevordev))
-- (Viewer) It is now possible to update parts of the configuration without rcreating the objects. Extra configuration can be loaded sync (if provided) ([RaananW](https://github.com/RaananW))
-- (Gulp) extra/external declarations can be prepended to final declarations during build. ([RaananW](https://github.com/RaananW))
-- (Viewer) Model can be normalized using configuration, camera is dynamically configured. ([RaananW](https://github.com/RaananW))
-- (Gulp) extra/external declarations can be prepended to final NPM declarations during build. ([RaananW](https://github.com/RaananW))
-- GUI.Line can have its world position set from one end or the other ([SvenFrankson](https://github.com/SvenFrankson))
-- Added FOV system to background material for zoom effects in skyboxes without adjusting camera FOV ([DavidHGillen](https://github.com/DavidHGillen))
-- Improved glTF loader by using promises for asynchronous operations. ([bghgary](https://github.com/bghgary)]
-- Improved glTF loader performance by compiling materials in parallel with downloading external resources. ([bghgary](https://github.com/bghgary)]
-- Added unit tests for the glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
-- Added promise-based async functions to the SceneLoader, Scene.whenReadyAsync, and material.forceCompilationAsync. ([bghgary](https://github.com/bghgary)]
-- Added checks to VertexData.merge to ensure data is valid before merging. ([bghgary](https://github.com/bghgary)]
-- Ability to set a mesh to customize the webVR gaze tracker ([trevordev](https://github.com/trevordev))
-- Added promise-based async functions for initWebVRAsync and useStandingMatrixAsync ([trevordev](https://github.com/trevordev))
-- Add stroke (outline) options on GUI text control ([SvenFrankson](https://github.com/SvenFrankson))
-- Add isThumbClamped option on GUI slider control ([JeanPhilippeKernel](https://github.com/JeanPhilippeKernel))
-- Add floating point texture support for RenderTargetCubeTexture ([PeapBoy](https://github.com/NicolasBuecher))
-- Support for mutli-touch when interacting with multiple gui elements simultaneously ([trevordev](https://github.com/trevordev))
-- (Viewer) Declaration file published, ready for npm. ([RaananW](https://github.com/RaananW))
-- Added Draco mesh compression support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
-- (Viewer) XHR requests not use Tools.LoadFile and are disposed correctly - [#3671](https://github.com/BabylonJS/Babylon.js/issues/3671) ([RaananW](https://github.com/RaananW))
-
-## Bug fixes
-
-- `setPivotMatrix` ws not setting pivot correctly. This is now fixed. We also introduced a new `setPreTransformMatrix` to reproduce the sometimes needed behavior of the previous `setPivotMatrix` function ([deltakosh](https://github.com/deltakosh))
-- SPS solid particle `.pivot` property now also behaves like the standard mesh pivot. Former behavior (particle translation) can be kept with the particle property `.translateFromPivot` set to true ([jbousquie](https://github.com/jbousquie))
-- Texture extension detection in `Engine.CreateTexture` ([sebavan](https://github.com/sebavan))
-- SPS internal temporary vector3 instead of Tmp.Vector3 to avoid possible concurrent uses ([jbousquie](https://github.com/jbousquie))
-- Fixed a bug when calling load on an empty assets manager - [#3739](https://github.com/BabylonJS/Babylon.js/issues/3739). ([RaananW](https://github.com/RaananW))
-- Enabling teleportation in the vr helper class caused a redundant post process to be added ([trevordev](https://github.com/trevordev))
-- (Viewer) Fixed a bug where loading another mesh positioned it incorrectly ([RaananW](https://github.com/RaananW))
-
-## Breaking changes
-
-- Removed the unused PostProcessRenderPass class and extended postProcessingRenderingEffect to support multiple PostProcesses ([trevordev](https://github.com/trevordev))
-- VertexData.merge no longer supports merging of data that do not have the same set of attributes. ([bghgary](https://github.com/bghgary)]
-- glTF 2.0 loader will now create a mesh for each primitive instead of merging the primitives together into one mesh. ([bghgary](https://github.com/bghgary)]
+# 3.2.0
+
+## Major updates
+
+- Support for [GPU particles](https://doc.babylonjs.com/babylon101/particles#gpu-particles) ([deltakosh](https://github.com/deltakosh))
+- Improved building process: We now run a full visual validation test for each pull request. Furthermore, code comments and what's new updates are now mandatory ([sebavan](https://github.com/sebavan))
+- Introduced texture binding atlas. This optimization allows the engine to reuse texture bindings instead of rebinding textures when they are not on constant sampler indexes ([deltakosh](https://github.com/deltakosh))
+- New [AnimationGroup class](http://doc.babylonjs.com/how_to/group) to control simultaneously multiple animations with different targets ([deltakosh](https://github.com/deltakosh))
+- `WebVRCamera` now supports GearVR ([brianzinn](https://github.com/brianzinn))
+- New glTF [serializer](https://github.com/BabylonJS/Babylon.js/tree/master/serializers/src/glTF/2.0). You can now export glTF or glb files directly from a Babylon scene ([kcoley](https://github.com/kcoley))
+- Babylon.js now uses Promises in addition to callbacks. We created several `xxxAsync` functions all over the framework (`SceneLoader.AppendAsync` for instance, which returns a Promise). A polyfill is also integrated to support older browsers ([deltakosh](https://github.com/deltakosh))
+- Introduced [Projection Texture on SpotLight](http://doc.babylonjs.com/babylon101/lights#projection-texture) ([lostink](https://github.com/lostink))
+- Introduced support for [local cubemaps](http://doc.babylonjs.com/how_to/reflect#using-local-cubemap-mode) ([deltakosh](https://github.com/deltakosh))
+- Added [VideoDome](http://doc.babylonjs.com/how_to/360videodome) class to easily support 360 videos ([DavidHGillen](https://github.com/DavidHGillen))
+- Added [GlowLayer](https://doc.babylonjs.com/how_to/glow_layer) to easily support glow from emissive materials ([sebavan](https://github.com/sebavan))
+
+## Updates
+
+- Tons of functions and classes received the code comments they deserved (All the community)
+- Added `particleSystem.reset()` to clear a particle system ([deltakosh](https://github.com/deltakosh))
+- Added support for all RGBA orders (BGR, RGB, etc..) for the DDS loader ([deltakosh](https://github.com/deltakosh))
+- Improved [SceneOptimizer](http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer) to provide better adaptability ([deltakosh](https://github.com/deltakosh))
+- Improved `scene.isReady()` function which now takes in account shadows and LOD ([deltakosh](https://github.com/deltakosh))
+- New watcher configuration for VSCode. Now the task only compiles changed files ([sebavan](https://github.com/sebavan))
+- Added new draw modes to engine (points, lines, linesloop, linestrip, trianglestrip, trianglefan) ([benaadams](https://github.com/benaadams))
+- Added GUI Textblock.lineSpacing setter and getter to configure vertical space between lines in pixels or percentage values when working with text wrapping ([carloslanderas](https://github.com/carloslanderas))
+- VRHelper now has onSelectedMeshUnselected observable that will notify observers when the current selected mesh gets unselected
+  ([carloslanderas](https://github.com/carloslanderas))
+- VRHelper now has onBeforeCameraTeleport and onAfterCameraTeleport observables that will be notified before and after camera teleportation is triggered.
+  ([carloslanderas](https://github.com/carloslanderas))
+- VRHelper now has the public property teleportationEnabled to enable / disable camera teleportation.
+   ([carloslanderas](https://github.com/carloslanderas))
+- VRHelper now exposes onNewMeshPicked observable that will notify a PickingInfo object after meshSelectionPredicate evaluation
+   ([carloslanderas](https://github.com/carloslanderas))
+- `AssetsManager` will now clear its `tasks` lsit from all successfully loaded tasks ([deltakosh](https://github.com/deltakosh))
+- Added documentation to WebVRCamera and VRExperienceHelper ([trevordev](https://github.com/trevordev))
+- Introduced `isStroke` on `HighlightLayerOptions` which makes the highlight solid ([PixelsCommander](https://github.com/pixelscommander))
+- (Viewer) There is now an option to paste payload instead of a URL for configuration ([RaananW](https://github.com/RaananW))
+- (Viewer) Models can be loaded async using JavaScript ([RaananW](https://github.com/RaananW))
+- VRHelper will notify now onSelectedMeshUnselected observable to subscribers when the applied ray selection predicate does not produce a hit and a mesh compliant with the meshSelectionPredicate was previously selected
+   ([carloslanderas](https://github.com/carloslanderas))
+- (Viewer) initScene and initEngine can now be extended. onProgress during model loading is implemented as observable. ([RaananW](https://github.com/RaananW))
+- glTF loader now supports the KHR_lights extension ([MiiBond](https://github.com/MiiBond))
+- Added depth of field effect to the default pipeline ([trevordev](https://github.com/trevordev))
+- The observable can now notify observers using promise-based callback chain. ([RaananW](https://github.com/RaananW))
+- Added base64 helper functions to `Tools` ([bghgary](https://github.com/bghgary))
+- Added `createDefaultCamera` and `createDefaultLight` functions to `Scene` ([bghgary](https://github.com/bghgary))
+- Gulp process now supports multiple outputs when using webpack. ([RaananW](https://github.com/RaananW))
+- (Viewer) Scene Optimizer intergrated in viewer. ([RaananW](https://github.com/RaananW))
+- (Viewer) The viewer supports custom shaders in the configuration. ([RaananW](https://github.com/RaananW))
+- Documented PostProcessRenderEffect, DefaultRenderingPipeline, BlurPostProcess, DepthOfFieldEffect, PostProcess, PostProcessManager, Effect classes ([trevordev](https://github.com/trevordev))
+- SPS internal storage of each solid particle rotation matrix ([jbousquie](https://github.com/jbousquie)) 
+- SPS particle parenting feature ([jbousquie](https://github.com/jbousquie))
+- (Viewer) Introducing the viewer labs - testing new features. ([RaananW](https://github.com/RaananW))
+- AssetContainer Class and loading methods ([trevordev](https://github.com/trevordev))
+- KeepAssets class and AssetContainer.moveAllFromScene ([HoloLite](http://www.html5gamedevs.com/profile/28694-hololite/) [trevordev](https://github.com/trevordev))
+- (Viewer) It is now possible to update parts of the configuration without rcreating the objects. Extra configuration can be loaded sync (if provided) ([RaananW](https://github.com/RaananW))
+- (Gulp) extra/external declarations can be prepended to final declarations during build. ([RaananW](https://github.com/RaananW))
+- (Viewer) Model can be normalized using configuration, camera is dynamically configured. ([RaananW](https://github.com/RaananW))
+- (Gulp) extra/external declarations can be prepended to final NPM declarations during build. ([RaananW](https://github.com/RaananW))
+- GUI.Line can have its world position set from one end or the other ([SvenFrankson](https://github.com/SvenFrankson))
+- Added FOV system to background material for zoom effects in skyboxes without adjusting camera FOV ([DavidHGillen](https://github.com/DavidHGillen))
+- Improved glTF loader by using promises for asynchronous operations. ([bghgary](https://github.com/bghgary)]
+- Improved glTF loader performance by compiling materials in parallel with downloading external resources. ([bghgary](https://github.com/bghgary)]
+- Added unit tests for the glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
+- Added promise-based async functions to the SceneLoader, Scene.whenReadyAsync, and material.forceCompilationAsync. ([bghgary](https://github.com/bghgary)]
+- Added checks to VertexData.merge to ensure data is valid before merging. ([bghgary](https://github.com/bghgary)]
+- Ability to set a mesh to customize the webVR gaze tracker ([trevordev](https://github.com/trevordev))
+- Added promise-based async functions for initWebVRAsync and useStandingMatrixAsync ([trevordev](https://github.com/trevordev))
+- Add stroke (outline) options on GUI text control ([SvenFrankson](https://github.com/SvenFrankson))
+- Add isThumbClamped option on GUI slider control ([JeanPhilippeKernel](https://github.com/JeanPhilippeKernel))
+- Add floating point texture support for RenderTargetCubeTexture ([PeapBoy](https://github.com/NicolasBuecher))
+- Support for mutli-touch when interacting with multiple gui elements simultaneously ([trevordev](https://github.com/trevordev))
+- (Viewer) Declaration file published, ready for npm. ([RaananW](https://github.com/RaananW))
+- Added Draco mesh compression support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
+- (Viewer) XHR requests not use Tools.LoadFile and are disposed correctly - [#3671](https://github.com/BabylonJS/Babylon.js/issues/3671) ([RaananW](https://github.com/RaananW))
+- Added `Tools.WorkerPool` class for web worker management. ([bghgary](https://github.com/bghgary))
+
+## Bug fixes
+
+- `setPivotMatrix` ws not setting pivot correctly. This is now fixed. We also introduced a new `setPreTransformMatrix` to reproduce the sometimes needed behavior of the previous `setPivotMatrix` function ([deltakosh](https://github.com/deltakosh))
+- SPS solid particle `.pivot` property now also behaves like the standard mesh pivot. Former behavior (particle translation) can be kept with the particle property `.translateFromPivot` set to true ([jbousquie](https://github.com/jbousquie))
+- Texture extension detection in `Engine.CreateTexture` ([sebavan](https://github.com/sebavan))
+- SPS internal temporary vector3 instead of Tmp.Vector3 to avoid possible concurrent uses ([jbousquie](https://github.com/jbousquie))
+- Fixed a bug when calling load on an empty assets manager - [#3739](https://github.com/BabylonJS/Babylon.js/issues/3739). ([RaananW](https://github.com/RaananW))
+- Enabling teleportation in the vr helper class caused a redundant post process to be added ([trevordev](https://github.com/trevordev))
+- (Viewer) Fixed a bug where loading another mesh positioned it incorrectly ([RaananW](https://github.com/RaananW))
+
+## Breaking changes
+
+- Removed the unused PostProcessRenderPass class and extended postProcessingRenderingEffect to support multiple PostProcesses ([trevordev](https://github.com/trevordev))
+- VertexData.merge no longer supports merging of data that do not have the same set of attributes. ([bghgary](https://github.com/bghgary)]
+- glTF 2.0 loader will now create a mesh for each primitive instead of merging the primitives together into one mesh. ([bghgary](https://github.com/bghgary)]

+ 26 - 5
loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts

@@ -1,7 +1,7 @@
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON.GLTF2.Extensions {
-    // https://github.com/KhronosGroup/glTF/pull/874
+    // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
 
     const NAME = "KHR_draco_mesh_compression";
 
@@ -13,6 +13,25 @@ module BABYLON.GLTF2.Extensions {
     export class KHR_draco_mesh_compression extends GLTFLoaderExtension {
         public readonly name = NAME;
 
+        private _dracoCompression: Nullable<DracoCompression> = null;
+
+        constructor(loader: GLTFLoader) {
+            super(loader);
+
+            // Disable extension if decoder is not available.
+            if (!DracoCompression.DecoderUrl) {
+                this.enabled = false;
+            }
+        }
+
+        public dispose(): void {
+            if (this._dracoCompression) {
+                this._dracoCompression.dispose();
+            }
+
+            super.dispose();
+        }
+
         protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>> {
             return this._loadExtensionAsync<IKHRDracoMeshCompression, VertexData>(context, primitive, (extensionContext, extension) => {
                 if (primitive.mode != undefined) {
@@ -54,7 +73,11 @@ module BABYLON.GLTF2.Extensions {
                 var bufferView = GLTFLoader._GetProperty(extensionContext, this._loader._gltf.bufferViews, extension.bufferView);
                 return this._loader._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView).then(data => {
                     try {
-                        return DracoCompression.Decode(data, attributes);
+                        if (!this._dracoCompression) {
+                            this._dracoCompression = new DracoCompression();
+                        }
+
+                        return this._dracoCompression.decodeMeshAsync(data, attributes);
                     }
                     catch (e) {
                         throw new Error(`${context}: ${e.message}`);
@@ -64,7 +87,5 @@ module BABYLON.GLTF2.Extensions {
         }
     }
 
-    if (DracoCompression.IsSupported) {
-        GLTFLoader._Register(NAME, loader => new KHR_draco_mesh_compression(loader));
-    }
+    GLTFLoader._Register(NAME, loader => new KHR_draco_mesh_compression(loader));
 }

+ 6 - 0
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -1568,7 +1568,13 @@ module BABYLON.GLTF2 {
             delete this._gltf;
             delete this._babylonScene;
             this._completePromises.length = 0;
+
+            for (const name in this._extensions) {
+                this._extensions[name].dispose();
+            }
+
             this._extensions = {};
+
             delete this._rootBabylonMesh;
             delete this._progressCallback;
 

+ 5 - 1
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -1,7 +1,7 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON.GLTF2 {
-    export abstract class GLTFLoaderExtension implements IGLTFLoaderExtension {
+    export abstract class GLTFLoaderExtension implements IGLTFLoaderExtension, IDisposable {
         public enabled = true;
         public abstract readonly name: string;
 
@@ -11,6 +11,10 @@ module BABYLON.GLTF2 {
             this._loader = loader;
         }
 
+        public dispose(): void {
+            delete this._loader;
+        }
+
         // #region Overridable Methods
 
         /** Override this method to modify the default behavior for loading scenes. */

+ 3 - 3
localDev/index.html

@@ -5,10 +5,10 @@
     <title>Local Development</title>
 
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
-    <script src="https://preview.babylonjs.com/Oimo.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
+    <script src="../dist/preview%20release/cannon.js"></script>
+    <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
+    <script src="../dist/preview%20release/Oimo.js"></script>
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>
     <script src="src/webgl-debug.js"></script>
 

+ 1 - 1
sandbox/index-local.html

@@ -4,7 +4,7 @@
     <title>BabylonJS - Sandbox</title>
     <link href="index.css" rel="stylesheet" />
     <script src="../dist/preview%20release/cannon.js"></script>
-    <script src="../dist/preview%20release/draco_decoder.js"></script>
+    <script src="../dist/preview%20release/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="../dist/preview%20release/Oimo.js"></script>
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>
 </head>

+ 1 - 1
sandbox/index.html

@@ -27,7 +27,7 @@
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
 
     <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
+    <script src="https://preview.babylonjs.com/draco_decoder.js" type="text/x-draco-decoder"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 163 - 70
src/Mesh/Compression/babylon.dracoCompression.ts

@@ -6,101 +6,194 @@ module BABYLON {
     /**
      * Draco compression (https://google.github.io/draco/)
      */
-    export class DracoCompression {
+    export class DracoCompression implements IDisposable {
+        private _workerPool: WorkerPool;
+
+        /**
+         * Gets the url to the draco decoder if available.
+         */
+        public static DecoderUrl: Nullable<string> = DracoCompression._GetDefaultDecoderUrl();
+
         /**
-         * Returns whether Draco compression is supported.
+         * Constructor
+         * @param numWorkers The number of workers for async operations
          */
-        public static get IsSupported(): boolean {
-            return Tools.IsWindowObjectExist() && !!window.DracoDecoderModule;
+        constructor(numWorkers = (navigator.hardwareConcurrency || 4)) {
+            const workers = new Array<Worker>(numWorkers);
+            for (let i = 0; i < workers.length; i++) {
+                const worker = new Worker(DracoCompression._WorkerBlobUrl);
+                worker.postMessage({ id: "initDecoder", url: DracoCompression.DecoderUrl });
+                workers[i] = worker;
+            }
+
+            this._workerPool = new WorkerPool(workers);
         }
 
         /**
-         * Decodes Draco compressed data to vertex data.
+         * Stop all async operations and release resources.
+         */
+        public dispose(): void {
+            this._workerPool.dispose();
+            delete this._workerPool;
+        }
+
+        /**
+         * Decode Draco compressed mesh data to vertex data.
          * @param data The array buffer view for the Draco compression data
          * @param attributes A map of attributes from vertex buffer kinds to Draco unique ids
-         * @returns The decoded vertex data
+         * @returns A promise that resolves with the decoded vertex data
          */
-        public static Decode(data: ArrayBufferView, attributes: { [kind: string]: number }): VertexData {
-            const dracoModule = new DracoDecoderModule();
-            const buffer = new dracoModule.DecoderBuffer();
-            buffer.Init(data, data.byteLength);
-
-            const decoder = new dracoModule.Decoder();
-            let geometry: any;
-            let status: any;
-
-            const vertexData = new VertexData();
-
-            try {
-                const type = decoder.GetEncodedGeometryType(buffer);
-                switch (type) {
-                    case dracoModule.TRIANGULAR_MESH:
-                        geometry = new dracoModule.Mesh();
-                        status = decoder.DecodeBufferToMesh(buffer, geometry);
-                        break;
-                    case dracoModule.POINT_CLOUD:
-                        geometry = new dracoModule.PointCloud();
-                        status = decoder.DecodeBufferToPointCloud(buffer, geometry);
-                        break;
-                    default:
-                        throw new Error(`Invalid geometry type ${type}`);
-                }
+        public decodeMeshAsync(data: ArrayBufferView, attributes: { [kind: string]: number }): Promise<VertexData> {
+            return new Promise((resolve, reject) => {
+                this._workerPool.push((worker, onComplete) => {
+                    const vertexData = new VertexData();
 
-                if (!status.ok() || !geometry.ptr) {
-                    throw new Error(status.error_msg());
-                }
+                    const onError = (error: ErrorEvent) => {
+                        worker.removeEventListener("error", onError);
+                        worker.removeEventListener("message", onMessage);
+                        reject(error);
+                        onComplete();
+                    };
 
-                const numPoints = geometry.num_points();
-
-                if (type === dracoModule.TRIANGULAR_MESH) {
-                    const numFaces = geometry.num_faces();
-                    const faceIndices = new dracoModule.DracoInt32Array();
-                    try {
-                        vertexData.indices = new Uint32Array(numFaces * 3);
-                        for (let i = 0; i < numFaces; i++) {
-                            decoder.GetFaceFromMesh(geometry, i, faceIndices);
-                            const offset = i * 3;
-                            vertexData.indices[offset + 0] = faceIndices.GetValue(0);
-                            vertexData.indices[offset + 1] = faceIndices.GetValue(1);
-                            vertexData.indices[offset + 2] = faceIndices.GetValue(2);
+                    const onMessage = (message: MessageEvent) => {
+                        if (message.data === "done") {
+                            worker.removeEventListener("error", onError);
+                            worker.removeEventListener("message", onMessage);
+                            resolve(vertexData);
+                            onComplete();
                         }
+                        else if (message.data.id === "indices") {
+                            vertexData.indices = message.data.value;
+                        }
+                        else {
+                            vertexData.set(message.data.value, message.data.id);
+                        }
+                    };
+
+                    worker.addEventListener("error", onError);
+                    worker.addEventListener("message", onMessage);
+
+                    const dataCopy = new Uint8Array(data.byteLength);
+                    dataCopy.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
+
+                    worker.postMessage({ id: "decodeMesh", data: dataCopy, attributes: attributes }, [dataCopy.buffer]);
+                });
+            });
+        }
+
+        /**
+         * The worker function that gets converted to a blob url to pass into a worker.
+         */
+        private static _Worker(): void {
+            // self is actually a DedicatedWorkerGlobalScope
+            const _self = self as any as {
+                onmessage: (event: MessageEvent) => void;
+                postMessage: (message: any, transfer?: any[]) => void;
+                close: () => void;
+            };
+
+            const decodeMesh = (data: ArrayBufferView, attributes: { [kind: string]: number }): void => {
+                const dracoModule = new DracoDecoderModule();
+                const buffer = new dracoModule.DecoderBuffer();
+                buffer.Init(data, data.byteLength);
+
+                const decoder = new dracoModule.Decoder();
+                let geometry: any;
+                let status: any;
+
+                try {
+                    const type = decoder.GetEncodedGeometryType(buffer);
+                    switch (type) {
+                        case dracoModule.TRIANGULAR_MESH:
+                            geometry = new dracoModule.Mesh();
+                            status = decoder.DecodeBufferToMesh(buffer, geometry);
+                            break;
+                        case dracoModule.POINT_CLOUD:
+                            geometry = new dracoModule.PointCloud();
+                            status = decoder.DecodeBufferToPointCloud(buffer, geometry);
+                            break;
+                        default:
+                            throw new Error(`Invalid geometry type ${type}`);
                     }
-                    finally {
-                        dracoModule.destroy(faceIndices);
+
+                    if (!status.ok() || !geometry.ptr) {
+                        throw new Error(status.error_msg());
                     }
-                }
 
-                for (const kind in attributes) {
-                    const uniqueId = attributes[kind];
-                    const attribute = decoder.GetAttributeByUniqueId(geometry, uniqueId);
-                    const dracoData = new dracoModule.DracoFloat32Array();
-                    try {
-                        if (attribute.num_components() !== VertexBuffer.DeduceStride(kind)) {
-                            throw new Error(`Unsupported number of components for ${kind}`);
+                    const numPoints = geometry.num_points();
+
+                    if (type === dracoModule.TRIANGULAR_MESH) {
+                        const numFaces = geometry.num_faces();
+                        const faceIndices = new dracoModule.DracoInt32Array();
+                        try {
+                            const indices = new Uint32Array(numFaces * 3);
+                            for (let i = 0; i < numFaces; i++) {
+                                decoder.GetFaceFromMesh(geometry, i, faceIndices);
+                                const offset = i * 3;
+                                indices[offset + 0] = faceIndices.GetValue(0);
+                                indices[offset + 1] = faceIndices.GetValue(1);
+                                indices[offset + 2] = faceIndices.GetValue(2);
+                            }
+                            _self.postMessage({ id: "indices", value: indices }, [indices.buffer]);
+                        }
+                        finally {
+                            dracoModule.destroy(faceIndices);
                         }
+                    }
 
-                        decoder.GetAttributeFloatForAllPoints(geometry, attribute, dracoData);
-                        const babylonData = new Float32Array(numPoints * attribute.num_components());
-                        for (let i = 0; i < babylonData.length; i++) {
-                            babylonData[i] = dracoData.GetValue(i);
+                    for (const kind in attributes) {
+                        const uniqueId = attributes[kind];
+                        const attribute = decoder.GetAttributeByUniqueId(geometry, uniqueId);
+                        const dracoData = new dracoModule.DracoFloat32Array();
+                        try {
+                            decoder.GetAttributeFloatForAllPoints(geometry, attribute, dracoData);
+                            const babylonData = new Float32Array(numPoints * attribute.num_components());
+                            for (let i = 0; i < babylonData.length; i++) {
+                                babylonData[i] = dracoData.GetValue(i);
+                            }
+                            _self.postMessage({ id: kind, value: babylonData }, [babylonData.buffer]);
+                        }
+                        finally {
+                            dracoModule.destroy(dracoData);
                         }
-                        vertexData.set(babylonData, kind);
                     }
-                    finally {
-                        dracoModule.destroy(dracoData);
+                }
+                finally {
+                    if (geometry) {
+                        dracoModule.destroy(geometry);
                     }
+
+                    dracoModule.destroy(decoder);
+                    dracoModule.destroy(buffer);
                 }
+
+                _self.postMessage("done");
             }
-            finally {
-                if (geometry) {
-                    dracoModule.destroy(geometry);
+
+            _self.onmessage = event => {
+                switch (event.data.id) {
+                    case "initDecoder": {
+                        importScripts(event.data.url);
+                        break;
+                    }
+                    case "decodeMesh": {
+                        decodeMesh(event.data.data, event.data.attributes);
+                        break;
+                    }
                 }
+            };
+        }
 
-                dracoModule.destroy(decoder);
-                dracoModule.destroy(buffer);
+        private static _WorkerBlobUrl = URL.createObjectURL(new Blob([`(${DracoCompression._Worker.toString()})()`], { type: "application/javascript" }));
+
+        private static _GetDefaultDecoderUrl(): Nullable<string> {
+            for (let i = 0; i < document.scripts.length; i++) {
+                if (document.scripts[i].type === "text/x-draco-decoder") {
+                    return document.scripts[i].src;
+                }
             }
 
-            return vertexData;
+            return null;
         }
     }
 }

+ 66 - 0
src/Tools/babylon.workerPool.ts

@@ -0,0 +1,66 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+
+module BABYLON {
+    interface WorkerInfo {
+        worker: Worker;
+        active: boolean;
+    }
+
+    /**
+     * Helper class to push actions to a pool of workers.
+     */
+    export class WorkerPool implements IDisposable {
+        private _workerInfos: Array<WorkerInfo>;
+        private _pendingActions = new Array<(worker: Worker, onComplete: () => void) => void>();
+
+        /**
+         * Constructor
+         * @param workers Array of workers to use for actions
+         */
+        constructor(workers: Array<Worker>) {
+            this._workerInfos = workers.map(worker => ({
+                worker: worker,
+                active: false
+            }));
+        }
+
+        /**
+         * Terminates all workers and clears any pending actions.
+         */
+        public dispose(): void {
+            for (const workerInfo of this._workerInfos) {
+                workerInfo.worker.terminate();
+            }
+
+            delete this._workerInfos;
+            delete this._pendingActions;
+        }
+
+        /**
+         * Pushes an action to the worker pool. If all the workers are active, the action will be
+         * pended until a worker has completed its action.
+         * @param action The action to perform. Call onComplete when the action is complete.
+         */
+        public push(action: (worker: Worker, onComplete: () => void) => void): void {
+            for (const workerInfo of this._workerInfos) {
+                if (!workerInfo.active) {
+                    this._execute(workerInfo, action);
+                    return;
+                }
+            }
+
+            this._pendingActions.push(action);
+        }
+
+        private _execute(workerInfo: WorkerInfo, action: (worker: Worker, onComplete: () => void) => void): void {
+            workerInfo.active = true;
+            action(workerInfo.worker, () => {
+                workerInfo.active = false;
+                const nextAction = this._pendingActions.shift();
+                if (nextAction) {
+                    this._execute(workerInfo, nextAction);
+                }
+            });
+        }
+    }
+}

+ 0 - 1
tests/validation/index.html

@@ -3,7 +3,6 @@
 <head>
 	<title>BabylonJS - Build validation page</title>
 	<link href="index.css" rel="stylesheet" />
-    <script src="../../dist/preview%20release/draco_decoder.js"></script>
 	<script src="../../Tools/DevLoader/BabylonLoader.js"></script>
 </head>
 <body>

+ 0 - 1
tests/validation/karma.conf.browserstack.js

@@ -14,7 +14,6 @@ module.exports = function (config) {
         frameworks: ['mocha', 'chai', 'sinon'],
 
         files: [
-            './dist/preview release/draco_decoder.js',
             './Tools/DevLoader/BabylonLoader.js',
             './tests/validation/index.css',
             './tests/validation/integration.js',

+ 0 - 1
tests/validation/karma.conf.js

@@ -14,7 +14,6 @@ module.exports = function (config) {
         frameworks: ['mocha', 'chai', 'sinon'],
 
         files: [
-            './dist/preview release/draco_decoder.js',
             './Tools/DevLoader/BabylonLoader.js',
             './tests/validation/index.css',
             './tests/validation/integration.js',

+ 1 - 0
tests/validation/validation.js

@@ -305,6 +305,7 @@ function runTest(index, done) {
 BABYLON.SceneLoader.ShowLoadingScreen = false;
 BABYLON.Database.IDBStorageEnabled = false;
 BABYLON.SceneLoader.ForceFullSceneLoadingForIncremental = true;
+BABYLON.DracoCompression.DecoderUrl = BABYLON.Tools.GetFolderPath(document.location.href) + "../../dist/preview%20release/draco_decoder.js";
 
 canvas = document.createElement("canvas");
 canvas.className = "renderCanvas";