소스 검색

merge BabylonJS/master

Raanan Weber 7 년 전
부모
커밋
6801a8dbeb
97개의 변경된 파일20377개의 추가작업 그리고 17953개의 파일을 삭제
  1. 5988 5908
      Playground/babylon.d.txt
  2. 1 1
      Playground/debug.html
  3. 1 1
      Playground/frame.html
  4. 1 1
      Playground/full.html
  5. 1 1
      Playground/index-local.html
  6. 1 1
      Playground/index.html
  7. 1 1
      Playground/indexStable.html
  8. 1 1
      Playground/zipContent/index.html
  9. 8 2
      Tools/Gulp/config.json
  10. 3 2
      Tools/Gulp/gulp-addDtsExport.js
  11. 2 5
      Tools/Gulp/gulpfile.js
  12. 11 0
      Tools/Publisher/index.js
  13. 1 1
      Viewer/src/configuration/configuration.ts
  14. 6 2
      Viewer/src/templateManager.ts
  15. 4 5
      Viewer/src/viewer/defaultViewer.ts
  16. 0 2
      Viewer/src/viewer/viewer.ts
  17. 2641 2571
      dist/preview release/babylon.d.ts
  18. 53 53
      dist/preview release/babylon.js
  19. 649 397
      dist/preview release/babylon.max.js
  20. 51 51
      dist/preview release/babylon.worker.js
  21. 5432 5356
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  22. 54 54
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  23. 690 411
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  24. 692 413
      dist/preview release/customConfigurations/minimalGLTFViewer/es6.js
  25. 651 399
      dist/preview release/es6.js
  26. 248 0
      dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts
  27. 28 0
      dist/preview release/gltf2Interface/package.json
  28. 6 2
      dist/preview release/gui/babylon.gui.d.ts
  29. 24 22
      dist/preview release/gui/babylon.gui.js
  30. 3 3
      dist/preview release/gui/babylon.gui.min.js
  31. 6 2
      dist/preview release/gui/babylon.gui.module.d.ts
  32. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  33. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  34. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  35. 5 1
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  36. 27 9
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  37. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  38. 5 1
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  39. 27 9
      dist/preview release/loaders/babylon.glTFFileLoader.js
  40. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  41. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  42. 27 9
      dist/preview release/loaders/babylonjs.loaders.js
  43. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  44. 5 1
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  45. 3 0
      dist/preview release/loaders/package.json
  46. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  47. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  48. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  49. 3 3
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  50. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  51. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  52. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  53. 62 24
      dist/preview release/serializers/babylon.glTF2Serializer.d.ts
  54. 281 362
      dist/preview release/serializers/babylon.glTF2Serializer.js
  55. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  56. 281 362
      dist/preview release/serializers/babylonjs.serializers.js
  57. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  58. 62 24
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  59. 3 0
      dist/preview release/serializers/package.json
  60. 2 93
      dist/preview release/typedocValidationBaseline.json
  61. 67 67
      dist/preview release/viewer/babylon.viewer.js
  62. 740 420
      dist/preview release/viewer/babylon.viewer.max.js
  63. 0 3
      dist/preview release/viewer/package.json
  64. 10 3
      dist/preview release/what's new.md
  65. 19 19
      gui/src/advancedDynamicTexture.ts
  66. 6 6
      gui/src/controls/control.ts
  67. 26 5
      loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts
  68. 6 0
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  69. 5 1
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  70. 3 3
      localDev/index.html
  71. 1 1
      sandbox/index-local.html
  72. 1 1
      sandbox/index.html
  73. 353 412
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  74. 383 297
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  75. 242 5
      src/Engine/babylon.engine.ts
  76. 4 0
      src/Engine/babylon.webgl2.ts
  77. 15 1
      src/Materials/Background/babylon.backgroundMaterial.ts
  78. 9 1
      src/Materials/Textures/babylon.cubeTexture.ts
  79. 36 0
      src/Materials/Textures/babylon.hdrCubeTexture.ts
  80. 22 0
      src/Materials/Textures/babylon.internalTexture.ts
  81. 23 1
      src/Materials/Textures/babylon.renderTargetTexture.ts
  82. 163 70
      src/Mesh/Compression/babylon.dracoCompression.ts
  83. 7 0
      src/Particles/babylon.particleSystem.ts
  84. 4 1
      src/PostProcess/RenderPipeline/Pipelines/babylon.defaultRenderingPipeline.ts
  85. 2 6
      src/PostProcess/babylon.circleOfConfusionPostProcess.ts
  86. 3 4
      src/PostProcess/babylon.depthOfFieldEffect.ts
  87. 36 6
      src/Rendering/babylon.depthRenderer.ts
  88. 4 0
      src/Shaders/background.fragment.fx
  89. 66 0
      src/Tools/babylon.workerPool.ts
  90. 1 0
      src/babylon.mixins.ts
  91. 41 24
      src/babylon.scene.ts
  92. BIN
      tests/validation/ReferenceImages/depthOfField.png
  93. 1 1
      tests/validation/config.json
  94. 0 1
      tests/validation/index.html
  95. 0 1
      tests/validation/karma.conf.browserstack.js
  96. 0 1
      tests/validation/karma.conf.js
  97. 1 0
      tests/validation/validation.js

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 5988 - 5908
Playground/babylon.d.txt


+ 1 - 1
Playground/debug.html

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

+ 1 - 1
Playground/frame.html

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

+ 1 - 1
Playground/full.html

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

+ 1 - 1
Playground/index-local.html

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

+ 1 - 1
Playground/index.html

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

+ 1 - 1
Playground/indexStable.html

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

+ 1 - 1
Playground/zipContent/index.html

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

+ 8 - 2
Tools/Gulp/config.json

@@ -186,6 +186,7 @@
                 "../../src/Tools/babylon.smartArray.js",
                 "../../src/Tools/babylon.tools.js",
                 "../../src/Tools/babylon.promise.js",
+                "../../src/Tools/babylon.workerPool.js",
                 "../../src/States/babylon.alphaCullingState.js",
                 "../../src/States/babylon.depthCullingState.js",
                 "../../src/States/babylon.stencilState.js",
@@ -1534,6 +1535,10 @@
                 "name": "Loaders",
                 "module": "babylonjs-loaders"
             },
+            "extraTypesDependencies": [
+                "babylonjs",
+                "babylonjs-gltf2interface"
+            ],
             "extendsRoot": true
         }
     },
@@ -1560,8 +1565,9 @@
             "distOutputDirectory": "/serializers/",
             "buildAsModule": true,
             "moduleName": "babylonjs-serializers",
-            "extraDeclarations": [
-                "../../dist/babylon.glTF2Interface.d.ts"
+            "extraTypesDependencies": [
+                "babylonjs",
+                "babylonjs-gltf2interface"
             ],
             "outputFilename": "babylonjs.serializers",
             "moduleDeclaration": {

+ 3 - 2
Tools/Gulp/gulp-addDtsExport.js

@@ -17,8 +17,9 @@ module.exports = function (varName, moduleName, subModule, extendsRoot, dependen
         if (dependencies) {
             referenceText = '';
             dependencies.forEach(element => {
-                referenceText += `/// <reference types="babylonjs/${element}"/>
-`
+                // was "babylonjs/${element}""
+                referenceText += `/// <reference types="${element}"/>
+`;
             });
         }
 

+ 2 - 5
Tools/Gulp/gulpfile.js

@@ -325,13 +325,10 @@ var buildExternalLibraries = function (settings) {
             let dtsFiles = files.map(function (filename) {
                 return filename.replace(".js", ".d.ts");
             });
-            if (settings.build.extraDeclarations) {
-                settings.build.extraDeclarations.forEach(file => { dtsFiles.unshift(file) })
-            }
             let dtsTask = gulp.src(dtsFiles)
                 .pipe(concat(settings.build.outputFilename + ".module.d.ts"))
                 .pipe(replace(referenceSearchRegex, ""))
-                .pipe(addDtsExport(settings.build.moduleDeclaration, settings.build.moduleName, true, settings.build.extendsRoot))
+                .pipe(addDtsExport(settings.build.moduleDeclaration, settings.build.moduleName, true, settings.build.extendsRoot, settings.build.extraTypesDependencies))
                 .pipe(gulp.dest(outputDirectory));
 
             return merge2([srcTask, dtsTask]);
@@ -421,7 +418,7 @@ var buildExternalLibrary = function (library, settings, watch) {
             var dts2 = tsProcess.dts
                 .pipe(concat(library.output))
                 .pipe(replace(referenceSearchRegex, ""))
-                .pipe(addDtsExport(library.moduleDeclaration, library.moduleName, true, library.extendsRoot))
+                .pipe(addDtsExport(library.moduleDeclaration, library.moduleName, true, library.extendsRoot, config.build.extraTypesDependencies))
                 .pipe(rename({ extname: ".module.d.ts" }))
                 .pipe(gulp.dest(outputDirectory));
             waitAll = merge2([dev, code, css, dts, dts2]);

+ 11 - 0
Tools/Publisher/index.js

@@ -25,6 +25,10 @@ let packages = [
         path: basePath + '/postProcessesLibrary/'
     },
     {
+        name: 'gltf2interface',
+        path: basePath + '/gltf2interface/'
+    },
+    {
         name: 'loaders',
         path: basePath + '/loaders/'
     },
@@ -70,6 +74,13 @@ function processPackages(version) {
         } else {
             let packageJson = require(package.path + 'package.json');
             packageJson.version = version;
+            if (packageJson.dependencies) {
+                Object.keys(packageJson.dependencies).forEach(key => {
+                    if (key.indexOf("babylonjs") !== -1) {
+                        packageJson.dependencies[key] = version;
+                    }
+                });
+            }
             if (packageJson.peerDependencies) packageJson.peerDependencies.babylonjs = minimumDependency;
             fs.writeFileSync(package.path + 'package.json', JSON.stringify(packageJson, null, 4));
             console.log('Publishing ' + package.name + " from " + package.path);

+ 1 - 1
Viewer/src/configuration/configuration.ts

@@ -257,5 +257,5 @@ export interface IImageProcessingConfiguration {
     vignetteBlendMode?: number;
     vignetteM?: boolean;
     applyByPostProcess?: boolean;
-
+    isEnabled?: boolean;
 }

+ 6 - 2
Viewer/src/templateManager.ts

@@ -125,6 +125,7 @@ export class TemplateManager {
             let templateStructure = {};
             // now iterate through all templates and check for children:
             let buildTree = (parentObject, name) => {
+                this.templates[name].isInHtmlTree = true;
                 let childNodes = this.templates[name].getChildElements().filter(n => !!this.templates[n]);
                 childNodes.forEach(element => {
                     parentObject[element] = {};
@@ -149,7 +150,7 @@ export class TemplateManager {
 
     private checkLoadedState() {
         let done = Object.keys(this.templates).length === 0 || Object.keys(this.templates).every((key) => {
-            return this.templates[key].isLoaded && !!this.templates[key].parent;
+            return (this.templates[key].isLoaded && !!this.templates[key].parent) || !this.templates[key].isInHtmlTree;
         });
 
         if (done) {
@@ -205,6 +206,8 @@ export class Template {
      */
     public isShown: boolean;
 
+    public isInHtmlTree: boolean;
+
     public parent: HTMLElement;
 
     public initPromise: Promise<Template>;
@@ -225,6 +228,7 @@ export class Template {
 
         this.isLoaded = false;
         this.isShown = false;
+        this.isInHtmlTree = false;
         /*
         if (configuration.id) {
             this.parent.id = configuration.id;
@@ -361,7 +365,7 @@ export class Template {
     private getTemplateAsHtml(templateConfig: ITemplateConfiguration): Promise<string> {
         if (!templateConfig) {
             return Promise.reject('No templateConfig provided');
-        } else if (templateConfig.html) {
+        } else if (templateConfig.html !== undefined) {
             return Promise.resolve(templateConfig.html);
         } else {
             let location = getTemplateLocation(templateConfig);

+ 4 - 5
Viewer/src/viewer/defaultViewer.ts

@@ -260,7 +260,7 @@ export class DefaultViewer extends AbstractViewer {
 
     public showOverlayScreen(subScreen: string) {
         let template = this.templateManager.getTemplate('overlay');
-        if (!template) return Promise.reject('Overlay template not found');
+        if (!template) return Promise.resolve('Overlay template not found');
 
         return template.show((template => {
 
@@ -285,7 +285,7 @@ export class DefaultViewer extends AbstractViewer {
 
     public hideOverlayScreen() {
         let template = this.templateManager.getTemplate('overlay');
-        if (!template) return Promise.reject('Overlay template not found');
+        if (!template) return Promise.resolve('Overlay template not found');
 
         return template.hide((template => {
             template.parent.style.opacity = "0";
@@ -313,7 +313,7 @@ export class DefaultViewer extends AbstractViewer {
 
     public showLoadingScreen() {
         let template = this.templateManager.getTemplate('loadingScreen');
-        if (!template) return Promise.reject('oading Screen template not found');
+        if (!template) return Promise.resolve('Loading Screen template not found');
 
         return template.show((template => {
 
@@ -332,7 +332,7 @@ export class DefaultViewer extends AbstractViewer {
 
     public hideLoadingScreen() {
         let template = this.templateManager.getTemplate('loadingScreen');
-        if (!template) return Promise.reject('oading Screen template not found');
+        if (!template) return Promise.resolve('Loading Screen template not found');
 
         return template.hide((template => {
             template.parent.style.opacity = "0";
@@ -347,7 +347,6 @@ export class DefaultViewer extends AbstractViewer {
 
     protected configureLights(lightsConfiguration: { [name: string]: ILightConfiguration | boolean } = {}, focusMeshes: Array<AbstractMesh> = this.scene.meshes) {
         super.configureLights(lightsConfiguration, focusMeshes);
-        console.log("flashlight", this.configuration.lab);
         // labs feature - flashlight
         if (this.configuration.lab && this.configuration.lab.flashlight) {
             let pointerPosition = BABYLON.Vector3.Zero();

+ 0 - 2
Viewer/src/viewer/viewer.ts

@@ -600,10 +600,8 @@ export abstract class AbstractViewer {
 
             if (unitSize) {
                 meshesToNormalize.forEach(mesh => {
-                    console.log(mesh.scaling.x)
                     mesh.normalizeToUnitCube(true);
                     mesh.computeWorldMatrix(true);
-                    console.log(mesh.scaling.x)
                 });
             }
             if (center) {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2641 - 2571
dist/preview release/babylon.d.ts


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 53 - 53
dist/preview release/babylon.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 649 - 397
dist/preview release/babylon.max.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 51 - 51
dist/preview release/babylon.worker.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 5432 - 5356
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 54 - 54
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 690 - 411
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 692 - 413
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 651 - 399
dist/preview release/es6.js


+ 248 - 0
dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts

@@ -0,0 +1,248 @@
+declare module BABYLON.GLTF2 {
+    const enum AccessorComponentType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+    }
+    const enum AccessorType {
+        SCALAR = "SCALAR",
+        VEC2 = "VEC2",
+        VEC3 = "VEC3",
+        VEC4 = "VEC4",
+        MAT2 = "MAT2",
+        MAT3 = "MAT3",
+        MAT4 = "MAT4",
+    }
+    const enum AnimationChannelTargetPath {
+        TRANSLATION = "translation",
+        ROTATION = "rotation",
+        SCALE = "scale",
+        WEIGHTS = "weights",
+    }
+    const enum AnimationSamplerInterpolation {
+        LINEAR = "LINEAR",
+        STEP = "STEP",
+        CUBICSPLINE = "CUBICSPLINE",
+    }
+    const enum CameraType {
+        PERSPECTIVE = "perspective",
+        ORTHOGRAPHIC = "orthographic",
+    }
+    const enum ImageMimeType {
+        JPEG = "image/jpeg",
+        PNG = "image/png",
+    }
+    const enum MaterialAlphaMode {
+        OPAQUE = "OPAQUE",
+        MASK = "MASK",
+        BLEND = "BLEND",
+    }
+    const enum MeshPrimitiveMode {
+        POINTS = 0,
+        LINES = 1,
+        LINE_LOOP = 2,
+        LINE_STRIP = 3,
+        TRIANGLES = 4,
+        TRIANGLE_STRIP = 5,
+        TRIANGLE_FAN = 6,
+    }
+    const enum TextureMagFilter {
+        NEAREST = 9728,
+        LINEAR = 9729,
+    }
+    const enum TextureMinFilter {
+        NEAREST = 9728,
+        LINEAR = 9729,
+        NEAREST_MIPMAP_NEAREST = 9984,
+        LINEAR_MIPMAP_NEAREST = 9985,
+        NEAREST_MIPMAP_LINEAR = 9986,
+        LINEAR_MIPMAP_LINEAR = 9987,
+    }
+    const enum TextureWrapMode {
+        CLAMP_TO_EDGE = 33071,
+        MIRRORED_REPEAT = 33648,
+        REPEAT = 10497,
+    }
+    interface IProperty {
+        extensions?: {
+            [key: string]: any;
+        };
+        extras?: any;
+    }
+    interface IChildRootProperty extends IProperty {
+        name?: string;
+    }
+    interface IAccessorSparseIndices extends IProperty {
+        bufferView: number;
+        byteOffset?: number;
+        componentType: AccessorComponentType;
+    }
+    interface IAccessorSparseValues extends IProperty {
+        bufferView: number;
+        byteOffset?: number;
+    }
+    interface IAccessorSparse extends IProperty {
+        count: number;
+        indices: IAccessorSparseIndices;
+        values: IAccessorSparseValues;
+    }
+    interface IAccessor extends IChildRootProperty {
+        bufferView?: number;
+        byteOffset?: number;
+        componentType: AccessorComponentType;
+        normalized?: boolean;
+        count: number;
+        type: AccessorType;
+        max?: number[];
+        min?: number[];
+        sparse?: IAccessorSparse;
+    }
+    interface IAnimationChannel extends IProperty {
+        sampler: number;
+        target: IAnimationChannelTarget;
+    }
+    interface IAnimationChannelTarget extends IProperty {
+        node: number;
+        path: AnimationChannelTargetPath;
+    }
+    interface IAnimationSampler extends IProperty {
+        input: number;
+        interpolation?: AnimationSamplerInterpolation;
+        output: number;
+    }
+    interface IAnimation extends IChildRootProperty {
+        channels: IAnimationChannel[];
+        samplers: IAnimationSampler[];
+    }
+    interface IAsset extends IChildRootProperty {
+        copyright?: string;
+        generator?: string;
+        version: string;
+        minVersion?: string;
+    }
+    interface IBuffer extends IChildRootProperty {
+        uri?: string;
+        byteLength: number;
+    }
+    interface IBufferView extends IChildRootProperty {
+        buffer: number;
+        byteOffset?: number;
+        byteLength: number;
+        byteStride?: number;
+    }
+    interface ICameraOrthographic extends IProperty {
+        xmag: number;
+        ymag: number;
+        zfar: number;
+        znear: number;
+    }
+    interface ICameraPerspective extends IProperty {
+        aspectRatio: number;
+        yfov: number;
+        zfar: number;
+        znear: number;
+    }
+    interface ICamera extends IChildRootProperty {
+        orthographic?: ICameraOrthographic;
+        perspective?: ICameraPerspective;
+        type: CameraType;
+    }
+    interface IImage extends IChildRootProperty {
+        uri?: string;
+        mimeType?: ImageMimeType;
+        bufferView?: number;
+    }
+    interface IMaterialNormalTextureInfo extends ITextureInfo {
+        scale?: number;
+    }
+    interface IMaterialOcclusionTextureInfo extends ITextureInfo {
+        strength?: number;
+    }
+    interface IMaterialPbrMetallicRoughness {
+        baseColorFactor?: number[];
+        baseColorTexture?: ITextureInfo;
+        metallicFactor?: number;
+        roughnessFactor?: number;
+        metallicRoughnessTexture?: ITextureInfo;
+    }
+    interface IMaterial extends IChildRootProperty {
+        pbrMetallicRoughness?: IMaterialPbrMetallicRoughness;
+        normalTexture?: IMaterialNormalTextureInfo;
+        occlusionTexture?: IMaterialOcclusionTextureInfo;
+        emissiveTexture?: ITextureInfo;
+        emissiveFactor?: number[];
+        alphaMode?: MaterialAlphaMode;
+        alphaCutoff?: number;
+        doubleSided?: boolean;
+    }
+    interface IMeshPrimitive extends IProperty {
+        attributes: {
+            [name: string]: number;
+        };
+        indices?: number;
+        material?: number;
+        mode?: MeshPrimitiveMode;
+        targets?: {
+            [name: string]: number;
+        }[];
+    }
+    interface IMesh extends IChildRootProperty {
+        primitives: IMeshPrimitive[];
+        weights?: number[];
+    }
+    interface INode extends IChildRootProperty {
+        camera?: number;
+        children?: number[];
+        skin?: number;
+        matrix?: number[];
+        mesh?: number;
+        rotation?: number[];
+        scale?: number[];
+        translation?: number[];
+        weights?: number[];
+    }
+    interface ISampler extends IChildRootProperty {
+        magFilter?: TextureMagFilter;
+        minFilter?: TextureMinFilter;
+        wrapS?: TextureWrapMode;
+        wrapT?: TextureWrapMode;
+    }
+    interface IScene extends IChildRootProperty {
+        nodes: number[];
+    }
+    interface ISkin extends IChildRootProperty {
+        inverseBindMatrices?: number;
+        skeleton?: number;
+        joints: number[];
+    }
+    interface ITexture extends IChildRootProperty {
+        sampler?: number;
+        source: number;
+    }
+    interface ITextureInfo {
+        index: number;
+        texCoord?: number;
+    }
+    interface IGLTF extends IProperty {
+        accessors?: IAccessor[];
+        animations?: IAnimation[];
+        asset: IAsset;
+        buffers?: IBuffer[];
+        bufferViews?: IBufferView[];
+        cameras?: ICamera[];
+        extensionsUsed?: string[];
+        extensionsRequired?: string[];
+        images?: IImage[];
+        materials?: IMaterial[];
+        meshes?: IMesh[];
+        nodes?: INode[];
+        samplers?: ISampler[];
+        scene?: number;
+        scenes?: IScene[];
+        skins?: ISkin[];
+        textures?: ITexture[];
+    }
+}

+ 28 - 0
dist/preview release/gltf2Interface/package.json

@@ -0,0 +1,28 @@
+{
+    "name": "babylonjs-gltf2interface",
+    "description": "A typescript declaration of babylon's gltf2 inteface.",
+    "version": "3.2.0-alpha8",
+    "repository": {
+        "type": "git",
+        "url": "https://github.com/BabylonJS/Babylon.js.git"
+    },
+    "files": [
+        "babylon.glTF2Interface.d.ts",
+        "package.json"
+    ],
+    "typings": "babylon.glTF2Interface.d.ts",
+    "keywords": [
+        "3D",
+        "javascript",
+        "html5",
+        "webgl",
+        "gltf2"
+    ],
+    "license": "Apache-2.0",
+    "peerDependencies": {
+        "babylonjs": ">=3.2.0-alpha"
+    },
+    "engines": {
+        "node": "*"
+    }
+}

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

@@ -16,8 +16,12 @@ declare module BABYLON.GUI {
         private _background;
         _rootContainer: Container;
         _lastPickedControl: Control;
-        _lastControlOver: Nullable<Control>;
-        _lastControlDown: Nullable<Control>;
+        _lastControlOver: {
+            [pointerId: number]: Control;
+        };
+        _lastControlDown: {
+            [pointerId: number]: Control;
+        };
         _capturingControl: {
             [pointerId: number]: Control;
         };

+ 24 - 22
dist/preview release/gui/babylon.gui.js

@@ -33,6 +33,8 @@ 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._lastControlOver = {};
+                _this._lastControlDown = {};
                 _this._capturingControl = {};
                 _this._linkedControls = new Array();
                 _this._isFullscreen = false;
@@ -358,10 +360,10 @@ var BABYLON;
                 }
                 if (!this._rootContainer._processPicking(x, y, type, pointerId, buttonIndex)) {
                     if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
-                        if (this._lastControlOver) {
-                            this._lastControlOver._onPointerOut(this._lastControlOver);
+                        if (this._lastControlOver[pointerId]) {
+                            this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
                         }
-                        this._lastControlOver = null;
+                        delete this._lastControlOver[pointerId];
                     }
                 }
                 this._manageFocus();
@@ -417,17 +419,17 @@ var BABYLON;
                         }
                     }
                     else if (pi.type === BABYLON.PointerEventTypes.POINTERUP) {
-                        if (_this._lastControlDown) {
-                            _this._lastControlDown.forcePointerUp(pointerId);
+                        if (_this._lastControlDown[pointerId]) {
+                            _this._lastControlDown[pointerId].forcePointerUp(pointerId);
                         }
-                        _this._lastControlDown = null;
+                        delete _this._lastControlDown[pointerId];
                         _this.focusedControl = null;
                     }
                     else if (pi.type === BABYLON.PointerEventTypes.POINTERMOVE) {
-                        if (_this._lastControlOver) {
-                            _this._lastControlOver._onPointerOut(_this._lastControlOver);
+                        if (_this._lastControlOver[pointerId]) {
+                            _this._lastControlOver[pointerId]._onPointerOut(_this._lastControlOver[pointerId]);
                         }
-                        _this._lastControlOver = null;
+                        delete _this._lastControlOver[pointerId];
                     }
                 });
                 mesh.enablePointerMoveEvents = supportPointerMove;
@@ -456,15 +458,15 @@ var BABYLON;
             };
             AdvancedDynamicTexture.prototype._attachToOnPointerOut = function (scene) {
                 var _this = this;
-                this._canvasPointerOutObserver = scene.getEngine().onCanvasPointerOutObservable.add(function () {
-                    if (_this._lastControlOver) {
-                        _this._lastControlOver._onPointerOut(_this._lastControlOver);
+                this._canvasPointerOutObserver = scene.getEngine().onCanvasPointerOutObservable.add(function (pointerEvent) {
+                    if (_this._lastControlOver[pointerEvent.pointerId]) {
+                        _this._lastControlOver[pointerEvent.pointerId]._onPointerOut(_this._lastControlOver[pointerEvent.pointerId]);
                     }
-                    _this._lastControlOver = null;
-                    if (_this._lastControlDown) {
-                        _this._lastControlDown.forcePointerUp();
+                    delete _this._lastControlOver[pointerEvent.pointerId];
+                    if (_this._lastControlDown[pointerEvent.pointerId]) {
+                        _this._lastControlDown[pointerEvent.pointerId].forcePointerUp();
                     }
-                    _this._lastControlDown = null;
+                    delete _this._lastControlDown[pointerEvent.pointerId];
                 });
             };
             // Statics
@@ -1726,27 +1728,27 @@ var BABYLON;
                 this._dummyVector2.copyFromFloats(x, y);
                 if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
                     this._onPointerMove(this, this._dummyVector2);
-                    var previousControlOver = this._host._lastControlOver;
+                    var previousControlOver = this._host._lastControlOver[pointerId];
                     if (previousControlOver && previousControlOver !== this) {
                         previousControlOver._onPointerOut(this);
                     }
                     if (previousControlOver !== this) {
                         this._onPointerEnter(this);
                     }
-                    this._host._lastControlOver = this;
+                    this._host._lastControlOver[pointerId] = this;
                     return true;
                 }
                 if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
                     this._onPointerDown(this, this._dummyVector2, pointerId, buttonIndex);
-                    this._host._lastControlDown = this;
+                    this._host._lastControlDown[pointerId] = this;
                     this._host._lastPickedControl = this;
                     return true;
                 }
                 if (type === BABYLON.PointerEventTypes.POINTERUP) {
-                    if (this._host._lastControlDown) {
-                        this._host._lastControlDown._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex);
+                    if (this._host._lastControlDown[pointerId]) {
+                        this._host._lastControlDown[pointerId]._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex);
                     }
-                    this._host._lastControlDown = null;
+                    delete this._host._lastControlDown[pointerId];
                     return true;
                 }
                 return false;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/gui/babylon.gui.min.js


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

@@ -22,8 +22,12 @@ declare module BABYLON.GUI {
         private _background;
         _rootContainer: Container;
         _lastPickedControl: Control;
-        _lastControlOver: Nullable<Control>;
-        _lastControlDown: Nullable<Control>;
+        _lastControlOver: {
+            [pointerId: number]: Control;
+        };
+        _lastControlDown: {
+            [pointerId: number]: Control;
+        };
         _capturingControl: {
             [pointerId: number]: Control;
         };

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 5 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -360,11 +360,12 @@ declare module BABYLON.GLTF2 {
 
 
 declare module BABYLON.GLTF2 {
-    abstract class GLTFLoaderExtension implements IGLTFLoaderExtension {
+    abstract class GLTFLoaderExtension implements IGLTFLoaderExtension, IDisposable {
         enabled: boolean;
         readonly abstract name: string;
         protected _loader: GLTFLoader;
         constructor(loader: GLTFLoader);
+        dispose(): void;
         /** Override this method to modify the default behavior for loading scenes. */
         protected _loadSceneAsync(context: string, node: ILoaderScene): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading nodes. */
@@ -416,6 +417,9 @@ declare module BABYLON.GLTF2.Extensions {
 declare module BABYLON.GLTF2.Extensions {
     class KHR_draco_mesh_compression extends GLTFLoaderExtension {
         readonly name: string;
+        private _dracoCompression;
+        constructor(loader: GLTFLoader);
+        dispose(): void;
         protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
     }
 }

+ 27 - 9
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -1812,6 +1812,9 @@ var BABYLON;
                 delete this._gltf;
                 delete this._babylonScene;
                 this._completePromises.length = 0;
+                for (var name_3 in this._extensions) {
+                    this._extensions[name_3].dispose();
+                }
                 this._extensions = {};
                 delete this._rootBabylonMesh;
                 delete this._progressCallback;
@@ -1821,8 +1824,8 @@ var BABYLON;
             };
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
                 for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
-                    var name_3 = _a[_i];
-                    var extension = this._extensions[name_3];
+                    var name_4 = _a[_i];
+                    var extension = this._extensions[name_4];
                     if (extension.enabled) {
                         var promise = actionAsync(extension);
                         if (promise) {
@@ -1853,6 +1856,9 @@ var BABYLON;
                 this.enabled = true;
                 this._loader = loader;
             }
+            GLTFLoaderExtension.prototype.dispose = function () {
+                delete this._loader;
+            };
             // #region Overridable Methods
             /** Override this method to modify the default behavior for loading scenes. */
             GLTFLoaderExtension.prototype._loadSceneAsync = function (context, node) { return null; };
@@ -2080,15 +2086,26 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
-            // https://github.com/KhronosGroup/glTF/pull/874
+            // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
             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;
+                function KHR_draco_mesh_compression(loader) {
+                    var _this = _super.call(this, loader) || this;
                     _this.name = NAME;
+                    _this._dracoCompression = null;
+                    // Disable extension if decoder is not available.
+                    if (!BABYLON.DracoCompression.DecoderUrl) {
+                        _this.enabled = false;
+                    }
                     return _this;
                 }
+                KHR_draco_mesh_compression.prototype.dispose = function () {
+                    if (this._dracoCompression) {
+                        this._dracoCompression.dispose();
+                    }
+                    _super.prototype.dispose.call(this);
+                };
                 KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
                     var _this = this;
                     return this._loadExtensionAsync(context, primitive, function (extensionContext, extension) {
@@ -2125,7 +2142,10 @@ var BABYLON;
                         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);
+                                if (!_this._dracoCompression) {
+                                    _this._dracoCompression = new BABYLON.DracoCompression();
+                                }
+                                return _this._dracoCompression.decodeMeshAsync(data, attributes);
                             }
                             catch (e) {
                                 throw new Error(context + ": " + e.message);
@@ -2136,9 +2156,7 @@ var BABYLON;
                 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); });
-            }
+            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 = {}));

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 5 - 1
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -915,11 +915,12 @@ declare module BABYLON.GLTF2 {
 
 
 declare module BABYLON.GLTF2 {
-    abstract class GLTFLoaderExtension implements IGLTFLoaderExtension {
+    abstract class GLTFLoaderExtension implements IGLTFLoaderExtension, IDisposable {
         enabled: boolean;
         readonly abstract name: string;
         protected _loader: GLTFLoader;
         constructor(loader: GLTFLoader);
+        dispose(): void;
         /** Override this method to modify the default behavior for loading scenes. */
         protected _loadSceneAsync(context: string, node: ILoaderScene): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading nodes. */
@@ -971,6 +972,9 @@ declare module BABYLON.GLTF2.Extensions {
 declare module BABYLON.GLTF2.Extensions {
     class KHR_draco_mesh_compression extends GLTFLoaderExtension {
         readonly name: string;
+        private _dracoCompression;
+        constructor(loader: GLTFLoader);
+        dispose(): void;
         protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
     }
 }

+ 27 - 9
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3988,6 +3988,9 @@ var BABYLON;
                 delete this._gltf;
                 delete this._babylonScene;
                 this._completePromises.length = 0;
+                for (var name_3 in this._extensions) {
+                    this._extensions[name_3].dispose();
+                }
                 this._extensions = {};
                 delete this._rootBabylonMesh;
                 delete this._progressCallback;
@@ -3997,8 +4000,8 @@ var BABYLON;
             };
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
                 for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
-                    var name_3 = _a[_i];
-                    var extension = this._extensions[name_3];
+                    var name_4 = _a[_i];
+                    var extension = this._extensions[name_4];
                     if (extension.enabled) {
                         var promise = actionAsync(extension);
                         if (promise) {
@@ -4029,6 +4032,9 @@ var BABYLON;
                 this.enabled = true;
                 this._loader = loader;
             }
+            GLTFLoaderExtension.prototype.dispose = function () {
+                delete this._loader;
+            };
             // #region Overridable Methods
             /** Override this method to modify the default behavior for loading scenes. */
             GLTFLoaderExtension.prototype._loadSceneAsync = function (context, node) { return null; };
@@ -4256,15 +4262,26 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
-            // https://github.com/KhronosGroup/glTF/pull/874
+            // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
             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;
+                function KHR_draco_mesh_compression(loader) {
+                    var _this = _super.call(this, loader) || this;
                     _this.name = NAME;
+                    _this._dracoCompression = null;
+                    // Disable extension if decoder is not available.
+                    if (!BABYLON.DracoCompression.DecoderUrl) {
+                        _this.enabled = false;
+                    }
                     return _this;
                 }
+                KHR_draco_mesh_compression.prototype.dispose = function () {
+                    if (this._dracoCompression) {
+                        this._dracoCompression.dispose();
+                    }
+                    _super.prototype.dispose.call(this);
+                };
                 KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
                     var _this = this;
                     return this._loadExtensionAsync(context, primitive, function (extensionContext, extension) {
@@ -4301,7 +4318,10 @@ var BABYLON;
                         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);
+                                if (!_this._dracoCompression) {
+                                    _this._dracoCompression = new BABYLON.DracoCompression();
+                                }
+                                return _this._dracoCompression.decodeMeshAsync(data, attributes);
                             }
                             catch (e) {
                                 throw new Error(context + ": " + e.message);
@@ -4312,9 +4332,7 @@ var BABYLON;
                 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); });
-            }
+            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 = {}));

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 27 - 9
dist/preview release/loaders/babylonjs.loaders.js

@@ -4956,6 +4956,9 @@ var BABYLON;
                 delete this._gltf;
                 delete this._babylonScene;
                 this._completePromises.length = 0;
+                for (var name_3 in this._extensions) {
+                    this._extensions[name_3].dispose();
+                }
                 this._extensions = {};
                 delete this._rootBabylonMesh;
                 delete this._progressCallback;
@@ -4965,8 +4968,8 @@ var BABYLON;
             };
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
                 for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
-                    var name_3 = _a[_i];
-                    var extension = this._extensions[name_3];
+                    var name_4 = _a[_i];
+                    var extension = this._extensions[name_4];
                     if (extension.enabled) {
                         var promise = actionAsync(extension);
                         if (promise) {
@@ -4997,6 +5000,9 @@ var BABYLON;
                 this.enabled = true;
                 this._loader = loader;
             }
+            GLTFLoaderExtension.prototype.dispose = function () {
+                delete this._loader;
+            };
             // #region Overridable Methods
             /** Override this method to modify the default behavior for loading scenes. */
             GLTFLoaderExtension.prototype._loadSceneAsync = function (context, node) { return null; };
@@ -5206,15 +5212,26 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
-            // https://github.com/KhronosGroup/glTF/pull/874
+            // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
             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;
+                function KHR_draco_mesh_compression(loader) {
+                    var _this = _super.call(this, loader) || this;
                     _this.name = NAME;
+                    _this._dracoCompression = null;
+                    // Disable extension if decoder is not available.
+                    if (!BABYLON.DracoCompression.DecoderUrl) {
+                        _this.enabled = false;
+                    }
                     return _this;
                 }
+                KHR_draco_mesh_compression.prototype.dispose = function () {
+                    if (this._dracoCompression) {
+                        this._dracoCompression.dispose();
+                    }
+                    _super.prototype.dispose.call(this);
+                };
                 KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
                     var _this = this;
                     return this._loadExtensionAsync(context, primitive, function (extensionContext, extension) {
@@ -5251,7 +5268,10 @@ var BABYLON;
                         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);
+                                if (!_this._dracoCompression) {
+                                    _this._dracoCompression = new BABYLON.DracoCompression();
+                                }
+                                return _this._dracoCompression.decodeMeshAsync(data, attributes);
                             }
                             catch (e) {
                                 throw new Error(context + ": " + e.message);
@@ -5262,9 +5282,7 @@ var BABYLON;
                 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); });
-            }
+            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 = {}));

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


+ 5 - 1
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -1016,11 +1016,12 @@ declare module BABYLON.GLTF2 {
 
 
 declare module BABYLON.GLTF2 {
-    abstract class GLTFLoaderExtension implements IGLTFLoaderExtension {
+    abstract class GLTFLoaderExtension implements IGLTFLoaderExtension, IDisposable {
         enabled: boolean;
         readonly abstract name: string;
         protected _loader: GLTFLoader;
         constructor(loader: GLTFLoader);
+        dispose(): void;
         /** Override this method to modify the default behavior for loading scenes. */
         protected _loadSceneAsync(context: string, node: ILoaderScene): Nullable<Promise<void>>;
         /** Override this method to modify the default behavior for loading nodes. */
@@ -1072,6 +1073,9 @@ declare module BABYLON.GLTF2.Extensions {
 declare module BABYLON.GLTF2.Extensions {
     class KHR_draco_mesh_compression extends GLTFLoaderExtension {
         readonly name: string;
+        private _dracoCompression;
+        constructor(loader: GLTFLoader);
+        dispose(): void;
         protected _loadVertexDataAsync(context: string, primitive: ILoaderMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<VertexData>>;
     }
 }

+ 3 - 0
dist/preview release/loaders/package.json

@@ -26,6 +26,9 @@
         "loaders"
     ],
     "license": "Apache-2.0",
+    "dependencies": {
+        "babylonjs-gltf2interface": "^3.2.0-alpha8"
+    },
     "peerDependencies": {
         "babylonjs": ">=3.2.0-alpha"
     },

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 3
dist/preview release/materialsLibrary/babylonjs.materials.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


+ 62 - 24
dist/preview release/serializers/babylon.glTF2Serializer.d.ts

@@ -100,6 +100,18 @@ declare module BABYLON.GLTF2 {
          */
         private imageData;
         /**
+         * Stores a map of the unique id of a node to its index in the node array.
+         */
+        private nodeMap;
+        /**
+         * Stores the binary buffer used to store geometry data.
+         */
+        private binaryBuffer;
+        /**
+         * Specifies if the Babylon scene should be converted to right-handed on export.
+         */
+        private convertToRightHandedSystem;
+        /**
          * Creates a glTF Exporter instance, which can accept optional exporter options.
          * @param babylonScene - Babylon scene object
          * @param options - Options to modify the behavior of the exporter.
@@ -117,26 +129,42 @@ declare module BABYLON.GLTF2 {
         private createBufferView(bufferIndex, byteOffset, byteLength, byteStride?, name?);
         /**
          * Creates an accessor based on the supplied arguments
-         * @param bufferviewIndex
-         * @param name
-         * @param type
-         * @param componentType
-         * @param count
-         * @param min
-         * @param max
+         * @param bufferviewIndex - The index of the bufferview referenced by this accessor.
+         * @param name - The name of the accessor.
+         * @param type - The type of the accessor.
+         * @param componentType - The datatype of components in the attribute.
+         * @param count - The number of attributes referenced by this accessor.
+         * @param byteOffset - The offset relative to the start of the bufferView in bytes.
+         * @param min - Minimum value of each component in this attribute.
+         * @param max - Maximum value of each component in this attribute.
          * @returns - accessor for glTF
          */
-        private createAccessor(bufferviewIndex, name, type, componentType, count, byteOffset?, min?, max?);
+        private createAccessor(bufferviewIndex, name, type, componentType, count, byteOffset, min, max);
         /**
-         * Calculates the minimum and maximum values of an array of floats, based on stride
-         * @param buff - Data to check for min and max values.
-         * @param vertexStart - Start offset to calculate min and max values.
+         * Calculates the minimum and maximum values of an array of position floats.
+         * @param positions - Positions array of a mesh.
+         * @param vertexStart - Starting vertex offset to calculate min and max values.
          * @param vertexCount - Number of vertices to check for min and max values.
-         * @param stride - Offset between consecutive attributes.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          * @returns - min number array and max number array.
          */
-        private calculateMinMax(buff, vertexStart, vertexCount, stride, useRightHandedSystem);
+        private calculateMinMaxPositions(positions, vertexStart, vertexCount);
+        /**
+         * Converts a vector3 array to right-handed.
+         * @param vector - vector3 Array to convert to right-handed.
+         * @returns - right-handed Vector3 array.
+         */
+        private static GetRightHandedVector3(vector);
+        /**
+         * Converts a vector4 array to right-handed.
+         * @param vector - vector4 Array to convert to right-handed.
+         * @returns - right-handed vector4 array.
+         */
+        private static GetRightHandedVector4(vector);
+        /**
+         * Converts a quaternion to right-handed.
+         * @param quaternion - Source quaternion to convert to right-handed.
+         */
+        private static GetRightHandedQuaternion(quaternion);
         /**
          * Writes mesh attribute data to a data buffer.
          * Returns the bytelength of the data.
@@ -145,10 +173,9 @@ declare module BABYLON.GLTF2 {
          * @param strideSize - Represents the offset between consecutive attributes
          * @param byteOffset - The offset to start counting bytes from.
          * @param dataBuffer - The buffer to write the binary data to.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          * @returns - Byte length of the attribute data.
          */
-        private writeAttributeData(vertexBufferKind, meshAttributeArray, strideSize, vertexBufferOffset, byteOffset, dataBuffer, useRightHandedSystem);
+        private writeAttributeData(vertexBufferKind, meshAttributeArray, strideSize, vertexBufferOffset, byteOffset, dataBuffer);
         /**
          * Generates glTF json data
          * @param shouldUseGlb - Indicates whether the json should be written for a glb file.
@@ -185,38 +212,49 @@ declare module BABYLON.GLTF2 {
          * Sets the TRS for each node
          * @param node - glTF Node for storing the transformation data.
          * @param babylonMesh - Babylon mesh used as the source for the transformation data.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          */
-        private setNodeTransformation(node, babylonMesh, useRightHandedSystem);
+        private setNodeTransformation(node, babylonMesh);
         /**
          * Creates a bufferview based on the vertices type for the Babylon mesh
          * @param kind - Indicates the type of vertices data.
          * @param babylonMesh - The Babylon mesh to get the vertices data from.
          * @param byteOffset - The offset from the buffer to start indexing from.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          * @param dataBuffer - The buffer to write the bufferview data to.
          * @returns bytelength of the bufferview data.
          */
-        private createBufferViewKind(kind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
+        private createBufferViewKind(kind, babylonMesh, byteOffset, dataBuffer);
         /**
          * Sets data for the primitive attributes of each submesh
          * @param mesh - glTF Mesh object to store the primitive attribute information.
          * @param babylonMesh - Babylon mesh to get the primitive attribute data from.
          * @param byteOffset - The offset in bytes of the buffer data.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          * @param dataBuffer - Buffer to write the attribute data to.
          * @returns - bytelength of the primitive attributes plus the passed in byteOffset.
          */
-        private setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
+        private setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
         /**
          * Creates a glTF scene based on the array of meshes.
          * Returns the the total byte offset.
          * @param babylonScene - Babylon scene to get the mesh data from.
          * @param byteOffset - Offset to start from in bytes.
-         * @param dataBuffer - Buffer to write geometry data to.
          * @returns bytelength + byteoffset
          */
-        private createScene(babylonScene, byteOffset, dataBuffer);
+        private createScene(babylonScene, byteOffset);
+        /**
+         * Creates a mapping of Node unique id to node index
+         * @param scene - Babylon Scene.
+         * @param byteOffset - The initial byte offset.
+         * @returns - Node mapping of unique id to index.
+         */
+        private createNodeMap(scene, byteOffset);
+        /**
+         * Creates a glTF node from a Babylon mesh.
+         * @param babylonMesh - Source Babylon mesh.
+         * @param byteOffset - The initial byte offset.
+         * @param dataBuffer - Buffer for storing geometry data.
+         * @returns - Object containing an INode and byteoffset.
+         */
+        private createNode(babylonMesh, byteOffset, dataBuffer);
     }
 }
 

+ 281 - 362
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -80,12 +80,10 @@ var BABYLON;
                 this.materials = new Array();
                 this.textures = new Array();
                 this.imageData = {};
-                if (options !== undefined) {
+                this.convertToRightHandedSystem = !this.babylonScene.useRightHandedSystem;
+                if (options) {
                     this.options = options;
                 }
-                var totalByteLength = 0;
-                totalByteLength = this.createScene(this.babylonScene, totalByteLength, null);
-                this.totalByteLength = totalByteLength;
             }
             /**
              * Creates a buffer view based on teh supplied arguments
@@ -98,7 +96,7 @@ var BABYLON;
              */
             _Exporter.prototype.createBufferView = function (bufferIndex, byteOffset, byteLength, byteStride, name) {
                 var bufferview = { buffer: bufferIndex, byteLength: byteLength };
-                if (byteOffset > 0) {
+                if (byteOffset) {
                     bufferview.byteOffset = byteOffset;
                 }
                 if (name) {
@@ -111,13 +109,14 @@ var BABYLON;
             };
             /**
              * Creates an accessor based on the supplied arguments
-             * @param bufferviewIndex
-             * @param name
-             * @param type
-             * @param componentType
-             * @param count
-             * @param min
-             * @param max
+             * @param bufferviewIndex - The index of the bufferview referenced by this accessor.
+             * @param name - The name of the accessor.
+             * @param type - The type of the accessor.
+             * @param componentType - The datatype of components in the attribute.
+             * @param count - The number of attributes referenced by this accessor.
+             * @param byteOffset - The offset relative to the start of the bufferView in bytes.
+             * @param min - Minimum value of each component in this attribute.
+             * @param max - Maximum value of each component in this attribute.
              * @returns - accessor for glTF
              */
             _Exporter.prototype.createAccessor = function (bufferviewIndex, name, type, componentType, count, byteOffset, min, max) {
@@ -134,40 +133,60 @@ var BABYLON;
                 return accessor;
             };
             /**
-             * Calculates the minimum and maximum values of an array of floats, based on stride
-             * @param buff - Data to check for min and max values.
-             * @param vertexStart - Start offset to calculate min and max values.
+             * Calculates the minimum and maximum values of an array of position floats.
+             * @param positions - Positions array of a mesh.
+             * @param vertexStart - Starting vertex offset to calculate min and max values.
              * @param vertexCount - Number of vertices to check for min and max values.
-             * @param stride - Offset between consecutive attributes.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              * @returns - min number array and max number array.
              */
-            _Exporter.prototype.calculateMinMax = function (buff, vertexStart, vertexCount, stride, useRightHandedSystem) {
+            _Exporter.prototype.calculateMinMaxPositions = function (positions, vertexStart, vertexCount) {
                 var min = [Infinity, Infinity, Infinity];
                 var max = [-Infinity, -Infinity, -Infinity];
+                var positionStrideSize = 3;
                 var end = vertexStart + vertexCount;
-                if (vertexCount > 0) {
+                if (vertexCount) {
                     for (var i = vertexStart; i < end; ++i) {
-                        var index = stride * i;
-                        var scale = 1;
-                        for (var j = 0; j < stride; ++j) {
-                            if (j === (stride - 1) && !useRightHandedSystem) {
-                                scale = -1;
-                            }
-                            var num = scale * buff[index];
+                        var indexOffset = positionStrideSize * i;
+                        var position = BABYLON.Vector3.FromArray(positions, indexOffset);
+                        var vector = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(position).asArray() : position.asArray();
+                        for (var j = 0; j < positionStrideSize; ++j) {
+                            var num = vector[j];
                             if (num < min[j]) {
                                 min[j] = num;
                             }
                             if (num > max[j]) {
                                 max[j] = num;
                             }
-                            ++index;
+                            ++indexOffset;
                         }
                     }
                 }
                 return { min: min, max: max };
             };
             /**
+             * Converts a vector3 array to right-handed.
+             * @param vector - vector3 Array to convert to right-handed.
+             * @returns - right-handed Vector3 array.
+             */
+            _Exporter.GetRightHandedVector3 = function (vector) {
+                return new BABYLON.Vector3(vector.x, vector.y, -vector.z);
+            };
+            /**
+             * Converts a vector4 array to right-handed.
+             * @param vector - vector4 Array to convert to right-handed.
+             * @returns - right-handed vector4 array.
+             */
+            _Exporter.GetRightHandedVector4 = function (vector) {
+                return new BABYLON.Vector4(vector.x, vector.y, -vector.z, -vector.w);
+            };
+            /**
+             * Converts a quaternion to right-handed.
+             * @param quaternion - Source quaternion to convert to right-handed.
+             */
+            _Exporter.GetRightHandedQuaternion = function (quaternion) {
+                return new BABYLON.Quaternion(-quaternion.x, -quaternion.y, quaternion.z, quaternion.w);
+            };
+            /**
              * Writes mesh attribute data to a data buffer.
              * Returns the bytelength of the data.
              * @param vertexBufferKind - Indicates what kind of vertex data is being passed in.
@@ -175,112 +194,35 @@ var BABYLON;
              * @param strideSize - Represents the offset between consecutive attributes
              * @param byteOffset - The offset to start counting bytes from.
              * @param dataBuffer - The buffer to write the binary data to.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              * @returns - Byte length of the attribute data.
              */
-            _Exporter.prototype.writeAttributeData = function (vertexBufferKind, meshAttributeArray, strideSize, vertexBufferOffset, byteOffset, dataBuffer, useRightHandedSystem) {
+            _Exporter.prototype.writeAttributeData = function (vertexBufferKind, meshAttributeArray, strideSize, vertexBufferOffset, byteOffset, dataBuffer) {
                 var byteOff = byteOffset;
-                var start = 0;
                 var end = meshAttributeArray.length / strideSize;
                 var byteLength = 0;
-                switch (vertexBufferKind) {
-                    case BABYLON.VertexBuffer.PositionKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                            if (useRightHandedSystem) {
-                                dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 2], true);
-                            }
-                            else {
-                                dataBuffer.setFloat32(byteOff, -meshAttributeArray[index + 2], true);
-                            }
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
-                    }
-                    case BABYLON.VertexBuffer.NormalKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                            if (useRightHandedSystem) {
-                                dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 2], true);
-                            }
-                            else {
-                                dataBuffer.setFloat32(byteOff, -meshAttributeArray[index + 2], true);
-                            }
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
-                    }
-                    case BABYLON.VertexBuffer.TangentKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                            if (useRightHandedSystem) {
-                                dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 2], true);
-                            }
-                            else {
-                                dataBuffer.setFloat32(byteOff, -meshAttributeArray[index + 2], true);
-                            }
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 3], true);
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
+                for (var k = 0; k < end; ++k) {
+                    var index = k * strideSize;
+                    var vector = [];
+                    if (vertexBufferKind === BABYLON.VertexBuffer.PositionKind || vertexBufferKind === BABYLON.VertexBuffer.NormalKind) {
+                        var vertexData = BABYLON.Vector3.FromArray(meshAttributeArray, index);
+                        vector = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(vertexData).asArray() : vertexData.asArray();
                     }
-                    case BABYLON.VertexBuffer.ColorKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 2], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 3], true);
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
+                    else if (vertexBufferKind === BABYLON.VertexBuffer.TangentKind || vertexBufferKind === BABYLON.VertexBuffer.ColorKind) {
+                        var vertexData = BABYLON.Vector4.FromArray(meshAttributeArray, index);
+                        vector = (this.convertToRightHandedSystem && !(vertexBufferKind === BABYLON.VertexBuffer.ColorKind)) ? _Exporter.GetRightHandedVector4(vertexData).asArray() : vertexData.asArray();
                     }
-                    case BABYLON.VertexBuffer.UVKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
+                    else if (vertexBufferKind === BABYLON.VertexBuffer.UVKind || vertexBufferKind === BABYLON.VertexBuffer.UV2Kind) {
+                        vector = [meshAttributeArray[index], meshAttributeArray[index + 1]];
                     }
-                    case BABYLON.VertexBuffer.UV2Kind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
+                    else {
+                        BABYLON.Tools.Warn("Unsupported Vertex Buffer Type: " + vertexBufferKind);
                     }
-                    default: {
-                        throw new Error("Unsupported vertex buffer type: " + vertexBufferKind);
+                    for (var i = 0; i < vector.length; ++i) {
+                        dataBuffer.setFloat32(byteOff, vector[i], true);
+                        byteOff += 4;
                     }
                 }
+                byteLength = meshAttributeArray.length * 4;
                 return byteLength;
             };
             /**
@@ -295,32 +237,32 @@ var BABYLON;
                 var glTF = {
                     asset: this.asset
                 };
-                if (buffer.byteLength > 0) {
+                if (buffer.byteLength) {
                     glTF.buffers = [buffer];
                 }
-                if (this.nodes && this.nodes.length !== 0) {
+                if (this.nodes && this.nodes.length) {
                     glTF.nodes = this.nodes;
                 }
-                if (this.meshes && this.meshes.length !== 0) {
+                if (this.meshes && this.meshes.length) {
                     glTF.meshes = this.meshes;
                 }
-                if (this.scenes && this.scenes.length !== 0) {
+                if (this.scenes && this.scenes.length) {
                     glTF.scenes = this.scenes;
                     glTF.scene = 0;
                 }
-                if (this.bufferViews && this.bufferViews.length !== 0) {
+                if (this.bufferViews && this.bufferViews.length) {
                     glTF.bufferViews = this.bufferViews;
                 }
-                if (this.accessors && this.accessors.length !== 0) {
+                if (this.accessors && this.accessors.length) {
                     glTF.accessors = this.accessors;
                 }
-                if (this.materials && this.materials.length !== 0) {
+                if (this.materials && this.materials.length) {
                     glTF.materials = this.materials;
                 }
-                if (this.textures && this.textures.length !== 0) {
+                if (this.textures && this.textures.length) {
                     glTF.textures = this.textures;
                 }
-                if (this.images && this.images.length !== 0) {
+                if (this.images && this.images.length) {
                     if (!shouldUseGlb) {
                         glTF.images = this.images;
                     }
@@ -331,7 +273,7 @@ var BABYLON;
                         var byteOffset = this.totalByteLength;
                         for (var i = 0; i < imageLength; ++i) {
                             var image = this.images[i];
-                            if (image.uri !== undefined) {
+                            if (image.uri) {
                                 var imageData = this.imageData[image.uri];
                                 var imageName = image.uri.split('.')[0] + " image";
                                 var bufferView = this.createBufferView(0, byteOffset, imageData.data.length, undefined, imageName);
@@ -359,15 +301,15 @@ var BABYLON;
              * @returns - GLTFData with glTF file data.
              */
             _Exporter.prototype._generateGLTF = function (glTFPrefix) {
-                var jsonText = this.generateJSON(false, glTFPrefix, true);
                 var binaryBuffer = this.generateBinary();
+                var jsonText = this.generateJSON(false, glTFPrefix, true);
                 var bin = new Blob([binaryBuffer], { type: 'application/octet-stream' });
                 var glTFFileName = glTFPrefix + '.gltf';
                 var glTFBinFile = glTFPrefix + '.bin';
                 var container = new BABYLON._GLTFData();
                 container.glTFFiles[glTFFileName] = jsonText;
                 container.glTFFiles[glTFBinFile] = bin;
-                if (this.imageData !== null) {
+                if (this.imageData) {
                     for (var image in this.imageData) {
                         container.glTFFiles[image] = new Blob([this.imageData[image].data], { type: this.imageData[image].mimeType });
                     }
@@ -380,10 +322,8 @@ var BABYLON;
              */
             _Exporter.prototype.generateBinary = function () {
                 var byteOffset = 0;
-                var binaryBuffer = new ArrayBuffer(this.totalByteLength);
-                var dataBuffer = new DataView(binaryBuffer);
-                byteOffset = this.createScene(this.babylonScene, byteOffset, dataBuffer);
-                return binaryBuffer;
+                byteOffset = this.createScene(this.babylonScene, byteOffset);
+                return this.binaryBuffer;
             };
             /**
              * Pads the number to a multiple of 4
@@ -402,8 +342,8 @@ var BABYLON;
              * @returns - object with glb filename as key and data as value
              */
             _Exporter.prototype._generateGLB = function (glTFPrefix) {
-                var jsonText = this.generateJSON(true);
                 var binaryBuffer = this.generateBinary();
+                var jsonText = this.generateJSON(true);
                 var glbFileName = glTFPrefix + '.glb';
                 var headerLength = 12;
                 var chunkLengthPrefix = 8;
@@ -469,36 +409,20 @@ var BABYLON;
              * Sets the TRS for each node
              * @param node - glTF Node for storing the transformation data.
              * @param babylonMesh - Babylon mesh used as the source for the transformation data.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              */
-            _Exporter.prototype.setNodeTransformation = function (node, babylonMesh, useRightHandedSystem) {
+            _Exporter.prototype.setNodeTransformation = function (node, babylonMesh) {
                 if (!(babylonMesh.position.x === 0 && babylonMesh.position.y === 0 && babylonMesh.position.z === 0)) {
-                    if (useRightHandedSystem) {
-                        node.translation = babylonMesh.position.asArray();
-                    }
-                    else {
-                        node.translation = [babylonMesh.position.x, babylonMesh.position.y, -babylonMesh.position.z];
-                    }
+                    node.translation = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(babylonMesh.position).asArray() : babylonMesh.position.asArray();
                 }
                 if (!(babylonMesh.scaling.x === 1 && babylonMesh.scaling.y === 1 && babylonMesh.scaling.z === 1)) {
-                    if (useRightHandedSystem) {
-                        node.scale = babylonMesh.scaling.asArray();
-                    }
-                    else {
-                        node.scale = [babylonMesh.scaling.x, babylonMesh.scaling.y, -babylonMesh.scaling.z];
-                    }
+                    node.scale = babylonMesh.scaling.asArray();
                 }
                 var rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(babylonMesh.rotation.y, babylonMesh.rotation.x, babylonMesh.rotation.z);
                 if (babylonMesh.rotationQuaternion) {
                     rotationQuaternion = rotationQuaternion.multiply(babylonMesh.rotationQuaternion);
                 }
                 if (!(rotationQuaternion.x === 0 && rotationQuaternion.y === 0 && rotationQuaternion.z === 0 && rotationQuaternion.w === 1)) {
-                    if (useRightHandedSystem) {
-                        node.rotation = rotationQuaternion.asArray();
-                    }
-                    else {
-                        node.rotation = [-rotationQuaternion.x, -rotationQuaternion.y, rotationQuaternion.z, rotationQuaternion.w];
-                    }
+                    node.rotation = this.convertToRightHandedSystem ? _Exporter.GetRightHandedQuaternion(rotationQuaternion).asArray() : rotationQuaternion.asArray();
                 }
             };
             /**
@@ -506,11 +430,10 @@ var BABYLON;
              * @param kind - Indicates the type of vertices data.
              * @param babylonMesh - The Babylon mesh to get the vertices data from.
              * @param byteOffset - The offset from the buffer to start indexing from.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              * @param dataBuffer - The buffer to write the bufferview data to.
              * @returns bytelength of the bufferview data.
              */
-            _Exporter.prototype.createBufferViewKind = function (kind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer) {
+            _Exporter.prototype.createBufferViewKind = function (kind, babylonMesh, byteOffset, dataBuffer) {
                 var bufferMesh = null;
                 var byteLength = 0;
                 if (babylonMesh instanceof BABYLON.Mesh) {
@@ -519,62 +442,29 @@ var BABYLON;
                 else if (babylonMesh instanceof BABYLON.InstancedMesh) {
                     bufferMesh = babylonMesh.sourceMesh;
                 }
-                if (bufferMesh !== null) {
+                if (bufferMesh) {
                     var vertexBuffer = null;
                     var vertexBufferOffset = null;
                     var vertexData = null;
                     var vertexStrideSize = null;
-                    if (bufferMesh.getVerticesDataKinds().indexOf(kind) > -1) {
+                    if (bufferMesh.isVerticesDataPresent(kind)) {
                         vertexBuffer = bufferMesh.getVertexBuffer(kind);
-                        vertexBufferOffset = vertexBuffer.getOffset();
-                        vertexData = vertexBuffer.getData();
-                        vertexStrideSize = vertexBuffer.getStrideSize();
-                        if (dataBuffer && vertexData) {
-                            byteLength = this.writeAttributeData(kind, vertexData, vertexStrideSize, vertexBufferOffset, byteOffset, dataBuffer, useRightHandedSystem);
-                            byteOffset += byteLength;
-                        }
-                        else {
-                            var bufferViewName = null;
-                            switch (kind) {
-                                case BABYLON.VertexBuffer.PositionKind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "Position - " + bufferMesh.name;
-                                    break;
-                                }
-                                case BABYLON.VertexBuffer.NormalKind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "Normal - " + bufferMesh.name;
-                                    break;
-                                }
-                                case BABYLON.VertexBuffer.TangentKind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "Tangent - " + bufferMesh.name;
-                                    break;
-                                }
-                                case BABYLON.VertexBuffer.ColorKind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "Color - " + bufferMesh.name;
-                                    break;
+                        if (vertexBuffer) {
+                            vertexBufferOffset = vertexBuffer.getOffset();
+                            vertexData = vertexBuffer.getData();
+                            if (vertexData) {
+                                vertexStrideSize = vertexBuffer.getStrideSize();
+                                if (dataBuffer && vertexData) {
+                                    byteLength = this.writeAttributeData(kind, vertexData, vertexStrideSize, vertexBufferOffset, byteOffset, dataBuffer);
+                                    byteOffset += byteLength;
                                 }
-                                case BABYLON.VertexBuffer.UVKind: {
+                                else {
                                     byteLength = vertexData.length * 4;
-                                    bufferViewName = "TexCoord 0 - " + bufferMesh.name;
-                                    break;
-                                }
-                                case BABYLON.VertexBuffer.UV2Kind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "TexCoord 1 - " + bufferMesh.name;
-                                    break;
-                                }
-                                default: {
-                                    BABYLON.Tools.Warn("Unsupported VertexBuffer kind: " + kind);
+                                    var bufferView = this.createBufferView(0, byteOffset, byteLength, vertexStrideSize * 4, kind + " - " + bufferMesh.name);
+                                    byteOffset += byteLength;
+                                    this.bufferViews.push(bufferView);
                                 }
                             }
-                            if (bufferViewName !== null) {
-                                var bufferView = this.createBufferView(0, byteOffset, byteLength, vertexStrideSize * 4, bufferViewName);
-                                byteOffset += byteLength;
-                                this.bufferViews.push(bufferView);
-                            }
                         }
                     }
                 }
@@ -585,11 +475,10 @@ var BABYLON;
              * @param mesh - glTF Mesh object to store the primitive attribute information.
              * @param babylonMesh - Babylon mesh to get the primitive attribute data from.
              * @param byteOffset - The offset in bytes of the buffer data.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              * @param dataBuffer - Buffer to write the attribute data to.
              * @returns - bytelength of the primitive attributes plus the passed in byteOffset.
              */
-            _Exporter.prototype.setPrimitiveAttributes = function (mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer) {
+            _Exporter.prototype.setPrimitiveAttributes = function (mesh, babylonMesh, byteOffset, dataBuffer) {
                 var bufferMesh = null;
                 if (babylonMesh instanceof BABYLON.Mesh) {
                     bufferMesh = babylonMesh;
@@ -597,147 +486,134 @@ var BABYLON;
                 else if (babylonMesh instanceof BABYLON.InstancedMesh) {
                     bufferMesh = babylonMesh.sourceMesh;
                 }
-                var positionBufferViewIndex = null;
-                var normalBufferViewIndex = null;
-                var colorBufferViewIndex = null;
-                var tangentBufferViewIndex = null;
-                var texCoord0BufferViewIndex = null;
-                var texCoord1BufferViewIndex = null;
+                var attributeData = [
+                    { kind: BABYLON.VertexBuffer.PositionKind, accessorType: "VEC3" /* VEC3 */ },
+                    { kind: BABYLON.VertexBuffer.NormalKind, accessorType: "VEC3" /* VEC3 */ },
+                    { kind: BABYLON.VertexBuffer.ColorKind, accessorType: "VEC4" /* VEC4 */ },
+                    { kind: BABYLON.VertexBuffer.TangentKind, accessorType: "VEC4" /* VEC4 */ },
+                    { kind: BABYLON.VertexBuffer.UVKind, accessorType: "VEC2" /* VEC2 */ },
+                    { kind: BABYLON.VertexBuffer.UV2Kind, accessorType: "VEC2" /* VEC2 */ },
+                ];
                 var indexBufferViewIndex = null;
-                if (bufferMesh !== null) {
+                if (bufferMesh) {
                     // For each BabylonMesh, create bufferviews for each 'kind'
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.PositionKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        positionBufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.NormalKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        normalBufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.ColorKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        colorBufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.TangentKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.TangentKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        colorBufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.UVKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        texCoord0BufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.UV2Kind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        texCoord1BufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.getTotalIndices() > 0) {
-                        var indices = bufferMesh.getIndices();
-                        if (dataBuffer) {
-                            var end = indices.length;
-                            var byteOff = byteOffset;
-                            for (var k = 0; k < end; ++k) {
-                                dataBuffer.setUint32(byteOff, indices[k], true);
-                                byteOff += 4;
-                            }
-                            byteOffset = byteOff;
-                        }
-                        else {
-                            var byteLength = indices.length * 4;
-                            var bufferView = this.createBufferView(0, byteOffset, byteLength, undefined, "Indices - " + bufferMesh.name);
-                            byteOffset += byteLength;
-                            this.bufferViews.push(bufferView);
-                            indexBufferViewIndex = this.bufferViews.length - 1;
+                    for (var _i = 0, attributeData_1 = attributeData; _i < attributeData_1.length; _i++) {
+                        var attribute = attributeData_1[_i];
+                        var attributeKind = attribute.kind;
+                        if (bufferMesh.isVerticesDataPresent(attributeKind)) {
+                            byteOffset += this.createBufferViewKind(attributeKind, babylonMesh, byteOffset, dataBuffer);
+                            attribute.bufferViewIndex = this.bufferViews.length - 1;
                         }
                     }
-                }
-                // go through all mesh primitives (submeshes)
-                for (var j = 0; j < babylonMesh.subMeshes.length; ++j) {
-                    var submesh = babylonMesh.subMeshes[j];
-                    var meshPrimitive = { attributes: {} };
-                    if (bufferMesh !== null) {
-                        // Create a bufferview storing all the positions
-                        if (!dataBuffer) {
-                            // Loop through each attribute of the submesh (mesh primitive)
-                            if (positionBufferViewIndex !== null) {
-                                var positionVertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.PositionKind);
-                                var positions = positionVertexBuffer.getData();
-                                var positionStrideSize = positionVertexBuffer.getStrideSize();
-                                // Create accessor
-                                var result = this.calculateMinMax(positions, 0, positions.length / positionStrideSize, positionStrideSize, useRightHandedSystem);
-                                var accessor = this.createAccessor(positionBufferViewIndex, "Position", "VEC3" /* VEC3 */, 5126 /* FLOAT */, positions.length / positionStrideSize, 0, result.min, result.max);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.POSITION = this.accessors.length - 1;
-                            }
-                            if (normalBufferViewIndex !== null) {
-                                var normalVertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.NormalKind);
-                                var normals = normalVertexBuffer.getData();
-                                var normalStrideSize = normalVertexBuffer.getStrideSize();
-                                // Create accessor
-                                var accessor = this.createAccessor(normalBufferViewIndex, "Normal", "VEC3" /* VEC3 */, 5126 /* FLOAT */, normals.length / normalStrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.NORMAL = this.accessors.length - 1;
-                            }
-                            if (tangentBufferViewIndex !== null) {
-                                var tangentVertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.TangentKind);
-                                var tangents = tangentVertexBuffer.getData();
-                                var tangentStrideSize = tangentVertexBuffer.getStrideSize();
-                                // Create accessor
-                                var accessor = this.createAccessor(tangentBufferViewIndex, "Tangent", "VEC4" /* VEC4 */, 5126 /* FLOAT */, tangents.length / tangentStrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.TANGENT = this.accessors.length - 1;
-                            }
-                            if (colorBufferViewIndex !== null) {
-                                var colorVertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.ColorKind);
-                                var colors = colorVertexBuffer.getData();
-                                var colorStrideSize = colorVertexBuffer.getStrideSize();
-                                // Create accessor
-                                var accessor = this.createAccessor(colorBufferViewIndex, "Color", "VEC4" /* VEC4 */, 5126 /* FLOAT */, colors.length / colorStrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.COLOR_0 = this.accessors.length - 1;
-                            }
-                            if (texCoord0BufferViewIndex !== null) {
-                                // Create accessor
-                                var texCoord0VertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.UVKind);
-                                var texCoord0s = texCoord0VertexBuffer.getData();
-                                var texCoord0StrideSize = texCoord0VertexBuffer.getStrideSize();
-                                var accessor = this.createAccessor(texCoord0BufferViewIndex, "Texture Coords 0", "VEC2" /* VEC2 */, 5126 /* FLOAT */, texCoord0s.length / texCoord0StrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
-                            }
-                            if (texCoord1BufferViewIndex !== null) {
-                                // Create accessor
-                                var texCoord1VertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.UV2Kind);
-                                var texCoord1s = texCoord1VertexBuffer.getData();
-                                var texCoord1StrideSize = texCoord1VertexBuffer.getStrideSize();
-                                var accessor = this.createAccessor(texCoord1BufferViewIndex, "Texture Coords 1", "VEC2" /* VEC2 */, 5126 /* FLOAT */, texCoord1s.length / texCoord1StrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
+                    if (bufferMesh.getTotalIndices()) {
+                        var indices = bufferMesh.getIndices();
+                        if (indices) {
+                            if (dataBuffer) {
+                                var end = indices.length;
+                                var byteOff = byteOffset;
+                                for (var k = 0; k < end; ++k) {
+                                    dataBuffer.setUint32(byteOff, indices[k], true);
+                                    byteOff += 4;
+                                }
+                                byteOffset = byteOff;
                             }
-                            if (indexBufferViewIndex) {
-                                // Create accessor
-                                var accessor = this.createAccessor(indexBufferViewIndex, "Indices", "SCALAR" /* SCALAR */, 5125 /* UNSIGNED_INT */, submesh.indexCount, submesh.indexStart * 4);
-                                this.accessors.push(accessor);
-                                meshPrimitive.indices = this.accessors.length - 1;
+                            else {
+                                var byteLength = indices.length * 4;
+                                var bufferView = this.createBufferView(0, byteOffset, byteLength, undefined, "Indices - " + bufferMesh.name);
+                                byteOffset += byteLength;
+                                this.bufferViews.push(bufferView);
+                                indexBufferViewIndex = this.bufferViews.length - 1;
                             }
                         }
-                        if (bufferMesh.material) {
-                            if (bufferMesh.material instanceof BABYLON.StandardMaterial || bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial) {
-                                var materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
-                                meshPrimitive.material = materialIndex;
+                    }
+                    if (babylonMesh.subMeshes) {
+                        // go through all mesh primitives (submeshes)
+                        for (var _a = 0, _b = babylonMesh.subMeshes; _a < _b.length; _a++) {
+                            var submesh = _b[_a];
+                            var meshPrimitive = { attributes: {} };
+                            // Create a bufferview storing all the positions
+                            if (!dataBuffer) {
+                                for (var _c = 0, attributeData_2 = attributeData; _c < attributeData_2.length; _c++) {
+                                    var attribute = attributeData_2[_c];
+                                    var attributeKind = attribute.kind;
+                                    if (bufferMesh.isVerticesDataPresent(attributeKind)) {
+                                        var vertexBuffer = bufferMesh.getVertexBuffer(attributeKind);
+                                        if (vertexBuffer) {
+                                            var bufferData = vertexBuffer.getData();
+                                            if (bufferData) {
+                                                var strideSize = vertexBuffer.getStrideSize();
+                                                var minMax = void 0;
+                                                var min = null;
+                                                var max = null;
+                                                var bufferViewIndex = attribute.bufferViewIndex;
+                                                if (bufferViewIndex != undefined) {
+                                                    if (attributeKind == BABYLON.VertexBuffer.PositionKind) {
+                                                        minMax = this.calculateMinMaxPositions(bufferData, 0, bufferData.length / strideSize);
+                                                        min = minMax.min;
+                                                        max = minMax.max;
+                                                    }
+                                                    var accessor = this.createAccessor(bufferViewIndex, attributeKind + " - " + babylonMesh.name, attribute.accessorType, 5126 /* FLOAT */, bufferData.length / strideSize, 0, min, max);
+                                                    this.accessors.push(accessor);
+                                                    switch (attributeKind) {
+                                                        case BABYLON.VertexBuffer.PositionKind: {
+                                                            meshPrimitive.attributes.POSITION = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.NormalKind: {
+                                                            meshPrimitive.attributes.NORMAL = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.ColorKind: {
+                                                            meshPrimitive.attributes.COLOR_0 = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.TangentKind: {
+                                                            meshPrimitive.attributes.TANGENT = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.UVKind: {
+                                                            meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.UV2Kind: {
+                                                            meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        default: {
+                                                            BABYLON.Tools.Warn("Unsupported Vertex Buffer Type: " + attributeKind);
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                                if (indexBufferViewIndex) {
+                                    // Create accessor
+                                    var accessor = this.createAccessor(indexBufferViewIndex, "indices - " + babylonMesh.name, "SCALAR" /* SCALAR */, 5125 /* UNSIGNED_INT */, submesh.indexCount, submesh.indexStart * 4, null, null);
+                                    this.accessors.push(accessor);
+                                    meshPrimitive.indices = this.accessors.length - 1;
+                                }
                             }
-                            else if (bufferMesh.material instanceof BABYLON.MultiMaterial) {
-                                var babylonMultiMaterial = bufferMesh.material;
-                                var material = babylonMultiMaterial.subMaterials[submesh.materialIndex];
-                                if (material !== null) {
-                                    var materialIndex = babylonMesh.getScene().materials.indexOf(material);
+                            if (bufferMesh.material) {
+                                if (bufferMesh.material instanceof BABYLON.StandardMaterial || bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial) {
+                                    var materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
                                     meshPrimitive.material = materialIndex;
                                 }
+                                else if (bufferMesh.material instanceof BABYLON.MultiMaterial) {
+                                    var babylonMultiMaterial = bufferMesh.material;
+                                    var material = babylonMultiMaterial.subMaterials[submesh.materialIndex];
+                                    if (material) {
+                                        var materialIndex = babylonMesh.getScene().materials.indexOf(material);
+                                        meshPrimitive.material = materialIndex;
+                                    }
+                                }
+                                else {
+                                    BABYLON.Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
+                                }
                             }
-                            else {
-                                BABYLON.Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
-                            }
+                            mesh.primitives.push(meshPrimitive);
                         }
-                        mesh.primitives.push(meshPrimitive);
                     }
                 }
                 return byteOffset;
@@ -747,47 +623,90 @@ var BABYLON;
              * Returns the the total byte offset.
              * @param babylonScene - Babylon scene to get the mesh data from.
              * @param byteOffset - Offset to start from in bytes.
-             * @param dataBuffer - Buffer to write geometry data to.
              * @returns bytelength + byteoffset
              */
-            _Exporter.prototype.createScene = function (babylonScene, byteOffset, dataBuffer) {
-                if (babylonScene.meshes.length > 0) {
+            _Exporter.prototype.createScene = function (babylonScene, byteOffset) {
+                if (babylonScene.meshes.length) {
                     var babylonMeshes = babylonScene.meshes;
                     var scene = { nodes: new Array() };
-                    if (dataBuffer == null) {
-                        GLTF2._GLTFMaterial.ConvertMaterialsToGLTF(babylonScene.materials, "image/jpeg" /* JPEG */, this.images, this.textures, this.materials, this.imageData, true);
-                    }
+                    GLTF2._GLTFMaterial.ConvertMaterialsToGLTF(babylonScene.materials, "image/jpeg" /* JPEG */, this.images, this.textures, this.materials, this.imageData, true);
+                    var result = this.createNodeMap(babylonScene, byteOffset);
+                    this.nodeMap = result.nodeMap;
+                    this.totalByteLength = result.byteOffset;
+                    this.binaryBuffer = new ArrayBuffer(this.totalByteLength);
+                    var dataBuffer = new DataView(this.binaryBuffer);
                     for (var i = 0; i < babylonMeshes.length; ++i) {
                         if (this.options &&
-                            this.options.shouldExportMesh !== undefined &&
+                            this.options.shouldExportMesh != undefined &&
                             !this.options.shouldExportMesh(babylonMeshes[i])) {
                             continue;
                         }
                         else {
-                            // create node to hold translation/rotation/scale and the mesh
-                            var node = { mesh: -1 };
                             var babylonMesh = babylonMeshes[i];
-                            var useRightHandedSystem = babylonMesh.getScene().useRightHandedSystem;
-                            // Set transformation
-                            this.setNodeTransformation(node, babylonMesh, useRightHandedSystem);
-                            // create mesh
-                            var mesh = { primitives: new Array() };
-                            mesh.primitives = [];
-                            byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                            // go through all mesh primitives (submeshes)
-                            this.meshes.push(mesh);
-                            node.mesh = this.meshes.length - 1;
-                            if (babylonMesh.name) {
-                                node.name = babylonMesh.name;
+                            // Build Hierarchy with the node map.
+                            var glTFNodeIndex = this.nodeMap[babylonMesh.uniqueId];
+                            var glTFNode = this.nodes[glTFNodeIndex];
+                            if (!babylonMesh.parent) {
+                                scene.nodes.push(glTFNodeIndex);
                             }
-                            this.nodes.push(node);
-                            scene.nodes.push(this.nodes.length - 1);
+                            var directDescendents = babylonMesh.getDescendants(true);
+                            if (!glTFNode.children && directDescendents && directDescendents.length) {
+                                glTFNode.children = [];
+                                for (var _i = 0, directDescendents_1 = directDescendents; _i < directDescendents_1.length; _i++) {
+                                    var descendent = directDescendents_1[_i];
+                                    glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
+                                }
+                            }
+                            var mesh = { primitives: new Array() };
+                            byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
                         }
                     }
                     this.scenes.push(scene);
                 }
                 return byteOffset;
             };
+            /**
+             * Creates a mapping of Node unique id to node index
+             * @param scene - Babylon Scene.
+             * @param byteOffset - The initial byte offset.
+             * @returns - Node mapping of unique id to index.
+             */
+            _Exporter.prototype.createNodeMap = function (scene, byteOffset) {
+                var nodeMap = {};
+                for (var _i = 0, _a = scene.meshes; _i < _a.length; _i++) {
+                    var babylonMesh = _a[_i];
+                    var result = this.createNode(babylonMesh, byteOffset, null);
+                    this.nodes.push(result.node);
+                    nodeMap[babylonMesh.uniqueId] = this.nodes.length - 1;
+                    byteOffset = result.byteOffset;
+                }
+                return { nodeMap: nodeMap, byteOffset: byteOffset };
+            };
+            /**
+             * Creates a glTF node from a Babylon mesh.
+             * @param babylonMesh - Source Babylon mesh.
+             * @param byteOffset - The initial byte offset.
+             * @param dataBuffer - Buffer for storing geometry data.
+             * @returns - Object containing an INode and byteoffset.
+             */
+            _Exporter.prototype.createNode = function (babylonMesh, byteOffset, dataBuffer) {
+                // create node to hold translation/rotation/scale and the mesh
+                var node = {};
+                if (babylonMesh.name) {
+                    node.name = babylonMesh.name;
+                }
+                // Set transformation
+                this.setNodeTransformation(node, babylonMesh);
+                // create mesh
+                var mesh = { primitives: new Array() };
+                mesh.primitives = [];
+                byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
+                if (mesh.primitives.length) {
+                    this.meshes.push(mesh);
+                    node.mesh = this.meshes.length - 1;
+                }
+                return { node: node, byteOffset: byteOffset };
+            };
             return _Exporter;
         }());
         GLTF2._Exporter = _Exporter;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


+ 281 - 362
dist/preview release/serializers/babylonjs.serializers.js

@@ -224,12 +224,10 @@ var BABYLON;
                 this.materials = new Array();
                 this.textures = new Array();
                 this.imageData = {};
-                if (options !== undefined) {
+                this.convertToRightHandedSystem = !this.babylonScene.useRightHandedSystem;
+                if (options) {
                     this.options = options;
                 }
-                var totalByteLength = 0;
-                totalByteLength = this.createScene(this.babylonScene, totalByteLength, null);
-                this.totalByteLength = totalByteLength;
             }
             /**
              * Creates a buffer view based on teh supplied arguments
@@ -242,7 +240,7 @@ var BABYLON;
              */
             _Exporter.prototype.createBufferView = function (bufferIndex, byteOffset, byteLength, byteStride, name) {
                 var bufferview = { buffer: bufferIndex, byteLength: byteLength };
-                if (byteOffset > 0) {
+                if (byteOffset) {
                     bufferview.byteOffset = byteOffset;
                 }
                 if (name) {
@@ -255,13 +253,14 @@ var BABYLON;
             };
             /**
              * Creates an accessor based on the supplied arguments
-             * @param bufferviewIndex
-             * @param name
-             * @param type
-             * @param componentType
-             * @param count
-             * @param min
-             * @param max
+             * @param bufferviewIndex - The index of the bufferview referenced by this accessor.
+             * @param name - The name of the accessor.
+             * @param type - The type of the accessor.
+             * @param componentType - The datatype of components in the attribute.
+             * @param count - The number of attributes referenced by this accessor.
+             * @param byteOffset - The offset relative to the start of the bufferView in bytes.
+             * @param min - Minimum value of each component in this attribute.
+             * @param max - Maximum value of each component in this attribute.
              * @returns - accessor for glTF
              */
             _Exporter.prototype.createAccessor = function (bufferviewIndex, name, type, componentType, count, byteOffset, min, max) {
@@ -278,40 +277,60 @@ var BABYLON;
                 return accessor;
             };
             /**
-             * Calculates the minimum and maximum values of an array of floats, based on stride
-             * @param buff - Data to check for min and max values.
-             * @param vertexStart - Start offset to calculate min and max values.
+             * Calculates the minimum and maximum values of an array of position floats.
+             * @param positions - Positions array of a mesh.
+             * @param vertexStart - Starting vertex offset to calculate min and max values.
              * @param vertexCount - Number of vertices to check for min and max values.
-             * @param stride - Offset between consecutive attributes.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              * @returns - min number array and max number array.
              */
-            _Exporter.prototype.calculateMinMax = function (buff, vertexStart, vertexCount, stride, useRightHandedSystem) {
+            _Exporter.prototype.calculateMinMaxPositions = function (positions, vertexStart, vertexCount) {
                 var min = [Infinity, Infinity, Infinity];
                 var max = [-Infinity, -Infinity, -Infinity];
+                var positionStrideSize = 3;
                 var end = vertexStart + vertexCount;
-                if (vertexCount > 0) {
+                if (vertexCount) {
                     for (var i = vertexStart; i < end; ++i) {
-                        var index = stride * i;
-                        var scale = 1;
-                        for (var j = 0; j < stride; ++j) {
-                            if (j === (stride - 1) && !useRightHandedSystem) {
-                                scale = -1;
-                            }
-                            var num = scale * buff[index];
+                        var indexOffset = positionStrideSize * i;
+                        var position = BABYLON.Vector3.FromArray(positions, indexOffset);
+                        var vector = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(position).asArray() : position.asArray();
+                        for (var j = 0; j < positionStrideSize; ++j) {
+                            var num = vector[j];
                             if (num < min[j]) {
                                 min[j] = num;
                             }
                             if (num > max[j]) {
                                 max[j] = num;
                             }
-                            ++index;
+                            ++indexOffset;
                         }
                     }
                 }
                 return { min: min, max: max };
             };
             /**
+             * Converts a vector3 array to right-handed.
+             * @param vector - vector3 Array to convert to right-handed.
+             * @returns - right-handed Vector3 array.
+             */
+            _Exporter.GetRightHandedVector3 = function (vector) {
+                return new BABYLON.Vector3(vector.x, vector.y, -vector.z);
+            };
+            /**
+             * Converts a vector4 array to right-handed.
+             * @param vector - vector4 Array to convert to right-handed.
+             * @returns - right-handed vector4 array.
+             */
+            _Exporter.GetRightHandedVector4 = function (vector) {
+                return new BABYLON.Vector4(vector.x, vector.y, -vector.z, -vector.w);
+            };
+            /**
+             * Converts a quaternion to right-handed.
+             * @param quaternion - Source quaternion to convert to right-handed.
+             */
+            _Exporter.GetRightHandedQuaternion = function (quaternion) {
+                return new BABYLON.Quaternion(-quaternion.x, -quaternion.y, quaternion.z, quaternion.w);
+            };
+            /**
              * Writes mesh attribute data to a data buffer.
              * Returns the bytelength of the data.
              * @param vertexBufferKind - Indicates what kind of vertex data is being passed in.
@@ -319,112 +338,35 @@ var BABYLON;
              * @param strideSize - Represents the offset between consecutive attributes
              * @param byteOffset - The offset to start counting bytes from.
              * @param dataBuffer - The buffer to write the binary data to.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              * @returns - Byte length of the attribute data.
              */
-            _Exporter.prototype.writeAttributeData = function (vertexBufferKind, meshAttributeArray, strideSize, vertexBufferOffset, byteOffset, dataBuffer, useRightHandedSystem) {
+            _Exporter.prototype.writeAttributeData = function (vertexBufferKind, meshAttributeArray, strideSize, vertexBufferOffset, byteOffset, dataBuffer) {
                 var byteOff = byteOffset;
-                var start = 0;
                 var end = meshAttributeArray.length / strideSize;
                 var byteLength = 0;
-                switch (vertexBufferKind) {
-                    case BABYLON.VertexBuffer.PositionKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                            if (useRightHandedSystem) {
-                                dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 2], true);
-                            }
-                            else {
-                                dataBuffer.setFloat32(byteOff, -meshAttributeArray[index + 2], true);
-                            }
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
-                    }
-                    case BABYLON.VertexBuffer.NormalKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                            if (useRightHandedSystem) {
-                                dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 2], true);
-                            }
-                            else {
-                                dataBuffer.setFloat32(byteOff, -meshAttributeArray[index + 2], true);
-                            }
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
-                    }
-                    case BABYLON.VertexBuffer.TangentKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                            if (useRightHandedSystem) {
-                                dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 2], true);
-                            }
-                            else {
-                                dataBuffer.setFloat32(byteOff, -meshAttributeArray[index + 2], true);
-                            }
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 3], true);
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
+                for (var k = 0; k < end; ++k) {
+                    var index = k * strideSize;
+                    var vector = [];
+                    if (vertexBufferKind === BABYLON.VertexBuffer.PositionKind || vertexBufferKind === BABYLON.VertexBuffer.NormalKind) {
+                        var vertexData = BABYLON.Vector3.FromArray(meshAttributeArray, index);
+                        vector = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(vertexData).asArray() : vertexData.asArray();
                     }
-                    case BABYLON.VertexBuffer.ColorKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 2], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 3], true);
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
+                    else if (vertexBufferKind === BABYLON.VertexBuffer.TangentKind || vertexBufferKind === BABYLON.VertexBuffer.ColorKind) {
+                        var vertexData = BABYLON.Vector4.FromArray(meshAttributeArray, index);
+                        vector = (this.convertToRightHandedSystem && !(vertexBufferKind === BABYLON.VertexBuffer.ColorKind)) ? _Exporter.GetRightHandedVector4(vertexData).asArray() : vertexData.asArray();
                     }
-                    case BABYLON.VertexBuffer.UVKind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
+                    else if (vertexBufferKind === BABYLON.VertexBuffer.UVKind || vertexBufferKind === BABYLON.VertexBuffer.UV2Kind) {
+                        vector = [meshAttributeArray[index], meshAttributeArray[index + 1]];
                     }
-                    case BABYLON.VertexBuffer.UV2Kind: {
-                        for (var k = start; k < end; ++k) {
-                            var index = k * strideSize;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index], true);
-                            byteOff += 4;
-                            dataBuffer.setFloat32(byteOff, meshAttributeArray[index + 1], true);
-                            byteOff += 4;
-                        }
-                        byteLength = meshAttributeArray.length * 4;
-                        break;
+                    else {
+                        BABYLON.Tools.Warn("Unsupported Vertex Buffer Type: " + vertexBufferKind);
                     }
-                    default: {
-                        throw new Error("Unsupported vertex buffer type: " + vertexBufferKind);
+                    for (var i = 0; i < vector.length; ++i) {
+                        dataBuffer.setFloat32(byteOff, vector[i], true);
+                        byteOff += 4;
                     }
                 }
+                byteLength = meshAttributeArray.length * 4;
                 return byteLength;
             };
             /**
@@ -439,32 +381,32 @@ var BABYLON;
                 var glTF = {
                     asset: this.asset
                 };
-                if (buffer.byteLength > 0) {
+                if (buffer.byteLength) {
                     glTF.buffers = [buffer];
                 }
-                if (this.nodes && this.nodes.length !== 0) {
+                if (this.nodes && this.nodes.length) {
                     glTF.nodes = this.nodes;
                 }
-                if (this.meshes && this.meshes.length !== 0) {
+                if (this.meshes && this.meshes.length) {
                     glTF.meshes = this.meshes;
                 }
-                if (this.scenes && this.scenes.length !== 0) {
+                if (this.scenes && this.scenes.length) {
                     glTF.scenes = this.scenes;
                     glTF.scene = 0;
                 }
-                if (this.bufferViews && this.bufferViews.length !== 0) {
+                if (this.bufferViews && this.bufferViews.length) {
                     glTF.bufferViews = this.bufferViews;
                 }
-                if (this.accessors && this.accessors.length !== 0) {
+                if (this.accessors && this.accessors.length) {
                     glTF.accessors = this.accessors;
                 }
-                if (this.materials && this.materials.length !== 0) {
+                if (this.materials && this.materials.length) {
                     glTF.materials = this.materials;
                 }
-                if (this.textures && this.textures.length !== 0) {
+                if (this.textures && this.textures.length) {
                     glTF.textures = this.textures;
                 }
-                if (this.images && this.images.length !== 0) {
+                if (this.images && this.images.length) {
                     if (!shouldUseGlb) {
                         glTF.images = this.images;
                     }
@@ -475,7 +417,7 @@ var BABYLON;
                         var byteOffset = this.totalByteLength;
                         for (var i = 0; i < imageLength; ++i) {
                             var image = this.images[i];
-                            if (image.uri !== undefined) {
+                            if (image.uri) {
                                 var imageData = this.imageData[image.uri];
                                 var imageName = image.uri.split('.')[0] + " image";
                                 var bufferView = this.createBufferView(0, byteOffset, imageData.data.length, undefined, imageName);
@@ -503,15 +445,15 @@ var BABYLON;
              * @returns - GLTFData with glTF file data.
              */
             _Exporter.prototype._generateGLTF = function (glTFPrefix) {
-                var jsonText = this.generateJSON(false, glTFPrefix, true);
                 var binaryBuffer = this.generateBinary();
+                var jsonText = this.generateJSON(false, glTFPrefix, true);
                 var bin = new Blob([binaryBuffer], { type: 'application/octet-stream' });
                 var glTFFileName = glTFPrefix + '.gltf';
                 var glTFBinFile = glTFPrefix + '.bin';
                 var container = new BABYLON._GLTFData();
                 container.glTFFiles[glTFFileName] = jsonText;
                 container.glTFFiles[glTFBinFile] = bin;
-                if (this.imageData !== null) {
+                if (this.imageData) {
                     for (var image in this.imageData) {
                         container.glTFFiles[image] = new Blob([this.imageData[image].data], { type: this.imageData[image].mimeType });
                     }
@@ -524,10 +466,8 @@ var BABYLON;
              */
             _Exporter.prototype.generateBinary = function () {
                 var byteOffset = 0;
-                var binaryBuffer = new ArrayBuffer(this.totalByteLength);
-                var dataBuffer = new DataView(binaryBuffer);
-                byteOffset = this.createScene(this.babylonScene, byteOffset, dataBuffer);
-                return binaryBuffer;
+                byteOffset = this.createScene(this.babylonScene, byteOffset);
+                return this.binaryBuffer;
             };
             /**
              * Pads the number to a multiple of 4
@@ -546,8 +486,8 @@ var BABYLON;
              * @returns - object with glb filename as key and data as value
              */
             _Exporter.prototype._generateGLB = function (glTFPrefix) {
-                var jsonText = this.generateJSON(true);
                 var binaryBuffer = this.generateBinary();
+                var jsonText = this.generateJSON(true);
                 var glbFileName = glTFPrefix + '.glb';
                 var headerLength = 12;
                 var chunkLengthPrefix = 8;
@@ -613,36 +553,20 @@ var BABYLON;
              * Sets the TRS for each node
              * @param node - glTF Node for storing the transformation data.
              * @param babylonMesh - Babylon mesh used as the source for the transformation data.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              */
-            _Exporter.prototype.setNodeTransformation = function (node, babylonMesh, useRightHandedSystem) {
+            _Exporter.prototype.setNodeTransformation = function (node, babylonMesh) {
                 if (!(babylonMesh.position.x === 0 && babylonMesh.position.y === 0 && babylonMesh.position.z === 0)) {
-                    if (useRightHandedSystem) {
-                        node.translation = babylonMesh.position.asArray();
-                    }
-                    else {
-                        node.translation = [babylonMesh.position.x, babylonMesh.position.y, -babylonMesh.position.z];
-                    }
+                    node.translation = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(babylonMesh.position).asArray() : babylonMesh.position.asArray();
                 }
                 if (!(babylonMesh.scaling.x === 1 && babylonMesh.scaling.y === 1 && babylonMesh.scaling.z === 1)) {
-                    if (useRightHandedSystem) {
-                        node.scale = babylonMesh.scaling.asArray();
-                    }
-                    else {
-                        node.scale = [babylonMesh.scaling.x, babylonMesh.scaling.y, -babylonMesh.scaling.z];
-                    }
+                    node.scale = babylonMesh.scaling.asArray();
                 }
                 var rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(babylonMesh.rotation.y, babylonMesh.rotation.x, babylonMesh.rotation.z);
                 if (babylonMesh.rotationQuaternion) {
                     rotationQuaternion = rotationQuaternion.multiply(babylonMesh.rotationQuaternion);
                 }
                 if (!(rotationQuaternion.x === 0 && rotationQuaternion.y === 0 && rotationQuaternion.z === 0 && rotationQuaternion.w === 1)) {
-                    if (useRightHandedSystem) {
-                        node.rotation = rotationQuaternion.asArray();
-                    }
-                    else {
-                        node.rotation = [-rotationQuaternion.x, -rotationQuaternion.y, rotationQuaternion.z, rotationQuaternion.w];
-                    }
+                    node.rotation = this.convertToRightHandedSystem ? _Exporter.GetRightHandedQuaternion(rotationQuaternion).asArray() : rotationQuaternion.asArray();
                 }
             };
             /**
@@ -650,11 +574,10 @@ var BABYLON;
              * @param kind - Indicates the type of vertices data.
              * @param babylonMesh - The Babylon mesh to get the vertices data from.
              * @param byteOffset - The offset from the buffer to start indexing from.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              * @param dataBuffer - The buffer to write the bufferview data to.
              * @returns bytelength of the bufferview data.
              */
-            _Exporter.prototype.createBufferViewKind = function (kind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer) {
+            _Exporter.prototype.createBufferViewKind = function (kind, babylonMesh, byteOffset, dataBuffer) {
                 var bufferMesh = null;
                 var byteLength = 0;
                 if (babylonMesh instanceof BABYLON.Mesh) {
@@ -663,62 +586,29 @@ var BABYLON;
                 else if (babylonMesh instanceof BABYLON.InstancedMesh) {
                     bufferMesh = babylonMesh.sourceMesh;
                 }
-                if (bufferMesh !== null) {
+                if (bufferMesh) {
                     var vertexBuffer = null;
                     var vertexBufferOffset = null;
                     var vertexData = null;
                     var vertexStrideSize = null;
-                    if (bufferMesh.getVerticesDataKinds().indexOf(kind) > -1) {
+                    if (bufferMesh.isVerticesDataPresent(kind)) {
                         vertexBuffer = bufferMesh.getVertexBuffer(kind);
-                        vertexBufferOffset = vertexBuffer.getOffset();
-                        vertexData = vertexBuffer.getData();
-                        vertexStrideSize = vertexBuffer.getStrideSize();
-                        if (dataBuffer && vertexData) {
-                            byteLength = this.writeAttributeData(kind, vertexData, vertexStrideSize, vertexBufferOffset, byteOffset, dataBuffer, useRightHandedSystem);
-                            byteOffset += byteLength;
-                        }
-                        else {
-                            var bufferViewName = null;
-                            switch (kind) {
-                                case BABYLON.VertexBuffer.PositionKind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "Position - " + bufferMesh.name;
-                                    break;
-                                }
-                                case BABYLON.VertexBuffer.NormalKind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "Normal - " + bufferMesh.name;
-                                    break;
-                                }
-                                case BABYLON.VertexBuffer.TangentKind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "Tangent - " + bufferMesh.name;
-                                    break;
-                                }
-                                case BABYLON.VertexBuffer.ColorKind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "Color - " + bufferMesh.name;
-                                    break;
+                        if (vertexBuffer) {
+                            vertexBufferOffset = vertexBuffer.getOffset();
+                            vertexData = vertexBuffer.getData();
+                            if (vertexData) {
+                                vertexStrideSize = vertexBuffer.getStrideSize();
+                                if (dataBuffer && vertexData) {
+                                    byteLength = this.writeAttributeData(kind, vertexData, vertexStrideSize, vertexBufferOffset, byteOffset, dataBuffer);
+                                    byteOffset += byteLength;
                                 }
-                                case BABYLON.VertexBuffer.UVKind: {
+                                else {
                                     byteLength = vertexData.length * 4;
-                                    bufferViewName = "TexCoord 0 - " + bufferMesh.name;
-                                    break;
-                                }
-                                case BABYLON.VertexBuffer.UV2Kind: {
-                                    byteLength = vertexData.length * 4;
-                                    bufferViewName = "TexCoord 1 - " + bufferMesh.name;
-                                    break;
-                                }
-                                default: {
-                                    BABYLON.Tools.Warn("Unsupported VertexBuffer kind: " + kind);
+                                    var bufferView = this.createBufferView(0, byteOffset, byteLength, vertexStrideSize * 4, kind + " - " + bufferMesh.name);
+                                    byteOffset += byteLength;
+                                    this.bufferViews.push(bufferView);
                                 }
                             }
-                            if (bufferViewName !== null) {
-                                var bufferView = this.createBufferView(0, byteOffset, byteLength, vertexStrideSize * 4, bufferViewName);
-                                byteOffset += byteLength;
-                                this.bufferViews.push(bufferView);
-                            }
                         }
                     }
                 }
@@ -729,11 +619,10 @@ var BABYLON;
              * @param mesh - glTF Mesh object to store the primitive attribute information.
              * @param babylonMesh - Babylon mesh to get the primitive attribute data from.
              * @param byteOffset - The offset in bytes of the buffer data.
-             * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
              * @param dataBuffer - Buffer to write the attribute data to.
              * @returns - bytelength of the primitive attributes plus the passed in byteOffset.
              */
-            _Exporter.prototype.setPrimitiveAttributes = function (mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer) {
+            _Exporter.prototype.setPrimitiveAttributes = function (mesh, babylonMesh, byteOffset, dataBuffer) {
                 var bufferMesh = null;
                 if (babylonMesh instanceof BABYLON.Mesh) {
                     bufferMesh = babylonMesh;
@@ -741,147 +630,134 @@ var BABYLON;
                 else if (babylonMesh instanceof BABYLON.InstancedMesh) {
                     bufferMesh = babylonMesh.sourceMesh;
                 }
-                var positionBufferViewIndex = null;
-                var normalBufferViewIndex = null;
-                var colorBufferViewIndex = null;
-                var tangentBufferViewIndex = null;
-                var texCoord0BufferViewIndex = null;
-                var texCoord1BufferViewIndex = null;
+                var attributeData = [
+                    { kind: BABYLON.VertexBuffer.PositionKind, accessorType: "VEC3" /* VEC3 */ },
+                    { kind: BABYLON.VertexBuffer.NormalKind, accessorType: "VEC3" /* VEC3 */ },
+                    { kind: BABYLON.VertexBuffer.ColorKind, accessorType: "VEC4" /* VEC4 */ },
+                    { kind: BABYLON.VertexBuffer.TangentKind, accessorType: "VEC4" /* VEC4 */ },
+                    { kind: BABYLON.VertexBuffer.UVKind, accessorType: "VEC2" /* VEC2 */ },
+                    { kind: BABYLON.VertexBuffer.UV2Kind, accessorType: "VEC2" /* VEC2 */ },
+                ];
                 var indexBufferViewIndex = null;
-                if (bufferMesh !== null) {
+                if (bufferMesh) {
                     // For each BabylonMesh, create bufferviews for each 'kind'
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.PositionKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        positionBufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.NormalKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        normalBufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.ColorKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        colorBufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.TangentKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.TangentKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        colorBufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.UVKind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        texCoord0BufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
-                        byteOffset += this.createBufferViewKind(BABYLON.VertexBuffer.UV2Kind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                        texCoord1BufferViewIndex = this.bufferViews.length - 1;
-                    }
-                    if (bufferMesh.getTotalIndices() > 0) {
-                        var indices = bufferMesh.getIndices();
-                        if (dataBuffer) {
-                            var end = indices.length;
-                            var byteOff = byteOffset;
-                            for (var k = 0; k < end; ++k) {
-                                dataBuffer.setUint32(byteOff, indices[k], true);
-                                byteOff += 4;
-                            }
-                            byteOffset = byteOff;
-                        }
-                        else {
-                            var byteLength = indices.length * 4;
-                            var bufferView = this.createBufferView(0, byteOffset, byteLength, undefined, "Indices - " + bufferMesh.name);
-                            byteOffset += byteLength;
-                            this.bufferViews.push(bufferView);
-                            indexBufferViewIndex = this.bufferViews.length - 1;
+                    for (var _i = 0, attributeData_1 = attributeData; _i < attributeData_1.length; _i++) {
+                        var attribute = attributeData_1[_i];
+                        var attributeKind = attribute.kind;
+                        if (bufferMesh.isVerticesDataPresent(attributeKind)) {
+                            byteOffset += this.createBufferViewKind(attributeKind, babylonMesh, byteOffset, dataBuffer);
+                            attribute.bufferViewIndex = this.bufferViews.length - 1;
                         }
                     }
-                }
-                // go through all mesh primitives (submeshes)
-                for (var j = 0; j < babylonMesh.subMeshes.length; ++j) {
-                    var submesh = babylonMesh.subMeshes[j];
-                    var meshPrimitive = { attributes: {} };
-                    if (bufferMesh !== null) {
-                        // Create a bufferview storing all the positions
-                        if (!dataBuffer) {
-                            // Loop through each attribute of the submesh (mesh primitive)
-                            if (positionBufferViewIndex !== null) {
-                                var positionVertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.PositionKind);
-                                var positions = positionVertexBuffer.getData();
-                                var positionStrideSize = positionVertexBuffer.getStrideSize();
-                                // Create accessor
-                                var result = this.calculateMinMax(positions, 0, positions.length / positionStrideSize, positionStrideSize, useRightHandedSystem);
-                                var accessor = this.createAccessor(positionBufferViewIndex, "Position", "VEC3" /* VEC3 */, 5126 /* FLOAT */, positions.length / positionStrideSize, 0, result.min, result.max);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.POSITION = this.accessors.length - 1;
-                            }
-                            if (normalBufferViewIndex !== null) {
-                                var normalVertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.NormalKind);
-                                var normals = normalVertexBuffer.getData();
-                                var normalStrideSize = normalVertexBuffer.getStrideSize();
-                                // Create accessor
-                                var accessor = this.createAccessor(normalBufferViewIndex, "Normal", "VEC3" /* VEC3 */, 5126 /* FLOAT */, normals.length / normalStrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.NORMAL = this.accessors.length - 1;
-                            }
-                            if (tangentBufferViewIndex !== null) {
-                                var tangentVertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.TangentKind);
-                                var tangents = tangentVertexBuffer.getData();
-                                var tangentStrideSize = tangentVertexBuffer.getStrideSize();
-                                // Create accessor
-                                var accessor = this.createAccessor(tangentBufferViewIndex, "Tangent", "VEC4" /* VEC4 */, 5126 /* FLOAT */, tangents.length / tangentStrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.TANGENT = this.accessors.length - 1;
-                            }
-                            if (colorBufferViewIndex !== null) {
-                                var colorVertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.ColorKind);
-                                var colors = colorVertexBuffer.getData();
-                                var colorStrideSize = colorVertexBuffer.getStrideSize();
-                                // Create accessor
-                                var accessor = this.createAccessor(colorBufferViewIndex, "Color", "VEC4" /* VEC4 */, 5126 /* FLOAT */, colors.length / colorStrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.COLOR_0 = this.accessors.length - 1;
-                            }
-                            if (texCoord0BufferViewIndex !== null) {
-                                // Create accessor
-                                var texCoord0VertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.UVKind);
-                                var texCoord0s = texCoord0VertexBuffer.getData();
-                                var texCoord0StrideSize = texCoord0VertexBuffer.getStrideSize();
-                                var accessor = this.createAccessor(texCoord0BufferViewIndex, "Texture Coords 0", "VEC2" /* VEC2 */, 5126 /* FLOAT */, texCoord0s.length / texCoord0StrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
-                            }
-                            if (texCoord1BufferViewIndex !== null) {
-                                // Create accessor
-                                var texCoord1VertexBuffer = bufferMesh.getVertexBuffer(BABYLON.VertexBuffer.UV2Kind);
-                                var texCoord1s = texCoord1VertexBuffer.getData();
-                                var texCoord1StrideSize = texCoord1VertexBuffer.getStrideSize();
-                                var accessor = this.createAccessor(texCoord1BufferViewIndex, "Texture Coords 1", "VEC2" /* VEC2 */, 5126 /* FLOAT */, texCoord1s.length / texCoord1StrideSize);
-                                this.accessors.push(accessor);
-                                meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
+                    if (bufferMesh.getTotalIndices()) {
+                        var indices = bufferMesh.getIndices();
+                        if (indices) {
+                            if (dataBuffer) {
+                                var end = indices.length;
+                                var byteOff = byteOffset;
+                                for (var k = 0; k < end; ++k) {
+                                    dataBuffer.setUint32(byteOff, indices[k], true);
+                                    byteOff += 4;
+                                }
+                                byteOffset = byteOff;
                             }
-                            if (indexBufferViewIndex) {
-                                // Create accessor
-                                var accessor = this.createAccessor(indexBufferViewIndex, "Indices", "SCALAR" /* SCALAR */, 5125 /* UNSIGNED_INT */, submesh.indexCount, submesh.indexStart * 4);
-                                this.accessors.push(accessor);
-                                meshPrimitive.indices = this.accessors.length - 1;
+                            else {
+                                var byteLength = indices.length * 4;
+                                var bufferView = this.createBufferView(0, byteOffset, byteLength, undefined, "Indices - " + bufferMesh.name);
+                                byteOffset += byteLength;
+                                this.bufferViews.push(bufferView);
+                                indexBufferViewIndex = this.bufferViews.length - 1;
                             }
                         }
-                        if (bufferMesh.material) {
-                            if (bufferMesh.material instanceof BABYLON.StandardMaterial || bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial) {
-                                var materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
-                                meshPrimitive.material = materialIndex;
+                    }
+                    if (babylonMesh.subMeshes) {
+                        // go through all mesh primitives (submeshes)
+                        for (var _a = 0, _b = babylonMesh.subMeshes; _a < _b.length; _a++) {
+                            var submesh = _b[_a];
+                            var meshPrimitive = { attributes: {} };
+                            // Create a bufferview storing all the positions
+                            if (!dataBuffer) {
+                                for (var _c = 0, attributeData_2 = attributeData; _c < attributeData_2.length; _c++) {
+                                    var attribute = attributeData_2[_c];
+                                    var attributeKind = attribute.kind;
+                                    if (bufferMesh.isVerticesDataPresent(attributeKind)) {
+                                        var vertexBuffer = bufferMesh.getVertexBuffer(attributeKind);
+                                        if (vertexBuffer) {
+                                            var bufferData = vertexBuffer.getData();
+                                            if (bufferData) {
+                                                var strideSize = vertexBuffer.getStrideSize();
+                                                var minMax = void 0;
+                                                var min = null;
+                                                var max = null;
+                                                var bufferViewIndex = attribute.bufferViewIndex;
+                                                if (bufferViewIndex != undefined) {
+                                                    if (attributeKind == BABYLON.VertexBuffer.PositionKind) {
+                                                        minMax = this.calculateMinMaxPositions(bufferData, 0, bufferData.length / strideSize);
+                                                        min = minMax.min;
+                                                        max = minMax.max;
+                                                    }
+                                                    var accessor = this.createAccessor(bufferViewIndex, attributeKind + " - " + babylonMesh.name, attribute.accessorType, 5126 /* FLOAT */, bufferData.length / strideSize, 0, min, max);
+                                                    this.accessors.push(accessor);
+                                                    switch (attributeKind) {
+                                                        case BABYLON.VertexBuffer.PositionKind: {
+                                                            meshPrimitive.attributes.POSITION = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.NormalKind: {
+                                                            meshPrimitive.attributes.NORMAL = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.ColorKind: {
+                                                            meshPrimitive.attributes.COLOR_0 = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.TangentKind: {
+                                                            meshPrimitive.attributes.TANGENT = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.UVKind: {
+                                                            meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        case BABYLON.VertexBuffer.UV2Kind: {
+                                                            meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
+                                                            break;
+                                                        }
+                                                        default: {
+                                                            BABYLON.Tools.Warn("Unsupported Vertex Buffer Type: " + attributeKind);
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                                if (indexBufferViewIndex) {
+                                    // Create accessor
+                                    var accessor = this.createAccessor(indexBufferViewIndex, "indices - " + babylonMesh.name, "SCALAR" /* SCALAR */, 5125 /* UNSIGNED_INT */, submesh.indexCount, submesh.indexStart * 4, null, null);
+                                    this.accessors.push(accessor);
+                                    meshPrimitive.indices = this.accessors.length - 1;
+                                }
                             }
-                            else if (bufferMesh.material instanceof BABYLON.MultiMaterial) {
-                                var babylonMultiMaterial = bufferMesh.material;
-                                var material = babylonMultiMaterial.subMaterials[submesh.materialIndex];
-                                if (material !== null) {
-                                    var materialIndex = babylonMesh.getScene().materials.indexOf(material);
+                            if (bufferMesh.material) {
+                                if (bufferMesh.material instanceof BABYLON.StandardMaterial || bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial) {
+                                    var materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
                                     meshPrimitive.material = materialIndex;
                                 }
+                                else if (bufferMesh.material instanceof BABYLON.MultiMaterial) {
+                                    var babylonMultiMaterial = bufferMesh.material;
+                                    var material = babylonMultiMaterial.subMaterials[submesh.materialIndex];
+                                    if (material) {
+                                        var materialIndex = babylonMesh.getScene().materials.indexOf(material);
+                                        meshPrimitive.material = materialIndex;
+                                    }
+                                }
+                                else {
+                                    BABYLON.Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
+                                }
                             }
-                            else {
-                                BABYLON.Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
-                            }
+                            mesh.primitives.push(meshPrimitive);
                         }
-                        mesh.primitives.push(meshPrimitive);
                     }
                 }
                 return byteOffset;
@@ -891,47 +767,90 @@ var BABYLON;
              * Returns the the total byte offset.
              * @param babylonScene - Babylon scene to get the mesh data from.
              * @param byteOffset - Offset to start from in bytes.
-             * @param dataBuffer - Buffer to write geometry data to.
              * @returns bytelength + byteoffset
              */
-            _Exporter.prototype.createScene = function (babylonScene, byteOffset, dataBuffer) {
-                if (babylonScene.meshes.length > 0) {
+            _Exporter.prototype.createScene = function (babylonScene, byteOffset) {
+                if (babylonScene.meshes.length) {
                     var babylonMeshes = babylonScene.meshes;
                     var scene = { nodes: new Array() };
-                    if (dataBuffer == null) {
-                        GLTF2._GLTFMaterial.ConvertMaterialsToGLTF(babylonScene.materials, "image/jpeg" /* JPEG */, this.images, this.textures, this.materials, this.imageData, true);
-                    }
+                    GLTF2._GLTFMaterial.ConvertMaterialsToGLTF(babylonScene.materials, "image/jpeg" /* JPEG */, this.images, this.textures, this.materials, this.imageData, true);
+                    var result = this.createNodeMap(babylonScene, byteOffset);
+                    this.nodeMap = result.nodeMap;
+                    this.totalByteLength = result.byteOffset;
+                    this.binaryBuffer = new ArrayBuffer(this.totalByteLength);
+                    var dataBuffer = new DataView(this.binaryBuffer);
                     for (var i = 0; i < babylonMeshes.length; ++i) {
                         if (this.options &&
-                            this.options.shouldExportMesh !== undefined &&
+                            this.options.shouldExportMesh != undefined &&
                             !this.options.shouldExportMesh(babylonMeshes[i])) {
                             continue;
                         }
                         else {
-                            // create node to hold translation/rotation/scale and the mesh
-                            var node = { mesh: -1 };
                             var babylonMesh = babylonMeshes[i];
-                            var useRightHandedSystem = babylonMesh.getScene().useRightHandedSystem;
-                            // Set transformation
-                            this.setNodeTransformation(node, babylonMesh, useRightHandedSystem);
-                            // create mesh
-                            var mesh = { primitives: new Array() };
-                            mesh.primitives = [];
-                            byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
-                            // go through all mesh primitives (submeshes)
-                            this.meshes.push(mesh);
-                            node.mesh = this.meshes.length - 1;
-                            if (babylonMesh.name) {
-                                node.name = babylonMesh.name;
+                            // Build Hierarchy with the node map.
+                            var glTFNodeIndex = this.nodeMap[babylonMesh.uniqueId];
+                            var glTFNode = this.nodes[glTFNodeIndex];
+                            if (!babylonMesh.parent) {
+                                scene.nodes.push(glTFNodeIndex);
                             }
-                            this.nodes.push(node);
-                            scene.nodes.push(this.nodes.length - 1);
+                            var directDescendents = babylonMesh.getDescendants(true);
+                            if (!glTFNode.children && directDescendents && directDescendents.length) {
+                                glTFNode.children = [];
+                                for (var _i = 0, directDescendents_1 = directDescendents; _i < directDescendents_1.length; _i++) {
+                                    var descendent = directDescendents_1[_i];
+                                    glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
+                                }
+                            }
+                            var mesh = { primitives: new Array() };
+                            byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
                         }
                     }
                     this.scenes.push(scene);
                 }
                 return byteOffset;
             };
+            /**
+             * Creates a mapping of Node unique id to node index
+             * @param scene - Babylon Scene.
+             * @param byteOffset - The initial byte offset.
+             * @returns - Node mapping of unique id to index.
+             */
+            _Exporter.prototype.createNodeMap = function (scene, byteOffset) {
+                var nodeMap = {};
+                for (var _i = 0, _a = scene.meshes; _i < _a.length; _i++) {
+                    var babylonMesh = _a[_i];
+                    var result = this.createNode(babylonMesh, byteOffset, null);
+                    this.nodes.push(result.node);
+                    nodeMap[babylonMesh.uniqueId] = this.nodes.length - 1;
+                    byteOffset = result.byteOffset;
+                }
+                return { nodeMap: nodeMap, byteOffset: byteOffset };
+            };
+            /**
+             * Creates a glTF node from a Babylon mesh.
+             * @param babylonMesh - Source Babylon mesh.
+             * @param byteOffset - The initial byte offset.
+             * @param dataBuffer - Buffer for storing geometry data.
+             * @returns - Object containing an INode and byteoffset.
+             */
+            _Exporter.prototype.createNode = function (babylonMesh, byteOffset, dataBuffer) {
+                // create node to hold translation/rotation/scale and the mesh
+                var node = {};
+                if (babylonMesh.name) {
+                    node.name = babylonMesh.name;
+                }
+                // Set transformation
+                this.setNodeTransformation(node, babylonMesh);
+                // create mesh
+                var mesh = { primitives: new Array() };
+                mesh.primitives = [];
+                byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
+                if (mesh.primitives.length) {
+                    this.meshes.push(mesh);
+                    node.mesh = this.meshes.length - 1;
+                }
+                return { node: node, byteOffset: byteOffset };
+            };
             return _Exporter;
         }());
         GLTF2._Exporter = _Exporter;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 62 - 24
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -363,6 +363,18 @@ declare module BABYLON.GLTF2 {
          */
         private imageData;
         /**
+         * Stores a map of the unique id of a node to its index in the node array.
+         */
+        private nodeMap;
+        /**
+         * Stores the binary buffer used to store geometry data.
+         */
+        private binaryBuffer;
+        /**
+         * Specifies if the Babylon scene should be converted to right-handed on export.
+         */
+        private convertToRightHandedSystem;
+        /**
          * Creates a glTF Exporter instance, which can accept optional exporter options.
          * @param babylonScene - Babylon scene object
          * @param options - Options to modify the behavior of the exporter.
@@ -380,26 +392,42 @@ declare module BABYLON.GLTF2 {
         private createBufferView(bufferIndex, byteOffset, byteLength, byteStride?, name?);
         /**
          * Creates an accessor based on the supplied arguments
-         * @param bufferviewIndex
-         * @param name
-         * @param type
-         * @param componentType
-         * @param count
-         * @param min
-         * @param max
+         * @param bufferviewIndex - The index of the bufferview referenced by this accessor.
+         * @param name - The name of the accessor.
+         * @param type - The type of the accessor.
+         * @param componentType - The datatype of components in the attribute.
+         * @param count - The number of attributes referenced by this accessor.
+         * @param byteOffset - The offset relative to the start of the bufferView in bytes.
+         * @param min - Minimum value of each component in this attribute.
+         * @param max - Maximum value of each component in this attribute.
          * @returns - accessor for glTF
          */
-        private createAccessor(bufferviewIndex, name, type, componentType, count, byteOffset?, min?, max?);
+        private createAccessor(bufferviewIndex, name, type, componentType, count, byteOffset, min, max);
         /**
-         * Calculates the minimum and maximum values of an array of floats, based on stride
-         * @param buff - Data to check for min and max values.
-         * @param vertexStart - Start offset to calculate min and max values.
+         * Calculates the minimum and maximum values of an array of position floats.
+         * @param positions - Positions array of a mesh.
+         * @param vertexStart - Starting vertex offset to calculate min and max values.
          * @param vertexCount - Number of vertices to check for min and max values.
-         * @param stride - Offset between consecutive attributes.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          * @returns - min number array and max number array.
          */
-        private calculateMinMax(buff, vertexStart, vertexCount, stride, useRightHandedSystem);
+        private calculateMinMaxPositions(positions, vertexStart, vertexCount);
+        /**
+         * Converts a vector3 array to right-handed.
+         * @param vector - vector3 Array to convert to right-handed.
+         * @returns - right-handed Vector3 array.
+         */
+        private static GetRightHandedVector3(vector);
+        /**
+         * Converts a vector4 array to right-handed.
+         * @param vector - vector4 Array to convert to right-handed.
+         * @returns - right-handed vector4 array.
+         */
+        private static GetRightHandedVector4(vector);
+        /**
+         * Converts a quaternion to right-handed.
+         * @param quaternion - Source quaternion to convert to right-handed.
+         */
+        private static GetRightHandedQuaternion(quaternion);
         /**
          * Writes mesh attribute data to a data buffer.
          * Returns the bytelength of the data.
@@ -408,10 +436,9 @@ declare module BABYLON.GLTF2 {
          * @param strideSize - Represents the offset between consecutive attributes
          * @param byteOffset - The offset to start counting bytes from.
          * @param dataBuffer - The buffer to write the binary data to.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          * @returns - Byte length of the attribute data.
          */
-        private writeAttributeData(vertexBufferKind, meshAttributeArray, strideSize, vertexBufferOffset, byteOffset, dataBuffer, useRightHandedSystem);
+        private writeAttributeData(vertexBufferKind, meshAttributeArray, strideSize, vertexBufferOffset, byteOffset, dataBuffer);
         /**
          * Generates glTF json data
          * @param shouldUseGlb - Indicates whether the json should be written for a glb file.
@@ -448,38 +475,49 @@ declare module BABYLON.GLTF2 {
          * Sets the TRS for each node
          * @param node - glTF Node for storing the transformation data.
          * @param babylonMesh - Babylon mesh used as the source for the transformation data.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          */
-        private setNodeTransformation(node, babylonMesh, useRightHandedSystem);
+        private setNodeTransformation(node, babylonMesh);
         /**
          * Creates a bufferview based on the vertices type for the Babylon mesh
          * @param kind - Indicates the type of vertices data.
          * @param babylonMesh - The Babylon mesh to get the vertices data from.
          * @param byteOffset - The offset from the buffer to start indexing from.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          * @param dataBuffer - The buffer to write the bufferview data to.
          * @returns bytelength of the bufferview data.
          */
-        private createBufferViewKind(kind, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
+        private createBufferViewKind(kind, babylonMesh, byteOffset, dataBuffer);
         /**
          * Sets data for the primitive attributes of each submesh
          * @param mesh - glTF Mesh object to store the primitive attribute information.
          * @param babylonMesh - Babylon mesh to get the primitive attribute data from.
          * @param byteOffset - The offset in bytes of the buffer data.
-         * @param useRightHandedSystem - Indicates whether the data should be modified for a right or left handed coordinate system.
          * @param dataBuffer - Buffer to write the attribute data to.
          * @returns - bytelength of the primitive attributes plus the passed in byteOffset.
          */
-        private setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
+        private setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
         /**
          * Creates a glTF scene based on the array of meshes.
          * Returns the the total byte offset.
          * @param babylonScene - Babylon scene to get the mesh data from.
          * @param byteOffset - Offset to start from in bytes.
-         * @param dataBuffer - Buffer to write geometry data to.
          * @returns bytelength + byteoffset
          */
-        private createScene(babylonScene, byteOffset, dataBuffer);
+        private createScene(babylonScene, byteOffset);
+        /**
+         * Creates a mapping of Node unique id to node index
+         * @param scene - Babylon Scene.
+         * @param byteOffset - The initial byte offset.
+         * @returns - Node mapping of unique id to index.
+         */
+        private createNodeMap(scene, byteOffset);
+        /**
+         * Creates a glTF node from a Babylon mesh.
+         * @param babylonMesh - Source Babylon mesh.
+         * @param byteOffset - The initial byte offset.
+         * @param dataBuffer - Buffer for storing geometry data.
+         * @returns - Object containing an INode and byteoffset.
+         */
+        private createNode(babylonMesh, byteOffset, dataBuffer);
     }
 }
 

+ 3 - 0
dist/preview release/serializers/package.json

@@ -26,6 +26,9 @@
         "serializers"
     ],
     "license": "Apache-2.0",
+    "dependencies": {
+        "babylonjs-gltf2interface": "^3.2.0-alpha8"
+    },
     "peerDependencies": {
         "babylonjs": ">=3.2.0-alpha"
     },

+ 2 - 93
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 7253,
+  "errors": 7238,
   "babylon.typedoc.json": {
-    "errors": 7253,
+    "errors": 7238,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {
@@ -8873,61 +8873,6 @@
         }
       }
     },
-    "DepthRenderer": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Constructor": {
-        "new DepthRenderer": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "scene": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "type": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      },
-      "Method": {
-        "dispose": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "getDepthMap": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "isReady": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "subMesh": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "useInstances": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      }
-    },
     "DisplayPassPostProcess": {
       "Class": {
         "Comments": {
@@ -27690,11 +27635,6 @@
             "MissingText": true
           }
         },
-        "disableDepthRenderer": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "disableGeometryBufferRenderer": {
           "Comments": {
             "MissingText": true
@@ -27715,11 +27655,6 @@
             "MissingText": true
           }
         },
-        "enableDepthRenderer": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "enableGeometryBufferRenderer": {
           "Comments": {
             "MissingText": true
@@ -28271,11 +28206,6 @@
             "MissingText": true
           }
         },
-        "getWorldExtends": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "incrementRenderId": {
           "Comments": {
             "MissingText": true
@@ -28609,37 +28539,16 @@
         "simulatePointerDown": {
           "Comments": {
             "MissingReturn": true
-          },
-          "Parameter": {
-            "pickResult": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
           }
         },
         "simulatePointerMove": {
           "Comments": {
             "MissingReturn": true
-          },
-          "Parameter": {
-            "pickResult": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
           }
         },
         "simulatePointerUp": {
           "Comments": {
             "MissingReturn": true
-          },
-          "Parameter": {
-            "pickResult": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
           }
         },
         "sortLightsByPriority": {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 67 - 67
dist/preview release/viewer/babylon.viewer.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 740 - 420
dist/preview release/viewer/babylon.viewer.max.js


+ 0 - 3
dist/preview release/viewer/package.json

@@ -27,9 +27,6 @@
         "viewer"
     ],
     "license": "Apache-2.0",
-    "peerDependencies": {
-        "babylonjs": ">=3.2.0-alpha"
-    },
     "engines": {
         "node": "*"
     }

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

@@ -13,6 +13,8 @@
 - Introduced support for [local cubemaps](http://doc.babylonjs.com/how_to/reflect#using-local-cubemap-mode) ([deltakosh](https://github.com/deltakosh))
 - Added [VideoDome](http://doc.babylonjs.com/how_to/360videodome) class to easily support 360 videos ([DavidHGillen](https://github.com/DavidHGillen))
 - Added [GlowLayer](https://doc.babylonjs.com/how_to/glow_layer) to easily support glow from emissive materials ([sebavan](https://github.com/sebavan))
+- New [AssetContainer](http://doc.babylonjs.com/how_to/how_to_use_assetcontainer) Class and loading methods ([trevordev](https://github.com/trevordev))
+- Added depth of field effect to the default pipeline ([trevordev](https://github.com/trevordev))
 
 ## Updates
 
@@ -41,7 +43,6 @@
    ([carloslanderas](https://github.com/carloslanderas))
 - (Viewer) initScene and initEngine can now be extended. onProgress during model loading is implemented as observable. ([RaananW](https://github.com/RaananW))
 - glTF loader now supports the KHR_lights extension ([MiiBond](https://github.com/MiiBond))
-- Added depth of field effect to the default pipeline ([trevordev](https://github.com/trevordev))
 - The observable can now notify observers using promise-based callback chain. ([RaananW](https://github.com/RaananW))
 - Added base64 helper functions to `Tools` ([bghgary](https://github.com/bghgary))
 - Added `createDefaultCamera` and `createDefaultLight` functions to `Scene` ([bghgary](https://github.com/bghgary))
@@ -49,10 +50,9 @@
 - (Viewer) Scene Optimizer intergrated in viewer. ([RaananW](https://github.com/RaananW))
 - (Viewer) The viewer supports custom shaders in the configuration. ([RaananW](https://github.com/RaananW))
 - Documented PostProcessRenderEffect, DefaultRenderingPipeline, BlurPostProcess, DepthOfFieldEffect, PostProcess, PostProcessManager, Effect classes ([trevordev](https://github.com/trevordev))
-- SPS internal storage of each solid particle rotation matrix ([jbousquie](https://github.com/jbousquie)) 
+- SPS internal storage of each solid particle rotation matrix ([jbousquie](https://github.com/jbousquie))
 - SPS particle parenting feature ([jbousquie](https://github.com/jbousquie))
 - (Viewer) Introducing the viewer labs - testing new features. ([RaananW](https://github.com/RaananW))
-- AssetContainer Class and loading methods ([trevordev](https://github.com/trevordev))
 - KeepAssets class and AssetContainer.moveAllFromScene ([HoloLite](http://www.html5gamedevs.com/profile/28694-hololite/) [trevordev](https://github.com/trevordev))
 - (Viewer) It is now possible to update parts of the configuration without rcreating the objects. Extra configuration can be loaded sync (if provided) ([RaananW](https://github.com/RaananW))
 - (Gulp) extra/external declarations can be prepended to final declarations during build. ([RaananW](https://github.com/RaananW))
@@ -73,7 +73,12 @@
 - Support for mutli-touch when interacting with multiple gui elements simultaneously ([trevordev](https://github.com/trevordev))
 - (Viewer) Declaration file published, ready for npm. ([RaananW](https://github.com/RaananW))
 - Added Draco mesh compression support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
+- Support multiple simultaneous webVR controller gui interactions in WebVRExperienceHelper ([trevordev](https://github.com/trevordev))
 - (Viewer) XHR requests not use Tools.LoadFile and are disposed correctly - [#3671](https://github.com/BabylonJS/Babylon.js/issues/3671) ([RaananW](https://github.com/RaananW))
+- Added `Tools.WorkerPool` class for web worker management. ([bghgary](https://github.com/bghgary))
+- Support depth maps for multiple active cameras for post processes like depth of field ([trevordev](https://github.com/trevordev))
+- Integrates depth texture support in the engine ([sebavan](https://github.com/sebavan))
+- NPM package now has a dependency system, updated during build ([RaananW](https://github.com/RaananW))
 
 ## Bug fixes
 
@@ -84,9 +89,11 @@
 - Fixed a bug when calling load on an empty assets manager - [#3739](https://github.com/BabylonJS/Babylon.js/issues/3739). ([RaananW](https://github.com/RaananW))
 - Enabling teleportation in the vr helper class caused a redundant post process to be added ([trevordev](https://github.com/trevordev))
 - (Viewer) Fixed a bug where loading another mesh positioned it incorrectly ([RaananW](https://github.com/RaananW))
+- (Viewer) Disabling templates now work correctly ([RaananW](https://github.com/RaananW))
 
 ## Breaking changes
 
 - Removed the unused PostProcessRenderPass class and extended postProcessingRenderingEffect to support multiple PostProcesses ([trevordev](https://github.com/trevordev))
 - VertexData.merge no longer supports merging of data that do not have the same set of attributes. ([bghgary](https://github.com/bghgary)]
 - glTF 2.0 loader will now create a mesh for each primitive instead of merging the primitives together into one mesh. ([bghgary](https://github.com/bghgary)]
+- Engine's onCanvasPointerOutObservable will now return a PointerEvent instead of the Engine. ([trevordev](https://github.com/trevordev))

+ 19 - 19
gui/src/advancedDynamicTexture.ts

@@ -14,12 +14,12 @@ module BABYLON.GUI {
         private _preKeyboardObserver: Nullable<Observer<KeyboardInfoPre>>;
         private _pointerMoveObserver: Nullable<Observer<PointerInfoPre>>;
         private _pointerObserver: Nullable<Observer<PointerInfo>>;
-        private _canvasPointerOutObserver: Nullable<Observer<Engine>>;
+        private _canvasPointerOutObserver: Nullable<Observer<PointerEvent>>;
         private _background: string;
         public _rootContainer = new Container("root");
         public _lastPickedControl: Control;
-        public _lastControlOver: Nullable<Control>;
-        public _lastControlDown: Nullable<Control>;
+        public _lastControlOver: {[pointerId:number]:Control} = {};
+        public _lastControlDown: {[pointerId:number]:Control} = {};
         public _capturingControl: {[pointerId:number]:Control} = {};
         public _shouldBlockPointer: boolean;
         public _layerToDispose: Nullable<Layer>;
@@ -393,11 +393,11 @@ module BABYLON.GUI {
             if (!this._rootContainer._processPicking(x, y, type, pointerId, buttonIndex)) {
 
                 if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
-                    if (this._lastControlOver) {
-                        this._lastControlOver._onPointerOut(this._lastControlOver);
+                    if (this._lastControlOver[pointerId]) {
+                        this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
                     }
 
-                    this._lastControlOver = null;
+                    delete this._lastControlOver[pointerId];
                 }
             }
 
@@ -461,17 +461,17 @@ module BABYLON.GUI {
                         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(pointerId);
+                    if (this._lastControlDown[pointerId]) {
+                        this._lastControlDown[pointerId].forcePointerUp(pointerId);
                     }
-                    this._lastControlDown = null;
+                    delete this._lastControlDown[pointerId];
 
                     this.focusedControl = null;
                 } else if (pi.type === BABYLON.PointerEventTypes.POINTERMOVE) {
-                    if (this._lastControlOver) {
-                        this._lastControlOver._onPointerOut(this._lastControlOver);
+                    if (this._lastControlOver[pointerId]) {
+                        this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
                     }
-                    this._lastControlOver = null;
+                    delete this._lastControlOver[pointerId];
                 }
             });
 
@@ -505,16 +505,16 @@ module BABYLON.GUI {
         }
 
         private _attachToOnPointerOut(scene: Scene): void {
-            this._canvasPointerOutObserver = scene.getEngine().onCanvasPointerOutObservable.add(() => {
-                if (this._lastControlOver) {
-                    this._lastControlOver._onPointerOut(this._lastControlOver);
+            this._canvasPointerOutObserver = scene.getEngine().onCanvasPointerOutObservable.add((pointerEvent) => {
+                if (this._lastControlOver[pointerEvent.pointerId]) {
+                    this._lastControlOver[pointerEvent.pointerId]._onPointerOut(this._lastControlOver[pointerEvent.pointerId]);
                 }
-                this._lastControlOver = null;
+                delete this._lastControlOver[pointerEvent.pointerId];
 
-                if (this._lastControlDown) {
-                    this._lastControlDown.forcePointerUp();
+                if (this._lastControlDown[pointerEvent.pointerId]) {
+                    this._lastControlDown[pointerEvent.pointerId].forcePointerUp();
                 }
-                this._lastControlDown = null;
+                delete this._lastControlDown[pointerEvent.pointerId];
             });
         }
 

+ 6 - 6
gui/src/controls/control.ts

@@ -943,7 +943,7 @@ module BABYLON.GUI {
             if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
                 this._onPointerMove(this, this._dummyVector2);
 
-                var previousControlOver = this._host._lastControlOver;
+                var previousControlOver = this._host._lastControlOver[pointerId];
                 if (previousControlOver && previousControlOver !== this) {
                     previousControlOver._onPointerOut(this);
                 }
@@ -952,22 +952,22 @@ module BABYLON.GUI {
                     this._onPointerEnter(this);
                 }
 
-                this._host._lastControlOver = this;
+                this._host._lastControlOver[pointerId] = this;
                 return true;
             }
 
             if (type === BABYLON.PointerEventTypes.POINTERDOWN) {
                 this._onPointerDown(this, this._dummyVector2, pointerId, buttonIndex);
-                this._host._lastControlDown = this;
+                this._host._lastControlDown[pointerId] = this;
                 this._host._lastPickedControl = this;
                 return true;
             }
 
             if (type === BABYLON.PointerEventTypes.POINTERUP) {
-                if (this._host._lastControlDown) {
-                    this._host._lastControlDown._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex);
+                if (this._host._lastControlDown[pointerId]) {
+                    this._host._lastControlDown[pointerId]._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex);
                 }
-                this._host._lastControlDown = null;
+                delete this._host._lastControlDown[pointerId];
                 return true;
             }
 

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

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

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

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

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

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

+ 3 - 3
localDev/index.html

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

+ 1 - 1
sandbox/index-local.html

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

+ 1 - 1
sandbox/index.html

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

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 353 - 412
serializers/src/glTF/2.0/babylon.glTFExporter.ts


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 383 - 297
src/Cameras/VR/babylon.vrExperienceHelper.ts


+ 242 - 5
src/Engine/babylon.engine.ts

@@ -217,6 +217,18 @@
     }
 
     /**
+     * Define options used to create a depth texture
+     */
+    export class DepthTextureCreationOptions {
+        /** Specifies wether or not a stencil should be allocated in the texture */
+        generateStencil?: boolean;
+        /** Specifies wether or not bilinear filtering is enable on the texture */
+        bilinearFiltering?: boolean;
+        /** Specifies the comparison function to set on the texture. If 0 or undefined, the texture is not in comparison mode */
+        comparisonFunction?: number;
+    }
+
+    /**
      * Regroup several parameters relative to the browser in use
      */
     export class EngineCapabilities {
@@ -613,7 +625,7 @@
         /**
          * Observable event triggered each time the canvas receives pointerout event
          */
-        public onCanvasPointerOutObservable = new Observable<Engine>();
+        public onCanvasPointerOutObservable = new Observable<PointerEvent>();
 
         /**
          * Observable event triggered before each texture is initialized
@@ -694,7 +706,7 @@
         // Focus
         private _onFocus: () => void;
         private _onBlur: () => void;
-        private _onCanvasPointerOut: () => void;
+        private _onCanvasPointerOut: (event: PointerEvent) => void;
         private _onCanvasBlur: () => void;
         private _onCanvasFocus: () => void;
 
@@ -996,8 +1008,8 @@
                     this._windowIsBackground = false;
                 };
 
-                this._onCanvasPointerOut = () => {
-                    this.onCanvasPointerOutObservable.notifyObservers(this);
+                this._onCanvasPointerOut = (ev) => {
+                    this.onCanvasPointerOutObservable.notifyObservers(ev);
                 };
 
                 window.addEventListener("blur", this._onBlur);
@@ -1290,6 +1302,7 @@
 
                 if (depthTextureExtension != null) {
                     this._caps.depthTextureExtension = true;
+                    this._gl.UNSIGNED_INT_24_8 = depthTextureExtension.UNSIGNED_INT_24_8_WEBGL;
                 }
             }
 
@@ -1927,7 +1940,16 @@
             });
         }
 
-        public bindFramebuffer(texture: InternalTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number, forceFullscreenViewport?: boolean): void {
+        /**
+         * Binds the frame buffer to the specified texture.
+         * @param texture The texture to render to or null for the default canvas
+         * @param faceIndex The face of the texture to render to in case of cube texture
+         * @param requiredWidth The width of the target to render to
+         * @param requiredHeight The height of the target to render to
+         * @param forceFullscreenViewport Forces the viewport to be the entire texture/screen if true
+         * @param depthStencilTexture The depth stencil texture to use to render
+         */
+        public bindFramebuffer(texture: InternalTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number, forceFullscreenViewport?: boolean, depthStencilTexture?: InternalTexture): void {
             if (this._currentRenderTarget) {
                 this.unBindFramebuffer(this._currentRenderTarget);
             }
@@ -1939,6 +1961,15 @@
                     faceIndex = 0;
                 }
                 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture._webGLTexture, 0);
+
+                if (depthStencilTexture) {
+                    if (depthStencilTexture._generateStencilBuffer) {
+                        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, depthStencilTexture, 0);
+                    }
+                    else {
+                        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, depthStencilTexture, 0);
+                    }
+                }
             }
 
             if (this._cachedViewport && !forceFullscreenViewport) {
@@ -3637,6 +3668,212 @@
             }
         }
 
+        /**
+         * Updates a depth texture Comparison Mode and Function.
+         * If the comparison Function is equal to 0, the mode will be set to none.
+         * Otherwise, this only works in webgl 2 and requires a shadow sampler in the shader.
+         * @param texture The texture to set the comparison function for
+         * @param comparisonFunction The comparison function to set, 0 if no comparison required
+         */
+        public updateTextureComparisonFunction(texture: InternalTexture, comparisonFunction: number): void {
+            if (this.webGLVersion === 1) {
+                Tools.Error("WebGL 1 does not support texture comparison.");
+                return;
+            }
+
+            var gl = this._gl;
+
+            if (texture.isCube) {
+                this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, texture, true);
+
+                if (comparisonFunction === 0) {
+                    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, Engine.LEQUAL);
+                    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.NONE);
+                }
+                else {
+                    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, comparisonFunction);
+                    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+                }
+
+                this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
+            } else {
+                this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
+
+                if (comparisonFunction === 0) {
+                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, Engine.LEQUAL);
+                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.NONE);
+                }
+                else {
+                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, comparisonFunction);
+                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+                }
+
+                this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+            }
+
+            texture._comparisonFunction = comparisonFunction;
+        }
+
+        private _setupDepthStencilTexture(internalTexture: InternalTexture, size: number | { width: number, height: number }, generateStencil: boolean, bilinearFiltering: boolean, comparisonFunction: number) : void {
+            var width = (<{ width: number, height: number }>size).width || <number>size;
+            var height = (<{ width: number, height: number }>size).height || <number>size;
+            internalTexture.baseWidth = width;
+            internalTexture.baseHeight = height;
+            internalTexture.width = width;
+            internalTexture.height = height;
+            internalTexture.isReady = true;
+            internalTexture.samples = 1;
+            internalTexture.generateMipMaps = false;
+            internalTexture._generateDepthBuffer = true;
+            internalTexture._generateStencilBuffer = generateStencil;
+            internalTexture.samplingMode = bilinearFiltering ? Texture.NEAREST_SAMPLINGMODE : Texture.BILINEAR_SAMPLINGMODE;
+            internalTexture.type = Engine.TEXTURETYPE_UNSIGNED_INT;
+            internalTexture._comparisonFunction = comparisonFunction;
+
+            var gl = this._gl;
+            var target = internalTexture.isCube ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
+            var samplingParameters = getSamplingParameters(internalTexture.samplingMode, false, gl);
+            gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, samplingParameters.mag);
+            gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, samplingParameters.min);
+            gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+            gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+
+            if (comparisonFunction === 0) {
+                gl.texParameteri(target, gl.TEXTURE_COMPARE_FUNC, Engine.LEQUAL);
+                gl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, gl.NONE);
+            }
+            else {
+                gl.texParameteri(target, gl.TEXTURE_COMPARE_FUNC, comparisonFunction);
+                gl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+            }
+        }
+
+        /**
+         * Creates a depth stencil texture.
+         * This is only available in WebGL 2 or with the depth texture extension available.
+         * @param size The size of face edge in the texture.
+         * @param options The options defining the texture.
+         * @returns The texture
+         */
+        public createDepthStencilTexture(size: number | { width: number, height: number }, options: DepthTextureCreationOptions) : InternalTexture {
+            var internalTexture = new InternalTexture(this, InternalTexture.DATASOURCE_DEPTHTEXTURE);
+
+            if (!this._caps.depthTextureExtension) {
+                Tools.Error("Depth texture is not supported by your browser or hardware.");
+                return internalTexture;
+            }
+
+            var internalOptions = {
+                bilinearFiltering: false,
+                comparisonFunction: 0,
+                generateStencil: false,
+                ...options
+            }
+
+            var gl = this._gl;
+            this._bindTextureDirectly(gl.TEXTURE_2D, internalTexture, true);
+
+            this._setupDepthStencilTexture(internalTexture, size, internalOptions.generateStencil, internalOptions.bilinearFiltering, internalOptions.comparisonFunction);
+
+            if (this.webGLVersion > 1) {
+                if (internalOptions.generateStencil) {
+                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH24_STENCIL8, internalTexture.width, internalTexture.height, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null);
+                }
+                else {
+                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT24, internalTexture.width, internalTexture.height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
+                }
+            }
+            else {
+                if (internalOptions.generateStencil) {
+                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_STENCIL, internalTexture.width, internalTexture.height, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null);
+                }
+                else {
+                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, internalTexture.width, internalTexture.height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
+                }
+            }
+
+            this._bindTextureDirectly(gl.TEXTURE_2D, null);
+
+            return internalTexture;
+        }
+
+        /**
+         * Creates a depth stencil cube texture.
+         * This is only available in WebGL 2.
+         * @param size The size of face edge in the cube texture.
+         * @param options The options defining the cube texture.
+         * @returns The cube texture
+         */
+        public createDepthStencilCubeTexture(size: number, options: DepthTextureCreationOptions) : InternalTexture {
+            var internalTexture = new InternalTexture(this, InternalTexture.DATASOURCE_UNKNOWN);
+            internalTexture.isCube = true;
+
+            if (this.webGLVersion === 1) {
+                Tools.Error("Depth cube texture is not supported by WebGL 1.");
+                return internalTexture;
+            }
+
+            var internalOptions = {
+                bilinearFiltering: false,
+                comparisonFunction: 0,
+                generateStencil: false,
+                ...options
+            }
+
+            var gl = this._gl;
+            this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, internalTexture, true);
+
+            this._setupDepthStencilTexture(internalTexture, size, internalOptions.generateStencil, internalOptions.bilinearFiltering, internalOptions.comparisonFunction);
+
+            // Create the depth/stencil buffer
+            for (var face = 0; face < 6; face++) {
+                if (internalOptions.generateStencil) {
+                    gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, gl.DEPTH24_STENCIL8, size, size, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null);
+                }
+                else {
+                    gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, gl.DEPTH_COMPONENT24, size, size, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
+                }
+            }
+
+            this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
+
+            return internalTexture;
+        }
+
+        /**
+         * Sets the frame buffer Depth / Stencil attachement of the render target to the defined depth stencil texture.
+         * @param renderTarget The render target to set the frame buffer for
+         */
+        public setFrameBufferDepthStencilTexture(renderTarget: RenderTargetTexture): void {
+            // Create the framebuffer
+            var internalTexture = renderTarget.getInternalTexture();
+            if (!internalTexture || !internalTexture._framebuffer || !renderTarget.depthStencilTexture) {
+                return;
+            }
+
+            var gl = this._gl;
+            var depthStencilTexture = renderTarget.depthStencilTexture;
+
+            this.bindUnboundFramebuffer(internalTexture._framebuffer);
+            if (depthStencilTexture.isCube) {
+                if (depthStencilTexture._generateStencilBuffer) {
+                    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_CUBE_MAP_POSITIVE_X, depthStencilTexture, 0);
+                }
+                else {
+                    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_CUBE_MAP_POSITIVE_X, depthStencilTexture, 0);
+                }
+            }
+            else {
+                if (depthStencilTexture._generateStencilBuffer) {
+                    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, depthStencilTexture, 0);
+                }
+                else {
+                    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthStencilTexture, 0);
+                }
+            }
+            this.bindUnboundFramebuffer(null);
+        }
+
         public createRenderTargetTexture(size: number | { width: number, height: number }, options: boolean | RenderTargetCreationOptions): InternalTexture {
             let fullOptions = new RenderTargetCreationOptions();
 

+ 4 - 0
src/Engine/babylon.webgl2.ts

@@ -5,8 +5,12 @@
 
 interface WebGLRenderingContext {
     readonly RASTERIZER_DISCARD: number;
+    readonly DEPTH_COMPONENT24: number;
     readonly TEXTURE_3D: number;
     readonly TEXTURE_2D_ARRAY: number;
+    readonly TEXTURE_COMPARE_FUNC: number;
+    readonly TEXTURE_COMPARE_MODE: number;
+    readonly COMPARE_REF_TO_TEXTURE: number;
     readonly TEXTURE_WRAP_R: number;
 
     texImage3D(target: number, level: number, internalformat: number, width: number, height: number, depth: number, border: number, format: number, type: number, pixels: ArrayBufferView | null): void;

+ 15 - 1
src/Materials/Background/babylon.backgroundMaterial.ts

@@ -64,7 +64,14 @@
          */
         public NOISE = false;
 
-        // Image Processing Configuration.
+
+
+        /**
+         * is the reflection texture in BGR color scheme? 
+         * Mainly used to solve a bug in ios10 video tag
+         */
+        public REFLECTIONBGR = false;
+
         public IMAGEPROCESSING = false;
         public VIGNETTE = false;
         public VIGNETTEBLENDMODEMULTIPLY = false;
@@ -521,6 +528,12 @@
             (<ImageProcessingConfiguration>this.imageProcessingConfiguration).colorCurves = value;
         }
 
+        /**
+         * Due to a bug in iOS10, video tags (which are using the background material) are in BGR and not RGB.
+         * Setting this flag to true (not done automatically!) will convert it back to RGB.
+         */
+        public switchToBGR: boolean = false;
+
         // Temp values kept as cache in the material.
         private _renderTargets = new SmartArray<RenderTargetTexture>(16);
         private _reflectionControls = Vector4.Zero();
@@ -635,6 +648,7 @@
                         defines.REFLECTIONMAP_OPPOSITEZ = this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ;
                         defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha;
                         defines.EQUIRECTANGULAR_RELFECTION_FOV = this.useEquirectangularFOV;
+                        defines.REFLECTIONBGR = this.switchToBGR;
 
                         if (reflectionTexture.coordinatesMode === Texture.INVCUBIC_MODE) {
                             defines.INVERTCUBICMAP = true;

+ 9 - 1
src/Materials/Textures/babylon.cubeTexture.ts

@@ -144,11 +144,19 @@
         public setReflectionTextureMatrix(value: Matrix): void {
             this._textureMatrix = value;
         }
-
+        
         public static Parse(parsedTexture: any, scene: Scene, rootUrl: string): CubeTexture {
             var texture = SerializationHelper.Parse(() => {
                 return new CubeTexture(rootUrl + parsedTexture.name, scene, parsedTexture.extensions);
             }, parsedTexture, scene);
+            
+            // Local Cubemaps
+            if (parsedTexture.boundingBoxPosition) {
+                texture.boundingBoxPosition = BABYLON.Vector3.FromArray(parsedTexture.boundingBoxPosition);
+            }
+            if (parsedTexture.boundingBoxSize) {
+                texture.boundingBoxSize = BABYLON.Vector3.FromArray(parsedTexture.boundingBoxSize);
+            }
 
             // Animations
             if (parsedTexture.animations) {

+ 36 - 0
src/Materials/Textures/babylon.hdrCubeTexture.ts

@@ -58,6 +58,34 @@ module BABYLON {
         }
 
         /**
+         * Gets or sets the center of the bounding box associated with the cube texture
+         * It must define where the camera used to render the texture was set
+         */
+        public boundingBoxPosition = Vector3.Zero();
+
+        private _boundingBoxSize: Vector3;
+
+        /**
+         * Gets or sets the size of the bounding box associated with the cube texture
+         * When defined, the cubemap will switch to local mode
+         * @see https://community.arm.com/graphics/b/blog/posts/reflections-based-on-local-cubemaps-in-unity
+         * @example https://www.babylonjs-playground.com/#RNASML
+         */
+        public set boundingBoxSize(value: Vector3) {
+            if (this._boundingBoxSize && this._boundingBoxSize.equals(value)) {
+                return;
+            }
+            this._boundingBoxSize = value;
+            let scene = this.getScene();
+            if (scene) {
+                scene.markAllMaterialsAsDirty(Material.TextureDirtyFlag);
+            }
+        }
+        public get boundingBoxSize(): Vector3 {
+            return this._boundingBoxSize;
+        }
+        
+        /**
          * Instantiates an HDRTexture from the following parameters.
          * 
          * @param url The location of the HDR raw data (Panorama stored in RGBE format)
@@ -442,6 +470,14 @@ module BABYLON {
                 texture.coordinatesMode = parsedTexture.coordinatesMode;
                 texture.isBlocking = parsedTexture.isBlocking;
             }
+            if (texture) {
+                if (parsedTexture.boundingBoxPosition) {
+                    (<any>texture).boundingBoxPosition = BABYLON.Vector3.FromArray(parsedTexture.boundingBoxPosition);
+                }
+                if (parsedTexture.boundingBoxSize) {
+                    (<any>texture).boundingBoxSize = BABYLON.Vector3.FromArray(parsedTexture.boundingBoxSize);
+                }
+            }
             return texture;
         }
 

+ 22 - 0
src/Materials/Textures/babylon.internalTexture.ts

@@ -49,6 +49,10 @@ module BABYLON {
          * Texture content is raw 3D data
          */
         public static DATASOURCE_RAW3D = 10;
+        /**
+         * Texture content is a depth texture
+         */
+        public static DATASOURCE_DEPTHTEXTURE = 11;
 
         /**
          * Defines if the texture is ready
@@ -180,6 +184,8 @@ module BABYLON {
         /** @ignore */
         public _generateDepthBuffer: boolean;
         /** @ignore */
+        public _comparisonFunction: number = 0;
+        /** @ignore */
         public _sphericalPolynomial: Nullable<SphericalPolynomial>;
         /** @ignore */
         public _lodGenerationScale: number;
@@ -311,6 +317,22 @@ module BABYLON {
 
                     this.isReady = true;
                     return;
+                case InternalTexture.DATASOURCE_DEPTHTEXTURE:
+                    let depthTextureOptions = {
+                        bilinearFiltering: this.samplingMode !== Texture.BILINEAR_SAMPLINGMODE,
+                        comparisonFunction: this._comparisonFunction,
+                        generateStencil: this._generateStencilBuffer,
+                    };
+
+                    if (this.isCube) {
+                        proxy = this._engine.createDepthStencilTexture({ width: this.width, height: this.height }, depthTextureOptions);
+                    } else {
+                        proxy = this._engine.createDepthStencilCubeTexture(this.width, depthTextureOptions);
+                    }
+                    proxy._swapAndDie(this);
+
+                    this.isReady = true;
+                    return;
 
                 case InternalTexture.DATASOURCE_CUBE:
                     proxy = this._engine.createCubeTexture(this.url, null, this._files, !this.generateMipMaps, () => {

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

@@ -156,6 +156,28 @@
             return this._boundingBoxSize;
         }
 
+        /**
+         * In case the RTT has been created with a depth texture, get the associated 
+         * depth texture.
+         * Otherwise, return null.
+         */
+        public depthStencilTexture: Nullable<InternalTexture>;
+
+        /**
+         * Instantiate a render target texture. This is mainly to render of screen the scene to for instance apply post processse
+         * or used a shadow, depth texture...
+         * @param name The friendly name of the texture
+         * @param size The size of the RTT (number if square, or {with: number, height:number} or {ratio:} to define a ratio from the main scene)
+         * @param scene The scene the RTT belongs to. The latest created scene will be used if not precised.
+         * @param generateMipMaps True if mip maps need to be generated after render.
+         * @param doNotChangeAspectRatio True to not change the aspect ratio of the scene in the RTT
+         * @param type The type of the buffer in the RTT (int, half float, float...)
+         * @param isCube True if a cube texture needs to be created
+         * @param samplingMode The sampling mode to be usedwith the render target (Linear, Nearest...)
+         * @param generateDepthBuffer True to generate a depth buffer
+         * @param generateStencilBuffer True to generate a stencil buffer
+         * @param isMulti True if multiple textures need to be created (Draw Buffers)
+         */
         constructor(name: string, size: number | {width: number, height: number} | {ratio: number}, scene: Nullable<Scene>, generateMipMaps?: boolean, doNotChangeAspectRatio: boolean = true, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, public isCube = false, samplingMode = Texture.TRILINEAR_SAMPLINGMODE, generateDepthBuffer = true, generateStencilBuffer = false, isMulti = false) {
             super(null, scene, !generateMipMaps);
             scene = this.getScene();
@@ -551,7 +573,7 @@
             }
             else if (!useCameraPostProcess || !scene.postProcessManager._prepareFrame(this._texture)) {
                 if (this._texture) {
-                    engine.bindFramebuffer(this._texture, this.isCube ? faceIndex : undefined, undefined, undefined, this.ignoreCameraViewport);
+                    engine.bindFramebuffer(this._texture, this.isCube ? faceIndex : undefined, undefined, undefined, this.ignoreCameraViewport, this.depthStencilTexture ? this.depthStencilTexture : undefined);
                 }
             }
 

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

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

+ 7 - 0
src/Particles/babylon.particleSystem.ts

@@ -333,6 +333,13 @@
         private _isAnimationSheetEnabled: boolean;
 
         /**
+         * Gets the current list of active particles
+         */
+        public get particles(): Particle[] {
+            return this._particles;
+        }
+
+        /**
          * Returns the string "ParticleSystem"
          * @returns a string containing the class name
          */

+ 4 - 1
src/PostProcess/RenderPipeline/Pipelines/babylon.defaultRenderingPipeline.ts

@@ -286,7 +286,10 @@
             this._reset();
 
             if(this.depthOfFieldEnabled){
-                this.depthOfField = new DepthOfFieldEffect(this._scene, this._depthOfFieldBlurLevel, this._defaultPipelineTextureType);
+                // Enable and get current depth map
+                var depthTexture = this._scene.enableDepthRenderer(this._cameras[0]).getDepthMap();
+
+                this.depthOfField = new DepthOfFieldEffect(this._scene, depthTexture, this._depthOfFieldBlurLevel, this._defaultPipelineTextureType);
                 this.addEffect(this.depthOfField);
             }
 

+ 2 - 6
src/PostProcess/babylon.circleOfConfusionPostProcess.ts

@@ -23,7 +23,6 @@ module BABYLON {
         /**
          * Creates a new instance of @see CircleOfConfusionPostProcess
          * @param name The name of the effect.
-         * @param scene The scene the effect belongs to.
          * @param depthTexture The depth texture of the scene to compute the circle of confusion.
          * @param options The required width/height ratio to downsize to before computing the render pass.
          * @param camera The camera to apply the render pass to.
@@ -32,7 +31,7 @@ module BABYLON {
          * @param reusable If the post process can be reused on the same frame. (default: false)
          * @param textureType Type of textures used when performing the post process. (default: 0)
          */
-        constructor(name: string, scene: Scene, depthTexture: RenderTargetTexture, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT) {
+        constructor(name: string, depthTexture: RenderTargetTexture, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Engine.TEXTURETYPE_UNSIGNED_INT) {
             super(name, "circleOfConfusion", ["cameraMinMaxZ", "focusDistance", "cocPrecalculation"], ["depthSampler"], options, camera, samplingMode, engine, reusable, null, textureType);
             this.onApplyObservable.add((effect: Effect) => {
                 effect.setTexture("depthSampler", depthTexture);
@@ -43,10 +42,7 @@ module BABYLON {
                 
                 effect.setFloat('focusDistance', this.focusDistance);
                 effect.setFloat('cocPrecalculation', cocPrecalculation);
-                
-                if(scene.activeCamera){
-                    effect.setFloat2('cameraMinMaxZ', scene.activeCamera.minZ, scene.activeCamera.maxZ);
-                }
+                effect.setFloat2('cameraMinMaxZ', depthTexture.activeCamera!.minZ, depthTexture.activeCamera!.maxZ);
             })
         }
     }

+ 3 - 4
src/PostProcess/babylon.depthOfFieldEffect.ts

@@ -66,14 +66,13 @@ module BABYLON {
         /**
          * Creates a new instance of @see DepthOfFieldEffect
          * @param scene The scene the effect belongs to.
+         * @param depthTexture The depth texture of the scene to compute the circle of confusion.
          * @param pipelineTextureType The type of texture to be used when performing the post processing.
          */
-        constructor(scene: Scene, blurLevel: DepthOfFieldEffectBlurLevel = DepthOfFieldEffectBlurLevel.Low, pipelineTextureType = 0) {
+        constructor(scene: Scene, depthTexture: RenderTargetTexture, blurLevel: DepthOfFieldEffectBlurLevel = DepthOfFieldEffectBlurLevel.Low, pipelineTextureType = 0) {
             super(scene.getEngine(), "depth of field", ()=>{
-                // Enable and get current depth map
-                var depthMap = scene.enableDepthRenderer().getDepthMap();
                 // Circle of confusion value for each pixel is used to determine how much to blur that pixel
-                this._circleOfConfusion = new BABYLON.CircleOfConfusionPostProcess("circleOfConfusion", scene, depthMap, 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType);
+                this._circleOfConfusion = new BABYLON.CircleOfConfusionPostProcess("circleOfConfusion", depthTexture, 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType);
                 // Capture circle of confusion texture
                 this._depthOfFieldPass = new PassPostProcess("depthOfFieldPass", 1.0, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, pipelineTextureType);
                 this._depthOfFieldPass.autoClear = false;

+ 36 - 6
src/Rendering/babylon.depthRenderer.ts

@@ -1,13 +1,25 @@
 module BABYLON {
+    /**
+     * This represents a depth renderer in Babylon.
+     * A depth renderer will render to it's depth map every frame which can be displayed or used in post processing
+     */
     export class DepthRenderer {
         private _scene: Scene;
         private _depthMap: RenderTargetTexture;
         private _effect: Effect;
 
         private _cachedDefines: string;
-
-        constructor(scene: Scene, type: number = Engine.TEXTURETYPE_FLOAT) {
+        private _camera:Nullable<Camera>;
+
+        /**
+         * Instantiates a depth renderer
+         * @param scene The scene the renderer belongs to
+         * @param type The texture type of the depth map (default: Engine.TEXTURETYPE_FLOAT)
+         * @param camera The camera to be used to render the depth map (default: scene's active camera)
+         */
+        constructor(scene: Scene, type: number = Engine.TEXTURETYPE_FLOAT, camera:Nullable<Camera> = null) {
             this._scene = scene;
+            this._camera = camera;
             var engine = scene.getEngine();
 
             // Render target
@@ -17,6 +29,11 @@
             this._depthMap.refreshRate = 1;
             this._depthMap.renderParticles = false;
             this._depthMap.renderList = null;
+
+            // Camera to get depth map from to support multiple concurrent cameras
+            this._depthMap.activeCamera = this._camera;
+            this._depthMap.ignoreCameraViewport = true;
+            this._depthMap.useCameraPostProcesses = false;
             
             // set default depth value to 1.0 (far away)
             this._depthMap.onClearObservable.add((engine: Engine) => {
@@ -45,14 +62,15 @@
                 }
 
                 var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null);
-
-                if (this.isReady(subMesh, hardwareInstancedRendering) && scene.activeCamera) {
+                
+                var camera = this._camera || scene.activeCamera;
+                if (this.isReady(subMesh, hardwareInstancedRendering) && camera) {
                     engine.enableEffect(this._effect);
                     mesh._bind(subMesh, this._effect, Material.TriangleFillMode);
 
                     this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
 
-                    this._effect.setFloat2("depthValues", scene.activeCamera.minZ, scene.activeCamera.minZ + scene.activeCamera.maxZ);
+                    this._effect.setFloat2("depthValues", camera.minZ, camera.minZ + camera.maxZ);
 
                     // Alpha test
                     if (material && material.needAlphaTesting()) {
@@ -96,6 +114,12 @@
             };
         }
 
+        /**
+         * Creates the depth rendering effect and checks if the effect is ready.
+         * @param subMesh The submesh to be used to render the depth map of
+         * @param useInstances If multiple world instances should be used
+         * @returns if the depth renderer is ready to render the depth map
+         */
         public isReady(subMesh: SubMesh, useInstances: boolean): boolean {
             var material: any = subMesh.getMaterial();
             if (material.disableDepthWrite) {
@@ -157,11 +181,17 @@
             return this._effect.isReady();
         }
 
+        /**
+         * Gets the texture which the depth map will be written to.
+         * @returns The depth map texture
+         */
         public getDepthMap(): RenderTargetTexture {
             return this._depthMap;
         }
 
-        // Methods
+        /**
+         * Disposes of the depth renderer.
+         */
         public dispose(): void {
             this._depthMap.dispose();
         }

+ 4 - 0
src/Shaders/background.fragment.fx

@@ -190,6 +190,10 @@ vec3 reflectionColor = vec3(1., 1., 1.);
         reflectionColor = toLinearSpace(reflectionColor.rgb);
     #endif
 
+    #ifdef REFLECTIONBGR
+        reflectionColor = reflectionColor.bgr;
+    #endif
+
     // _____________________________ Levels _____________________________________
     reflectionColor *= vReflectionInfos.x;
 #endif

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

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

+ 1 - 0
src/babylon.mixins.ts

@@ -60,6 +60,7 @@ interface WebGLRenderingContext {
     RED: number;
     RG: number;
 
+    UNSIGNED_INT_24_8: number;
     DEPTH24_STENCIL8: number;
 
     /* Multiple Render Targets */

+ 41 - 24
src/babylon.scene.ts

@@ -934,7 +934,7 @@
 
         private _debugLayer: DebugLayer;
 
-        private _depthRenderer: Nullable<DepthRenderer>;
+        private _depthRenderer: {[id:string]:DepthRenderer} = {};
         private _geometryBufferRenderer: Nullable<GeometryBufferRenderer>;
 
         /**
@@ -1228,10 +1228,11 @@
         /**
          * Use this method to simulate a pointer move on a mesh
          * The pickResult parameter can be obtained from a scene.pick or scene.pickWithRay
+         * @param pickResult pickingInfo of the object wished to simulate pointer event on
+         * @param pointerEventInit pointer event state to be used when simulating the pointer event (eg. pointer id for multitouch)
          */
-        public simulatePointerMove(pickResult: PickingInfo): Scene {
-            let evt = new PointerEvent("pointermove");
-
+        public simulatePointerMove(pickResult: PickingInfo, pointerEventInit?: PointerEventInit): Scene {
+            let evt = new PointerEvent("pointermove", pointerEventInit);
             return this._processPointerMove(pickResult, evt);
         }
 
@@ -1294,9 +1295,11 @@
         /**
          * Use this method to simulate a pointer down on a mesh
          * The pickResult parameter can be obtained from a scene.pick or scene.pickWithRay
+         * @param pickResult pickingInfo of the object wished to simulate pointer event on
+         * @param pointerEventInit pointer event state to be used when simulating the pointer event (eg. pointer id for multitouch)
          */
-        public simulatePointerDown(pickResult: PickingInfo): Scene {
-            let evt = new PointerEvent("pointerdown");
+        public simulatePointerDown(pickResult: PickingInfo, pointerEventInit?: PointerEventInit): Scene {
+            let evt = new PointerEvent("pointerdown", pointerEventInit);
 
             return this._processPointerDown(pickResult, evt);
         }
@@ -1359,9 +1362,11 @@
         /**
          * Use this method to simulate a pointer up on a mesh
          * The pickResult parameter can be obtained from a scene.pick or scene.pickWithRay
+         * @param pickResult pickingInfo of the object wished to simulate pointer event on
+         * @param pointerEventInit pointer event state to be used when simulating the pointer event (eg. pointer id for multitouch)
          */
-        public simulatePointerUp(pickResult: PickingInfo): Scene {
-            let evt = new PointerEvent("pointerup");
+        public simulatePointerUp(pickResult: PickingInfo, pointerEventInit?: PointerEventInit): Scene {
+            let evt = new PointerEvent("pointerup", pointerEventInit);
             let clickInfo = new ClickInfo();
             clickInfo.singleClick = true;
             clickInfo.ignore = true;
@@ -3416,7 +3421,7 @@
                 this._renderTargets.concatWithNoDuplicate(rigParent.customRenderTargets);
             }
 
-            if (this.renderTargetsEnabled && this._renderTargets.length > 0) {
+            if (this.renderTargetsEnabled && this._renderTargets.length > 0) {                
                 this._intermediateRendering = true;
                 Tools.StartPerformanceCounter("Render targets", this._renderTargets.length > 0);
                 for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
@@ -3574,7 +3579,7 @@
             }
 
             this.activeCamera = camera;
-            this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix());
+            this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix());           
         }
 
         private _checkIntersections(): void {
@@ -3782,8 +3787,8 @@
             }
 
             // Depth renderer
-            if (this._depthRenderer) {
-                this._renderTargets.push(this._depthRenderer.getDepthMap());
+            for(var key in this._depthRenderer){
+                this._renderTargets.push(this._depthRenderer[key].getDepthMap());
             }
 
             // Geometry renderer
@@ -3970,23 +3975,35 @@
             }
         }
 
-        public enableDepthRenderer(): DepthRenderer {
-            if (this._depthRenderer) {
-                return this._depthRenderer;
+        /**
+         * Creates a depth renderer a given camera which contains a depth map which can be used for post processing.
+         * @param camera The camera to create the depth renderer on (default: scene's active camera)
+         * @returns the created depth renderer
+         */
+        public enableDepthRenderer(camera?: Nullable<Camera>): DepthRenderer {
+            camera = camera || this.activeCamera;
+            if(!camera){
+                throw "No camera available to enable depth renderer";
             }
+            if (!this._depthRenderer[camera.id]) {
+                this._depthRenderer[camera.id] = new DepthRenderer(this, Engine.TEXTURETYPE_FLOAT, camera);
+            }            
 
-            this._depthRenderer = new DepthRenderer(this);
-
-            return this._depthRenderer;
+            return this._depthRenderer[camera.id];
         }
 
-        public disableDepthRenderer(): void {
-            if (!this._depthRenderer) {
+        /**
+         * Disables a depth renderer for a given camera
+         * @param camera The camera to disable the depth renderer on (default: scene's active camera)
+         */
+        public disableDepthRenderer(camera?: Nullable<Camera>): void {
+            camera = camera || this.activeCamera;
+            if (!camera || !this._depthRenderer[camera.id]) {
                 return;
             }
 
-            this._depthRenderer.dispose();
-            this._depthRenderer = null;
+            this._depthRenderer[camera.id].dispose();
+            delete this._depthRenderer[camera.id];
         }
 
         public enableGeometryBufferRenderer(ratio: number = 1): Nullable<GeometryBufferRenderer> {
@@ -4036,8 +4053,8 @@
 
             this.resetCachedMaterial();
 
-            if (this._depthRenderer) {
-                this._depthRenderer.dispose();
+            for(var key in this._depthRenderer){
+                this._depthRenderer[key].dispose();
             }
 
             if (this._gamepadManager) {

BIN
tests/validation/ReferenceImages/depthOfField.png


+ 1 - 1
tests/validation/config.json

@@ -261,7 +261,7 @@
     },
     {
       "title": "Depth of field",
-      "playgroundId": "#IDSQK2#21",
+      "playgroundId": "#IDSQK2#53",
       "renderCount": 20,
       "referenceImage": "depthOfField.png"
     },

+ 0 - 1
tests/validation/index.html

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

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

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

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

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

+ 1 - 0
tests/validation/validation.js

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