Browse Source

Merge remote-tracking branch 'BabylonJS/master' into viewer-gulp

Raanan Weber 7 năm trước cách đây
mục cha
commit
d4dcdcea0c
56 tập tin đã thay đổi với 34151 bổ sung31792 xóa
  1. 11381 11283
      Playground/babylon.d.txt
  2. 1 0
      Playground/debug.html
  3. 1 0
      Playground/frame.html
  4. 1 0
      Playground/full.html
  5. 3 2
      Playground/index-local.html
  6. 1 0
      Playground/index.html
  7. 1 0
      Playground/indexStable.html
  8. 1 0
      Playground/zipContent/index.html
  9. 17 6
      Tools/Gulp/config.json
  10. 21 0
      dist/preview release/Oimo.license
  11. 5631 5541
      dist/preview release/babylon.d.ts
  12. 46 45
      dist/preview release/babylon.js
  13. 350 117
      dist/preview release/babylon.max.js
  14. 46 45
      dist/preview release/babylon.worker.js
  15. 22 0
      dist/preview release/cannon.license
  16. 14186 14096
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  17. 46 46
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  18. 373 104
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  19. 375 106
      dist/preview release/customConfigurations/minimalGLTFViewer/es6.js
  20. 201 0
      dist/preview release/draco.license
  21. 31 0
      dist/preview release/draco_decoder.js
  22. 352 119
      dist/preview release/es6.js
  23. 22 19
      dist/preview release/gui/babylon.gui.d.ts
  24. 60 47
      dist/preview release/gui/babylon.gui.js
  25. 3 3
      dist/preview release/gui/babylon.gui.min.js
  26. 22 19
      dist/preview release/gui/babylon.gui.module.d.ts
  27. 14 2
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  28. 100 6
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  29. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  30. 14 2
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  31. 100 6
      dist/preview release/loaders/babylon.glTFFileLoader.js
  32. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  33. 91 6
      dist/preview release/loaders/babylonjs.loaders.js
  34. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  35. 14 2
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  36. 46 46
      dist/preview release/viewer/babylon.viewer.js
  37. 2 0
      dist/preview release/what's new.md
  38. 70 0
      loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts
  39. 7 2
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  40. 16 5
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  41. 1 0
      localDev/index.html
  42. 5 4
      sandbox/index-local.html
  43. 1 1
      sandbox/index.html
  44. 1 7
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  45. 11 2
      src/Engine/babylon.engine.ts
  46. 106 0
      src/Mesh/Compression/babylon.dracoCompression.ts
  47. 4 4
      src/Mesh/babylon.mesh.ts
  48. 4 7
      src/Mesh/babylon.vertexBuffer.ts
  49. 12 0
      src/Particles/babylon.iParticleEmitterType.ts
  50. 26 44
      src/Particles/babylon.boxParticleEmitter.ts
  51. 21 2
      src/Particles/babylon.coneParticleEmitter.ts
  52. 35 0
      src/Particles/babylon.sphereParticleEmitter.ts
  53. 82 22
      src/Particles/babylon.gpuParticleSystem.ts
  54. 66 11
      src/Particles/babylon.particleSystem.ts
  55. 99 5
      src/Shaders/gpuUpdateParticles.vertex.fx
  56. 1 0
      src/babylon.mixins.ts

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 11381 - 11283
Playground/babylon.d.txt


+ 1 - 0
Playground/debug.html

@@ -37,6 +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/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 - 0
Playground/frame.html

@@ -26,6 +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/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 - 0
Playground/full.html

@@ -26,6 +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/Oimo.js"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>

+ 3 - 2
Playground/index-local.html

@@ -16,8 +16,9 @@
     <!--Monaco-->
     <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/Oimo.js"></script>
+    <script src="../dist/preview%20release/cannon.js"></script>
+    <script src="../dist/preview%20release/draco_decoder.js"></script>
+    <script src="../dist/preview%20release/Oimo.js"></script>
     <script src="../tools/DevLoader/BabylonLoader.js"></script>
 
     <link href="css/index.css" rel="stylesheet" />

+ 1 - 0
Playground/index.html

@@ -37,6 +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/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 - 0
Playground/indexStable.html

@@ -37,6 +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/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 - 0
Playground/zipContent/index.html

@@ -9,6 +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/oimo.js"></script>
         
         <style>

+ 17 - 6
Tools/Gulp/config.json

@@ -37,6 +37,7 @@
             "solidParticles",
             "additionalMeshes",
             "meshBuilder",
+            "meshCompression",
             "audio",
             "additionalTextures",
             "shadows",
@@ -115,6 +116,7 @@
             "solidParticles",
             "additionalMeshes",
             "meshBuilder",
+            "meshCompression",
             "audio",
             "additionalTextures",
             "shadows",
@@ -272,10 +274,10 @@
             "files": [
                 "../../src/Particles/babylon.particle.js",
                 "../../src/Particles/babylon.particleSystem.js",
-                "../../src/Particles/babylon.boxParticleEmitter.js",
-                "../../src/Particles/babylon.coneParticleEmitter.js",
-                "../../src/Particles/babylon.sphereParticleEmitter.js",
-                "../../src/Particles/babylon.iParticleEmitterType.js"
+                "../../src/Particles/EmitterTypes/babylon.boxParticleEmitter.js",
+                "../../src/Particles/EmitterTypes/babylon.coneParticleEmitter.js",
+                "../../src/Particles/EmitterTypes/babylon.sphereParticleEmitter.js",
+                "../../src/Particles/EmitterTypes/babylon.IParticleEmitterType.js"
             ],
             "dependUpon": [
                 "core"
@@ -287,10 +289,11 @@
         },
         "gpuParticles": {
             "files": [
-                "../../src/Particles/babylon.gpuParticleSystem.js"
+                "../../src/Particles/babylon.gpuParticleSystem.js"          
             ],
             "dependUpon": [
-                "core"
+                "core",
+                "particles"
             ],
             "shaders": [
                 "gpuRenderParticles.vertex",
@@ -427,6 +430,12 @@
                 "additionalMeshes"
             ]
         },
+        "meshCompression" :
+        {
+            "files": [
+                "../../src/Mesh/Compression/babylon.dracoCompression.js"
+            ]
+        },
         "shaderMaterial": {
             "files": [
                 "../../src/Materials/babylon.shaderMaterial.js"
@@ -1479,6 +1488,7 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_lights.ts"
                 ],
@@ -1499,6 +1509,7 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_lights.ts"
                 ],

+ 21 - 0
dist/preview release/Oimo.license

@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright © 2010-2017 three.js authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 5631 - 5541
dist/preview release/babylon.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 46 - 45
dist/preview release/babylon.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 350 - 117
dist/preview release/babylon.max.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 46 - 45
dist/preview release/babylon.worker.js


+ 22 - 0
dist/preview release/cannon.license

@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 cannon.js Authors
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 14186 - 14096
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 46 - 46
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 373 - 104
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -10897,6 +10897,16 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Engine, "TEXTUREFORMAT_RGBA32F", {
+            /**
+             * RGBA32F
+             */
+            get: function () {
+                return Engine._TEXTUREFORMAT_RGBA32F;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(Engine, "TEXTUREFORMAT_LUMINANCE_ALPHA", {
             get: function () {
                 return Engine._TEXTUREFORMAT_LUMINANCE_ALPHA;
@@ -10962,7 +10972,7 @@ var BABYLON;
         });
         Object.defineProperty(Engine, "Version", {
             get: function () {
-                return "3.2.0-alpha7";
+                return "3.2.0-alpha8";
             },
             enumerable: true,
             configurable: true
@@ -12994,6 +13004,7 @@ var BABYLON;
                     internalFormat = this._gl.RGB;
                     break;
                 case Engine.TEXTUREFORMAT_RGBA:
+                case Engine.TEXTUREFORMAT_RGBA32F:
                     internalFormat = this._gl.RGBA;
                     break;
                 case Engine.TEXTUREFORMAT_R32F:
@@ -15060,6 +15071,7 @@ var BABYLON;
         Engine._TEXTUREFORMAT_R32F = 6;
         Engine._TEXTUREFORMAT_RG32F = 7;
         Engine._TEXTUREFORMAT_RGB32F = 8;
+        Engine._TEXTUREFORMAT_RGBA32F = 9;
         Engine._TEXTURETYPE_UNSIGNED_INT = 0;
         Engine._TEXTURETYPE_FLOAT = 1;
         Engine._TEXTURETYPE_HALF_FLOAT = 2;
@@ -25724,10 +25736,6 @@ var BABYLON;
          */
         VertexBuffer.DeduceStride = function (kind) {
             switch (kind) {
-                case VertexBuffer.PositionKind:
-                    return 3;
-                case VertexBuffer.NormalKind:
-                    return 3;
                 case VertexBuffer.UVKind:
                 case VertexBuffer.UV2Kind:
                 case VertexBuffer.UV3Kind:
@@ -25735,14 +25743,15 @@ var BABYLON;
                 case VertexBuffer.UV5Kind:
                 case VertexBuffer.UV6Kind:
                     return 2;
-                case VertexBuffer.TangentKind:
+                case VertexBuffer.NormalKind:
+                case VertexBuffer.PositionKind:
+                    return 3;
                 case VertexBuffer.ColorKind:
-                    return 4;
                 case VertexBuffer.MatricesIndicesKind:
                 case VertexBuffer.MatricesIndicesExtraKind:
-                    return 4;
                 case VertexBuffer.MatricesWeightsKind:
                 case VertexBuffer.MatricesWeightsExtraKind:
+                case VertexBuffer.TangentKind:
                     return 4;
                 default:
                     throw new Error("Invalid kind '" + kind + "'");
@@ -27672,7 +27681,7 @@ var BABYLON;
                             weight = matricesWeightsData[matWeightIdx + inf];
                             if (weight <= 0)
                                 break;
-                            BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[matWeightIdx + inf] * 16, weight, tempMatrix);
+                            BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesData[matWeightIdx + inf] * 16), weight, tempMatrix);
                             finalMatrix.addToSelf(tempMatrix);
                         }
                         if (needExtras) {
@@ -27680,7 +27689,7 @@ var BABYLON;
                                 weight = matricesWeightsExtraData[matWeightIdx + inf];
                                 if (weight <= 0)
                                     break;
-                                BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesExtraData[matWeightIdx + inf] * 16, weight, tempMatrix);
+                                BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesExtraData[matWeightIdx + inf] * 16), weight, tempMatrix);
                                 finalMatrix.addToSelf(tempMatrix);
                             }
                         }
@@ -29821,7 +29830,7 @@ var BABYLON;
                 for (inf = 0; inf < 4; inf++) {
                     weight = matricesWeightsData[matWeightIdx + inf];
                     if (weight > 0) {
-                        BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[matWeightIdx + inf] * 16, weight, tempMatrix);
+                        BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesData[matWeightIdx + inf] * 16), weight, tempMatrix);
                         finalMatrix.addToSelf(tempMatrix);
                     }
                     else
@@ -29831,7 +29840,7 @@ var BABYLON;
                     for (inf = 0; inf < 4; inf++) {
                         weight = matricesWeightsExtraData[matWeightIdx + inf];
                         if (weight > 0) {
-                            BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesExtraData[matWeightIdx + inf] * 16, weight, tempMatrix);
+                            BABYLON.Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesExtraData[matWeightIdx + inf] * 16), weight, tempMatrix);
                             finalMatrix.addToSelf(tempMatrix);
                         }
                         else
@@ -50541,22 +50550,6 @@ var BABYLON;
              */
             this.gravity = BABYLON.Vector3.Zero();
             /**
-             * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
-             */
-            this.direction1 = new BABYLON.Vector3(0, 1.0, 0);
-            /**
-             * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
-             */
-            this.direction2 = new BABYLON.Vector3(0, 1.0, 0);
-            /**
-             * Minimum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
-             */
-            this.minEmitBox = new BABYLON.Vector3(-0.5, -0.5, -0.5);
-            /**
-             * Maximum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
-             */
-            this.maxEmitBox = new BABYLON.Vector3(0.5, 0.5, 0.5);
-            /**
              * Random color of each particle after it has been emitted, between color1 and color2 vectors.
              */
             this.color1 = new BABYLON.Color4(1.0, 1.0, 1.0, 1.0);
@@ -50639,8 +50632,8 @@ var BABYLON;
             this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = positions;
             this._vertexBuffers[BABYLON.VertexBuffer.ColorKind] = colors;
             this._vertexBuffers["options"] = options;
-            // Default behaviors
-            this.particleEmitterType = new BABYLON.BoxParticleEmitter(this);
+            // Default emitter type
+            this.particleEmitterType = new BABYLON.BoxParticleEmitter();
             this.updateFunction = function (particles) {
                 for (var index = 0; index < particles.length; index++) {
                     var particle = particles[index];
@@ -50667,6 +50660,82 @@ var BABYLON;
                 }
             };
         }
+        Object.defineProperty(ParticleSystem.prototype, "direction1", {
+            /**
+              * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
+              * This only works when particleEmitterTyps is a BoxParticleEmitter
+              */
+            get: function () {
+                if (this.particleEmitterType.direction1) {
+                    return this.particleEmitterType.direction1;
+                }
+                return BABYLON.Vector3.Zero();
+            },
+            set: function (value) {
+                if (this.particleEmitterType.direction1) {
+                    this.particleEmitterType.direction1 = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(ParticleSystem.prototype, "direction2", {
+            /**
+             * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
+             * This only works when particleEmitterTyps is a BoxParticleEmitter
+             */
+            get: function () {
+                if (this.particleEmitterType.direction2) {
+                    return this.particleEmitterType.direction2;
+                }
+                return BABYLON.Vector3.Zero();
+            },
+            set: function (value) {
+                if (this.particleEmitterType.direction2) {
+                    this.particleEmitterType.direction2 = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(ParticleSystem.prototype, "minEmitBox", {
+            /**
+             * Minimum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
+             * This only works when particleEmitterTyps is a BoxParticleEmitter
+             */
+            get: function () {
+                if (this.particleEmitterType.minEmitBox) {
+                    return this.particleEmitterType.minEmitBox;
+                }
+                return BABYLON.Vector3.Zero();
+            },
+            set: function (value) {
+                if (this.particleEmitterType.minEmitBox) {
+                    this.particleEmitterType.minEmitBox = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(ParticleSystem.prototype, "maxEmitBox", {
+            /**
+             * Maximum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
+             * This only works when particleEmitterTyps is a BoxParticleEmitter
+             */
+            get: function () {
+                if (this.particleEmitterType.maxEmitBox) {
+                    return this.particleEmitterType.maxEmitBox;
+                }
+                return BABYLON.Vector3.Zero();
+            },
+            set: function (value) {
+                if (this.particleEmitterType.maxEmitBox) {
+                    this.particleEmitterType.maxEmitBox = value;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(ParticleSystem.prototype, "onDispose", {
             /**
              * Sets a callback that will be triggered when the system is disposed.
@@ -50974,13 +51043,14 @@ var BABYLON;
         };
         /**
          * Renders the particle system in its current state.
-         * @returns the current number of particles.
+         * @returns the current number of particles
          */
         ParticleSystem.prototype.render = function () {
             var effect = this._getEffect();
             // Check
-            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady() || !this._particles.length)
+            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady() || !this._particles.length) {
                 return 0;
+            }
             var engine = this._scene.getEngine();
             // Render
             engine.enableEffect(effect);
@@ -51091,7 +51161,7 @@ var BABYLON;
          * @returns the emitter
          */
         ParticleSystem.prototype.createBoxEmitter = function (direction1, direction2, minEmitBox, maxEmitBox) {
-            var particleEmitter = new BABYLON.BoxParticleEmitter(this);
+            var particleEmitter = new BABYLON.BoxParticleEmitter();
             this.direction1 = direction1;
             this.direction2 = direction2;
             this.minEmitBox = minEmitBox;
@@ -51286,79 +51356,27 @@ var BABYLON;
      * It emits the particles randomly between 2 given directions.
      */
     var BoxParticleEmitter = /** @class */ (function () {
-        // to be updated like the rest of emitters when breaking changes.
-        // all property should be come public variables and passed through constructor.
         /**
          * Creates a new instance of @see BoxParticleEmitter
-         * @param _particleSystem the particle system associated with the emitter
          */
-        function BoxParticleEmitter(_particleSystem) {
-            this._particleSystem = _particleSystem;
-        }
-        Object.defineProperty(BoxParticleEmitter.prototype, "direction1", {
-            /**
-             * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
-             */
-            get: function () {
-                return this._particleSystem.direction1;
-            },
-            /**
-             * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
-             */
-            set: function (value) {
-                this._particleSystem.direction1 = value;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(BoxParticleEmitter.prototype, "direction2", {
+        function BoxParticleEmitter() {
             /**
              * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
              */
-            get: function () {
-                return this._particleSystem.direction2;
-            },
+            this.direction1 = new BABYLON.Vector3(0, 1.0, 0);
             /**
              * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
              */
-            set: function (value) {
-                this._particleSystem.direction2 = value;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(BoxParticleEmitter.prototype, "minEmitBox", {
-            /**
-             * Minimum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
-             */
-            get: function () {
-                return this._particleSystem.minEmitBox;
-            },
+            this.direction2 = new BABYLON.Vector3(0, 1.0, 0);
             /**
              * Minimum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
              */
-            set: function (value) {
-                this._particleSystem.minEmitBox = value;
-            },
-            enumerable: true,
-            configurable: true
-        });
-        Object.defineProperty(BoxParticleEmitter.prototype, "maxEmitBox", {
-            /**
-             * Maximum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
-             */
-            get: function () {
-                return this._particleSystem.maxEmitBox;
-            },
+            this.minEmitBox = new BABYLON.Vector3(-0.5, -0.5, -0.5);
             /**
              * Maximum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
              */
-            set: function (value) {
-                this._particleSystem.maxEmitBox = value;
-            },
-            enumerable: true,
-            configurable: true
-        });
+            this.maxEmitBox = new BABYLON.Vector3(0.5, 0.5, 0.5);
+        }
         /**
          * Called by the particle System when the direction is computed for the created particle.
          * @param emitPower is the power of the particle (speed)
@@ -51389,10 +51407,27 @@ var BABYLON;
          * @returns the new emitter
          */
         BoxParticleEmitter.prototype.clone = function () {
-            var newOne = new BoxParticleEmitter(this._particleSystem);
+            var newOne = new BoxParticleEmitter();
             BABYLON.Tools.DeepCopy(this, newOne);
             return newOne;
         };
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */
+        BoxParticleEmitter.prototype.applyToShader = function (effect) {
+            effect.setVector3("direction1", this.direction1);
+            effect.setVector3("direction2", this.direction2);
+            effect.setVector3("minEmitBox", this.minEmitBox);
+            effect.setVector3("maxEmitBox", this.maxEmitBox);
+        };
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns a string containng the defines string
+         */
+        BoxParticleEmitter.prototype.getEffectDefines = function () {
+            return "#define BOXEMITTER";
+        };
         return BoxParticleEmitter;
     }());
     BABYLON.BoxParticleEmitter = BoxParticleEmitter;
@@ -51489,7 +51524,7 @@ var BABYLON;
             radius = radius * h / this._height;
             var randX = radius * Math.sin(s);
             var randZ = radius * Math.cos(s);
-            var randY = h;
+            var randY = h * this._height;
             BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(randX, randY, randZ, worldMatrix, positionToUpdate);
         };
         /**
@@ -51501,6 +51536,23 @@ var BABYLON;
             BABYLON.Tools.DeepCopy(this, newOne);
             return newOne;
         };
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */
+        ConeParticleEmitter.prototype.applyToShader = function (effect) {
+            effect.setFloat("radius", this.radius);
+            effect.setFloat("angle", this.angle);
+            effect.setFloat("height", this._height);
+            effect.setFloat("directionRandomizer", this.directionRandomizer);
+        };
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns a string containng the defines string
+         */
+        ConeParticleEmitter.prototype.getEffectDefines = function () {
+            return "#define CONEEMITTER";
+        };
         return ConeParticleEmitter;
     }());
     BABYLON.ConeParticleEmitter = ConeParticleEmitter;
@@ -51575,6 +51627,21 @@ var BABYLON;
             BABYLON.Tools.DeepCopy(this, newOne);
             return newOne;
         };
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */
+        SphereParticleEmitter.prototype.applyToShader = function (effect) {
+            effect.setFloat("radius", this.radius);
+            effect.setFloat("directionRandomizer", this.directionRandomizer);
+        };
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns a string containng the defines string
+         */
+        SphereParticleEmitter.prototype.getEffectDefines = function () {
+            return "#define SPHEREEMITTER";
+        };
         return SphereParticleEmitter;
     }());
     BABYLON.SphereParticleEmitter = SphereParticleEmitter;
@@ -51626,6 +51693,22 @@ var BABYLON;
             BABYLON.Tools.DeepCopy(this, newOne);
             return newOne;
         };
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */
+        SphereDirectedParticleEmitter.prototype.applyToShader = function (effect) {
+            effect.setFloat("radius", this.radius);
+            effect.setVector3("direction1", this.direction1);
+            effect.setVector3("direction2", this.direction2);
+        };
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns a string containng the defines string
+         */
+        SphereDirectedParticleEmitter.prototype.getEffectDefines = function () {
+            return "#define SPHEREEMITTER\n#define DIRECTEDSPHEREEMITTER";
+        };
         return SphereDirectedParticleEmitter;
     }(SphereParticleEmitter));
     BABYLON.SphereDirectedParticleEmitter = SphereDirectedParticleEmitter;
@@ -51635,7 +51718,7 @@ var BABYLON;
 
 
 
-//# sourceMappingURL=babylon.iParticleEmitterType.js.map
+//# sourceMappingURL=babylon.IParticleEmitterType.js.map
 
 var BABYLON;
 (function (BABYLON) {
@@ -55491,6 +55574,110 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.meshBuilder.js.map
 
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+var BABYLON;
+(function (BABYLON) {
+    /**
+     * Draco compression (https://google.github.io/draco/)
+     */
+    var DracoCompression = /** @class */ (function () {
+        function DracoCompression() {
+        }
+        Object.defineProperty(DracoCompression, "IsSupported", {
+            /**
+             * Returns whether Draco compression is supported.
+             */
+            get: function () {
+                return !!window.DracoDecoderModule;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+         * Decodes Draco compressed 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
+         */
+        DracoCompression.Decode = function (data, attributes) {
+            var dracoModule = new DracoDecoderModule();
+            var buffer = new dracoModule.DecoderBuffer();
+            buffer.Init(data, data.byteLength);
+            var decoder = new dracoModule.Decoder();
+            var geometry;
+            var status;
+            var vertexData = new BABYLON.VertexData();
+            try {
+                var 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);
+                }
+                if (!status.ok() || !geometry.ptr) {
+                    throw new Error(status.error_msg());
+                }
+                var numPoints = geometry.num_points();
+                if (type === dracoModule.TRIANGULAR_MESH) {
+                    var numFaces = geometry.num_faces();
+                    var faceIndices = new dracoModule.DracoInt32Array();
+                    try {
+                        vertexData.indices = new Uint32Array(numFaces * 3);
+                        for (var i = 0; i < numFaces; i++) {
+                            decoder.GetFaceFromMesh(geometry, i, faceIndices);
+                            var offset = i * 3;
+                            vertexData.indices[offset + 0] = faceIndices.GetValue(0);
+                            vertexData.indices[offset + 1] = faceIndices.GetValue(1);
+                            vertexData.indices[offset + 2] = faceIndices.GetValue(2);
+                        }
+                    }
+                    finally {
+                        dracoModule.destroy(faceIndices);
+                    }
+                }
+                for (var kind in attributes) {
+                    var uniqueId = attributes[kind];
+                    var attribute = decoder.GetAttributeByUniqueId(geometry, uniqueId);
+                    var dracoData = new dracoModule.DracoFloat32Array();
+                    try {
+                        if (attribute.num_components() !== BABYLON.VertexBuffer.DeduceStride(kind)) {
+                            throw new Error("Unsupported number of components for " + kind);
+                        }
+                        decoder.GetAttributeFloatForAllPoints(geometry, attribute, dracoData);
+                        var babylonData = new Float32Array(numPoints * attribute.num_components());
+                        for (var i = 0; i < babylonData.length; i++) {
+                            babylonData[i] = dracoData.GetValue(i);
+                        }
+                        vertexData.set(babylonData, kind);
+                    }
+                    finally {
+                        dracoModule.destroy(dracoData);
+                    }
+                }
+            }
+            finally {
+                if (geometry) {
+                    dracoModule.destroy(geometry);
+                }
+                dracoModule.destroy(decoder);
+                dracoModule.destroy(buffer);
+            }
+            return vertexData;
+        };
+        return DracoCompression;
+    }());
+    BABYLON.DracoCompression = DracoCompression;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.dracoCompression.js.map
+
 var BABYLON;
 (function (BABYLON) {
     var AudioEngine = /** @class */ (function () {
@@ -80216,7 +80403,6 @@ var BABYLON;
                 imageProcessingConfiguration.vignetteEnabled = true;
                 this._postProcessMove = new BABYLON.ImageProcessingPostProcess("postProcessMove", 1.0, this._webVRCamera, undefined, undefined, undefined, undefined, imageProcessingConfiguration);
                 this._webVRCamera.detachPostProcess(this._postProcessMove);
-                this._passProcessMove = new BABYLON.PassPostProcess("pass", 1.0, this._webVRCamera);
                 this._teleportationInitialized = true;
                 if (this._isDefaultTeleportationTarget) {
                     this._createTeleportationCircles();
@@ -80585,6 +80771,7 @@ var BABYLON;
             this._postProcessMove.animations.push(animationPP2);
             this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0;
             this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0;
+            this._postProcessMove.samples = 4;
             this._webVRCamera.attachPostProcess(this._postProcessMove);
             this._scene.beginAnimation(this._postProcessMove, 0, 6, false, 1, function () {
                 _this._webVRCamera.detachPostProcess(_this._postProcessMove);
@@ -80854,9 +81041,6 @@ var BABYLON;
             if (this.isInVRMode) {
                 this.exitVR();
             }
-            if (this._passProcessMove) {
-                this._passProcessMove.dispose();
-            }
             if (this._postProcessMove) {
                 this._postProcessMove.dispose();
             }
@@ -92091,11 +92275,15 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
                 var _this = this;
+                var promise = GLTF2.GLTFLoaderExtension._LoadVertexDataAsync(this, context, primitive, babylonMesh);
+                if (promise) {
+                    return promise;
+                }
                 var attributes = primitive.attributes;
                 if (!attributes) {
                     throw new Error(context + ": Attributes are missing");
                 }
-                if (primitive.mode && primitive.mode !== 4 /* TRIANGLES */) {
+                if (primitive.mode != undefined && primitive.mode !== 4 /* TRIANGLES */) {
                     // TODO: handle other primitive modes
                     throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
                 }
@@ -93079,6 +93267,8 @@ var BABYLON;
             GLTFLoaderExtension.prototype._loadSceneAsync = function (context, node) { return null; };
             /** Override this method to modify the default behavior for loading nodes. */
             GLTFLoaderExtension.prototype._loadNodeAsync = function (context, node) { return null; };
+            /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+            GLTFLoaderExtension.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) { return null; };
             /** Override this method to modify the default behavior for loading materials. */
             GLTFLoaderExtension.prototype._loadMaterialAsync = function (context, material, babylonMesh) { return null; };
             /** Override this method to modify the default behavior for loading uris. */
@@ -93086,7 +93276,6 @@ var BABYLON;
             // #endregion
             /** Helper method called by a loader extension to load an glTF extension. */
             GLTFLoaderExtension.prototype._loadExtensionAsync = function (context, property, actionAsync) {
-                var _this = this;
                 if (!property.extensions) {
                     return null;
                 }
@@ -93097,10 +93286,13 @@ var BABYLON;
                 }
                 // Clear out the extension before executing the action to avoid recursing into the same property.
                 delete extensions[this.name];
-                return actionAsync(context + "/extensions/" + this.name, extension).then(function () {
-                    // Restore the extension after completing the action.
-                    extensions[_this.name] = extension;
-                });
+                try {
+                    return actionAsync(context + "/extensions/" + this.name, extension);
+                }
+                finally {
+                    // Restore the extension after executing the action.
+                    extensions[this.name] = extension;
+                }
             };
             /** Helper method called by the loader to allow extensions to override loading scenes. */
             GLTFLoaderExtension._LoadSceneAsync = function (loader, context, scene) {
@@ -93110,6 +93302,10 @@ var BABYLON;
             GLTFLoaderExtension._LoadNodeAsync = function (loader, context, node) {
                 return loader._applyExtensions(function (extension) { return extension._loadNodeAsync(context, node); });
             };
+            /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
+            GLTFLoaderExtension._LoadVertexDataAsync = function (loader, context, primitive, babylonMesh) {
+                return loader._applyExtensions(function (extension) { return extension._loadVertexDataAsync(context, primitive, babylonMesh); });
+            };
             /** Helper method called by the loader to allow extensions to override loading materials. */
             GLTFLoaderExtension._LoadMaterialAsync = function (loader, context, material, babylonMesh) {
                 return loader._applyExtensions(function (extension) { return extension._loadMaterialAsync(context, material, babylonMesh); });
@@ -93275,6 +93471,79 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            // https://github.com/KhronosGroup/glTF/pull/874
+            var NAME = "KHR_draco_mesh_compression";
+            var KHR_draco_mesh_compression = /** @class */ (function (_super) {
+                __extends(KHR_draco_mesh_compression, _super);
+                function KHR_draco_mesh_compression() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    _this.name = NAME;
+                    return _this;
+                }
+                KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, primitive, function (extensionContext, extension) {
+                        if (primitive.mode != undefined) {
+                            if (primitive.mode !== 5 /* TRIANGLE_STRIP */ &&
+                                primitive.mode !== 4 /* TRIANGLES */) {
+                                throw new Error(context + ": Unsupported mode " + primitive.mode);
+                            }
+                            // TODO: handle triangle strips
+                            if (primitive.mode === 5 /* TRIANGLE_STRIP */) {
+                                throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
+                            }
+                        }
+                        var attributes = {};
+                        var loadAttribute = function (name, kind) {
+                            var uniqueId = extension.attributes[name];
+                            if (uniqueId == undefined) {
+                                return;
+                            }
+                            babylonMesh._delayInfo = babylonMesh._delayInfo || [];
+                            if (babylonMesh._delayInfo.indexOf(kind) === -1) {
+                                babylonMesh._delayInfo.push(kind);
+                            }
+                            attributes[kind] = uniqueId;
+                        };
+                        loadAttribute("POSITION", BABYLON.VertexBuffer.PositionKind);
+                        loadAttribute("NORMAL", BABYLON.VertexBuffer.NormalKind);
+                        loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind);
+                        loadAttribute("TEXCOORD_0", BABYLON.VertexBuffer.UVKind);
+                        loadAttribute("TEXCOORD_1", BABYLON.VertexBuffer.UV2Kind);
+                        loadAttribute("JOINTS_0", BABYLON.VertexBuffer.MatricesIndicesKind);
+                        loadAttribute("WEIGHTS_0", BABYLON.VertexBuffer.MatricesWeightsKind);
+                        loadAttribute("COLOR_0", BABYLON.VertexBuffer.ColorKind);
+                        var bufferView = GLTF2.GLTFLoader._GetProperty(extensionContext, _this._loader._gltf.bufferViews, extension.bufferView);
+                        return _this._loader._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView).then(function (data) {
+                            try {
+                                return BABYLON.DracoCompression.Decode(data, attributes);
+                            }
+                            catch (e) {
+                                throw new Error(context + ": " + e.message);
+                            }
+                        });
+                    });
+                };
+                return KHR_draco_mesh_compression;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.KHR_draco_mesh_compression = KHR_draco_mesh_compression;
+            if (BABYLON.DracoCompression.IsSupported) {
+                GLTF2.GLTFLoader._Register(NAME, function (loader) { return new KHR_draco_mesh_compression(loader); });
+            }
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=KHR_draco_mesh_compression.js.map
+
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
             // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
             var NAME = "KHR_materials_pbrSpecularGlossiness";
             var KHR_materials_pbrSpecularGlossiness = /** @class */ (function (_super) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 375 - 106
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js


+ 201 - 0
dist/preview release/draco.license

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 31 - 0
dist/preview release/draco_decoder.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 352 - 119
dist/preview release/es6.js


+ 22 - 19
dist/preview release/gui/babylon.gui.d.ts

@@ -18,7 +18,9 @@ declare module BABYLON.GUI {
         _lastPickedControl: Control;
         _lastControlOver: Nullable<Control>;
         _lastControlDown: Nullable<Control>;
-        _capturingControl: Nullable<Control>;
+        _capturingControl: {
+            [pointerId: number]: Control;
+        };
         _shouldBlockPointer: boolean;
         _layerToDispose: Nullable<Layer>;
         _linkedControls: Control[];
@@ -49,7 +51,7 @@ declare module BABYLON.GUI {
         _getGlobalViewport(scene: Scene): Viewport;
         private _checkUpdate(camera);
         private _render();
-        private _doPicking(x, y, type, buttonIndex);
+        private _doPicking(x, y, type, pointerId, buttonIndex);
         attach(): void;
         attachToMesh(mesh: AbstractMesh, supportPointerMove?: boolean): void;
         moveFocusToControl(control: IFocusableControl): void;
@@ -189,6 +191,7 @@ declare module BABYLON.GUI {
         private _downCount;
         private _enterCount;
         private _doNotRender;
+        private _downPointerIds;
         isHitTestVisible: boolean;
         isPointerBlocker: boolean;
         isFocusInvisible: boolean;
@@ -299,14 +302,14 @@ declare module BABYLON.GUI {
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         contains(x: number, y: number): boolean;
-        _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean;
+        _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
         _onPointerEnter(target: Control): boolean;
         _onPointerOut(target: Control): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
-        forcePointerUp(): void;
-        _processObservables(type: number, x: number, y: number, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        forcePointerUp(pointerId?: Nullable<number>): void;
+        _processObservables(type: number, x: number, y: number, pointerId: number, buttonIndex: number): boolean;
         private _prepareFont();
         dispose(): void;
         private static _HORIZONTAL_ALIGNMENT_LEFT;
@@ -357,7 +360,7 @@ declare module BABYLON.GUI {
         protected _localDraw(context: CanvasRenderingContext2D): void;
         _link(root: Nullable<Container>, host: AdvancedDynamicTexture): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean;
+        _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         protected _clipForChildren(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         dispose(): void;
@@ -487,9 +490,9 @@ declare module BABYLON.GUI {
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         private _pointerIsDown;
         private _updateValueFromPointer(x, y);
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
     }
 }
 
@@ -509,7 +512,7 @@ declare module BABYLON.GUI {
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
     }
 }
 
@@ -530,7 +533,7 @@ declare module BABYLON.GUI {
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
     }
 }
 
@@ -699,11 +702,11 @@ declare module BABYLON.GUI {
         pointerUpAnimation: () => void;
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
-        _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean;
+        _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         _onPointerEnter(target: Control): boolean;
         _onPointerOut(target: Control): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
         static CreateImageButton(name: string, text: string, imageUrl: string): Button;
         static CreateImageOnlyButton(name: string, imageUrl: string): Button;
         static CreateSimpleButton(name: string, text: string): Button;
@@ -744,9 +747,9 @@ declare module BABYLON.GUI {
         private _updateValueFromPointer(x, y);
         private _isPointOnSquare(coordinates);
         private _isPointOnWheel(coordinates);
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
     }
 }
 
@@ -793,8 +796,8 @@ declare module BABYLON.GUI {
         processKey(keyCode: number, key?: string): void;
         processKeyboard(evt: KeyboardEvent): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
         dispose(): void;
     }
 }

+ 60 - 47
dist/preview release/gui/babylon.gui.js

@@ -33,6 +33,7 @@ var BABYLON;
                 var _this = _super.call(this, name, { width: width, height: height }, scene, generateMipMaps, samplingMode, BABYLON.Engine.TEXTUREFORMAT_RGBA) || this;
                 _this._isDirty = false;
                 _this._rootContainer = new GUI.Container("root");
+                _this._capturingControl = {};
                 _this._linkedControls = new Array();
                 _this._isFullscreen = false;
                 _this._fullscreenViewport = new BABYLON.Viewport(0, 0, 1, 1);
@@ -340,7 +341,7 @@ var BABYLON;
                 var measure = new GUI.Measure(0, 0, renderWidth, renderHeight);
                 this._rootContainer._draw(measure, context);
             };
-            AdvancedDynamicTexture.prototype._doPicking = function (x, y, type, buttonIndex) {
+            AdvancedDynamicTexture.prototype._doPicking = function (x, y, type, pointerId, buttonIndex) {
                 var scene = this.getScene();
                 if (!scene) {
                     return;
@@ -351,11 +352,11 @@ var BABYLON;
                     x = x * ((textureSize.width / this._renderScale) / engine.getRenderWidth());
                     y = y * ((textureSize.height / this._renderScale) / engine.getRenderHeight());
                 }
-                if (this._capturingControl) {
-                    this._capturingControl._processObservables(type, x, y, buttonIndex);
+                if (this._capturingControl[pointerId]) {
+                    this._capturingControl[pointerId]._processObservables(type, x, y, pointerId, buttonIndex);
                     return;
                 }
-                if (!this._rootContainer._processPicking(x, y, type, buttonIndex)) {
+                if (!this._rootContainer._processPicking(x, y, type, pointerId, buttonIndex)) {
                     if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
                         if (this._lastControlOver) {
                             this._lastControlOver._onPointerOut(this._lastControlOver);
@@ -389,7 +390,7 @@ var BABYLON;
                     var x = (scene.pointerX / engine.getHardwareScalingLevel() - viewport.x * engine.getRenderWidth()) / viewport.width;
                     var y = (scene.pointerY / engine.getHardwareScalingLevel() - viewport.y * engine.getRenderHeight()) / viewport.height;
                     _this._shouldBlockPointer = false;
-                    _this._doPicking(x, y, pi.type, pi.event.button);
+                    _this._doPicking(x, y, pi.type, pi.event.pointerId || 0, pi.event.button);
                     pi.skipOnPointerObservable = _this._shouldBlockPointer;
                 });
                 this._attachToOnPointerOut(scene);
@@ -407,16 +408,17 @@ var BABYLON;
                         && pi.type !== BABYLON.PointerEventTypes.POINTERDOWN) {
                         return;
                     }
+                    var pointerId = pi.event.pointerId || 0;
                     if (pi.pickInfo && pi.pickInfo.hit && pi.pickInfo.pickedMesh === mesh) {
                         var uv = pi.pickInfo.getTextureCoordinates();
                         if (uv) {
                             var size = _this.getSize();
-                            _this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi.type, pi.event.button);
+                            _this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi.type, pointerId, pi.event.button);
                         }
                     }
                     else if (pi.type === BABYLON.PointerEventTypes.POINTERUP) {
                         if (_this._lastControlDown) {
-                            _this._lastControlDown.forcePointerUp();
+                            _this._lastControlDown.forcePointerUp(pointerId);
                         }
                         _this._lastControlDown = null;
                         _this.focusedControl = null;
@@ -854,6 +856,7 @@ var BABYLON;
                 this._downCount = 0;
                 this._enterCount = 0;
                 this._doNotRender = false;
+                this._downPointerIds = {};
                 this.isHitTestVisible = true;
                 this.isPointerBlocker = false;
                 this.isFocusInvisible = false;
@@ -1659,14 +1662,14 @@ var BABYLON;
                 }
                 return true;
             };
-            Control.prototype._processPicking = function (x, y, type, buttonIndex) {
+            Control.prototype._processPicking = function (x, y, type, pointerId, buttonIndex) {
                 if (!this.isHitTestVisible || !this.isVisible || this._doNotRender) {
                     return false;
                 }
                 if (!this.contains(x, y)) {
                     return false;
                 }
-                this._processObservables(type, x, y, buttonIndex);
+                this._processObservables(type, x, y, pointerId, buttonIndex);
                 return true;
             };
             Control.prototype._onPointerMove = function (target, coordinates) {
@@ -1690,26 +1693,36 @@ var BABYLON;
                 if (canNotify && this.parent != null)
                     this.parent._onPointerOut(target);
             };
-            Control.prototype._onPointerDown = function (target, coordinates, buttonIndex) {
+            Control.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
                 if (this._downCount !== 0) {
                     return false;
                 }
                 this._downCount++;
+                this._downPointerIds[pointerId] = true;
                 var canNotify = this.onPointerDownObservable.notifyObservers(new GUI.Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
                 if (canNotify && this.parent != null)
-                    this.parent._onPointerDown(target, coordinates, buttonIndex);
+                    this.parent._onPointerDown(target, coordinates, pointerId, buttonIndex);
                 return true;
             };
-            Control.prototype._onPointerUp = function (target, coordinates, buttonIndex) {
+            Control.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
                 this._downCount = 0;
+                delete this._downPointerIds[pointerId];
                 var canNotify = this.onPointerUpObservable.notifyObservers(new GUI.Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
                 if (canNotify && this.parent != null)
-                    this.parent._onPointerUp(target, coordinates, buttonIndex);
+                    this.parent._onPointerUp(target, coordinates, pointerId, buttonIndex);
             };
-            Control.prototype.forcePointerUp = function () {
-                this._onPointerUp(this, BABYLON.Vector2.Zero(), 0);
+            Control.prototype.forcePointerUp = function (pointerId) {
+                if (pointerId === void 0) { pointerId = null; }
+                if (pointerId !== null) {
+                    this._onPointerUp(this, BABYLON.Vector2.Zero(), pointerId, 0);
+                }
+                else {
+                    for (var key in this._downPointerIds) {
+                        this._onPointerUp(this, BABYLON.Vector2.Zero(), +key, 0);
+                    }
+                }
             };
-            Control.prototype._processObservables = function (type, x, y, buttonIndex) {
+            Control.prototype._processObservables = function (type, x, y, pointerId, buttonIndex) {
                 this._dummyVector2.copyFromFloats(x, y);
                 if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
                     this._onPointerMove(this, this._dummyVector2);
@@ -1724,14 +1737,14 @@ var BABYLON;
                     return true;
                 }
                 if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
-                    this._onPointerDown(this, this._dummyVector2, buttonIndex);
+                    this._onPointerDown(this, this._dummyVector2, pointerId, buttonIndex);
                     this._host._lastControlDown = this;
                     this._host._lastPickedControl = this;
                     return true;
                 }
                 if (type === BABYLON.PointerEventTypes.POINTERUP) {
                     if (this._host._lastControlDown) {
-                        this._host._lastControlDown._onPointerUp(this, this._dummyVector2, buttonIndex);
+                        this._host._lastControlDown._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex);
                     }
                     this._host._lastControlDown = null;
                     return true;
@@ -2043,7 +2056,7 @@ var BABYLON;
                     this.onAfterDrawObservable.notifyObservers(this);
                 }
             };
-            Container.prototype._processPicking = function (x, y, type, buttonIndex) {
+            Container.prototype._processPicking = function (x, y, type, pointerId, buttonIndex) {
                 if (!this.isVisible || this.notRenderable) {
                     return false;
                 }
@@ -2053,14 +2066,14 @@ var BABYLON;
                 // Checking backwards to pick closest first
                 for (var index = this._children.length - 1; index >= 0; index--) {
                     var child = this._children[index];
-                    if (child._processPicking(x, y, type, buttonIndex)) {
+                    if (child._processPicking(x, y, type, pointerId, buttonIndex)) {
                         return true;
                     }
                 }
                 if (!this.isHitTestVisible) {
                     return false;
                 }
-                return this._processObservables(type, x, y, buttonIndex);
+                return this._processObservables(type, x, y, pointerId, buttonIndex);
             };
             Container.prototype._clipForChildren = function (context) {
                 // DO nothing
@@ -2933,13 +2946,13 @@ var BABYLON;
                 }
                 this.value = this._minimum + ((x - this._currentMeasure.left) / this._currentMeasure.width) * (this._maximum - this._minimum);
             };
-            Slider.prototype._onPointerDown = function (target, coordinates, buttonIndex) {
-                if (!_super.prototype._onPointerDown.call(this, target, coordinates, buttonIndex)) {
+            Slider.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
+                if (!_super.prototype._onPointerDown.call(this, target, coordinates, pointerId, buttonIndex)) {
                     return false;
                 }
                 this._pointerIsDown = true;
                 this._updateValueFromPointer(coordinates.x, coordinates.y);
-                this._host._capturingControl = this;
+                this._host._capturingControl[pointerId] = this;
                 return true;
             };
             Slider.prototype._onPointerMove = function (target, coordinates) {
@@ -2948,10 +2961,10 @@ var BABYLON;
                 }
                 _super.prototype._onPointerMove.call(this, target, coordinates);
             };
-            Slider.prototype._onPointerUp = function (target, coordinates, buttonIndex) {
+            Slider.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
                 this._pointerIsDown = false;
-                this._host._capturingControl = null;
-                _super.prototype._onPointerUp.call(this, target, coordinates, buttonIndex);
+                delete this._host._capturingControl[pointerId];
+                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex);
             };
             return Slider;
         }(GUI.Control));
@@ -3073,8 +3086,8 @@ var BABYLON;
                 context.restore();
             };
             // Events
-            Checkbox.prototype._onPointerDown = function (target, coordinates, buttonIndex) {
-                if (!_super.prototype._onPointerDown.call(this, target, coordinates, buttonIndex)) {
+            Checkbox.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
+                if (!_super.prototype._onPointerDown.call(this, target, coordinates, pointerId, buttonIndex)) {
                     return false;
                 }
                 this.isChecked = !this.isChecked;
@@ -3221,8 +3234,8 @@ var BABYLON;
                 context.restore();
             };
             // Events
-            RadioButton.prototype._onPointerDown = function (target, coordinates, buttonIndex) {
-                if (!_super.prototype._onPointerDown.call(this, target, coordinates, buttonIndex)) {
+            RadioButton.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
+                if (!_super.prototype._onPointerDown.call(this, target, coordinates, pointerId, buttonIndex)) {
                     return false;
                 }
                 this.isChecked = !this.isChecked;
@@ -3929,14 +3942,14 @@ var BABYLON;
                 return "Button";
             };
             // While being a container, the button behaves like a control.
-            Button.prototype._processPicking = function (x, y, type, buttonIndex) {
+            Button.prototype._processPicking = function (x, y, type, pointerId, buttonIndex) {
                 if (!this.isHitTestVisible || !this.isVisible || this.notRenderable) {
                     return false;
                 }
                 if (!_super.prototype.contains.call(this, x, y)) {
                     return false;
                 }
-                this._processObservables(type, x, y, buttonIndex);
+                this._processObservables(type, x, y, pointerId, buttonIndex);
                 return true;
             };
             Button.prototype._onPointerEnter = function (target) {
@@ -3954,8 +3967,8 @@ var BABYLON;
                 }
                 _super.prototype._onPointerOut.call(this, target);
             };
-            Button.prototype._onPointerDown = function (target, coordinates, buttonIndex) {
-                if (!_super.prototype._onPointerDown.call(this, target, coordinates, buttonIndex)) {
+            Button.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
+                if (!_super.prototype._onPointerDown.call(this, target, coordinates, pointerId, buttonIndex)) {
                     return false;
                 }
                 if (this.pointerDownAnimation) {
@@ -3963,11 +3976,11 @@ var BABYLON;
                 }
                 return true;
             };
-            Button.prototype._onPointerUp = function (target, coordinates, buttonIndex) {
+            Button.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
                 if (this.pointerUpAnimation) {
                     this.pointerUpAnimation();
                 }
-                _super.prototype._onPointerUp.call(this, target, coordinates, buttonIndex);
+                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex);
             };
             // Statics
             Button.CreateImageButton = function (name, text, imageUrl) {
@@ -4349,8 +4362,8 @@ var BABYLON;
                 }
                 return false;
             };
-            ColorPicker.prototype._onPointerDown = function (target, coordinates, buttonIndex) {
-                if (!_super.prototype._onPointerDown.call(this, target, coordinates, buttonIndex)) {
+            ColorPicker.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
+                if (!_super.prototype._onPointerDown.call(this, target, coordinates, pointerId, buttonIndex)) {
                     return false;
                 }
                 this._pointerIsDown = true;
@@ -4363,7 +4376,7 @@ var BABYLON;
                     this._pointerStartedOnWheel = true;
                 }
                 this._updateValueFromPointer(coordinates.x, coordinates.y);
-                this._host._capturingControl = this;
+                this._host._capturingControl[pointerId] = this;
                 return true;
             };
             ColorPicker.prototype._onPointerMove = function (target, coordinates) {
@@ -4372,10 +4385,10 @@ var BABYLON;
                 }
                 _super.prototype._onPointerMove.call(this, target, coordinates);
             };
-            ColorPicker.prototype._onPointerUp = function (target, coordinates, buttonIndex) {
+            ColorPicker.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
                 this._pointerIsDown = false;
-                this._host._capturingControl = null;
-                _super.prototype._onPointerUp.call(this, target, coordinates, buttonIndex);
+                delete this._host._capturingControl[pointerId];
+                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex);
             };
             return ColorPicker;
         }(GUI.Control));
@@ -4797,8 +4810,8 @@ var BABYLON;
                 }
                 context.restore();
             };
-            InputText.prototype._onPointerDown = function (target, coordinates, buttonIndex) {
-                if (!_super.prototype._onPointerDown.call(this, target, coordinates, buttonIndex)) {
+            InputText.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
+                if (!_super.prototype._onPointerDown.call(this, target, coordinates, pointerId, buttonIndex)) {
                     return false;
                 }
                 this._clickedCoordinate = coordinates.x;
@@ -4811,8 +4824,8 @@ var BABYLON;
                 this._host.focusedControl = this;
                 return true;
             };
-            InputText.prototype._onPointerUp = function (target, coordinates, buttonIndex) {
-                _super.prototype._onPointerUp.call(this, target, coordinates, buttonIndex);
+            InputText.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
+                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex);
             };
             InputText.prototype.dispose = function () {
                 _super.prototype.dispose.call(this);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/gui/babylon.gui.min.js


+ 22 - 19
dist/preview release/gui/babylon.gui.module.d.ts

@@ -24,7 +24,9 @@ declare module BABYLON.GUI {
         _lastPickedControl: Control;
         _lastControlOver: Nullable<Control>;
         _lastControlDown: Nullable<Control>;
-        _capturingControl: Nullable<Control>;
+        _capturingControl: {
+            [pointerId: number]: Control;
+        };
         _shouldBlockPointer: boolean;
         _layerToDispose: Nullable<Layer>;
         _linkedControls: Control[];
@@ -55,7 +57,7 @@ declare module BABYLON.GUI {
         _getGlobalViewport(scene: Scene): Viewport;
         private _checkUpdate(camera);
         private _render();
-        private _doPicking(x, y, type, buttonIndex);
+        private _doPicking(x, y, type, pointerId, buttonIndex);
         attach(): void;
         attachToMesh(mesh: AbstractMesh, supportPointerMove?: boolean): void;
         moveFocusToControl(control: IFocusableControl): void;
@@ -195,6 +197,7 @@ declare module BABYLON.GUI {
         private _downCount;
         private _enterCount;
         private _doNotRender;
+        private _downPointerIds;
         isHitTestVisible: boolean;
         isPointerBlocker: boolean;
         isFocusInvisible: boolean;
@@ -305,14 +308,14 @@ declare module BABYLON.GUI {
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         contains(x: number, y: number): boolean;
-        _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean;
+        _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
         _onPointerEnter(target: Control): boolean;
         _onPointerOut(target: Control): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
-        forcePointerUp(): void;
-        _processObservables(type: number, x: number, y: number, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        forcePointerUp(pointerId?: Nullable<number>): void;
+        _processObservables(type: number, x: number, y: number, pointerId: number, buttonIndex: number): boolean;
         private _prepareFont();
         dispose(): void;
         private static _HORIZONTAL_ALIGNMENT_LEFT;
@@ -363,7 +366,7 @@ declare module BABYLON.GUI {
         protected _localDraw(context: CanvasRenderingContext2D): void;
         _link(root: Nullable<Container>, host: AdvancedDynamicTexture): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean;
+        _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         protected _clipForChildren(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         dispose(): void;
@@ -493,9 +496,9 @@ declare module BABYLON.GUI {
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         private _pointerIsDown;
         private _updateValueFromPointer(x, y);
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
     }
 }
 
@@ -515,7 +518,7 @@ declare module BABYLON.GUI {
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
     }
 }
 
@@ -536,7 +539,7 @@ declare module BABYLON.GUI {
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
     }
 }
 
@@ -705,11 +708,11 @@ declare module BABYLON.GUI {
         pointerUpAnimation: () => void;
         constructor(name?: string | undefined);
         protected _getTypeName(): string;
-        _processPicking(x: number, y: number, type: number, buttonIndex: number): boolean;
+        _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         _onPointerEnter(target: Control): boolean;
         _onPointerOut(target: Control): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
         static CreateImageButton(name: string, text: string, imageUrl: string): Button;
         static CreateImageOnlyButton(name: string, imageUrl: string): Button;
         static CreateSimpleButton(name: string, text: string): Button;
@@ -750,9 +753,9 @@ declare module BABYLON.GUI {
         private _updateValueFromPointer(x, y);
         private _isPointOnSquare(coordinates);
         private _isPointOnWheel(coordinates);
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
     }
 }
 
@@ -799,8 +802,8 @@ declare module BABYLON.GUI {
         processKey(keyCode: number, key?: string): void;
         processKeyboard(evt: KeyboardEvent): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
-        _onPointerDown(target: Control, coordinates: Vector2, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, buttonIndex: number): void;
+        _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
         dispose(): void;
     }
 }

+ 14 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -331,7 +331,7 @@ declare module BABYLON.GLTF2 {
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
-        private _loadBufferViewAsync(context, bufferView);
+        _loadBufferViewAsync(context: string, bufferView: ILoaderBufferView): Promise<ArrayBufferView>;
         private _loadAccessorAsync(context, accessor);
         private _buildArrayBuffer<T>(typedArray, data, byteOffset, count, numComponents, byteStride?);
         private _getDefaultMaterial();
@@ -368,16 +368,20 @@ declare module BABYLON.GLTF2 {
         protected _loadSceneAsync(context: string, node: ILoaderScene): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading nodes. */
         protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>>;
+        /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
         /** Override this method to modify the default behavior for loading materials. */
         protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading uris. */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
         /** Helper method called by a loader extension to load an glTF extension. */
-        protected _loadExtensionAsync<T>(context: string, property: IProperty, actionAsync: (context: string, extension: T) => Promise<void>): Nullable<Promise<void>>;
+        protected _loadExtensionAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (context: string, extension: TProperty) => Promise<TResult>): Nullable<Promise<TResult>>;
         /** Helper method called by the loader to allow extensions to override loading scenes. */
         static _LoadSceneAsync(loader: GLTFLoader, context: string, scene: ILoaderScene): Nullable<Promise<void>>;
         /** Helper method called by the loader to allow extensions to override loading nodes. */
         static _LoadNodeAsync(loader: GLTFLoader, context: string, node: ILoaderNode): Nullable<Promise<void>>;
+        /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
+        static _LoadVertexDataAsync(loader: GLTFLoader, context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
         /** Helper method called by the loader to allow extensions to override loading materials. */
         static _LoadMaterialAsync(loader: GLTFLoader, context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;
         /** Helper method called by the loader to allow extensions to override loading uris. */
@@ -409,6 +413,14 @@ declare module BABYLON.GLTF2.Extensions {
 
 
 declare module BABYLON.GLTF2.Extensions {
+    class KHR_draco_mesh_compression extends GLTFLoaderExtension {
+        readonly name: string;
+        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
     class KHR_materials_pbrSpecularGlossiness extends GLTFLoaderExtension {
         readonly name: string;
         protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;

+ 100 - 6
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -854,11 +854,15 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
                 var _this = this;
+                var promise = GLTF2.GLTFLoaderExtension._LoadVertexDataAsync(this, context, primitive, babylonMesh);
+                if (promise) {
+                    return promise;
+                }
                 var attributes = primitive.attributes;
                 if (!attributes) {
                     throw new Error(context + ": Attributes are missing");
                 }
-                if (primitive.mode && primitive.mode !== 4 /* TRIANGLES */) {
+                if (primitive.mode != undefined && primitive.mode !== 4 /* TRIANGLES */) {
                     // TODO: handle other primitive modes
                     throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
                 }
@@ -1842,6 +1846,8 @@ var BABYLON;
             GLTFLoaderExtension.prototype._loadSceneAsync = function (context, node) { return null; };
             /** Override this method to modify the default behavior for loading nodes. */
             GLTFLoaderExtension.prototype._loadNodeAsync = function (context, node) { return null; };
+            /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+            GLTFLoaderExtension.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) { return null; };
             /** Override this method to modify the default behavior for loading materials. */
             GLTFLoaderExtension.prototype._loadMaterialAsync = function (context, material, babylonMesh) { return null; };
             /** Override this method to modify the default behavior for loading uris. */
@@ -1849,7 +1855,6 @@ var BABYLON;
             // #endregion
             /** Helper method called by a loader extension to load an glTF extension. */
             GLTFLoaderExtension.prototype._loadExtensionAsync = function (context, property, actionAsync) {
-                var _this = this;
                 if (!property.extensions) {
                     return null;
                 }
@@ -1860,10 +1865,13 @@ var BABYLON;
                 }
                 // Clear out the extension before executing the action to avoid recursing into the same property.
                 delete extensions[this.name];
-                return actionAsync(context + "/extensions/" + this.name, extension).then(function () {
-                    // Restore the extension after completing the action.
-                    extensions[_this.name] = extension;
-                });
+                try {
+                    return actionAsync(context + "/extensions/" + this.name, extension);
+                }
+                finally {
+                    // Restore the extension after executing the action.
+                    extensions[this.name] = extension;
+                }
             };
             /** Helper method called by the loader to allow extensions to override loading scenes. */
             GLTFLoaderExtension._LoadSceneAsync = function (loader, context, scene) {
@@ -1873,6 +1881,10 @@ var BABYLON;
             GLTFLoaderExtension._LoadNodeAsync = function (loader, context, node) {
                 return loader._applyExtensions(function (extension) { return extension._loadNodeAsync(context, node); });
             };
+            /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
+            GLTFLoaderExtension._LoadVertexDataAsync = function (loader, context, primitive, babylonMesh) {
+                return loader._applyExtensions(function (extension) { return extension._loadVertexDataAsync(context, primitive, babylonMesh); });
+            };
             /** Helper method called by the loader to allow extensions to override loading materials. */
             GLTFLoaderExtension._LoadMaterialAsync = function (loader, context, material, babylonMesh) {
                 return loader._applyExtensions(function (extension) { return extension._loadMaterialAsync(context, material, babylonMesh); });
@@ -2056,6 +2068,88 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            // https://github.com/KhronosGroup/glTF/pull/874
+            var NAME = "KHR_draco_mesh_compression";
+            var KHR_draco_mesh_compression = /** @class */ (function (_super) {
+                __extends(KHR_draco_mesh_compression, _super);
+                function KHR_draco_mesh_compression() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    _this.name = NAME;
+                    return _this;
+                }
+                KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, primitive, function (extensionContext, extension) {
+                        if (primitive.mode != undefined) {
+                            if (primitive.mode !== 5 /* TRIANGLE_STRIP */ &&
+                                primitive.mode !== 4 /* TRIANGLES */) {
+                                throw new Error(context + ": Unsupported mode " + primitive.mode);
+                            }
+                            // TODO: handle triangle strips
+                            if (primitive.mode === 5 /* TRIANGLE_STRIP */) {
+                                throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
+                            }
+                        }
+                        var attributes = {};
+                        var loadAttribute = function (name, kind) {
+                            var uniqueId = extension.attributes[name];
+                            if (uniqueId == undefined) {
+                                return;
+                            }
+                            babylonMesh._delayInfo = babylonMesh._delayInfo || [];
+                            if (babylonMesh._delayInfo.indexOf(kind) === -1) {
+                                babylonMesh._delayInfo.push(kind);
+                            }
+                            attributes[kind] = uniqueId;
+                        };
+                        loadAttribute("POSITION", BABYLON.VertexBuffer.PositionKind);
+                        loadAttribute("NORMAL", BABYLON.VertexBuffer.NormalKind);
+                        loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind);
+                        loadAttribute("TEXCOORD_0", BABYLON.VertexBuffer.UVKind);
+                        loadAttribute("TEXCOORD_1", BABYLON.VertexBuffer.UV2Kind);
+                        loadAttribute("JOINTS_0", BABYLON.VertexBuffer.MatricesIndicesKind);
+                        loadAttribute("WEIGHTS_0", BABYLON.VertexBuffer.MatricesWeightsKind);
+                        loadAttribute("COLOR_0", BABYLON.VertexBuffer.ColorKind);
+                        var bufferView = GLTF2.GLTFLoader._GetProperty(extensionContext, _this._loader._gltf.bufferViews, extension.bufferView);
+                        return _this._loader._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView).then(function (data) {
+                            try {
+                                return BABYLON.DracoCompression.Decode(data, attributes);
+                            }
+                            catch (e) {
+                                throw new Error(context + ": " + e.message);
+                            }
+                        });
+                    });
+                };
+                return KHR_draco_mesh_compression;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.KHR_draco_mesh_compression = KHR_draco_mesh_compression;
+            if (BABYLON.DracoCompression.IsSupported) {
+                GLTF2.GLTFLoader._Register(NAME, function (loader) { return new KHR_draco_mesh_compression(loader); });
+            }
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=KHR_draco_mesh_compression.js.map
+
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
             // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
             var NAME = "KHR_materials_pbrSpecularGlossiness";
             var KHR_materials_pbrSpecularGlossiness = /** @class */ (function (_super) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 14 - 2
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -886,7 +886,7 @@ declare module BABYLON.GLTF2 {
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
-        private _loadBufferViewAsync(context, bufferView);
+        _loadBufferViewAsync(context: string, bufferView: ILoaderBufferView): Promise<ArrayBufferView>;
         private _loadAccessorAsync(context, accessor);
         private _buildArrayBuffer<T>(typedArray, data, byteOffset, count, numComponents, byteStride?);
         private _getDefaultMaterial();
@@ -923,16 +923,20 @@ declare module BABYLON.GLTF2 {
         protected _loadSceneAsync(context: string, node: ILoaderScene): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading nodes. */
         protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>>;
+        /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
         /** Override this method to modify the default behavior for loading materials. */
         protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading uris. */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
         /** Helper method called by a loader extension to load an glTF extension. */
-        protected _loadExtensionAsync<T>(context: string, property: IProperty, actionAsync: (context: string, extension: T) => Promise<void>): Nullable<Promise<void>>;
+        protected _loadExtensionAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (context: string, extension: TProperty) => Promise<TResult>): Nullable<Promise<TResult>>;
         /** Helper method called by the loader to allow extensions to override loading scenes. */
         static _LoadSceneAsync(loader: GLTFLoader, context: string, scene: ILoaderScene): Nullable<Promise<void>>;
         /** Helper method called by the loader to allow extensions to override loading nodes. */
         static _LoadNodeAsync(loader: GLTFLoader, context: string, node: ILoaderNode): Nullable<Promise<void>>;
+        /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
+        static _LoadVertexDataAsync(loader: GLTFLoader, context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
         /** Helper method called by the loader to allow extensions to override loading materials. */
         static _LoadMaterialAsync(loader: GLTFLoader, context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;
         /** Helper method called by the loader to allow extensions to override loading uris. */
@@ -964,6 +968,14 @@ declare module BABYLON.GLTF2.Extensions {
 
 
 declare module BABYLON.GLTF2.Extensions {
+    class KHR_draco_mesh_compression extends GLTFLoaderExtension {
+        readonly name: string;
+        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
     class KHR_materials_pbrSpecularGlossiness extends GLTFLoaderExtension {
         readonly name: string;
         protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;

+ 100 - 6
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3030,11 +3030,15 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
                 var _this = this;
+                var promise = GLTF2.GLTFLoaderExtension._LoadVertexDataAsync(this, context, primitive, babylonMesh);
+                if (promise) {
+                    return promise;
+                }
                 var attributes = primitive.attributes;
                 if (!attributes) {
                     throw new Error(context + ": Attributes are missing");
                 }
-                if (primitive.mode && primitive.mode !== 4 /* TRIANGLES */) {
+                if (primitive.mode != undefined && primitive.mode !== 4 /* TRIANGLES */) {
                     // TODO: handle other primitive modes
                     throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
                 }
@@ -4018,6 +4022,8 @@ var BABYLON;
             GLTFLoaderExtension.prototype._loadSceneAsync = function (context, node) { return null; };
             /** Override this method to modify the default behavior for loading nodes. */
             GLTFLoaderExtension.prototype._loadNodeAsync = function (context, node) { return null; };
+            /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+            GLTFLoaderExtension.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) { return null; };
             /** Override this method to modify the default behavior for loading materials. */
             GLTFLoaderExtension.prototype._loadMaterialAsync = function (context, material, babylonMesh) { return null; };
             /** Override this method to modify the default behavior for loading uris. */
@@ -4025,7 +4031,6 @@ var BABYLON;
             // #endregion
             /** Helper method called by a loader extension to load an glTF extension. */
             GLTFLoaderExtension.prototype._loadExtensionAsync = function (context, property, actionAsync) {
-                var _this = this;
                 if (!property.extensions) {
                     return null;
                 }
@@ -4036,10 +4041,13 @@ var BABYLON;
                 }
                 // Clear out the extension before executing the action to avoid recursing into the same property.
                 delete extensions[this.name];
-                return actionAsync(context + "/extensions/" + this.name, extension).then(function () {
-                    // Restore the extension after completing the action.
-                    extensions[_this.name] = extension;
-                });
+                try {
+                    return actionAsync(context + "/extensions/" + this.name, extension);
+                }
+                finally {
+                    // Restore the extension after executing the action.
+                    extensions[this.name] = extension;
+                }
             };
             /** Helper method called by the loader to allow extensions to override loading scenes. */
             GLTFLoaderExtension._LoadSceneAsync = function (loader, context, scene) {
@@ -4049,6 +4057,10 @@ var BABYLON;
             GLTFLoaderExtension._LoadNodeAsync = function (loader, context, node) {
                 return loader._applyExtensions(function (extension) { return extension._loadNodeAsync(context, node); });
             };
+            /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
+            GLTFLoaderExtension._LoadVertexDataAsync = function (loader, context, primitive, babylonMesh) {
+                return loader._applyExtensions(function (extension) { return extension._loadVertexDataAsync(context, primitive, babylonMesh); });
+            };
             /** Helper method called by the loader to allow extensions to override loading materials. */
             GLTFLoaderExtension._LoadMaterialAsync = function (loader, context, material, babylonMesh) {
                 return loader._applyExtensions(function (extension) { return extension._loadMaterialAsync(context, material, babylonMesh); });
@@ -4232,6 +4244,88 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            // https://github.com/KhronosGroup/glTF/pull/874
+            var NAME = "KHR_draco_mesh_compression";
+            var KHR_draco_mesh_compression = /** @class */ (function (_super) {
+                __extends(KHR_draco_mesh_compression, _super);
+                function KHR_draco_mesh_compression() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    _this.name = NAME;
+                    return _this;
+                }
+                KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, primitive, function (extensionContext, extension) {
+                        if (primitive.mode != undefined) {
+                            if (primitive.mode !== 5 /* TRIANGLE_STRIP */ &&
+                                primitive.mode !== 4 /* TRIANGLES */) {
+                                throw new Error(context + ": Unsupported mode " + primitive.mode);
+                            }
+                            // TODO: handle triangle strips
+                            if (primitive.mode === 5 /* TRIANGLE_STRIP */) {
+                                throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
+                            }
+                        }
+                        var attributes = {};
+                        var loadAttribute = function (name, kind) {
+                            var uniqueId = extension.attributes[name];
+                            if (uniqueId == undefined) {
+                                return;
+                            }
+                            babylonMesh._delayInfo = babylonMesh._delayInfo || [];
+                            if (babylonMesh._delayInfo.indexOf(kind) === -1) {
+                                babylonMesh._delayInfo.push(kind);
+                            }
+                            attributes[kind] = uniqueId;
+                        };
+                        loadAttribute("POSITION", BABYLON.VertexBuffer.PositionKind);
+                        loadAttribute("NORMAL", BABYLON.VertexBuffer.NormalKind);
+                        loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind);
+                        loadAttribute("TEXCOORD_0", BABYLON.VertexBuffer.UVKind);
+                        loadAttribute("TEXCOORD_1", BABYLON.VertexBuffer.UV2Kind);
+                        loadAttribute("JOINTS_0", BABYLON.VertexBuffer.MatricesIndicesKind);
+                        loadAttribute("WEIGHTS_0", BABYLON.VertexBuffer.MatricesWeightsKind);
+                        loadAttribute("COLOR_0", BABYLON.VertexBuffer.ColorKind);
+                        var bufferView = GLTF2.GLTFLoader._GetProperty(extensionContext, _this._loader._gltf.bufferViews, extension.bufferView);
+                        return _this._loader._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView).then(function (data) {
+                            try {
+                                return BABYLON.DracoCompression.Decode(data, attributes);
+                            }
+                            catch (e) {
+                                throw new Error(context + ": " + e.message);
+                            }
+                        });
+                    });
+                };
+                return KHR_draco_mesh_compression;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.KHR_draco_mesh_compression = KHR_draco_mesh_compression;
+            if (BABYLON.DracoCompression.IsSupported) {
+                GLTF2.GLTFLoader._Register(NAME, function (loader) { return new KHR_draco_mesh_compression(loader); });
+            }
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=KHR_draco_mesh_compression.js.map
+
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
             // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
             var NAME = "KHR_materials_pbrSpecularGlossiness";
             var KHR_materials_pbrSpecularGlossiness = /** @class */ (function (_super) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 91 - 6
dist/preview release/loaders/babylonjs.loaders.js

@@ -3998,11 +3998,15 @@ var BABYLON;
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
                 var _this = this;
+                var promise = GLTF2.GLTFLoaderExtension._LoadVertexDataAsync(this, context, primitive, babylonMesh);
+                if (promise) {
+                    return promise;
+                }
                 var attributes = primitive.attributes;
                 if (!attributes) {
                     throw new Error(context + ": Attributes are missing");
                 }
-                if (primitive.mode && primitive.mode !== 4 /* TRIANGLES */) {
+                if (primitive.mode != undefined && primitive.mode !== 4 /* TRIANGLES */) {
                     // TODO: handle other primitive modes
                     throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
                 }
@@ -4986,6 +4990,8 @@ var BABYLON;
             GLTFLoaderExtension.prototype._loadSceneAsync = function (context, node) { return null; };
             /** Override this method to modify the default behavior for loading nodes. */
             GLTFLoaderExtension.prototype._loadNodeAsync = function (context, node) { return null; };
+            /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+            GLTFLoaderExtension.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) { return null; };
             /** Override this method to modify the default behavior for loading materials. */
             GLTFLoaderExtension.prototype._loadMaterialAsync = function (context, material, babylonMesh) { return null; };
             /** Override this method to modify the default behavior for loading uris. */
@@ -4993,7 +4999,6 @@ var BABYLON;
             // #endregion
             /** Helper method called by a loader extension to load an glTF extension. */
             GLTFLoaderExtension.prototype._loadExtensionAsync = function (context, property, actionAsync) {
-                var _this = this;
                 if (!property.extensions) {
                     return null;
                 }
@@ -5004,10 +5009,13 @@ var BABYLON;
                 }
                 // Clear out the extension before executing the action to avoid recursing into the same property.
                 delete extensions[this.name];
-                return actionAsync(context + "/extensions/" + this.name, extension).then(function () {
-                    // Restore the extension after completing the action.
-                    extensions[_this.name] = extension;
-                });
+                try {
+                    return actionAsync(context + "/extensions/" + this.name, extension);
+                }
+                finally {
+                    // Restore the extension after executing the action.
+                    extensions[this.name] = extension;
+                }
             };
             /** Helper method called by the loader to allow extensions to override loading scenes. */
             GLTFLoaderExtension._LoadSceneAsync = function (loader, context, scene) {
@@ -5017,6 +5025,10 @@ var BABYLON;
             GLTFLoaderExtension._LoadNodeAsync = function (loader, context, node) {
                 return loader._applyExtensions(function (extension) { return extension._loadNodeAsync(context, node); });
             };
+            /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
+            GLTFLoaderExtension._LoadVertexDataAsync = function (loader, context, primitive, babylonMesh) {
+                return loader._applyExtensions(function (extension) { return extension._loadVertexDataAsync(context, primitive, babylonMesh); });
+            };
             /** Helper method called by the loader to allow extensions to override loading materials. */
             GLTFLoaderExtension._LoadMaterialAsync = function (loader, context, material, babylonMesh) {
                 return loader._applyExtensions(function (extension) { return extension._loadMaterialAsync(context, material, babylonMesh); });
@@ -5182,6 +5194,79 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            // https://github.com/KhronosGroup/glTF/pull/874
+            var NAME = "KHR_draco_mesh_compression";
+            var KHR_draco_mesh_compression = /** @class */ (function (_super) {
+                __extends(KHR_draco_mesh_compression, _super);
+                function KHR_draco_mesh_compression() {
+                    var _this = _super !== null && _super.apply(this, arguments) || this;
+                    _this.name = NAME;
+                    return _this;
+                }
+                KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
+                    var _this = this;
+                    return this._loadExtensionAsync(context, primitive, function (extensionContext, extension) {
+                        if (primitive.mode != undefined) {
+                            if (primitive.mode !== 5 /* TRIANGLE_STRIP */ &&
+                                primitive.mode !== 4 /* TRIANGLES */) {
+                                throw new Error(context + ": Unsupported mode " + primitive.mode);
+                            }
+                            // TODO: handle triangle strips
+                            if (primitive.mode === 5 /* TRIANGLE_STRIP */) {
+                                throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
+                            }
+                        }
+                        var attributes = {};
+                        var loadAttribute = function (name, kind) {
+                            var uniqueId = extension.attributes[name];
+                            if (uniqueId == undefined) {
+                                return;
+                            }
+                            babylonMesh._delayInfo = babylonMesh._delayInfo || [];
+                            if (babylonMesh._delayInfo.indexOf(kind) === -1) {
+                                babylonMesh._delayInfo.push(kind);
+                            }
+                            attributes[kind] = uniqueId;
+                        };
+                        loadAttribute("POSITION", BABYLON.VertexBuffer.PositionKind);
+                        loadAttribute("NORMAL", BABYLON.VertexBuffer.NormalKind);
+                        loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind);
+                        loadAttribute("TEXCOORD_0", BABYLON.VertexBuffer.UVKind);
+                        loadAttribute("TEXCOORD_1", BABYLON.VertexBuffer.UV2Kind);
+                        loadAttribute("JOINTS_0", BABYLON.VertexBuffer.MatricesIndicesKind);
+                        loadAttribute("WEIGHTS_0", BABYLON.VertexBuffer.MatricesWeightsKind);
+                        loadAttribute("COLOR_0", BABYLON.VertexBuffer.ColorKind);
+                        var bufferView = GLTF2.GLTFLoader._GetProperty(extensionContext, _this._loader._gltf.bufferViews, extension.bufferView);
+                        return _this._loader._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView).then(function (data) {
+                            try {
+                                return BABYLON.DracoCompression.Decode(data, attributes);
+                            }
+                            catch (e) {
+                                throw new Error(context + ": " + e.message);
+                            }
+                        });
+                    });
+                };
+                return KHR_draco_mesh_compression;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.KHR_draco_mesh_compression = KHR_draco_mesh_compression;
+            if (BABYLON.DracoCompression.IsSupported) {
+                GLTF2.GLTFLoader._Register(NAME, function (loader) { return new KHR_draco_mesh_compression(loader); });
+            }
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=KHR_draco_mesh_compression.js.map
+
+
+
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
             // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
             var NAME = "KHR_materials_pbrSpecularGlossiness";
             var KHR_materials_pbrSpecularGlossiness = /** @class */ (function (_super) {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


+ 14 - 2
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -987,7 +987,7 @@ declare module BABYLON.GLTF2 {
         private _loadAnimationChannelAsync(context, animationContext, animation, channel, babylonAnimationGroup);
         private _loadAnimationSamplerAsync(context, sampler);
         private _loadBufferAsync(context, buffer);
-        private _loadBufferViewAsync(context, bufferView);
+        _loadBufferViewAsync(context: string, bufferView: ILoaderBufferView): Promise<ArrayBufferView>;
         private _loadAccessorAsync(context, accessor);
         private _buildArrayBuffer<T>(typedArray, data, byteOffset, count, numComponents, byteStride?);
         private _getDefaultMaterial();
@@ -1024,16 +1024,20 @@ declare module BABYLON.GLTF2 {
         protected _loadSceneAsync(context: string, node: ILoaderScene): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading nodes. */
         protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>>;
+        /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
         /** Override this method to modify the default behavior for loading materials. */
         protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading uris. */
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>>;
         /** Helper method called by a loader extension to load an glTF extension. */
-        protected _loadExtensionAsync<T>(context: string, property: IProperty, actionAsync: (context: string, extension: T) => Promise<void>): Nullable<Promise<void>>;
+        protected _loadExtensionAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (context: string, extension: TProperty) => Promise<TResult>): Nullable<Promise<TResult>>;
         /** Helper method called by the loader to allow extensions to override loading scenes. */
         static _LoadSceneAsync(loader: GLTFLoader, context: string, scene: ILoaderScene): Nullable<Promise<void>>;
         /** Helper method called by the loader to allow extensions to override loading nodes. */
         static _LoadNodeAsync(loader: GLTFLoader, context: string, node: ILoaderNode): Nullable<Promise<void>>;
+        /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
+        static _LoadVertexDataAsync(loader: GLTFLoader, context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
         /** Helper method called by the loader to allow extensions to override loading materials. */
         static _LoadMaterialAsync(loader: GLTFLoader, context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;
         /** Helper method called by the loader to allow extensions to override loading uris. */
@@ -1065,6 +1069,14 @@ declare module BABYLON.GLTF2.Extensions {
 
 
 declare module BABYLON.GLTF2.Extensions {
+    class KHR_draco_mesh_compression extends GLTFLoaderExtension {
+        readonly name: string;
+        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
     class KHR_materials_pbrSpecularGlossiness extends GLTFLoaderExtension {
         readonly name: string;
         protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>>;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 46 - 46
dist/preview release/viewer/babylon.viewer.js


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

@@ -71,6 +71,7 @@
 - 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. ([RaananW](https://github.com/RaananW))
+- Added Draco mesh compression support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
 
 ## Bug fixes
 
@@ -79,6 +80,7 @@
 - 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))
 
 ## Breaking changes
 

+ 70 - 0
loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts

@@ -0,0 +1,70 @@
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2.Extensions {
+    // https://github.com/KhronosGroup/glTF/pull/874
+
+    const NAME = "KHR_draco_mesh_compression";
+
+    interface IKHRDracoMeshCompression {
+        bufferView: number;
+        attributes: { [name: string]: number };
+    }
+
+    export class KHR_draco_mesh_compression extends GLTFLoaderExtension {
+        public readonly name = NAME;
+
+        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>> {
+            return this._loadExtensionAsync<IKHRDracoMeshCompression, VertexData>(context, primitive, (extensionContext, extension) => {
+                if (primitive.mode != undefined) {
+                    if (primitive.mode !== MeshPrimitiveMode.TRIANGLE_STRIP &&
+                        primitive.mode !== MeshPrimitiveMode.TRIANGLES) {
+                        throw new Error(`${context}: Unsupported mode ${primitive.mode}`);
+                    }
+
+                    // TODO: handle triangle strips
+                    if (primitive.mode === MeshPrimitiveMode.TRIANGLE_STRIP) {
+                        throw new Error(`${context}: Mode ${primitive.mode} is not currently supported`);
+                    }
+                }
+
+                const attributes: { [kind: string]: number } = {};
+                const loadAttribute = (name: string, kind: string) => {
+                    const uniqueId = extension.attributes[name];
+                    if (uniqueId == undefined) {
+                        return;
+                    }
+
+                    babylonMesh._delayInfo = babylonMesh._delayInfo || [];
+                    if (babylonMesh._delayInfo.indexOf(kind) === -1) {
+                        babylonMesh._delayInfo.push(kind);
+                    }
+
+                    attributes[kind] = uniqueId;
+                };
+
+                loadAttribute("POSITION", VertexBuffer.PositionKind);
+                loadAttribute("NORMAL", VertexBuffer.NormalKind);
+                loadAttribute("TANGENT", VertexBuffer.TangentKind);
+                loadAttribute("TEXCOORD_0", VertexBuffer.UVKind);
+                loadAttribute("TEXCOORD_1", VertexBuffer.UV2Kind);
+                loadAttribute("JOINTS_0", VertexBuffer.MatricesIndicesKind);
+                loadAttribute("WEIGHTS_0", VertexBuffer.MatricesWeightsKind);
+                loadAttribute("COLOR_0", VertexBuffer.ColorKind);
+
+                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);
+                    }
+                    catch (e) {
+                        throw new Error(`${context}: ${e.message}`);
+                    }
+                });
+            });
+        }
+    }
+
+    if (DracoCompression.IsSupported) {
+        GLTFLoader._Register(NAME, loader => new KHR_draco_mesh_compression(loader));
+    }
+}

+ 7 - 2
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -452,12 +452,17 @@ module BABYLON.GLTF2 {
         }
 
         private _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<VertexData> {
+            const promise = GLTFLoaderExtension._LoadVertexDataAsync(this, context, primitive, babylonMesh);
+            if (promise) {
+                return promise;
+            }
+
             const attributes = primitive.attributes;
             if (!attributes) {
                 throw new Error(context + ": Attributes are missing");
             }
 
-            if (primitive.mode && primitive.mode !== MeshPrimitiveMode.TRIANGLES) {
+            if (primitive.mode != undefined && primitive.mode !== MeshPrimitiveMode.TRIANGLES) {
                 // TODO: handle other primitive modes
                 throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
             }
@@ -1004,7 +1009,7 @@ module BABYLON.GLTF2 {
             return buffer._data;
         }
 
-        private _loadBufferViewAsync(context: string, bufferView: ILoaderBufferView): Promise<ArrayBufferView> {
+        public _loadBufferViewAsync(context: string, bufferView: ILoaderBufferView): Promise<ArrayBufferView> {
             if (bufferView._data) {
                 return bufferView._data;
             }

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

@@ -19,6 +19,9 @@ module BABYLON.GLTF2 {
         /** Override this method to modify the default behavior for loading nodes. */
         protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>> { return null; }
 
+        /** Override this method to modify the default behavior for loading mesh primitive vertex data. */
+        protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>> { return null; }
+
         /** Override this method to modify the default behavior for loading materials. */
         protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>> { return null; }
 
@@ -28,14 +31,14 @@ module BABYLON.GLTF2 {
         // #endregion
 
         /** Helper method called by a loader extension to load an glTF extension. */
-        protected _loadExtensionAsync<T>(context: string, property: IProperty, actionAsync: (context: string, extension: T) => Promise<void>): Nullable<Promise<void>> {
+        protected _loadExtensionAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (context: string, extension: TProperty) => Promise<TResult>): Nullable<Promise<TResult>> {
             if (!property.extensions) {
                 return null;
             }
 
             const extensions = property.extensions;
 
-            const extension = extensions[this.name] as T;
+            const extension = extensions[this.name] as TProperty;
             if (!extension) {
                 return null;
             }
@@ -43,10 +46,13 @@ module BABYLON.GLTF2 {
             // Clear out the extension before executing the action to avoid recursing into the same property.
             delete extensions[this.name];
 
-            return actionAsync(context + "/extensions/" + this.name, extension).then(() => {
-                // Restore the extension after completing the action.
+            try {
+                return actionAsync(context + "/extensions/" + this.name, extension);
+            }
+            finally {
+                // Restore the extension after executing the action.
                 extensions[this.name] = extension;
-            });
+            }
         }
 
         /** Helper method called by the loader to allow extensions to override loading scenes. */
@@ -59,6 +65,11 @@ module BABYLON.GLTF2 {
             return loader._applyExtensions(extension => extension._loadNodeAsync(context, node));
         }
 
+        /** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
+        public static _LoadVertexDataAsync(loader: GLTFLoader, context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>> {
+            return loader._applyExtensions(extension => extension._loadVertexDataAsync(context, primitive, babylonMesh));
+        }
+
         /** Helper method called by the loader to allow extensions to override loading materials. */
         public static _LoadMaterialAsync(loader: GLTFLoader, context: string, material: ILoaderMaterial, babylonMesh: Mesh): Nullable<Promise<void>> {
             return loader._applyExtensions(extension => extension._loadMaterialAsync(context, material, babylonMesh));

+ 1 - 0
localDev/index.html

@@ -6,6 +6,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/Oimo.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>

+ 5 - 4
sandbox/index-local.html

@@ -3,9 +3,10 @@
 <head>
     <title>BabylonJS - Sandbox</title>
     <link href="index.css" rel="stylesheet" />
-    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
-	<script src="../Tools/DevLoader/BabylonLoader.js"></script>
+    <script src="../dist/preview%20release/cannon.js"></script>
+    <script src="../dist/preview%20release/draco_decoder.js"></script>
+    <script src="../dist/preview%20release/Oimo.js"></script>
+    <script src="../Tools/DevLoader/BabylonLoader.js"></script>
 </head>
 <body>
     <canvas id="renderCanvas"></canvas>
@@ -52,6 +53,6 @@
     <script>
         BABYLONDEVTOOLS.Loader.require('index.js')
             .load();
-    </script>	
+    </script>
 </body>
 </html>

+ 1 - 1
sandbox/index.html

@@ -27,6 +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/Oimo.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
@@ -34,7 +35,6 @@
     <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
     <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
     <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
-
 </head>
 
 <body>

+ 1 - 7
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -120,7 +120,6 @@ module BABYLON {
         private _teleportationTarget: Mesh;
         private _isDefaultTeleportationTarget = true;
         private _postProcessMove: ImageProcessingPostProcess;
-        private _passProcessMove: PassPostProcess;
         private _teleportationFillColor: string = "#444444";
         private _teleportationBorderColor: string = "#FFFFFF";
         private _rotationAngle: number = 0;
@@ -801,7 +800,6 @@ module BABYLON {
                     imageProcessingConfiguration);
 
                 this._webVRCamera.detachPostProcess(this._postProcessMove)
-                this._passProcessMove = new PassPostProcess("pass", 1.0, this._webVRCamera);
                 this._teleportationInitialized = true;
                 if (this._isDefaultTeleportationTarget) {
                     this._createTeleportationCircles();
@@ -1293,7 +1291,7 @@ module BABYLON {
 
             this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0;
             this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0;
-
+            this._postProcessMove.samples = 4;
             this._webVRCamera.attachPostProcess(this._postProcessMove)
             this._scene.beginAnimation(this._postProcessMove, 0, 6, false, 1, () => {
                 this._webVRCamera.detachPostProcess(this._postProcessMove)
@@ -1596,10 +1594,6 @@ module BABYLON {
                 this.exitVR();
             }
 
-            if (this._passProcessMove) {
-                this._passProcessMove.dispose();
-            }
-
             if (this._postProcessMove) {
                 this._postProcessMove.dispose();
             }

+ 11 - 2
src/Engine/babylon.engine.ts

@@ -349,6 +349,7 @@
         private static _TEXTUREFORMAT_R32F = 6;
         private static _TEXTUREFORMAT_RG32F = 7;
         private static _TEXTUREFORMAT_RGB32F = 8;
+        private static _TEXTUREFORMAT_RGBA32F = 9;
 
         private static _TEXTURETYPE_UNSIGNED_INT = 0;
         private static _TEXTURETYPE_FLOAT = 1;
@@ -520,7 +521,14 @@
          */
         public static get TEXTUREFORMAT_RGB32F(): number {
             return Engine._TEXTUREFORMAT_RGB32F;
-        }               
+        }       
+        
+        /**
+         * RGBA32F
+         */
+        public static get TEXTUREFORMAT_RGBA32F(): number {
+            return Engine._TEXTUREFORMAT_RGBA32F;
+        }             
 
         public static get TEXTUREFORMAT_LUMINANCE_ALPHA(): number {
             return Engine._TEXTUREFORMAT_LUMINANCE_ALPHA;
@@ -565,7 +573,7 @@
         }
 
         public static get Version(): string {
-            return "3.2.0-alpha7";
+            return "3.2.0-alpha8";
         }
 
         // Updatable statics so stick with vars here
@@ -3411,6 +3419,7 @@
                     internalFormat = this._gl.RGB;
                     break;
                 case Engine.TEXTUREFORMAT_RGBA:
+                case Engine.TEXTUREFORMAT_RGBA32F:
                     internalFormat = this._gl.RGBA;
                     break;
                 case Engine.TEXTUREFORMAT_R32F:

+ 106 - 0
src/Mesh/Compression/babylon.dracoCompression.ts

@@ -0,0 +1,106 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+
+declare var DracoDecoderModule: any;
+
+module BABYLON {
+    /**
+     * Draco compression (https://google.github.io/draco/)
+     */
+    export class DracoCompression {
+        /**
+         * Returns whether Draco compression is supported.
+         */
+        public static get IsSupported(): boolean {
+            return !!window.DracoDecoderModule;
+        }
+
+        /**
+         * Decodes Draco compressed 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
+         */
+        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}`);
+                }
+
+                if (!status.ok() || !geometry.ptr) {
+                    throw new Error(status.error_msg());
+                }
+
+                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);
+                        }
+                    }
+                    finally {
+                        dracoModule.destroy(faceIndices);
+                    }
+                }
+
+                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}`);
+                        }
+
+                        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);
+                        }
+                        vertexData.set(babylonData, kind);
+                    }
+                    finally {
+                        dracoModule.destroy(dracoData);
+                    }
+                }
+            }
+            finally {
+                if (geometry) {
+                    dracoModule.destroy(geometry);
+                }
+
+                dracoModule.destroy(decoder);
+                dracoModule.destroy(buffer);
+            }
+
+            return vertexData;
+        }
+    }
+}

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

@@ -804,14 +804,14 @@
                         for (inf = 0; inf < 4; inf++) {
                             weight = matricesWeightsData[matWeightIdx + inf];
                             if (weight <= 0) break;
-                            Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[matWeightIdx + inf] * 16, weight, tempMatrix);
+                            Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesData[matWeightIdx + inf] * 16), weight, tempMatrix);
                             finalMatrix.addToSelf(tempMatrix);
                         }
                         if (needExtras) {
                             for (inf = 0; inf < 4; inf++) {
                                 weight = matricesWeightsExtraData![matWeightIdx + inf];
                                 if (weight <= 0) break;
-                                Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesExtraData![matWeightIdx + inf] * 16, weight, tempMatrix);
+                                Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesExtraData![matWeightIdx + inf] * 16), weight, tempMatrix);
                                 finalMatrix.addToSelf(tempMatrix);
                             }
                         }
@@ -3266,7 +3266,7 @@
                 for (inf = 0; inf < 4; inf++) {
                     weight = matricesWeightsData[matWeightIdx + inf];
                     if (weight > 0) {
-                        Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesData[matWeightIdx + inf] * 16, weight, tempMatrix);
+                        Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesData[matWeightIdx + inf] * 16), weight, tempMatrix);
                         finalMatrix.addToSelf(tempMatrix);
 
                     } else break;
@@ -3275,7 +3275,7 @@
                     for (inf = 0; inf < 4; inf++) {
                         weight = matricesWeightsExtraData![matWeightIdx + inf];
                         if (weight > 0) {
-                            Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, matricesIndicesExtraData![matWeightIdx + inf] * 16, weight, tempMatrix);
+                            Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesExtraData![matWeightIdx + inf] * 16), weight, tempMatrix);
                             finalMatrix.addToSelf(tempMatrix);
 
                         } else break;

+ 4 - 7
src/Mesh/babylon.vertexBuffer.ts

@@ -237,10 +237,6 @@
          */
         public static DeduceStride(kind: string): number {
             switch (kind) {
-                case VertexBuffer.PositionKind:
-                    return 3;
-                case VertexBuffer.NormalKind:
-                    return 3;
                 case VertexBuffer.UVKind:
                 case VertexBuffer.UV2Kind:
                 case VertexBuffer.UV3Kind:
@@ -248,14 +244,15 @@
                 case VertexBuffer.UV5Kind:
                 case VertexBuffer.UV6Kind:
                     return 2;
-                case VertexBuffer.TangentKind:
+                case VertexBuffer.NormalKind:
+                case VertexBuffer.PositionKind:
+                    return 3;
                 case VertexBuffer.ColorKind:
-                    return 4;
                 case VertexBuffer.MatricesIndicesKind:
                 case VertexBuffer.MatricesIndicesExtraKind:
-                    return 4;
                 case VertexBuffer.MatricesWeightsKind:
                 case VertexBuffer.MatricesWeightsExtraKind:
+                case VertexBuffer.TangentKind:
                     return 4;
                 default:
                     throw new Error("Invalid kind '" + kind + "'");

+ 12 - 0
src/Particles/babylon.iParticleEmitterType.ts

@@ -26,5 +26,17 @@ module BABYLON {
          * @returns the new emitter
          */
         clone(): IParticleEmitterType;
+
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */
+        applyToShader(effect: Effect): void;
+
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns the effect defines string
+         */
+        getEffectDefines(): string;
     }
 }

+ 26 - 44
src/Particles/babylon.boxParticleEmitter.ts

@@ -8,62 +8,25 @@ module BABYLON {
         /**
          * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
          */
-        public get direction1(): Vector3 {
-            return this._particleSystem.direction1;
-        }
+        public direction1 = new Vector3(0, 1.0, 0);
         /**
          * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
          */
-        public set direction1(value: Vector3) {
-            this._particleSystem.direction1 = value;
-        }
-
-        /**
-         * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
-         */
-        public get direction2(): Vector3 {
-            return this._particleSystem.direction2;
-        }
-        /**
-         * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
-         */
-        public set direction2(value: Vector3) {
-            this._particleSystem.direction2 = value;
-        }
+        public direction2 = new Vector3(0, 1.0, 0);
 
         /**
          * Minimum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
          */
-        public get minEmitBox(): Vector3 {
-            return this._particleSystem.minEmitBox;
-        }
-        /**
-         * Minimum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
-         */
-        public set minEmitBox(value: Vector3) {
-            this._particleSystem.minEmitBox = value;
-        }
-
+        public minEmitBox = new Vector3(-0.5, -0.5, -0.5);
         /**
          * Maximum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
          */
-        public get maxEmitBox(): Vector3 {
-            return this._particleSystem.maxEmitBox;
-        }
-        /**
-         * Maximum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
-         */
-        public set maxEmitBox(value: Vector3) {
-            this._particleSystem.maxEmitBox = value;
-        }
-        
-        // to be updated like the rest of emitters when breaking changes.
-        // all property should be come public variables and passed through constructor.
+        public maxEmitBox = new Vector3(0.5, 0.5, 0.5);  
+               
         /**
          * Creates a new instance of @see BoxParticleEmitter
-         * @param _particleSystem the particle system associated with the emitter
          */
-        constructor(private _particleSystem: ParticleSystem) {
+        constructor() {
 
         }
 
@@ -102,11 +65,30 @@ module BABYLON {
          */
         public clone(): BoxParticleEmitter
         {
-            let newOne = new BoxParticleEmitter(this._particleSystem);
+            let newOne = new BoxParticleEmitter();
 
             Tools.DeepCopy(this, newOne);
 
             return newOne;
         }
+
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */        
+        public applyToShader(effect: Effect): void {            
+            effect.setVector3("direction1", this.direction1);
+            effect.setVector3("direction2", this.direction2);
+            effect.setVector3("minEmitBox", this.minEmitBox);
+            effect.setVector3("maxEmitBox", this.maxEmitBox);
+        }
+
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns a string containng the defines string
+         */
+        public getEffectDefines(): string {
+            return "#define BOXEMITTER"
+        }
     }
 }

+ 21 - 2
src/Particles/babylon.coneParticleEmitter.ts

@@ -88,7 +88,7 @@ module BABYLON {
 
             var randX = radius * Math.sin(s);
             var randZ = radius * Math.cos(s);
-            var randY = h;
+            var randY = h * this._height;
 
             Vector3.TransformCoordinatesFromFloatsToRef(randX, randY, randZ, worldMatrix, positionToUpdate);
         }
@@ -103,6 +103,25 @@ module BABYLON {
             Tools.DeepCopy(this, newOne);
 
             return newOne;
-        }          
+        }        
+        
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */        
+        public applyToShader(effect: Effect): void {
+            effect.setFloat("radius", this.radius);
+            effect.setFloat("angle", this.angle);
+            effect.setFloat("height", this._height);
+            effect.setFloat("directionRandomizer", this.directionRandomizer);
+        }
+
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns a string containng the defines string
+         */
+        public getEffectDefines(): string {
+            return "#define CONEEMITTER"
+        }        
     }
 }

+ 35 - 0
src/Particles/babylon.sphereParticleEmitter.ts

@@ -67,6 +67,23 @@ module BABYLON {
             Tools.DeepCopy(this, newOne);
 
             return newOne;
+        }    
+        
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */        
+        public applyToShader(effect: Effect): void {
+            effect.setFloat("radius", this.radius);
+            effect.setFloat("directionRandomizer", this.directionRandomizer);
+        }    
+        
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns a string containng the defines string
+         */
+        public getEffectDefines(): string {
+            return "#define SPHEREEMITTER"
         }        
     }
 
@@ -118,6 +135,24 @@ module BABYLON {
             Tools.DeepCopy(this, newOne);
 
             return newOne;
+        }     
+        
+        /**
+         * Called by the {BABYLON.GPUParticleSystem} to setup the update shader
+         * @param effect defines the update shader
+         */        
+        public applyToShader(effect: Effect): void {
+            effect.setFloat("radius", this.radius);
+            effect.setVector3("direction1", this.direction1);
+            effect.setVector3("direction2", this.direction2);
+        }       
+        
+        /**
+         * Returns a string to use to update the GPU particles update shader
+         * @returns a string containng the defines string
+         */
+        public getEffectDefines(): string {
+            return "#define SPHEREEMITTER\n#define DIRECTEDSPHEREEMITTER"
         }          
     }
 }

+ 82 - 22
src/Particles/babylon.gpuParticleSystem.ts

@@ -56,6 +56,17 @@
         private _randomTexture: RawTexture;
 
         private readonly _attributesStrideSize = 14;
+        private _updateEffectOptions: EffectCreationOptions;
+
+        /**
+         * Gets a boolean indicating if the GPU particles can be rendered on current browser
+         */
+        public static get IsSupported(): boolean {
+            if (!Engine.LastCreatedEngine) {
+                return false;
+            }
+            return Engine.LastCreatedEngine.webGLVersion > 1;
+        }
 
         /**
         * An event triggered when the system is disposed.
@@ -120,6 +131,21 @@
         public gravity = Vector3.Zero();    
 
         /**
+         * Minimum power of emitting particles.
+         */
+        public minEmitPower = 1;
+        /**
+         * Maximum power of emitting particles.
+         */
+        public maxEmitPower = 1;        
+
+        /**
+         * The particle emitter type defines the emitter used by the particle system.
+         * It can be for example box, sphere, or cone...
+         */
+        public particleEmitterType: Nullable<IParticleEmitterType>;        
+
+        /**
          * Gets the maximum number of particles supported by this system
          */
         public get capacity(): number {
@@ -166,20 +192,31 @@
          * @param capacity The max number of particles alive at the same time
          * @param scene The scene the particle system belongs to
          */
-        constructor(name: string, capacity: number, scene: Scene) {
+        constructor(name: string, options: Partial<{
+                        capacity: number,
+                        randomTextureSize: number
+                    }>, scene: Scene) {
             this.id = name;
             this.name = name;
             this._scene = scene || Engine.LastCreatedScene;
-            this._capacity = capacity;
-            this._activeCount = capacity;
-            this._currentActiveCount = 0;
             this._engine = this._scene.getEngine();
 
+            let fullOptions = {
+                capacity: 50000,
+                randomTextureSize: this._engine.getCaps().maxTextureSize,
+                ...options
+            };
+
+            this._capacity = fullOptions.capacity;
+            this._activeCount = fullOptions.capacity;
+            this._currentActiveCount = 0;
+
             this._scene.particleSystems.push(this);
 
-            let updateEffectOptions: EffectCreationOptions = {
+            this._updateEffectOptions = {
                 attributes: ["position", "age", "life", "seed", "size", "color", "direction"],
-                uniformsNames: ["currentCount", "timeDelta", "generalRandom", "emitterWM", "lifeTime", "color1", "color2", "sizeRange", "gravity"],
+                uniformsNames: ["currentCount", "timeDelta", "generalRandoms", "emitterWM", "lifeTime", "color1", "color2", "sizeRange", "gravity", "emitPower",
+                                "direction1", "direction2", "minEmitBox", "maxEmitBox", "radius", "directionRandomizer", "height", "angle"],
                 uniformBuffersNames: [],
                 samplers:["randomSampler"],
                 defines: "",
@@ -191,19 +228,20 @@
                 transformFeedbackVaryings: ["outPosition", "outAge", "outLife", "outSeed", "outSize", "outColor", "outDirection"]
             };
 
-            this._updateEffect = new Effect("gpuUpdateParticles", updateEffectOptions, this._scene.getEngine());   
+            this._updateEffect = new Effect("gpuUpdateParticles", this._updateEffectOptions, this._scene.getEngine());   
 
             this._renderEffect = new Effect("gpuRenderParticles", ["position", "age", "life", "size", "color", "offset", "uv"], ["view", "projection", "colorDead"], ["textureSampler"], this._scene.getEngine());
 
             // Random data
-            var maxTextureSize = this._engine.getCaps().maxTextureSize;
+            var maxTextureSize = Math.min(this._engine.getCaps().maxTextureSize, fullOptions.randomTextureSize);
             var d = [];
             for (var i = 0; i < maxTextureSize; ++i) {
                 d.push(Math.random());
                 d.push(Math.random());
                 d.push(Math.random());
+                d.push(Math.random());
             }
-            this._randomTexture = new RawTexture(new Float32Array(d), maxTextureSize, 1, Engine.TEXTUREFORMAT_RGB32F, this._scene, false, false, Texture.NEAREST_SAMPLINGMODE, Engine.TEXTURETYPE_FLOAT)
+            this._randomTexture = new RawTexture(new Float32Array(d), maxTextureSize, 1, Engine.TEXTUREFORMAT_RGBA32F, this._scene, false, false, Texture.NEAREST_SAMPLINGMODE, Engine.TEXTURETYPE_FLOAT)
             this._randomTexture.wrapU = Texture.WRAP_ADDRESSMODE;
             this._randomTexture.wrapV = Texture.WRAP_ADDRESSMODE;
         }
@@ -212,11 +250,6 @@
          * Animates the particle system for the current frame by emitting new particles and or animating the living ones.
          */
         public animate(): void {
-            if (this._currentRenderId === this._scene.getRenderId()) {
-                return;
-            }
-
-            this._currentRenderId = this._scene.getRenderId();
             this._timeDelta = this.updateSpeed * this._scene.getAnimationRatio();               
         }
 
@@ -253,8 +286,8 @@
             return vao;
         }        
         
-        private _initialize(): void {
-            if (this._buffer0) {
+        private _initialize(force = false): void {
+            if (this._buffer0 && !force) {
                 return;
             }
 
@@ -312,34 +345,61 @@
             this._targetBuffer = this._buffer1;
 
         }
+
+        /** @ignore */
+        public _recreateUpdateEffect(defines: string) {
+            if (this._updateEffectOptions.defines === defines) {
+                return;
+            }
+            this._updateEffectOptions.defines = defines;
+            this._updateEffect = new Effect("gpuUpdateParticles", this._updateEffectOptions, this._scene.getEngine());   
+        }
+
         /**
          * Renders the particle system in its current state.
-         * @returns the current number of particles.
+         * @returns the current number of particles
          */
         public render(): number {
+            if (this.particleEmitterType) {
+                this._recreateUpdateEffect(this.particleEmitterType.getEffectDefines());
+            }
+
             if (!this.emitter || !this._updateEffect.isReady() || !this._renderEffect.isReady() ) {
                 return 0;
             }
 
+            if (this._currentRenderId === this._scene.getRenderId()) {
+                return 0;
+            }
+
+            this._currentRenderId = this._scene.getRenderId();
+            
+
             // Get everything ready to render
             this. _initialize();
 
             this._currentActiveCount = Math.min(this._activeCount, this._currentActiveCount + this.emitRate);
             
             // Enable update effect
+
             this._engine.enableEffect(this._updateEffect);
             this._engine.setState(false);    
             
             this._updateEffect.setFloat("currentCount", this._currentActiveCount);
             this._updateEffect.setFloat("timeDelta", this._timeDelta);
-            this._updateEffect.setFloat("generalRandom", Math.random());
+            this._updateEffect.setFloat3("generalRandoms", Math.random(), Math.random(), Math.random());
             this._updateEffect.setTexture("randomSampler", this._randomTexture);
             this._updateEffect.setFloat2("lifeTime", this.minLifeTime, this.maxLifeTime);
+            this._updateEffect.setFloat2("emitPower", this.minEmitPower, this.maxEmitPower);
             this._updateEffect.setDirectColor4("color1", this.color1);
             this._updateEffect.setDirectColor4("color2", this.color2);
             this._updateEffect.setFloat2("sizeRange", this.minSize, this.maxSize);
             this._updateEffect.setVector3("gravity", this.gravity);
 
+            if (this.particleEmitterType) {
+                this.particleEmitterType.applyToShader(this._updateEffect);
+            }
+
             let emitterWM: Matrix;
             if ((<AbstractMesh>this.emitter).position) {
                 var emitterMesh = (<AbstractMesh>this.emitter);
@@ -392,16 +452,16 @@
             // Switch buffers
             let tmpBuffer = this._sourceBuffer;
             this._sourceBuffer = this._targetBuffer;
-            this._targetBuffer = tmpBuffer;            
-
-            return 0;
+            this._targetBuffer = tmpBuffer;     
+            
+            return this._currentActiveCount;
         }
 
         /**
          * Rebuilds the particle system
          */
         public rebuild(): void {
-            
+            this._initialize(true);
         }
 
         /**

+ 66 - 11
src/Particles/babylon.particleSystem.ts

@@ -36,7 +36,7 @@
         animate(): void;
         /**
          * Renders the particle system in its current state.
-         * @returns the current number of particles.
+         * @returns the current number of particles
          */
         render(): number;
         /**
@@ -213,23 +213,77 @@
          */
         public gravity = Vector3.Zero();
 
-        /**
+       /**
          * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
+         * This only works when particleEmitterTyps is a BoxParticleEmitter
          */
-        public direction1 = new Vector3(0, 1.0, 0);
+        public get direction1(): Vector3 {
+            if ((<BoxParticleEmitter>this.particleEmitterType).direction1) {
+                return (<BoxParticleEmitter>this.particleEmitterType).direction1;
+            }
+
+            return Vector3.Zero();
+        }
+
+        public set direction1(value: Vector3) {
+            if ((<BoxParticleEmitter>this.particleEmitterType).direction1) {
+                (<BoxParticleEmitter>this.particleEmitterType).direction1 = value;
+            }
+        }
+
         /**
          * Random direction of each particle after it has been emitted, between direction1 and direction2 vectors.
+         * This only works when particleEmitterTyps is a BoxParticleEmitter
          */
-        public direction2 = new Vector3(0, 1.0, 0);
+        public get direction2(): Vector3 {
+            if ((<BoxParticleEmitter>this.particleEmitterType).direction2) {
+                return (<BoxParticleEmitter>this.particleEmitterType).direction2;
+            }
+
+            return Vector3.Zero();
+        }
+
+        public set direction2(value: Vector3) {
+            if ((<BoxParticleEmitter>this.particleEmitterType).direction2) {
+                (<BoxParticleEmitter>this.particleEmitterType).direction2 = value;
+            }
+        }
 
         /**
          * Minimum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
+         * This only works when particleEmitterTyps is a BoxParticleEmitter
          */
-        public minEmitBox = new Vector3(-0.5, -0.5, -0.5);
+        public get minEmitBox(): Vector3 {
+            if ((<BoxParticleEmitter>this.particleEmitterType).minEmitBox) {
+                return (<BoxParticleEmitter>this.particleEmitterType).minEmitBox;
+            }
+
+            return Vector3.Zero();
+        }
+
+        public set minEmitBox(value: Vector3) {
+            if ((<BoxParticleEmitter>this.particleEmitterType).minEmitBox) {
+                (<BoxParticleEmitter>this.particleEmitterType).minEmitBox = value;
+            }
+        }
+
         /**
          * Maximum box point around our emitter. Our emitter is the center of particles source, but if you want your particles to emit from more than one point, then you can tell it to do so.
+         * This only works when particleEmitterTyps is a BoxParticleEmitter
          */
-        public maxEmitBox = new Vector3(0.5, 0.5, 0.5);
+        public get maxEmitBox(): Vector3 {
+            if ((<BoxParticleEmitter>this.particleEmitterType).maxEmitBox) {
+                return (<BoxParticleEmitter>this.particleEmitterType).maxEmitBox;
+            }
+
+            return Vector3.Zero();
+        }
+
+        public set maxEmitBox(value: Vector3) {
+            if ((<BoxParticleEmitter>this.particleEmitterType).maxEmitBox) {
+                (<BoxParticleEmitter>this.particleEmitterType).maxEmitBox = value;
+            }
+        }
 
         /**
          * Random color of each particle after it has been emitted, between color1 and color2 vectors.
@@ -387,8 +441,8 @@
             this._vertexBuffers[VertexBuffer.ColorKind] = colors;
             this._vertexBuffers["options"] = options;
 
-            // Default behaviors
-            this.particleEmitterType = new BoxParticleEmitter(this);
+            // Default emitter type
+            this.particleEmitterType = new BoxParticleEmitter();
 
             this.updateFunction = (particles: Particle[]): void => {
                 for (var index = 0; index < particles.length; index++) {
@@ -767,14 +821,15 @@
 
         /**
          * Renders the particle system in its current state.
-         * @returns the current number of particles.
+         * @returns the current number of particles
          */
         public render(): number {
             var effect = this._getEffect();
 
             // Check
-            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady() || !this._particles.length)
+            if (!this.emitter || !effect.isReady() || !this.particleTexture || !this.particleTexture.isReady() || !this._particles.length) {
                 return 0;
+            }
 
             var engine = this._scene.getEngine();
 
@@ -898,7 +953,7 @@
          * @returns the emitter
          */
         public createBoxEmitter(direction1: Vector3, direction2: Vector3, minEmitBox: Vector3, maxEmitBox: Vector3): BoxParticleEmitter {
-            var particleEmitter = new BoxParticleEmitter(this);
+            var particleEmitter = new BoxParticleEmitter();
             this.direction1 = direction1;
             this.direction2 = direction2;
             this.minEmitBox = minEmitBox;

+ 99 - 5
src/Shaders/gpuUpdateParticles.vertex.fx

@@ -1,16 +1,43 @@
 #version 300 es
 
+#define PI 3.14159
+
 uniform float currentCount;
 uniform float timeDelta;
-uniform float generalRandom;
+uniform vec3 generalRandoms;
 uniform mat4 emitterWM;
 uniform vec2 lifeTime;
+uniform vec2 emitPower;
 uniform vec2 sizeRange;
 uniform vec4 color1;
 uniform vec4 color2;
 uniform vec3 gravity;
 uniform sampler2D randomSampler;
 
+#ifdef BOXEMITTER
+uniform vec3 direction1;
+uniform vec3 direction2;
+uniform vec3 minEmitBox;
+uniform vec3 maxEmitBox;
+#endif
+
+#ifdef SPHEREEMITTER
+uniform float radius;
+  #ifdef DIRECTEDSPHEREEMITTER
+  uniform vec3 direction1;
+  uniform vec3 direction2;
+  #else
+  uniform float directionRandomizer;
+  #endif
+#endif
+
+#ifdef CONEEMITTER
+uniform float radius;
+uniform float angle;
+uniform float height;
+uniform float directionRandomizer;
+#endif
+
 // Particles state
 in vec3 position;
 in float age;
@@ -33,13 +60,18 @@ vec3 getRandomVec3(float offset) {
   return texture(randomSampler, vec2(float(gl_VertexID) * offset / currentCount, 0)).rgb;
 }
 
+vec4 getRandomVec4(float offset) {
+  return texture(randomSampler, vec2(float(gl_VertexID) * offset / currentCount, 0));
+}
+
+
 void main() {
   if (age >= life) {
-    // Create the particle at origin
-    outPosition = (emitterWM * vec4(0., 0., 0., 1.)).xyz;
+    vec3 position;
+    vec3 direction;
 
     // Let's get some random values
-    vec3 randoms = getRandomVec3(generalRandom);
+    vec4 randoms = getRandomVec4(generalRandoms.x);
 
     // Age and life
     outAge = 0.0;
@@ -54,8 +86,70 @@ void main() {
     // Color
     outColor = color1 + (color2 - color1) * randoms.b;
 
+    // Position / Direction (based on emitter type)
+#ifdef BOXEMITTER
+    vec3 randoms2 = getRandomVec3(generalRandoms.y);
+    vec3 randoms3 = getRandomVec3(generalRandoms.z);
+
+    position = minEmitBox + (maxEmitBox - minEmitBox) * randoms2;
+
+    direction = direction1 + (direction2 - direction1) * randoms3;
+#elif defined(SPHEREEMITTER)
+    vec3 randoms2 = getRandomVec3(generalRandoms.y);
+    vec3 randoms3 = getRandomVec3(generalRandoms.z);
+
+    // Position on the sphere surface
+    float phi = 2.0 * PI * randoms2.x;
+    float theta = PI * randoms2.y;
+    float randX = cos(phi) * sin(theta);
+    float randY = cos(theta);
+    float randZ = sin(phi) * sin(theta);
+
+    position = radius * vec3(randX, randY, randZ);
+
+    #ifdef DIRECTEDSPHEREEMITTER
+      direction = direction1 + (direction2 - direction1) * randoms3;
+    #else
+        // Direction
+        direction = position + directionRandomizer * randoms3;
+    #endif
+#elif defined(CONEEMITTER)
+    vec3 randoms2 = getRandomVec3(generalRandoms.y);
+
+    float s = 2.0 * PI * randoms2.x;
+    float h = randoms2.y;
+    
+    // Better distribution in a cone at normal angles.
+    h = 1. - h * h;
+    float lRadius = radius * randoms2.z;
+    lRadius = lRadius * h / height;
+
+    float randX = lRadius * sin(s);
+    float randZ = lRadius * cos(s);
+    float randY = h  * height;
+
+    position = vec3(randX, randY, randZ); 
+
     // Direction
-    outDirection = 2.0 * (getRandomVec3(seed) - vec3(0.5, 0.5, 0.5));
+    if (angle == 0.) {
+      direction = vec3(0., 1.0, 0.);
+    } else {
+      vec3 randoms3 = getRandomVec3(generalRandoms.z);
+      direction = position + directionRandomizer * randoms3;
+    }
+#else    
+    // Create the particle at origin
+    position = vec3(0., 0., 0.);
+
+    // Spread in all directions
+    direction = 2.0 * (getRandomVec3(seed) - vec3(0.5, 0.5, 0.5));
+#endif
+
+    float power = emitPower.x + (emitPower.y - emitPower.x) * randoms.a;
+
+    outPosition = (emitterWM * vec4(position, 1.)).xyz;
+    outDirection = (emitterWM * vec4(normalize(direction) * power, 0.)).xyz;
+
   } else {   
     outPosition = position + (direction + gravity) * timeDelta;
     outAge = age + timeDelta;

+ 1 - 0
src/babylon.mixins.ts

@@ -18,6 +18,7 @@ interface Window {
     mozURL: typeof URL;
     msURL: typeof URL;
     VRFrameData: any; // WebVR, from specs 1.1
+    DracoDecoderModule: any;
 }
 
 interface WebGLRenderingContext {